AES 在线加密解密
在浏览器里用 AES-256-GCM 加密解密文本和文件,支持密码或原始密钥(含 IV 与附加数据,可解微信支付回调),密码错误明确提示认证失败,不上传。
- 在浏览器中处理
- 数据不离开你的设备
- 免费 · 无需注册
用微信扫描以下二维码即可分享
示例、说明与常见问题 带实际输出的示例、与同类工具的差别,以及常见问题。
示例一:用密码加密一句话
明文 数据库只读账号下周一启用,密码 correct horse battery staple,某一次的输出:
v2:qXfeC+pkpC/F/K3PR6ucLX6MQOcmQtyj+UUn9SYWmygCNoyV6H080bCB6fI6r1FJzypkhN0oWVRkA1VMXiCkXm6soo3Tqi/PZM0fJ28ANQk=
这 12 个汉字按 UTF-8 是 36 字节,所以 v2: 后面的 108 个 Base64 字符解码后是 80 字节:16 字节盐 + 12 字节 IV + 36 字节密文 + 16 字节认证标签。用同一个密码解密即可还原;再点一次加密,输出会变,因为盐和 IV 都是新的。
示例二:解密微信支付 APIv3 回调报文
微信支付的回调通知与平台证书下载接口用 AEAD_AES_256_GCM 加密 resource 字段,密钥是 32 字节的 APIv3 密钥,nonce 与 associated_data 按字符串参与解密,ciphertext 是 Base64 编码、末尾带 16 字节认证标签(见微信支付「如何解密回调报文和平台证书」,2024-11-29 更新)。在本工具里这样填:
| 回调字段 | 本工具 | 示例值(虚构) |
|---|---|---|
| APIv3 密钥 | 原始密钥,格式选「文本(UTF-8)」 | zerotool-example-apiv3-key-0032b |
nonce | IV 输入框 | 0123456789ab |
associated_data | AAD 输入框 | transaction |
ciphertext | 密文框 | TB0zfn/fWCjPw0A+a0ZbgqZ7CKokDC839Nw4ZaBq0aOtwBqOthxnj5Ak4KGHMF7BQ5W3PA72tzCaHxynWKK+5mdrbhBQFtsS |
点解密得到 {"out_trade_no":"ZT20260930001","trade_state":"SUCCESS"}。IV 规则:正好 24 位十六进制时按 12 字节读取,其他内容按文本的 UTF-8 字节读取,所以 12 位的 0123456789ab 按文本处理,与微信支付一致。把 AAD 改成 certificate 或清空,工具会提示认证失败。上面的密钥与报文是按同样规则用 Node.js 生成的示例;排查真实回调时,APIv3 密钥只在本机内存中使用,不会发往任何服务器。
报错说明
| 输入 | 提示 |
|---|---|
| 示例一的密文,密码输错 | 认证失败:密码或密钥不对,或者密文被改动、被截断。没有解密出任何内容。 |
U2FsdGVkX1… 开头的密文 | 这是 OpenSSL enc 或 CryptoJS 的输出…… |
把 v2: 改成 v3: | 未知的密文版本「v3:」。 |
| 密文中间混进一个全角字符 | 第 N 个字符「…」不是 Base64 字符。 |
密钥类型为原始密钥时粘贴 v2: 密文 | 这段密文以「v2:」开头,是用密码加密的。 |
如果密钥正确,但解出的字节不是 UTF-8 文本,工具会提供下载,不会显示乱码。
密文格式与 Python 代码
- 密码模式:
v2:+ Base64(或十六进制)的「盐 16 字节 | IV 12 字节 | 密文 | 认证标签 16 字节」,密钥由 PBKDF2-HMAC-SHA256 迭代 600,000 次得到 32 字节,取自 OWASP 密码存储速查表。 - 无前缀:同样的布局,是本页 2026-09-30 之前生成的(20 万次迭代)。工具先试 20 万次,再试 60 万次,因此也能读取其他程序按同一布局写出的密文。
- 原始密钥模式:Base64 或十六进制的「IV 12 字节 | 密文 | 认证标签」;填了 IV 时只有「密文 | 认证标签」,与微信支付的
ciphertext相同。 - 文件:同样的字节,不做 Base64;密码模式的文件以
v2:三个字节开头。
下面的 Python 代码(cryptography 45)与本工具互通:
import base64, os
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
def _key(password: str, salt: bytes, iterations: int) -> bytes:
kdf = PBKDF2HMAC(algorithm=hashes.SHA256(), length=32, salt=salt, iterations=iterations)
return kdf.derive(password.encode("utf-8"))
def encrypt(text: str, password: str) -> str:
salt, iv = os.urandom(16), os.urandom(12)
ct = AESGCM(_key(password, salt, 600_000)).encrypt(iv, text.encode("utf-8"), None)
return "v2:" + base64.b64encode(salt + iv + ct).decode()
def decrypt(token: str, password: str) -> str:
# 有 "v2:" 前缀为 60 万次迭代;无前缀为本工具 2026-09-30 之前的格式(20 万次)
token = token.strip()
iterations = 600_000 if token.startswith("v2:") else 200_000
data = base64.b64decode(token.removeprefix("v2:"))
salt, iv, ct = data[:16], data[16:28], data[28:]
return AESGCM(_key(password, salt, iterations)).decrypt(iv, ct, None).decode("utf-8")
def decrypt_raw(token: str, key_hex: str) -> str:
# 原始密钥模式、IV 输入框留空:Base64 或十六进制的 iv(12) | 密文 | 标签(16)
token = token.strip()
is_hex = all(c in "0123456789abcdefABCDEF" for c in token)
data = bytes.fromhex(token) if is_hex else base64.b64decode(token)
return AESGCM(bytes.fromhex(key_hex)).decrypt(data[:12], data[12:], None).decode("utf-8")
OpenSSL 与 CBC 密文
openssl enc 读不了这种格式:openssl-enc 手册写明该命令不支持 CCM、GCM 等认证加密模式,以后也不会支持;OpenSSL 3.6.1 对 -aes-256-gcm 的回应是 enc: AEAD ciphers not supported。
以 U2FsdGVkX1 开头的密文是「Salted__」的 Base64,来自 openssl enc 或 CryptoJS 的 AES.encrypt(文本, “口令”),一般是 AES-256-CBC。CBC 没有认证标签,密码错了也可能输出乱码。本工具识别到这个头会直接说明,请改用下面的命令(2026-09-30 实测):
# 用 openssl enc -pbkdf2 加密的
openssl enc -d -aes-256-cbc -pbkdf2 -a -A -in message.txt
# 用 CryptoJS 4.2.0 AES.encrypt(文本, "口令") 加密的
openssl enc -d -aes-256-cbc -md md5 -a -A -in message.txt
与其他 AES 在线工具的实测差异
2026-09-30 用桌面版 Chromium、同一段测试文本,观察页面发出的请求:
- 锤子在线工具(toolhelper.cn):点加密后把密钥、IV 与明文一起 POST 到
/SymmetricEncryption/AesEncrypt,在服务器端加密。它也有 GCM 的 nonce 与附加数据输入框,但用它解微信支付回调就意味着把 APIv3 密钥交给第三方服务器。 - 在线工具大全(lddgo.net):把明文与密码 POST 到
openapi.lddgo.net,默认模式是 ECB。 - CoderTools(codertools.net):在浏览器内运行,默认 CBC、密钥按文本;密钥错误时结果框为空,没有任何提示。
本工具只做 GCM,但每种失败都有明确提示,支持单独的 IV 与附加数据、文件加解密,页面不加载统计与广告。
限制
- 只支持 GCM,不做 CBC、ECB、CTR,读不了 openssl enc 与 CryptoJS 的输出,请用上面的命令。
- 密码模式格式固定(PBKDF2-HMAC-SHA256、60 万次、16 字节盐、无附加数据),认证标签固定 128 位。
- 文件上限 256 MB,整个在内存中处理。测试笔记本上 200 MB 文件约 0.8 秒,5 MB 文本约 1.7 秒(主要花在绘制文本框)。
- 原始密钥配随机 96 位 IV 时,NIST SP 800-38D 第 8.3 节规定同一密钥最多加密 232 次;密码模式每次都派生新密钥。
- 文件名不加密,
合同.pdf.enc仍能看出原名;加密文件本身不保存文件名。 - 弱密码加密后依然是弱密码,可用密码生成器生成;解密出的文件可用文件哈希校验核对 SHA-256。
FAQ
这个工具用的是 AES 的哪种模式?
只用 AES-GCM。密码模式是 AES-256-GCM,密钥由 PBKDF2-HMAC-SHA256 派生;原始密钥模式按密钥长度使用 AES-128、AES-192 或 AES-256。GCM 带 16 字节认证标签,密码不对或密文被改动时会提示「认证失败」,不会输出乱码。
同样的明文和密码,为什么每次加密结果都不一样?
每次加密都会重新生成 16 字节的随机盐和 12 字节的随机 IV。NIST SP 800-38D 要求同一密钥下 IV 不能重复,新盐也会派生出新密钥。这些不同的密文都能解密回同一段明文。
能用 OpenSSL 解密这里生成的密文吗?
不能。openssl enc 不支持 GCM,其手册写明以后也不会支持。请用本页的 Python 代码、Web Crypto API 或任意 AES-GCM 库按下文的字节布局解密。反过来,把 openssl enc 或 CryptoJS 生成的密文(以 U2FsdGVkX1 开头)粘进来,工具会识别出来并告诉你用哪条 openssl 命令。
我的文本、密码或文件会被上传吗?
不会。加解密都在浏览器标签页内通过 Web Crypto API 完成。页面不保存输入、不把输入写进网址,也不加载 Google Analytics 与 AdSense。
解微信支付回调时总是认证失败,常见原因是什么?
按微信支付文档,密钥是 32 字节的 APIv3 密钥字符串(密钥格式选「文本(UTF-8)」,不是十六进制或 Base64),nonce 与 associated_data 都按字符串原样填入 IV 与 AAD 输入框。associated_data 填错或漏填(文档注明它可能为空,为空时 AAD 框也留空)、密钥格式选成十六进制,都会导致认证失败。