Question

I am trying to field level encrypt data in Node using the crypto library.

It seems to work just fine, except with special characters like $ and -

Ex "Price-Smith"

Not sure why

function encrypt(data, key) {
    if (data === null)
        return null
    else if (typeof data === 'undefined')
        return undefined;
    else if (data === '')
        return '';

    var iv = crypto.randomBytes(16);

    var cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
    cipher.update(data, 'utf8', 'binary');
    return Buffer.concat([iv, cipher.final()]).toString('base64');
}

function decrypt(cipher, key) {
    if (cipher === null)
        return null
    else if (typeof cipher == 'undefined')
        return undefined;
    else if (cipher === '')
        return '';

    var cipher = new Buffer(cipher, 'base64');
    var iv = cipher.slice(0, 16);
    var ciphertext = cipher.slice(16);

    var decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
    decipher.update(ciphertext, 'binary', 'utf8');
    return decipher.final('utf8');
}

Error

TypeError: error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
at Decipheriv.Cipher.final (crypto.js:287:27)

A separate IV is used for each field value, otherwise fields values that are the same would have the same cipher. So I store the IV as the first 16 bytes and splice it off before decryption. Maybe this could be my problem area?

Thanks! Andrew

Was it helpful?

Solution

This is probably due to the size of the plaintext rather than the type of characters used. You need to concatenate the response from update() with the response from final(). Don't use += operator, it does not always work on arrays.

OTHER TIPS

Thanks @owlstead! Here is the working code:

function encrypt(data, key) {
    if (data === null)
        return null
    else if (typeof data === 'undefined')
        return undefined;
    else if (data === '')
        return '';

    var iv = crypto.randomBytes(16);

    var cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
    var encrypted = [cipher.update(data)];
    encrypted.push(cipher.final());

    return Buffer.concat([iv, Buffer.concat(encrypted)]).toString('base64');
}

function decrypt(cipher, key) {
    if (cipher === null)
        return null
    else if (typeof cipher == 'undefined')
        return undefined;
    else if (cipher === '')
        return '';

    var cipher = new Buffer(cipher, 'base64');
    var iv = cipher.slice(0, 16);
    var ciphertext = cipher.slice(16);

    var decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
    var decrypted = [decipher.update(ciphertext)];
    decrypted.push(decipher.final());

    return Buffer.concat(decrypted).toString('utf8');
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top