安全实用 本地计算 开箱即用 内置示例 不留痕迹

AES 在线加密解密

需要把一段文字加密后再发给别人、或存进笔记时,AES 是最常用的对称加密算法。本工具用 AES-CBC 加密,密钥不直接用你的口令,而是先用 PBKDF2-HMAC-SHA256 从口令派生(每次配一个随机盐),再随机生成初始向量,最后把盐、初始向量与密文一起打包输出。同一段文字用同一口令加密两次,结果完全不同。

想把一段私密文字存进云端笔记,或发给指定的人而不怕中途被看——对称加密是标准做法。这里从你的口令派生密钥、配随机盐和初始向量,同一段话加密两次结果都不同,安全性靠参数规范而不是「算法保密」;用前先记住一件事:口令忘了,神仙也解不开。

使用前记住三件事:忘记口令没有任何办法恢复,口令请记在稳妥的地方;解密时口令、密钥长度、迭代次数三个参数必须与加密时完全一致;输出是盐 16 字节加初始向量 16 字节再加密文的自定义拼接,与 OpenSSL 的 Salted__ 格式不同,跨系统解密需按此拆包。

使用步骤

  1. 加密:填明文与口令(建议 12 位以上混合字符),选密钥长度与迭代次数。
  2. 复制完整结果串(Base64 或十六进制),盐与 IV 已包含在内,一起发即可。
  3. 解密:粘贴完整结果串,选与加密时相同的口令与参数。
  4. 提示无法解密时,先查口令是否输错、参数是否一致、串是否被截断。

计算原理与示例

加密结果的打包格式

输出串的结构是固定的三段拼接:盐 16 字节 + 初始向量(IV)16 字节 + 密文,整体再按 Base64(默认)或十六进制显示。盐与初始向量不需要保密,跟着密文一起保存或发送即可;解密时工具会按同样的顺序拆包,所以你用本工具加密的内容,只要口令、密钥长度与迭代次数一致,就一定能解回来。

为什么两次加密结果不一样

每次加密都会用随机数生成新的盐与初始向量,因此同样的口令、同样的明文,两次加密得到的密文必然不同。这是刻意设计:如果相同明文总是产出相同密文,攻击者就能通过「密文一样」推断出「内容一样」,也能预先算好常见口令与明文组合的对照表(彩虹表)来反查。解密不受影响,因为盐和初始向量都随密文一起传递。

加密与解密的使用要点

加密方向要填明文与口令;解密方向要粘贴完整的加密结果串(不要漏掉开头,也不要把中间的空格当成内容),同时口令、密钥长度、迭代次数三个参数必须与加密时完全一致。如果口令输错或密文在传输中被改动了一个字符,工具会提示无法解密——这是 PKCS#7 填充校验在起作用,它说明数据校验失败,而不是工具坏了。

口径:AES-CBC(128 / 192 / 256 位)+ PKCS#7 填充,密钥用 PBKDF2-HMAC-SHA256 从口令派生(默认 10000 次迭代),盐与初始向量各 16 字节且每次随机;输出为 Base64 或十六进制,内容 = 盐 + 初始向量 + 密文。实现与 FIPS-197 标准向量及 node:crypto 逐字节对拍一致。

代码示例

Shell OpenSSL 命令行加解密

# 口令派生密钥(PBKDF2)+ 随机盐,思路与本工具一致
openssl enc -aes-256-cbc -pbkdf2 -iter 10000 -salt \
  -in plain.txt -out enc.txt
openssl enc -d -aes-256-cbc -pbkdf2 -iter 10000 \
  -in enc.txt -out plain.txt

# 注意:OpenSSL 的 Salted__ 头格式与本工具的三段拼接不同,
# 结果不能直接互换,需按前 16 字节盐、再 16 字节 IV 拆包

JavaScript 浏览器 WebCrypto 派生密钥

// 从口令派生 AES 密钥(与本工具同参数)
const baseKey = await crypto.subtle.importKey(
  "raw", new TextEncoder().encode(password), "PBKDF2", false, ["deriveKey"]);

const key = await crypto.subtle.deriveKey(
  { name: "PBKDF2", salt, iterations: 10000, hash: "SHA-256" },
  baseKey, { name: "AES-CBC", length: 256 }, false, ["encrypt", "decrypt"]);

// salt 与 iv 各 16 字节,须随密文一起保存

常见问题

忘记口令还能解密吗?

不能,没有任何办法。本工具不保存口令,也不会把口令藏在密文里——密钥是每次用你输入的口令现算出来的,口令不对就算不出正确密钥,结果只能是校验失败。这也正是 AES 加密的意义:没有后门,谁都绕不过口令。所以加密后请务先把口令记在稳妥的地方,并考虑用「口令提示」而不是直接写在同一处。

同一段文字同一个口令,为什么两次加密结果不一样?

因为每次加密都重新生成了随机的盐与初始向量,它们随密文一起保存,所以解密不受影响。这种设计叫语义安全:相同明文不产出相同密文,攻击者无法通过观察密文判断两段内容是否一致。如果你需要「确定性加密」(同样的输入总得到同样的输出,比如做去重查询),AES-CBC 的这套流程并不适合。

盐和初始向量是干什么用的,为什么要跟着密文一起存?

盐用于从口令派生密钥:没有盐时,同一个口令在任何地方算出的密钥都相同,攻击者可以预先为常见口令建好对照表;加了随机盐,每份密文的密钥都不同,预计算就失效了。初始向量用于让 CBC 模式的每一块密文都不相同,避免相同内容块产生相同密文。两者都不需要保密,但解密时必须拿到原始值,所以打包进密文一起传。

这个工具用的是 AES-GCM 吗?

不是,用的是 AES-CBC 加 PKCS#7 填充。CBC 是兼容性最好的模式,几乎所有语言和库都支持,方便你把结果拿到别的系统里解密。但 CBC 不是认证加密:它能察觉大部分篡改(解密后填充校验会失败),却不能像 GCM 那样给出明确的完整性验证。如果数据需要防篡改且两端都由你控制,建议改用支持 AES-GCM 的库。

输出格式应该选 Base64 还是十六进制?

看目标环境。Base64 更短(同样数据比十六进制少约四分之一字符),适合贴进 JSON、URL 参数、配置文件;十六进制只含 0~9 与 a~f,肉眼核对时不容易看错,也方便逐字节比对。两者只是同一段字节的两种写法,随时可以互相转换,解密时选对格式即可。

PBKDF2 的迭代次数选多少合适?

本工具提供 1000、10000、50000 三档,默认 10000。迭代次数越高,攻击者暴力尝试口令的成本越高,但你自己每次加密解密也要多等一会儿。日常使用 10000 是常见折中;如果要长期保存重要内容,建议选 50000 并配合一个长口令。注意解密时必须选与加密时相同的档位,否则密钥不同、无法解开。

口令有什么要求吗?

越长约好,建议至少 12 位并且混合大小写、数字与符号,不要使用姓名、生日、手机号、常见单词或它们的简单变形。PBKDF2 只是提高了暴力尝试的成本,并不能把弱口令变强——如果口令是「123456」,无论迭代多少次都能在可接受时间内被猜出来。另外,本工具不接受空口令。

我加密的内容和口令会被上传到服务器吗?

不会。AES、PBKDF2 与随机数生成全部由浏览器内的 JavaScript 完成,页面不发任何网络请求;结果也不会写进 localStorage——本工具没有「计算历史」区块,正是因为它处理的可能是真实凭证。可以用浏览器开发者工具的网络面板自行确认,断网状态下功能同样可用。

能和 OpenSSL、Java 等其他系统互相解密吗?

可以,只要对方用同样的参数:AES-128/192/256-CBC、PKCS#7 填充、PBKDF2-HMAC-SHA256 派生密钥,并从结果串头部取出盐与初始向量。本工具的输出是自定义的三段拼接格式,不是 OpenSSL 的 Salted__ 格式,所以不能直接把整串喂给 openssl 命令,需要先按「前 16 字节盐、再 16 字节 IV」拆出来。

延伸阅读

来自本站原创文章,讲清这个工具背后的算法与口径。