Node.js crypto key and iv to match java SecretKeySpec / IvParameterSpec

后端 未结 1 567
别那么骄傲
别那么骄傲 2021-02-06 13:44

I\'m trying to to port a Java (simple) encryption algorythm to Node JS. I will need to be able to decrypt/encrypt stuff encrypted/decrypted from the Java side.

I\'m stuc

相关标签:
1条回答
  • 2021-02-06 14:40

    Assuming you have the same password string as in the Java code, you can create a key buffer like this in node:

    var key = new Buffer(password, "utf8");
    

    Since you're using a zero filled IV (bad!) in Java, this is the equivalent code in node:

    var iv = new Buffer(16); // 16 byte buffer with random data
    iv.fill(0); // fill with zeros
    

    Since you're using CBC mode in Java, you have to do the same in node. Note that you have to select the correct key size when selecting the cipher string depending on your "password" length:

    var aesCipher = mCrypto.createCipheriv("aes-128-cbc", key, iv);
    // or
    var aesCipher = mCrypto.createCipheriv("aes-192-cbc", key, iv);
    // or
    var aesCipher = mCrypto.createCipheriv("aes-256-cbc", key, iv);
    

    Node will automatically apply PKCS#7 padding which is the same as PKCS#5 padding for AES.

    A password is not a key!

    A password has usually not the appropriate length to be used as a key (valid lengths are 16 byte, 24 byte and 32 byte for AES) and it is comprised of only printable characters which might make it easier for an attacker to brute force the key.

    What you would need to create a key from a password is key derivation function. Popular ones are PBKDF2, bcrypt and scrypt (with increasing cost).

    Random IV!

    You really should be generating a new random IV for every ciphertext that you produce. If you use a static IV, an attacker that observes your ciphertexts can determine that you sent the same or even similar messages. If you use a random IV, then the ciphertexts differ so much that an attacker cannot determine whether two different ciphertexts where created from the same plaintext or not. This is called semantic security.

    The random IV itself doesn't have to be secret, so you can easily prepend it to the ciphertext and slice it off before decryption.

    You can even combine this with the key derivation function (KDF). Simply generate a random salt for the KDF. A KDF is usually able to derive a variable amount of output bytes, so simply let it derive key || IV (concatenation) and then split them. Now, you only need to prepend the salt to the ciphertext.

    Authentication!

    Depending on your system, you might be vulnerable to attacks such as the padding oracle attack. The best defense against this is to authenticate the ciphertext. So you can either use an encrypt-then-MAC scheme with a strong MAC such as HMAC-SHA256 or an authenticated mode of operation such as GCM or EAX. Java and node both support GCM, but there is a little more work involved.

    0 讨论(0)
提交回复
热议问题