tools / des
des/
DES 对称加密和解密,用来对接还在用 DES 的老系统。模式、填充、密钥和 IV 的格式、字符集都可以选,结果和 Java、CryptoJS 一致,密钥不会离开浏览器。
明文
密文
历史记录
每次加密、解密成功后自动记一条,保留最近 20 条,只存在这台设备的浏览器里。不保存密钥,但会保存 IV 和解密出的明文,在公用电脑上用完请清空记录。
AES、DES、RSA 是什么,有什么区别
AES 和 DES 是对称加密:加密和解密用同一把密钥,就像同一把钥匙锁门也开门。它们速度快,适合加密大量数据,难处在于怎么把这把密钥安全地交给对方。
DES 是上世纪 70 年代的老标准,有效密钥只有 56 位,现在用专门的硬件或计算机集群可以暴力穷举破解,只适合对接还在用它的老系统。AES 是取代 DES 的新标准,密钥 128、192 或 256 位,目前没有可行的破解方法,是现在加密数据的首选。
RSA 是非对称加密:有一对密钥,公钥可以公开给任何人,用来加密;私钥自己保管,用来解密。就像一个谁都能往里投信、只有你有钥匙的信箱。好处是不用事先约定密钥,缺点是很慢,一次只能加密几百字节。实际系统常把两者结合:先用 RSA 加密一把随机生成的 AES 密钥发给对方,再用 AES 加密真正的数据。
加密模式是什么,选哪个
DES 每次只能加密 8 字节,模式决定一长串数据怎么切块、块与块之间怎么关联。ECB 每块单独加密,相同的内容会得到相同的密文,会暴露数据规律,不推荐。CBC 让每块先和上一块的密文混合再加密,第一块和 IV 混合,是最常见的选择。CFB、OFB、CTR 把 DES 变成一串密钥流和数据逐字节异或,可以不填充。
密钥、IV 和填充
DES 的密钥是 8 字节,其中每个字节的最低位是校验位、不参与运算,所以有效密钥只有 56 位。超过 8 字节时只用前 8 字节,和 Java 的 DESKeySpec、CryptoJS 一样;不足 8 字节会报错。除 ECB 外都要 8 字节的 IV,它不需要保密,但同一把密钥下不要重复使用。
ECB 和 CBC 要求数据长度是 8 字节的整数倍,不够时按填充方式补齐。PKCS5Padding 和 PKCS7Padding 对 DES 完全一样,是最常用的;ZeroPadding 补 0,解密时会去掉结尾所有的 0 字节,明文本身以 0 字节结尾时会一起被去掉;NoPadding 不补,要自己保证长度。
和 Java、CryptoJS 的写法怎么对应
Java 的 Cipher.getInstance("DES/CBC/PKCS5Padding") 就是选 CBC 和 PKCS5Padding;只写 "DES" 时默认是 ECB 和 PKCS5Padding。Java 的 CTR 只能用 NoPadding。CryptoJS.DES.encrypt 的模式和填充同名对应,CryptoJS.pad.Pkcs7 对应 PKCS7Padding。新系统请直接用 AES。
常见问题
这里能加解密 3DES(DESede、TripleDES)吗
不能,这里只有单重 DES。3DES 的密钥是 16 或 24 字节,粘贴进来只会用前 8 字节,算出来的结果和 3DES 不一样,密钥栏旁也会提示「只用前 8 字节」。需要 3DES 请换支持 DESede 的工具。
提示「密钥是 N 字节,DES 密钥至少要 8 字节」怎么办
少于 8 字节会报错,这里不会自动补零,需要自己补到 8 字节。更容易踩的是格式选错:16 个字符的 hex 密钥如果密钥格式选成了 string,会被当成 16 字节的文本,只用前 8 个字符,不会报错,只在密钥栏旁和结果下方提示「只用前 8 字节」,结果自然对不上。选 string 时字节数按所选字符集计算,一个汉字在 UTF-8 下占 3 字节。
提示「IV 必须是 8 字节」怎么办
DES 的 IV 要正好 8 字节,不是 AES 的 16 字节,除 ECB 外的模式都是这样。密钥超过 8 字节会取前 8 字节,IV 不会,多了或少了都直接报错,所以从 AES 参数里拿来的 16 字节 IV 要改成 8 字节。同样要先看格式:16 个字符的 hex 才是 8 字节,选 string 就是 16 字节。ECB 不用 IV,IV 栏会隐藏。
解密提示「填充不对」或「密文不是 8 的整数倍」怎么办
密文长度不是 8 的整数倍,多半是复制不完整,或者 hex 和 base64 选反了。填充不对,通常是密钥、IV、模式或填充方式有一项和加密时不一致。ZeroPadding 和 NoPadding 不检查填充,不会报这个错,但参数不对时结果是乱码。
解密结果开头一段是乱码,或提示「不是有效的 UTF-8 文本」
先查 IV。密文超过一个块时,CBC 和 CFB 模式下 IV 不对,只会让第一个 8 字节的块出错,后面的内容正常,也不会报填充错误,现象就是开头乱码、后面是对的。如果提示结果不是有效的文本,也可能是字符集和加密端不一致,比如对方用的是 GBK。把输出格式改成 hex,可以先确认解出来的字节本身对不对。
加密结果和 Java、CryptoJS 对不上,怎么排查
按这个顺序核对:模式和填充、密钥和 IV 的格式与字节数、字符集、输入输出格式。string 格式的明文不会去掉首尾空白,末尾多一个换行就是另一段数据。CTR、CFB、OFB 在这里也会按所选填充补齐,选 PKCS5Padding 时密文比明文长,后端用 NoPadding 的话这里也要选 NoPadding。CFB 是 64 位整块反馈,对方用 CFB8 的话对不上。
CryptoJS.DES.encrypt 的结果以 U2FsdGVkX1 开头,这里能解吗
不能。CryptoJS.DES.encrypt(明文, 字符串) 传字符串时,会把它当口令:随机加盐,再按 OpenSSL 的方式推出密钥和 IV,结果以 U2FsdGVkX1 开头,这种格式这里不支持。要和这里对上,请在 CryptoJS 里用 CryptoJS.enc.Utf8.parse 把密钥转成字节再传入,并明确指定 iv、mode 和 padding。
历史记录里存了什么,会上传吗
只存在这台设备浏览器的 localStorage 里,不会上传,页面代码里没有任何网络请求。每次成功加密或解密后记一条,最多保留 20 条,输入或结果超过 2 万字符的不记。记录里有参数、IV、输入和结果,以及一个由密钥前 8 字节算出的 8 位指纹(记录里 # 号后面的那串字符,用来区分是不是同一把密钥),不存密钥本身,所以点「填入」后要重新填密钥。每条可以单独删除,公用电脑上用完请点「清空记录」。