Search code examples
javanode.jsencryptionopensslaes

Encrypt in node and decrypt in java


I have an encrypt-code in Java. I'm trying to port the encrypt part to node. Basically, node will do the encryption using the crypto module, and then Java will do the decryption.

Here's how I do encryption in Java:

protected static String encrypt(String plaintext) {
    final byte[] KEY = {
            0x6d, 0x79, 0x56, 0x65, 0x72, 0x79, 0x54, 0x6f, 0x70,
            0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x4b
    };

    try {
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        final SecretKeySpec secretKey = new SecretKeySpec(KEY, "AES");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        final String encryptedString = Base64.encodeToString(
            cipher.doFinal(plaintext.getBytes()), Base64.DEFAULT);

        return encryptedString;
    } catch (Exception e) {
        return null;
    }
}

Here's how I do encryption in node:

var crypto = require('crypto'),
    key = new Buffer('6d7956657279546f705365637265744b', 'hex'),
    cipher = crypto.createCipher('aes-128-ecb', key),
    chunks = [];

cipher.setAutoPadding(true);
chunks.push(cipher.update(
    new Buffer(JSON.stringify({someKey: "someValue"}), 'utf8'),
    null, 'base64'));
chunks.push(cipher.final('base64'));

var encryptedString = chunks.join('');

In Java, I get the string T4RlJo5ENV8h1uvmOHzz1KjyXzBoBuqVLSTHsPppljA=. This gets decrypted correctly. However, in node, I get al084hEpTK7gOYGQRSGxF+WWKvNYhT4SC7MukrzHieM= which is obviously different and thus it won't get decrypted correctly.

I tried to look for people who has the same problem as me, and this github issue is the closest I can find. As suggested in that issue, I tried running openssl like so:

$ echo -e '{"someKey": "someValue"}' | openssl enc -a -e -aes-128-ecb -K "6d7956657279546f705365637265744b"
T4RlJo5ENV8h1uvmOHzz1MY2bhoFRHZ+ClxsV24l2BU=

The result I got was close enough to the one produced by java, but still different:

T4RlJo5ENV8h1uvmOHzz1MY2bhoFRHZ+ClxsV24l2BU=  // openssl
T4RlJo5ENV8h1uvmOHzz1KjyXzBoBuqVLSTHsPppljA=  // java
al084hEpTK7gOYGQRSGxF+WWKvNYhT4SC7MukrzHieM=  // node

Which brings me to the question, how do I make node output the same encrypted string as my java code? I can only change my code in node, but not in java.


Solution

  • Finally, I found the solution to my problem. Thanks to this guy. The key to the solution is the initialization vector. Quoting the gist:

    // ECB mode won't need IV, so keep it like this and it will work well.

    Here's how the solution looks like:

    var crypto = require('crypto'),
        iv = new Buffer(''),
        key = new Buffer('6d7956657279546f705365637265744b', 'hex'),
        cipher = cypto.createCipheriv('aes-128-ecb', key, iv),
        chunks = [];
    
    chunks.push(cipher.update(
        new Buffer(JSON.stringify({someKey: "someValue"}), 'utf8'),
        'buffer', 'base64'));
    chunks.push(cipher.final('base64'));
    var encryptedString = chunks.join('');