test-cryptojs-format.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. // 详细测试CryptoJS兼容的加密解密
  2. const CryptoJS = require('crypto-js');
  3. // 测试不同的加密方法和后端解密模拟
  4. console.log('=== 测试1: 标准CryptoJS加密 ===');
  5. const credentials = { username: 'admin', password: 'password123' };
  6. const secretKey = 'MyDifficultPassw';
  7. // 前端加密
  8. const encrypted = CryptoJS.AES.encrypt(JSON.stringify(credentials), secretKey);
  9. const base64String = encrypted.toString();
  10. console.log('加密结果:', base64String);
  11. // 检查是否以'Salted__'开头
  12. const rawData = Buffer.from(base64String, 'base64');
  13. const header = rawData.slice(0, 8).toString('utf8');
  14. console.log('前8字节:', header, '(是否为Salted__):', header === 'Salted__');
  15. // 尝试后端的第一种解密方式(CryptoJS格式)
  16. try {
  17. // 提取盐值和加密数据
  18. const salt = rawData.slice(8, 16); // 8字节盐值
  19. const encryptedData = rawData.slice(16); // 加密数据
  20. console.log('提取的盐值:', salt.toString('hex'));
  21. console.log('加密数据长度:', encryptedData.length);
  22. // 在Node.js中模拟PBKDF2派生密钥和IV的过程
  23. // 这里我们使用一种近似的方法来验证CryptoJS格式
  24. const decryptedWithCryptoJS = CryptoJS.AES.decrypt(base64String, secretKey).toString(CryptoJS.enc.Utf8);
  25. console.log('使用CryptoJS直接解密结果:', decryptedWithCryptoJS);
  26. if (decryptedWithCryptoJS === JSON.stringify(credentials)) {
  27. console.log('✅ CryptoJS格式解密成功');
  28. } else {
  29. console.log('❌ CryptoJS格式解密失败');
  30. }
  31. } catch (e) {
  32. console.log('❌ CryptoJS格式解密异常:', e.message);
  33. }
  34. console.log('\n=== 测试2: 手动构造AES/CBC/PKCS5Padding加密 ===');
  35. // 尝试更精确地匹配后端解密逻辑
  36. try {
  37. const CryptoJS = require('crypto-js');
  38. // 使用与后端一致的参数进行加密
  39. const key = CryptoJS.enc.Utf8.parse(secretKey);
  40. const iv = CryptoJS.enc.Utf8.parse('1234567812345678'); // 固定IV用于测试
  41. const encryptedCustom = CryptoJS.AES.encrypt(JSON.stringify(credentials), key, {
  42. iv: iv,
  43. mode: CryptoJS.mode.CBC,
  44. padding: CryptoJS.pad.Pkcs7
  45. });
  46. const base64Custom = encryptedCustom.toString();
  47. console.log('自定义加密结果:', base64Custom);
  48. // 检查是否以'Salted__'开头
  49. const rawDataCustom = Buffer.from(base64Custom, 'base64');
  50. const headerCustom = rawDataCustom.slice(0, 8).toString('utf8');
  51. console.log('自定义加密前8字节:', headerCustom, '(是否为Salted__):', headerCustom === 'Salted__');
  52. // 尝试解密
  53. const decryptedCustom = CryptoJS.AES.decrypt(base64Custom, key, {
  54. iv: iv,
  55. mode: CryptoJS.mode.CBC,
  56. padding: CryptoJS.pad.Pkcs7
  57. }).toString(CryptoJS.enc.Utf8);
  58. console.log('自定义解密结果:', decryptedCustom);
  59. console.log('自定义加密解密是否成功:', decryptedCustom === JSON.stringify(credentials));
  60. } catch (e) {
  61. console.log('❌ 自定义加密解密失败:', e.message);
  62. }
  63. console.log('\n=== 测试3: 模拟后端解密CryptoJS格式的逻辑 ===');
  64. // 由于Node.js环境无法完全模拟Java的解密过程,
  65. // 让我们创建一个测试来模拟Java解密CryptoJS格式的步骤
  66. // CryptoJS的加密过程大致如下:
  67. // 1. 生成8字节随机盐值
  68. // 2. 使用'U2FsdGVkX1'作为前缀 + 盐值 + 加密数据
  69. // 3. 对盐值和密码进行PBKDF2派生,得到密钥和IV
  70. // 4. 使用AES/CBC/PKCS5Padding加密数据
  71. // 我们可以通过CryptoJS来验证这种格式
  72. const saltedEncrypted = CryptoJS.AES.encrypt(JSON.stringify(credentials), secretKey);
  73. console.log('Salted格式加密:', saltedEncrypted.toString());
  74. // 验证是否可以正确解密
  75. const saltedDecrypted = CryptoJS.AES.decrypt(saltedEncrypted.toString(), secretKey).toString(CryptoJS.enc.Utf8);
  76. console.log('Salted格式解密:', saltedDecrypted);
  77. console.log('Salted格式是否成功:', saltedDecrypted === JSON.stringify(credentials));
  78. console.log('\n=== 结论 ===');
  79. console.log('前端和后端都应该使用相同的密钥:', secretKey);
  80. console.log('如果仍有问题,可能是后端解密算法与CryptoJS格式不完全兼容');