Skip navigation
edevmachine
Currently Being Moderated

encrypt/decrypt AES 256, vorsalt error

Jul 6, 2012 11:27 PM

Tags: #encrypt #generatesecretkey #aes #rijndael

Hiyas.

 

So I'm trying to get encrypt/decrypt to work for AES 256, with both 32byte key and 32byte IVorSalt. (Yup-new java security files v6 installed)

 

'IF' I 32byte key but dont use a IV at all, I get a nice looking AES 256 result. (I can tell it's AES 256 by looking the length of the encrypted string)

 

'IF' I use a 32byte key and 16bit salt, I get a AES 128 result (I know- as per docs theyre both s'posed to the same size, but the docs are wrong).

 

But when i switch to using both a 32byte key AND a 32byte salt I get the error below.

An error occurred while trying to encrypt or decrypt your input string: Bad parameters: invalid IvParameterSpec: com.rsa.jsafe.crypto.JSAFE_IVException: Invalid IV length. Should be 16.

 

Has anyone 'EVER' gotten encrypt to work for them using AES 256 32byte key and 32byte salt? Is this a bug in CF? Or Java? Or I am doing something wrong?

 

<!--- ///////////////////////////////////////////////////////////////////// ///// Here's the Code ///////////////////////////////////////////////////////////////////// //// --->

<cfset theAlgorithm  = "Rijndael/CBC/PKCS5Padding" />

 

<cfset gKey = "hzj+1o52d9N04JRsj3vTu09Q8jcX+fNmeyQZSDlZA5w="><!--- these 2 are the same --->

<!---<cfset gKey = ToBase64(BinaryDecode("8738fed68e7677d374e0946c8f7bd3bb4f50f23717f9f3 667b2419483959039c", "Hex"))>--->

 

<cfset theIV    = BinaryDecode("7fe8585328e9ac7b7fe8585328e9ac7b7fe8585328e9ac7b7fe8585 328e9ac7b","hex")>

<!---<cfset theIV128    = BinaryDecode("7fe8585328e9ac7b7fe8585328e9ac7b","hex")>--->

 

 

<cffunction    name="DoEncrypt" access="public" returntype="string" hint="Fires when the application is first created.">

    <cfargument    name="szToEncrypt" type="string" required="true"/>

   

    <cfset secretkey = gKey>               

   

    <cfset szReturn=encrypt(szToEncrypt, secretkey, theAlgorithm, "Base64", theIV)>

    <cfreturn szReturn>

</cffunction>   

 

<cffunction    name="DoDecrypt" access="public" returntype="string" hint="Fires when the application is first created.">

    <cfargument    name="szToDecrypt" type="string" required="true"/>

   

    <cfset secretkey = gKey>   

   

    <cfset szReturn=decrypt(szToDecrypt, secretkey, theAlgorithm, "Base64",theIV)>       

    <cfreturn szReturn>

</cffunction>

 

<cfset szStart = form["toencrypt"]>

<cfset szStart = "Test me!">

 

<cfset szEnc = DoEncrypt(szStart)>

<cfset szDec = DoDecrypt(szEnc)>

<cfoutput>#szEnc# #szDec#</cfoutput>

 
Replies
  • Currently Being Moderated
    Jul 8, 2012 5:08 PM   in reply to edevmachine

    Whether or not you are doing something wrong depends on what you are trying to do.

     

    When it comes to so-called AES 256 there are two options as to what this can mean.

     

    1. In most of the programming world, AES 256 means AES crypto with a 128-bit block size and a 256-bit key. The CBC Initialization vector should be the same size as the block, not the same size as the key. So it should be 128-bit

     

    2. In some parts of the programming world (primarily PHP) AES 256 is Rijndael crypto with a 256-bit block size. The problem here is that this is NOT AES. It uses the MCRYPT_RIJNDAEL_256 algorithm. Rijndael is the algorithm on which AES was built, but not everything that is Rijndael is AES.

     

    So if what you want is AES 256-bit crypto, then using a 256-bit key with a 128-bit IV is the correct way to do it. AES *only* has 128-bit block sizes. So this is neither a bug in Java or CF.

     

    If you actually need 256-bit block sizes, then I would guess you are probably trying to interoperate with a system that used PHP for crypto. If that is the case, I believe you will need to dig down into Java and do the crypto the hard way to support it. You may also need to add a new JCA/JCE Crypto provider if none of the standard providers included with CF have MCRYPT_RIJNDAEL_256.

     

    Good luck,

     

    Jason

     
    |
    Mark as:
  • Currently Being Moderated
    Jul 9, 2012 1:38 AM   in reply to edevmachine

    Hi edevmachine,

     

    This Bouncy Castle Encryption CFC supports Rijndael w/ 256-bit block size. (big thanks to Jason here and all who helped w/ that, btw!)

     

    Example:

    <cfscript>

      BouncyCastleCFC = new path.to.BouncyCastle();

      string = "ColdFusion Rocks!"; 

      key = binaryEncode(binaryDecode(generateSecretKey("Rijndael", 256), "base64"), "hex");//the CFC takes hex'd key

      ivSalt = binaryEncode(binaryDecode(generateSecretKey("Rijndael", 256), "base64"), "hex");//the CFC takes hex'd ivSalt

      encrypted = BouncyCastleCFC.doEncrypt(string, key, ivSalt);

      writeOutput(BouncyCastleCFC.doDecrypt(encrypted, key, ivSalt));

    </cfscript>

     

    Related links for anyone interested in adding 256-bit block size Rijndael support into ColdFusion:

    - An explanation of how to install the Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files into ColdFusion

    - An explanation of how to install the Bouncy Castle Crypto package into ColdFusion (near bottom, under the "Installing additional security providers" heading)

    - An explanation of how to connect the Bouncy Castle classes together
    - Bouncy Castle's doc for the Rijndael Engine

     

    And here is the full CFC as posted in the StackOverflow discussion:

     

    <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>

     

    Thanks!,

    -Aaron

     
    |
    Mark as:

More Like This

  • Retrieving data ...

Bookmarked By (0)

Answers + Points = Status

  • 10 points awarded for Correct Answers
  • 5 points awarded for Helpful Answers
  • 10,000+ points
  • 1,001-10,000 points
  • 501-1,000 points
  • 5-500 points