Skip to content

Instantly share code, notes, and snippets.

@bennadel
Created July 14, 2016 10:38
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bennadel/38d0b280658149796a2bf9ce1134db4e to your computer and use it in GitHub Desktop.
Save bennadel/38d0b280658149796a2bf9ce1134db4e to your computer and use it in GitHub Desktop.
Using AES / CBC / PKCS5Padding / IV Encryption In ColdFusion And Decrypting Values In Node.js
<cfscript>
// Generated using generateSecretKey( "AES", 128 ).
encryptionKey = "Glu0r6o0GzBZIe0Qsrh2FA==";
// Generated using randRange() with "SHA1PRNG" algorithm.
initializationVector = "53IQ1tPX3aHxzqV4AyePDg==";
// I am the value that we will be encrypted and decrypting.
input = "Get out back and hold the monkey!";
// Here, we're using the "CBC" feedback mode, or "Cipher Block Chaining". In this
// mode, each block of encrypted data is fed back into the encryption algorithm for
// the encryption of the next block. As such, even an input that contains repeating
// values will not result in an output with similar repetition.
encryptedInput = encrypt(
input,
encryptionKey,
"AES/CBC/PKCS5Padding",
"base64",
binaryDecode( initializationVector, "base64" )
);
decryptedInput = decrypt(
encryptedInput,
encryptionKey,
"AES/CBC/PKCS5Padding",
"base64",
binaryDecode( initializationVector, "base64" )
);
// Output the all the values, including an input / output test.
writeOutput( "Input: #input# <br />" );
writeOutput( "Encrypted Input: #encryptedInput# <br />" );
writeOutput( "Decrypted Input: #decryptedInput# <br />" );
writeOutput( "Values Match: #( compare( input, decryptedInput ) eq 0 )#" );
</cfscript>
// Require the core node modules.
var crypto = require( "crypto" );
// I am the value that we will be encrypted and decrypting.
var input = "Get out back and hold the monkey!";
// I am the encryption inputs generated and used in the ColdFusion code.
// --
// NOTE: Generated using generateSecretKey( "AES", 128 ) and randRange( "SHA1PRNG" ).
var encryptionKey = "Glu0r6o0GzBZIe0Qsrh2FA==";
var initializationVector = "53IQ1tPX3aHxzqV4AyePDg==";
// I am the encrypted input value as generated by ColdFusion's encrypt() method.
// --
// NOTE: encrypt( input, key, "AES/CBC/PKCS5Padding", "base64", IV );
var coldfusionEncryptedValue = "73vtXZp/0BQNi2NhTxyfmJLham1tiWoAmP8sNjdIc/CO5A1/PySOgxvFhQugYkaC";
// ----------------------------------------------------------------------------------- //
// ----------------------------------------------------------------------------------- //
// The CipherIV methods must take the inputs as a binary / buffer values.
var binaryEncryptionKey = new Buffer( encryptionKey, "base64" );
var binaryIV = new Buffer( initializationVector, "base64" );
// When creating the cipher in Node, we have to make sure we use the exact same
// algorithm and inputs that we used in ColdFusion. In this case, we're using the "AES"
// (Advanced Encryption Standard) with an "CBC" (Cipher Block Chaining) feedback mode
// and 128-bit key.
var cipher = crypto.createCipheriv( "AES-128-CBC", binaryEncryptionKey, binaryIV );
// When encrypting, we're converting the UTF-8 input to base64 output.
var encryptedInput = (
cipher.update( input, "utf8", "base64" ) +
cipher.final( "base64" )
);
// ----------------------------------------------------------------------------------- //
// ----------------------------------------------------------------------------------- //
var decipher = crypto.createDecipheriv( "AES-128-CBC", binaryEncryptionKey, binaryIV );
// When decrypting we're converting the base64 input to UTF-8 output.
var decryptedInput = (
decipher.update( encryptedInput, "base64", "utf8" ) +
decipher.final( "utf8" )
);
// Output the all the values, including an input / output test for ColdFusion and
// Node.js to see if the encrypted values match.
console.log( "Input:", input );
console.log( "Encrypted Input:", encryptedInput );
console.log( "Decrypted Input:", decryptedInput );
console.log( "Values Match:", ( input === decryptedInput ) );
console.log( "ColdFusion / Node Match:", ( coldfusionEncryptedValue === encryptedInput ) );
<cfscript>
// Generated cryptographically secure 128-bit key.
encryptionKey = generateSecretKey( "AES", 128 );
// When generating the initialization vector (IV) for the AES algorithm, we have to
// use a value that is the same size as the algorithm block size, which in the case
// of AES is 16-bytes. In order to create a cryptographically secure value, we'll
// use the "SHA1PRNG" algorithms in the randRange() function, which I BELIEVE is
// provided as part of the Java Cryptography Extension (JCE).
randomIntegers = [];
for ( i = 1 ; i <= 16 ; i++ ) {
arrayAppend( randomIntegers, randRange( -128, 127, "SHA1PRNG" ) );
}
initializationVector = javaCast( "byte[]", randomIntegers );
// Output the keys for use in the ColdFusion and Node.js demos.
writeOutput( "Key: #encryptionKey# <br />" );
writeOutput( "IV: #binaryEncode( initializationVector, 'base64' )# <br />" );
</cfscript>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment