I am trying to duplicate this PHP function in ColdFusion but I am getting an error that the Algorithm does not exist.
function encrypt_decrypt($action, $string) {
$output = false;
$encrypt_method = "AES-256-CBC";
$secret_key = 'This is my secret key';
$secret_iv = 'This is my secret iv';
// hash
$key = hash('sha256', $secret_key);
// iv - encrypt method AES-256-CBC expects 16 bytes - else you will get a warning
$iv = substr(hash('sha256', $secret_iv), 0, 16);
if ( $action == 'encrypt' ) {
$output = openssl_encrypt($string, $encrypt_method, $key, 0, $iv);
$output = base64_encode($output);
} else if( $action == 'decrypt' ) {
$output = openssl_decrypt(base64_decode($string), $encrypt_method, $key, 0, $iv);
}
return $output;
}
I am using Lucee 5.2.3.35
My Call
<cfset var secret_key = "This is my secret key">
<cfset var secret_iv = "This is my secret iv">
<cfset var key = Lcase(Hash(secret_key, "SHA-256"))>
<cfset var iv = Lcase(Left(Hash(secret_iv, "SHA-256"),16))>
<cfset output = Encrypt(arguments.string, key, 'AES-256-CBC', 'Base64', iv)>
ERROR
Cannot find any provider supporting AES-256-CBC
I then installed Bouncy Castle and tried using this cfc
<cfcomponent displayname="Bounce Castle Encryption Component" hint="This provides bouncy castle encryption services" output="false">
<cffunction name="createRijndaelBlockCipher" access="private">
<cfargument name="key" type="string" required="true" >
<cfargument name="ivSalt" type="string" required="true" >
<cfargument name="bEncrypt" type="boolean" required="false" default="1">
<cfargument name="blocksize" type="numeric" required="false" default=256>
<cfscript>
// Create a block cipher for Rijndael
var cryptEngine = createObject("java", "org.bouncycastle.crypto.engines.RijndaelEngine").init(arguments.blocksize);
// Create a Block Cipher in CBC mode
var blockCipher = createObject("java", "org.bouncycastle.crypto.modes.CBCBlockCipher").init(cryptEngine);
// Create Padding - Zero Byte Padding is apparently PHP compatible.
var zbPadding = CreateObject('java', 'org.bouncycastle.crypto.paddings.ZeroBytePadding').init();
// Create a JCE Cipher from the Block Cipher
var cipher = createObject("java", "org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher").init(blockCipher,zbPadding);
// Create the key params for the cipher
var binkey = binarydecode(arguments.key,"hex");
var keyParams = createObject("java", "org.bouncycastle.crypto.params.KeyParameter").init(BinKey);
var binIVSalt = Binarydecode(ivSalt,"hex");
var ivParams = createObject("java", "org.bouncycastle.crypto.params.ParametersWithIV").init(keyParams, binIVSalt);
cipher.init(javaCast("boolean",arguments.bEncrypt),ivParams);
return cipher;
</cfscript>
</cffunction>
<cffunction name="doEncrypt" access="public" returntype="string">
<cfargument name="message" type="string" required="true">
<cfargument name="key" type="string" required="true">
<cfargument name="ivSalt" type="string" required="true">
<cfscript>
var cipher = createRijndaelBlockCipher(key=arguments.key,ivSalt=arguments.ivSalt);
var byteMessage = arguments.message.getBytes();
var outArray = getByteArray(cipher.getOutputSize(arrayLen(byteMessage)));
var bufferLength = cipher.processBytes(byteMessage, 0, arrayLen(byteMessage), outArray, 0);
var cipherText = cipher.doFinal(outArray,bufferLength);
return toBase64(outArray);
</cfscript>
</cffunction>
<cffunction name="doDecrypt" access="public" returntype="string">
<cfargument name="message" type="string" required="true">
<cfargument name="key" type="string" required="true">
<cfargument name="ivSalt" type="string" required="true">
<cfscript>
var cipher = createRijndaelBlockCipher(key=arguments.key,ivSalt=arguments.ivSalt,bEncrypt=false);
var byteMessage = toBinary(arguments.message);
var outArray = getByteArray(cipher.getOutputSize(arrayLen(byteMessage)));
var bufferLength = cipher.processBytes(byteMessage, 0, arrayLen(byteMessage), outArray, 0);
var originalText = cipher.doFinal(outArray,bufferLength);
return createObject("java", "java.lang.String").init(outArray);
</cfscript>
</cffunction>
<cfscript>
function getByteArray(someLength)
{
byteClass = createObject("java", "java.lang.Byte").TYPE;
return createObject("java","java.lang.reflect.Array").newInstance(byteClass, someLength);
}
</cfscript>
</cfcomponent>
My Bouncy castle call
<cfset bc = CreateObject('component', 'model.services.bouncycastle')>
<cfset output = bc.doDecrypt(arguments.string,key,iv)>
But I get this error now.
initialisation vector must be the same length as block size
Does anyone have any suggestions on duplicating this PHP function exactly?
Thanks for any help