Search code examples
javascriptstringbinarycryptojs

Binary string in javascript above charcode 128


I'm trying to decrypt OpenSSL AES encrypted file, to do so I need to read the salt from the begining of the file, and give it with the password to CryptoJS openssl key derivation function to get the derivated key and iv.

Sadly, CryptoJS expect the salt as a String, and String in JS handle poorly binary data. A char over 128 is interpreted as 2 bits in JS (see: Trouble with binary string in javascript above character code 128):

// if you wanna test it, openssl command to generate a file from any file :
// openssl enc -aes-256-cbc -in file.txt -out file.enc -k password
fs.readFile('file.enc', function(err, data) {
    var Salted__ = data.toString("utf-8", 0, 8); // 'Salted__' prefix
    var salt = data.toString("hex", 8, 16); // the actual salt I want to give to CryptoJS
    // output in hex: 46d69efb7f57380b

    var buf = new Buffer(salt, "hex");
    console.log(buf);
    // output <Buffer 46 d6 9e fb 7f 57 38 0b>, exactly what I want, but it is a buffer not a String object.

    // the problem can be seen here:
    var buf2 = new Buffer(buf.toString());
    console.log(buf2);
    // output <Buffer 46 d6 9e ef bf bd 7f 57 38 0b>
    // as you can see, fb => ef bf bd

    // fun fact, when I try to do it manualy, I get another result (that seem more logical to me):
    var str = '';
    for (var i = 0; i < hex.length; i += 2)
        str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
    console.log(new Buffer(str));
    // output <Buffer 46 c3 96 c2 9e c3 bb 7f 57 38 0b>
    // in this case (I've tryed it char by char to be sure):
    // d6 => c3 96
    // 9e => c2 9e
    // fb => c3 bb

    var derivedParams = CryptoJS.kdf.OpenSSL.execute(password, 256/32, 128/32, buf.toString());
    console.log(derivedParams.key.toString());
    console.log(derivedParams.iv.toString());
    // output a wrong key and a wrong iv (I know what I should get using openssl enc -P option)

});

Any help or explanation on how JS work with binary string would be appreciated :)


Solution

  • I've found a solution !

    var salt = CryptoJS.enc.Hex.parse(salt);
    CryptoJS.kdf.OpenSSL.execute(password, 256/32, 128/32, salt);