nfroidure nfroidure - 1 month ago 21
Java Question

Difference between RC4 implementations

I have to implement a RC4 cipher in NodeJS, here is the code:

function cipher (CRYPTO, str) {
const cipher = crypto.createCipher(CRYPTO.cipherAlgorithm, CRYPTO.password);

return Buffer.concat([
cipher.update(str, 'utf-8'),
cipher.final()
]).toString(CRYPTO.encoding);
}

const CRYPTO = {
cipherAlgorithm: 'rc4',
password: 'trololol',
encoding: 'base64'
};

cipher(CRYPTO, '0612345678');
// returns 'yTXp/PZzn+wYsQ=='


When i check my implementation with open ssl, i've got the same result:

echo -ne "0612345678" | openssl rc4 -pass "pass:trololol" -e -nosalt | base64
> yTXp/PZzn+wYsQ==


But with our partner implementation, the result is really different. It is written in Java so i tried to do one and i have the same result than him:

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import javax.xml.bind.DatatypeConverter;

public class Encryptor {
private static String algorithm = "RC4";
public static String encrypt(String key, String value) {
try {
SecretKeySpec rc4Key = new SecretKeySpec(key.getBytes(), algorithm);
Cipher rc4 = Cipher.getInstance(algorithm);

rc4.init(Cipher.ENCRYPT_MODE, rc4Key);
byte [] encrypted = rc4.update(value.getBytes());
return DatatypeConverter.printBase64Binary(encrypted);
} catch (Exception ex) {
ex.printStackTrace();
}

return null;
}

public static void main(String[] args) {
String key = "trololol";
String value = "0612345678";

System.out.println(encrypt(key, value));
}
}


Running the above gives:

javac Encryptor.java && java Encryptor
> LYlbWr0URiz+wA==


Is it possible that the RC4 algorithm in Java differs from the other ones or is there something wrong in the Java implementation?

Answer

The difference is "password" vs "key."

For example with node and OpenSSL, "password" means some value to hash (using MD5) to generate the key for encryption/decryption.

If you instead use the "password" value as the key (with an empty IV), you will match the value received from Java. For example with node, change to the createCipheriv() function:

crypto.createCipheriv(CRYPTO.cipherAlgorithm, CRYPTO.password, Buffer.alloc(0));
Comments