Skip to content

Instantly share code, notes, and snippets.

@ericchen
Created July 10, 2012 08:11
Show Gist options
  • Save ericchen/3081970 to your computer and use it in GitHub Desktop.
Save ericchen/3081970 to your computer and use it in GitHub Desktop.
nodejs AES encrypt and decrypt
var crypto = require('crypto');
var AESCrypt = {};
AESCrypt.decrypt = function(cryptkey, iv, encryptdata) {
encryptdata = new Buffer(encryptdata, 'base64').toString('binary');
var decipher = crypto.createDecipheriv('aes-256-cbc', cryptkey, iv),
decoded = decipher.update(encryptdata);
decoded += decipher.final();
return decoded;
}
AESCrypt.encrypt = function(cryptkey, iv, cleardata) {
var encipher = crypto.createCipheriv('aes-256-cbc', cryptkey, iv),
encryptdata = encipher.update(cleardata);
encryptdata += encipher.final();
encode_encryptdata = new Buffer(encryptdata, 'binary').toString('base64');
return encode_encryptdata;
}
var cryptkey = crypto.createHash('sha256').update('Nixnogen').digest(),
iv = 'a2xhcgAAAAAAAAAA',
buf = "Here is some data for the encrypt", // 32 chars
enc = AESCrypt.encrypt(cryptkey, iv, buf);
var dec = AESCrypt.decrypt(cryptkey, iv, enc);
console.warn("encrypt length: ", enc.length);
console.warn("encrypt in Base64:", enc);
console.warn("decrypt all: " + dec);
@AttilaSATAN
Copy link

error on win7 64bit node v0.10.10

crypto.js:286 var ret = this._binding.final(); _______________________^ TypeError: error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length at Decipheriv.Cipher.final (crypto.js:286:27) at Object.AESCrypt.decrypt (F:\EclipseNodejsWorkspace\Project\app.js:169:25)

@dscape
Copy link

dscape commented Jul 28, 2013

TypeError: error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length
    at Decipheriv.Cipher.final (crypto.js:287:27)
    at Object.AESCrypt.decrypt (repl:7:21)
    at repl:1:27
    at REPLServer.self.eval (repl.js:110:21)
    at repl.js:249:20
    at REPLServer.self.eval (repl.js:122:7)
    at Interface.<anonymous> (repl.js:239:12)
    at Interface.EventEmitter.emit (events.js:95:17)
    at Interface._onLine (readline.js:202:10)
    at Interface._line (readline.js:531:8)

@blenderman-de
Copy link

can´t decrypt with node v0.10.18

crypto.js:287
  var ret = this._binding.final();
                          ^
TypeError: error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
    at Decipher.Cipher.final (crypto.js:287:27)
    at Object.efs.readFileSync (e:\response\node_modules\efs\efs.js:151:67)
    at Object.<anonymous> (e:\response\efs.js:7:5)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)
    at startup (node.js:119:16)
    at node.js:901:3

@cloudgifts
Copy link

Any solution here? I am seeing this error with Node v0.10.24

@cloudgifts
Copy link

Ok, so there was a change to Crypto in the switch from 0.8 to 0.10: "Crypto methods return Buffer objects by default, rather than binary-encoded strings" https://github.com/joyent/node/wiki/Api-changes-between-v0.8-and-v0.10

This means the above code needs to specify encodings.

These four lines:

decoded = decipher.update(encryptdata);
decoded += decipher.final();
encryptdata = encipher.update(cleardata);
encryptdata += encipher.final();

Are changed to:

decoded = decipher.update(encryptdata, 'binary', 'utf8');
decoded += decipher.final('utf8');
encryptdata = encipher.update(cleardata, 'utf8', 'binary');
encryptdata += encipher.final('binary');

This worked for me, but I am open to other suggestions.

@shesek
Copy link

shesek commented Dec 31, 2014

To do this with Buffers, without casting everyting to strings, you can use something like that:

decoded = decipher.update(encryptdata);
decoded = Buffer.concat([ decoded, decipher.final() ]);

encryptdata = encipher.update(cleardata);
encryptdata = Buffer.concat([ encryptdata, encipher.final() ]);

@mukulgupta2507
Copy link

@cloudgifts
@shesek

I'm facing exactly same problem while using this AES encrypt and decrypt.

crypto.js:202
  var ret = this._handle.final();
                         ^
Error: error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length
    at Error (native)
    at Decipher.Cipher.final (crypto.js:202:26)

These are my encrypt and decrypt functions:

var config = {
cryptkey: crypto.createHash('sha256').update('Nixnogen').digest(),
iv: "a2xhcgAAAAAAAAAA"
};

function encryptText(text){
    console.log(config.cryptkey);
        var cipher = crypto.createCipheriv('aes-256-cbc', config.cryptkey, config.iv);
        var crypted = cipher.update(text,'utf8','binary');
        crypted += cipher.final('binary');
    crypted = new Buffer(crypted, 'binary').toString('base64');
        return crypted;
}

function decryptText(text){
    console.log(config.cryptkey);
        if (text === null || typeof text === 'undefined' || text === '') {return text;};
    text = new Buffer(text, 'base64').toString('binary');
        var decipher = crypto.createDecipheriv('aes-256-cbc', config.cryptkey, config.iv);
        var dec = decipher.update(text,'binary','utf8');
        dec += decipher.final('utf8');
        return dec;
}

I'm using "node": ">=0.10.0" in my app.
Can anyone please tell me how to fix it? I have tried above solutions but none is working for me.

Thanks

@linkkingjay
Copy link

Ok, so there was a change to Crypto in the switch from 0.8 to 0.10: "Crypto methods return Buffer objects by default, rather than binary-encoded strings" https://github.com/joyent/node/wiki/Api-changes-between-v0.8-and-v0.10

This means the above code needs to specify encodings.

These four lines:

decoded = decipher.update(encryptdata);
decoded += decipher.final();
encryptdata = encipher.update(cleardata);
encryptdata += encipher.final();

Are changed to:

decoded = decipher.update(encryptdata, 'binary', 'utf8');
decoded += decipher.final('utf8');
encryptdata = encipher.update(cleardata, 'utf8', 'binary');
encryptdata += encipher.final('binary');

This worked for me, but I am open to other suggestions.

This worked for me, too.

@imvikaskohli
Copy link

imvikaskohli commented Apr 17, 2017

Ok, so there was a change to Crypto in the switch from 0.8 to 0.10: "Crypto methods return Buffer objects by default, rather than binary-encoded strings" https://github.com/joyent/node/wiki/Api-changes-between-v0.8-and-v0.10

This means the above code needs to specify encodings.

These four lines:

decoded = decipher.update(encryptdata);
decoded += decipher.final();
encryptdata = encipher.update(cleardata);
encryptdata += encipher.final();

Are changed to:

decoded = decipher.update(encryptdata, 'binary', 'utf8');
decoded += decipher.final('utf8');
encryptdata = encipher.update(cleardata, 'utf8', 'binary');
encryptdata += encipher.final('binary');

This worked for me too

Thanks @cloudgifts

@subhasisghosal
Copy link

It's not working for me. Still giving same error.

@bitcoinbrisbane
Copy link

I had the same issue, and worked it out by setting auto padding = true. I thought id add to the thread incase it helps someone else. This is some code for a project I'm working on.

app.post('/encyrptaes', (req, res) => {
    const algorithm = 'aes-256-cbc';

    var key = new Buffer(32);
    var password = Buffer.from('600f003a6ed434917afbbc7f03f2edf86a19f72448e2e9d05917e73e502f6970', 'hex')
    var cryptoStr = 'the quick brown fox';
    
    var iv = new Buffer(16);

    var buf = new Buffer(cryptoStr, 'base64');
    var crypt = buf.toString('base64');
    
    var cipher = crypto.createCipheriv(algorithm, password, iv);
    cipher.setAutoPadding(true); //If this is false I get the error.

    var c = cipher.update(crypt, 'base64', 'utf-8');
    c += cipher.final('utf-8'); 
    
    console.log('Encrypted content: ' + c);

    res.send({
        cyphertext: c,
        timestamp: Date.now()
    });
});

@KrishnanSriram
Copy link

How does it work for streams?

const encryptInputFile = async (filePath, cb) => {
try {
// Use the async crypto.scrypt() instead.
const key = crypto.scryptSync(PASSWORD, 'salt', 24);
// Use crypto.randomBytes() to generate a random iv instead of the static iv
// shown here.
const iv = Buffer.alloc(16, 0);
// Initialization vector.
const cipher = crypto.createCipheriv(ALGORITHM, key, iv);
// create input and output stream
const input = fs.createReadStream(filePath);
const output = fs.createWriteStream(TARGET_PATH);

    input.pipe(cipher).pipe(output);
    cb(null)
} catch (error) {
    console.log('ERROR: Encryption failed', error);
    cb(error);
}

}

const decryptFile = async (encryptedFile, targetPath, cb) => {
try {
// Use the async crypto.scrypt() instead.
const key = crypto.scryptSync(PASSWORD, 'salt', 24);
// The IV is usually passed along with the ciphertext.
const iv = Buffer.alloc(16, 0); // Initialization vector.

    const decipher = crypto.createDecipheriv(ALGORITHM, key, iv);
    console.log(`Source file: ${encryptedFile}, target file: ${targetPath}`);
    const input = fs.createReadStream(encryptedFile);
    const output = fs.createWriteStream(targetPath);

    input.pipe(decipher).pipe(output);
    cb(null);
} catch (error) {
    console.log('ERROR: Failed in decryption', error);
    cb(error);
}

}

error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length
at Decipheriv._flush (internal/crypto/cipher.js:143:29)
at Decipheriv.prefinish (_stream_transform.js:141:10)
at Decipheriv.emit (events.js:188:13)
at prefinish (_stream_writable.js:635:14)
at finishMaybe (_stream_writable.js:643:5)
at endWritable (_stream_writable.js:663:3)
at Decipheriv.Writable.end (_stream_writable.js:594:5)
at ReadStream.onend (_stream_readable.js:655:10)
at Object.onceWrapper (events.js:276:13)
at ReadStream.emit (events.js:193:15)
Emitted 'error' event at:
at errorOrDestroy (internal/streams/destroy.js:98:12)
at Decipheriv.onerror (_stream_readable.js:717:7)
at Decipheriv.emit (events.js:188:13)
at done (_stream_transform.js:208:19)
at _flush (_stream_transform.js:142:7)
at Decipheriv._flush (internal/crypto/cipher.js:145:5)
at Decipheriv.prefinish (_stream_transform.js:141:10)
[... lines matching original stack trace ...]
at finishMaybe (_stream_writable.js:643:5)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment