使用 Crypto-JS 可以非常方便地在 JavaScript 进行 MD5、SHA1、SHA2、SHA3、RIPEMD-160 哈希散列,进行 AES、DES、Rabbit、RC4、Triple DES 加解密。

Crypto-JS 相关 encrypt 函数会并不直接返回字符串,需要调用返回对象的 toString 方法,或者通过 Crypto-JS 转码才能得到真实的结果。

前端AES使用

  1. // 官方示例, 每次输出的密文都不一样
  2. CryptoJS.AES.encrypt("Message", "Secret Passphrase");
  3. // 正确用法
  4. var str = '123456';
  5. // 密钥 16 位
  6. var key = '0123456789abcdef';
  7. // 初始向量 initial vector 16 位
  8. var iv = '0123456789abcdef';
  9. // key 和 iv 可以一致
  10. key = CryptoJS.enc.Utf8.parse(key);
  11. iv = CryptoJS.enc.Utf8.parse(iv);
  12. var encrypted = CryptoJS.AES.encrypt(str, key, {
  13. iv: iv,
  14. mode: CryptoJS.mode.CBC,
  15. padding: CryptoJS.pad.Pkcs7
  16. });
  17. // 转换为字符串
  18. encrypted = encrypted.toString();
  19. // mode 支持 CBC、CFB、CTR、ECB、OFB, 默认 CBC
  20. // padding 支持 Pkcs7、AnsiX923、Iso10126
  21. // 、NoPadding、ZeroPadding, 默认 Pkcs7, 即 Pkcs5
  22. var decrypted = CryptoJS.AES.decrypt(encrypted, key, {
  23. iv: iv,
  24. mode: CryptoJS.mode.CBC,
  25. padding: CryptoJS.pad.Pkcs7
  26. });
  27. // 转换为 utf8 字符串
  28. decrypted = CryptoJS.enc.Utf8.stringify(decrypted);
  29. // 引入其他加密模式, 填充模式需要引入对应的 js 文件
  30. /*
  31. cryptojs/components/mode-cfb-min.js
  32. cryptojs/components/mode-ctr-min.js
  33. cryptojs/components/mode-ecb-min.js
  34. cryptojs/components/mode-ofb-min.js
  35. cryptojs/components/pad-ansix923-min.js
  36. cryptojs/components/pad-iso10126-min.js
  37. cryptojs/components/pad-iso97971-min.js
  38. cryptojs/components/pad-nopadding-min.js
  39. */

IV称为初始向量
AES加密需要:明文 + 密钥+ 偏移量(IV)+密码模式(算法/模式/填充)
AES解密需要:密文 + 密钥+ 偏移量(IV)+密码模式(算法/模式/填充)

mode 支持 CBC、CFB、CTR、ECB、OFB, 默认 CBC
padding 支持 Pkcs7、AnsiX923、Iso10126、NoPadding、ZeroPadding, 默认 Pkcs7, 即 Pkcs5

mode === ECB 时, 不需要 iv

java AES使用

java提供AES算法支持。支持的密钥长度为:128, 192, 或256位。由于美国进出口限制,默认的jre只支持128位,也就是16个字节的密钥。

支持的工作模式:

NONE
CBC
CCM
CFB, CFBx
CTR
CTS
ECB
GCM
OFB, OFBx
PCBC

支持的填充方式:

NoPadding
ISO10126Padding
OAEPPadding
PKCS1Padding
PKCS5Padding
SSL3Padding
当使用Cipher.getInstance(“AES”)时,默认获取的是AES/ECB/PKCS5Padding对应的实例。实际使用中这里一定要注意一下,建议实际应用中一定要显示指定工作模式和填充方式。若不显示指定,在跨语言、跨类库或跨系统调用时,容易踩坑。

java 和 js互相加解密问题

java和js互相加解密时,如果不指定工作模式和填充方式,会失败。在js中,一般使用crypto-js库来加解密。但是该类库默认的工作模式是CBC,默认填充方式PKCS7,与java的默认方式不一致。

很多同学在使用AES算法时,不显示指定工作模式和填充方式,在这里就会屡屡出错。问题就出在java和js(crypto-js)默认的工作模式和填充方式不一致。这里只要将两者的工作模式和填充指定一样即可。

第一种方式: js采用AES/CBC/ZeroPadding方式加密。由于java没有提供ZeroPadding填充方式,可以使用AES/CBC/NoPadding方式解密,解密后从后往前依次剔除0x00的字节,遇到非0x00的字节时停止。剩下的字节就是解密后的结果。不过,这种方式需要注意,原始文本转byte数组后,最后一个字节不能是0x00。如果是java加密,js解密,将过程反过来即可。
第二种方式(推荐使用):
前端: AES/CBC/Pkcs7 + iv
后端: AES/CBC/Pkcs5 + iv

相关链接: https://yyhan.github.io/2017/06/26/java-AES%E4%BD%BF%E7%94%A8/