在我回答我自己的问题之前,应该先表示感谢。感谢Dave Boyer(戴先生)、Jason Dean和Jason Delmore的帮助。
正如 Leigh 建议的那样,我必须使用 Bouncy Castle、轻量级 API 和其中的 Rijndael 密码引擎。
我最终得到了一个创建 rijndael 密码的函数以及使用密钥和 ivsalt 加密和解密字符串的函数。
<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>
doEncrypt 和 doDecrypt 函数是公开可见的,但不是创建 rijndael 密码的函数。加密和解密函数采用字符串、密钥和 ivSalt,分别返回加密或解密的字符串。
createRijndaelBlockCipher 需要一个密钥 ivSalt,它是一个布尔值,用于说明密码是否将用于加密或解密以及块大小,尽管块大小默认为 256 位。该函数的注释相当好,因此它应该是有意义的。
底部的 UDF(特别感谢 Jason Delmore 的那个金块)确保 ColdFusion 正确地为解密创建了一个字节数组。创建字节数组的其他一些方法不起作用或最终导致解密结果不一致或抛出填充缓冲区损坏错误。
就是这样。当标准的 AES 加密使用 128 位块并且 128 位密钥用于机密,192 位或更高位用于 TOP-SECRET 时,这需要付出太多努力。256 位块和 256 位密钥略高于顶部。仅仅因为你可以并不意味着你应该。
请记住 MCRYPT_RIJNDAEL_256 是块大小而不是加密级别。加密级别由您传递给 mcrypt_encrypt 的密钥强度设置,增加块大小不会增加加密强度。