使用 CryptoJS 从解密格式解析为填充最多的字符串时遇到问题

Trouble using CryptoJS parsing from decrypted format to string with most padding

我只是无法使用 CryptoJS 以我想要的方式工作。我正在尝试使用理想的 Pksc7 填充和 CBC 模式为 AES 创建跨语言可操作性。但是在这一点上,如果它有效,我将采用几乎所有填充。现在我不确定是我做错了什么,还是我的设置或 CryptoJS 有问题。我有一个比较大的测试 im 运行。最后,我需要为我的解密文本输出一个字符串,但我没有得到。这非常令人沮丧!

我已经在 docs 上下移动了很多次,到目前为止尝试了很多东西都没有可用的输出,请参阅下面的代码以解决问题。

这是我为了寻求帮助而查看的一些帖子 and this

我也是 运行 我的 Parse 服务器云代码中的这个。

上面帖子中的示例有效但不能解码回字符串,而且它只在没有填充的情况下有效——我不行...

现在任何帮助都会对我的智慧有所帮助:)

 var CryptoJS = require("crypto-js");
  const keygen = require('secure-random-password');

/// MY EXAMPLE I WOULD LIKE TO GET WORKING - FROM HERE

    var keygenKey = keygen.randomPassword({length: 32, characters: [keygen.lower, keygen.upper, keygen.digits] });
    var keygenIV = keygen.randomPassword({length: 16, characters: [keygen.lower, keygen.upper, keygen.digits] });
    
    var key = CryptoJS.enc.Hex.parse("keygenKey");
    var iv = CryptoJS.enc.Hex.parse("keygenIV");
    var plainText = CryptoJS.enc.Hex.parse("Hello world");

    var encrypted = await CryptoJS.AES.encrypt(plainText, key, {
      // format: JsonFormatter, // Tried the json formatter from docs - made no difference
      iv: iv,
      mode: CryptoJS.mode.CBC,
      padding: CryptoJS.pad.Pkcs7
    }).ciphertext.toString();

    var decrypted = await CryptoJS.AES.decrypt({ciphertext: encrypted}, key, {
      // format: JsonFormatter, // Tried the json formatter from docs - made no difference
      iv: iv,
      mode: CryptoJS.mode.CBC,
      padding: CryptoJS.pad.Pkcs7
    });

/// MY EXAMPLE I WOULD LIKE TO GET WORKING - TO HERE
    
    // Working - but I need padding so this is no good
    const examplePlain =  CryptoJS.enc.Hex.parse("Hello world");
    const exampleKey  = CryptoJS.enc.Hex.parse("000102030405060708090a0b0c0d0e0f");
    const exampleIV   = CryptoJS.enc.Hex.parse("101112131415161718191a1b1c1d1e1f");
    const exampleEncrypted = CryptoJS.AES.encrypt(examplePlain, exampleKey, {iv: exampleIV, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.NoPadding}).ciphertext.toString();
    const exampleDecrypted = CryptoJS.AES.decrypt({ciphertext: exampleEncrypted}, exampleKey, {iv: exampleIV, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.NoPadding});
    
    var utf8String = decrypted.toString(CryptoJS.enc.Utf8);
    var hex = CryptoJS.enc.Hex.stringify(decrypted).toString();
    var words = CryptoJS.enc.Utf8.parse(decrypted);
    var utf8 = CryptoJS.enc.Utf8.stringify(decrypted);

    return {
      "keygenIV": keygenIV,
      "keygenKey": keygenKey,
      "encrypted": encrypted.toString(),
      "decrypted": decrypted,
      "test_hex": hex,
      "test_words": words,
      "test_utf8": utf8,
      "test_utf8String": utf8String,
      "example_encrypted": exampleEncrypted,
      "example_decrypted": exampleDecrypted.toString()
  }

我要回收的垃圾

{
keygenIV: 23bfHtf9nmGSXg9G, 
keygenKey: B9PFLTwFC87z4WePzkcJLCMNvUnaXinV, 
encrypted: 95a3d7b2cd0bf5f35271afa9af359d5e, 
decrypted: {words: [487551153, 1344444817, 251806218, 1966320389, 418267123, -2081063279, -2093335598, 1651281808], sigBytes: -112, $super: {}}, 
test_hex: , 
test_words: {words: [], sigBytes: 0, $super: {}}, 
test_utf8: , 
test_utf8String: , 
example_encrypted: 0378aaa355b9, 
example_decrypted: 417e2f4a1f6192bf7b1a2ab3
}

关于垃圾的信息:

{
keygenIV: 23bfHtf9nmGSXg9G, // Perfect
keygenKey: B9PFLTwFC87z4WePzkcJLCMNvUnaXinV, // Perfect
encrypted: 95a3d7b2cd0bf5f35271afa9af359d5e, //Perfect

// Can't figure out a way to get this object formatted as string
decrypted: {words: [487551153, 1344444817, 251806218, 1966320389, 418267123, -2081063279, -2093335598, 1651281808], sigBytes: -112, $super: {}},

test_hex: , 
test_words: {words: [], sigBytes: 0, $super: {}}, 
test_utf8: , 
test_utf8String: , 
example_encrypted: 0378aaa355b9, // Whatever...

example_decrypted: 417e2f4a1f6192bf7b1a2ab3 // This does not decode by utf8 I get error: Malformed UTF-8 data
}

代码中存在一些编码错误:

  • keygen.randomPassword() 不是 return 十六进制编码的字符串,但是十六进制编码器用于解析。可以生成十六进制编码的密钥和 IV,例如如下:

    var keygenKey = keygen.randomPassword({length: 64, characters: '0123456789abcdef' }); // 32 bytes key
    var keygenIV = keygen.randomPassword({length: 32, characters: '0123456789abcdef' }); // 16 bytes IV
    

    还有,解析的时候引号一定要去掉:

    var key = CryptoJS.enc.Hex.parse(keygenKey);
    var iv = CryptoJS.enc.Hex.parse(keygenIV);
    

    请注意,CryptoJS 支持生成随机密钥和 IV,因此 secure-random-password 实际上不是必需的:

    var key = CryptoJS.lib.WordArray.random(32);
    var iv = CryptoJS.lib.WordArray.random(16);
    
  • 明文也是用hex编码解析的,这里必须使用utf8编码:

    var plainText = CryptoJS.enc.Utf8.parse("Hello world");
    
  • decrypt() 调用中,密文以十六进制编码传递,而必须传递 WordArray

    var decrypted =  CryptoJS.AES.decrypt({ciphertext: CryptoJS.enc.Hex.parse(encrypted)},...
    

通过这些修复,代码可以正常工作:

console.log({
    "keygenKey": keygenKey,
    "keygenIV": keygenIV,
    "encrypted": encrypted,
    "decrypted": decrypted.toString(CryptoJS.enc.Utf8),
});

举例

{
  keygenKey: '10b361a633bfbc163d312d9fd52730d36d19f4db08a7a14481637eaeb662d175',
  keygenIV: 'bbfd9b4361a1d6f2bd2a81db1dd7e81b',
  encrypted: 'c0771e1f8146ddaf82ea2198e6a2749e',
  decrypted: 'Hello world'
}