上传文件
  1. base64hub
  2. 密钥与哈希
  3. AES 解密

AES 解密 Base64 密文

粘贴加密的 Base64,输入密码即可读出消息。AES-GCM 在解密的同时校验完整性,所以密码错误或哪怕改动了一个字符,都会给出明确的错误提示。

免费 无需注册,不限次数 本地 不上传任何内容 防篡改校验 每次解密都会验证 GCM 标签 更新于 2026年10月27日
格式:在任何地方都能解密

输出 = Base64( 盐值 16 字节 ‖ IV 12 字节 ‖ 密文 ‖ GCM 标签 16 字节 )。密钥 = PBKDF2-HMAC-SHA256(以 UTF-8 编码的密码, 盐值, 310,000 次迭代, 32 字节)。加密算法:AES-256-GCM,无附加数据。解密代码:

Python (pip install cryptography)

import base64
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives import hashes

def decrypt(b64, password):
    data = base64.b64decode(b64)
    salt, iv, ct = data[:16], data[16:28], data[28:]
    key = PBKDF2HMAC(algorithm=hashes.SHA256(), length=32, salt=salt,
                     iterations=310000).derive(password.encode("utf-8"))
    return AESGCM(key).decrypt(iv, ct, None).decode("utf-8")
Node.js

const crypto = require("crypto");
function decrypt(b64, password) {
  const data = Buffer.from(b64, "base64");
  const salt = data.subarray(0, 16), iv = data.subarray(16, 28);
  const tag = data.subarray(data.length - 16), ct = data.subarray(28, data.length - 16);
  const key = crypto.pbkdf2Sync(password, salt, 310000, 32, "sha256");
  const d = crypto.createDecipheriv("aes-256-gcm", key, iv);
  d.setAuthTag(tag);
  return Buffer.concat([d.update(ct), d.final()]).toString("utf8");
}

在你的浏览器中处理。此页面无法将你的数据发送到任何地方: 我们如何确认

如何解密 AES 文本

  1. 默认已选中 解密,并载入了一个示例。它的密码是 correct horse battery staple,你可以先看看成功解密的效果。
  2. 把你的字符串粘贴到 加密的 Base64 中。标准 Base64 和 URL 安全 Base64 都可以,有没有 = 都行,换行会被忽略。
  3. 密钥类型选择 密码 时,输入密码;如果发送方改过迭代次数,还要填入相同的 PBKDF2 迭代次数(默认 310,000)。选择 原始密钥 时,以 Base64 或 hex 形式粘贴 16、24 或 32 字节的密钥。
  4. 点击 解密,或在密码框中按回车。消息会显示在 解密后的文本 下方。如果内容不是 UTF-8 文本,则以 Base64 显示,点击 下载 可以保存原始字节。

解密成功时会显示“已解密并通过认证”:GCM 标签匹配,说明文本与发送方加密的内容完全一致。

Base64 解密还是 Base64 解码?

很多人手里只有一个普通的 Base64 字符串,却去搜索“Base64 解密”。Base64 是一种没有密钥的编码,这样的字符串只需要解码,Base64 解码器就能做到。一个简单的判断方法:如果解码后得到可读的文本或可识别的文件,那它从来就没有被加密过。如果得到的是看似随机的字节,而且有人给了你一个密码,那你拿到的就是密文,这个页面正适合你,前提是它是按下面的格式生成的。Base64 不是加密解释了两者的区别。

用已知的值测试

下面这个字符串是在浏览器之外,用格式文档中的 Python encrypt() 函数、以密码 correct horse battery staple 加密得到的:

SD8wB+5V2GRfupy/yEY1xTUE8d5z9fwbzQ0gxeRzbtym1I4O7A9Q2NYnbYxEPYgvwJ4Q7DU5q/sugOx+B1Ro3ujkDXvnl/y2XYuji9A=

它解密后是 Meet me at the usual place at 10.。这 104 个字符解码为 77 个字节:16 字节盐值、12 字节 IV、33 字节密文和 16 字节标签。对于你粘贴的任何字符串,结果下方的明细都会显示同样的拆分。

错误提示及其含义

提示常见原因
解密失败:密码或密钥错误、模式错误,或数据已被修改密码错误、迭代次数不同、把原始密钥用于密码模式的数据(或者反过来),或者复制时丢了字符
太短,不可能是此工具生成的密文字符串被截断了,或者根本不是本工具生成的
AES 密钥必须是 16、24 或 32 字节原始密钥长度不对;请检查它是 Base64 还是 hex
此浏览器不支持 192 位 AES 密钥Chrome 和 Edge 只允许 128 位和 256 位密钥;请改用 Python 或 Node.js 解密
迭代次数必须在 1,000 到 10,000,000 之间迭代次数字段中的值不合理

GCM 不区分密码错误和数据被篡改:两种情况下标签都不匹配,也都不会输出任何内容。CBC 等不带认证的模式则可能返回一堆乱码而不报错。

本工具无法打开的字符串

这里的格式是固定的:密码模式为 Base64( salt[16] ‖ iv[12] ‖ ciphertext ‖ tag[16] ),原始密钥模式为 Base64( iv[12] ‖ ciphertext ‖ tag[16] ),算法为 AES-GCM,密钥派生为 310,000 次迭代的 PBKDF2-HMAC-SHA256。其他工具会写出其他格式,开头几个字符往往就能暴露它们:

开头生成方解密方式
U2FsdGVkX1使用口令的 openssl enc 或 CryptoJS(Salted__ 头部)用原来的加密算法和 KDF 选项执行 openssl enc -d -a
gAAAAAFernet 令牌(Python cryptography)Fernet(key).decrypt(token)
-----BEGIN PGP MESSAGE-----OpenPGPgpg --decrypt
-----BEGIN AGE ENCRYPTED FILE-----ageage --decrypt

更多可识别的开头收录在 常见 Base64 开头中。

在 Node.js 和 Python 中解密

同样的格式不用浏览器也能处理。在 Node.js 中:

const crypto = require("crypto");

function decrypt(b64, password) {
  const data = Buffer.from(b64, "base64");
  const salt = data.subarray(0, 16), iv = data.subarray(16, 28);
  const tag = data.subarray(data.length - 16), ct = data.subarray(28, data.length - 16);
  const key = crypto.pbkdf2Sync(password, salt, 310000, 32, "sha256");
  const d = crypto.createDecipheriv("aes-256-gcm", key, iv);
  d.setAuthTag(tag);
  return Buffer.concat([d.update(ct), d.final()]).toString("utf8");
}

function encrypt(text, password) {
  const salt = crypto.randomBytes(16), iv = crypto.randomBytes(12);
  const key = crypto.pbkdf2Sync(password, salt, 310000, 32, "sha256");
  const c = crypto.createCipheriv("aes-256-gcm", key, iv);
  const ct = Buffer.concat([c.update(text, "utf8"), c.final()]);
  return Buffer.concat([salt, iv, ct, c.getAuthTag()]).toString("base64");
}

对于 Python 中原始密钥模式的字符串,跳过盐值和 PBKDF2,IV 从第 0 字节开始:

import base64
from cryptography.hazmat.primitives.ciphers.aead import AESGCM

def decrypt_raw(b64, key_b64):
    data = base64.b64decode(b64)
    iv, ct = data[:12], data[12:]
    return AESGCM(base64.b64decode(key_b64)).decrypt(iv, ct, None).decode("utf-8")

Python 的密码模式版本见 AES 加密页面。这类加密适合把一个秘密从一个人传给另一个人;送达之后,请把它转存到密码管理器或密钥管理服务中,不要一直保留密文。

常见问题

没有密码能解密 Base64 吗?

如果只是 Base64,可以,因为根本没有什么需要解密的:把它粘贴到 Base64 解码器即可。如果是以 Base64 表示的 AES 密文,就不行。没有密码或密钥,这些字节无法恢复,也没有任何工具能猜出强密码。

密码明明是对的,为什么提示密码错误?

先检查 PBKDF2 迭代次数:它不保存在密文中,如果发送方改过这个值,必须告诉你具体数字。另外,请确认字符串复制完整,并且确实是本工具格式生成的。

这个工具能解密 OpenSSL 或 CryptoJS 加密的文本吗?

不能。以 U2FsdGVkX1 开头的字符串带有 OpenSSL 的 Salted__ 头部,使用不同的密钥派生方式,通常还是 CBC 模式。请用 openssl enc -d 加上加密时的相同选项来解密。

解密后的文本会被怎样处理?

它只显示在页面上,不会出现在其他任何地方。解密通过 WebCrypto 在你的浏览器中完成,页面的内容安全策略会阻止除 Cloudflare 的浏览量统计以外的所有网络请求,所以密码和消息都不会被发送出去。