javascriptencryptionrncryptor

RNCryptor JS simple case fails


I have used RNCryptor successfully in Objective-C, and now need to encrypt data for my iOS app from Javascript. But, this simple test fails...

<script type="text/javascript" src="js/utils/sjcl.js"></script>
<script type="text/javascript" src="js/utils/rncryptor.js"></script>

function testEncodeEncrypt_RN(plaintext) {
    var secret = "rosebud";
    var encrypted = RNCryptor.Encrypt(secret, plaintext);
    var decrypted = RNCryptor.Decrypt(secret, encrypted);
    console.log("decrypted to " + decrypted);
}

...with the error "Uncaught CORRUPT: pkcs#5 padding corrupt" thrown by sjcl.js.

I've tried various options objects, but I figure that no options ought to work for both Encrypt and Decrypt. Varying the input string and secret do no good, either. Any ideas?


Solution

  • /*
      Takes password string and plaintext bitArray
      options:
        iv
        encryption_salt
        html_salt
      Returns ciphertext bitArray
    */
    RNCryptor.Encrypt = function(password, plaintext, options) {
    

    Is plaintext a bitArray? If you're passing a UTF-8 string, you'll need to convert it with sjcl.codec.utf8String.toBits. There are also codecs for hex and base64 encoding. See the SJCL docs.

    The latest versions of SJCL will accept strings and autoconvert them to bitArrays, but I probably won't touch the JS implementation myself again until I finish work on the v4 format (should be before the end of 2015). I am happy to accept pull requests.

    Note that RNCryptor-js is not fully compatible with any of the other implementations (including the ObjC implementation). JavaScript is too slow to handle the 10,000 PBKDF2 iterations that are required for the v3 format, so it defaults to using 1,000. That means you have to modify the code on the other side to match (or configure JS to use 10,000, but it'll take 10x as long to deal with passwords). Look for the two .rounds configuration settings in RNCryptor.h.

    One of the major goals of the v4 format is to make iteration count configurable to make JavaScript capable of interoperating (unfortunately by dramatically reducing the security of the encryption, but it's all JavaScript can handle today).