Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

Encrypt with Node.js Crypto module and decrypt with Java (in Android app)

Encrypt with Node.js Crypto module and decrypt with Java (in Android app)

Problem

Looking for a way to encrypt data (mainly strings) in node and decrypt in an android app (java).

Have successfully done so in each one (encrypt/decrypt in node, and encrypt/decrypt in java) but can't seem to get it to work between them.

Possibly I'm not encrypting/decrypting in the same way, but each library in each language has different names for same things...

Any help appreciated.

here's some code: Node.js

var crypto = require('crypto')
var cipher = crypto.createCipher('aes-128-cbc','somepass')
var text = "uncle had a little farm"
var crypted = cipher.update(text,'utf8','hex')
crypted += cipher.final('hex')
//now crypted contains the hex representation of the ciphertext

and java

private static String decrypt(byte[] raw, byte[] encrypted) throws Exception {
    SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.DECRYPT_MODE, skeySpec );
    byte[] decrypted = cipher.doFinal(encrypted);
    return new String(decrypted);
}

the Raw Key is created like this

private static byte[] getRawKey(String seed) throws Exception {
    KeyGenerator kgen = KeyGenerator.getInstance("AES");
    SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
    byte[] seedBytes = seed.getBytes()
    sr.setSeed(seedBytes);
    kgen.init(128, sr); // 192 and 256 bits may not be available
    SecretKey skey = kgen.generateKey();
    byte[] raw = skey.getEncoded();
    return raw;
}

while the encrypted hex string is converted to bytes like this

public static byte[] toByte(String hexString) {
    int len = hexString.length()/2;
    byte[] result = new byte[len];
    for (int i = 0; i 
Problem courtesy of: Shh

Solution

Apparently if you pass a passphrase to crypto.createCipher() it uses OpenSSL's EVP_BytesToKey() to derive the key. You can either pass a raw byte buffer and use the same to initialize Java's SecretKey, or emulate EVP_BytesToKey() in your Java code. Use $ man EVP_BytesToKey for more details, but essentially it hashes the passphrase multiple times with MD5 and concatenates a salt.

As for using a raw key, something like this should let you use a raw key:

var c = crypto.createCipheriv("aes-128-ecb", new Buffer("00010203050607080a0b0c0d0f101112", "hex").toString("binary"), "");

Note that since you are using CBC, you need to use the same IV for encryption and decryption (you might want to append it to your message, etc.)

Mandatory warning: implementing a crypto protocol yourself is rarely a good idea. Even if you get this to work, are you going to use the same key for all messages? For how long? If you decide to rotate the key, how to you manage this. Etc, .etc.

Solution courtesy of: Nikolay Elenkov

Discussion

View additional discussion.



This post first appeared on Node.js Recipes, please read the originial post: here

Share the post

Encrypt with Node.js Crypto module and decrypt with Java (in Android app)

×

Subscribe to Node.js Recipes

Get updates delivered right to your inbox!

Thank you for your subscription

×