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

我无法让任何东西以我想要的方式使用CryptoJS。我正在尝试用Pksc7填充为AES创建跨语言的可操作性,理想的情况是&;CBC模式。但在这一点上,如果有效的话,我几乎可以接受任何填充物。现在我不确定是我做错了什么,还是我的设置或CryptoJS有问题。我有一个比较大的测试在运行。最后,我需要解密文本的字符串输出,但我得不到。这太令人沮丧了!

我已经在docs上上下下试了很多次,到目前为止尝试了这么多方法,但没有可用的输出,请参阅下面的代码以了解问题。

以下是我查找帮助的一些帖子this和this

我还在我的解析服务器云代码中运行此代码。

上面帖子中的例子可以工作,但不能解码回字符串,而且它只在没有填充的情况下工作-对我来说不行...

任何帮助都会对我的智慧有很大帮助:)

 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()不返回十六进制编码的字符串,但是十六进制编码器用于解析。可以生成十六进制编码的密钥和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);
    
  • 明文也使用十六进制编码器进行解析,此处必须应用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'
}

相关文章