Created
July 14, 2016 10:38
Using AES / CBC / PKCS5Padding / IV Encryption In ColdFusion And Decrypting Values In Node.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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 ) ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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