Search code examples
javacoldfusionencryption-symmetric

How can I encrypt a string in Java to be the exact same as it is encrypted in ColdFusion?


I have data encrypted in ColdFusion that I need to be able to decrypt and encrypt to the same exact value using Java. I was hoping someone may be able to help me with this. I will specify everything used in ColdFusion except for the actual PasswordKey, which I must keep secret for security purposes. The PasswordKey is 23 characters long. It uses upper and lowercase letters, numbers, and the + and = signs. I know this is a lot to ask, but any help would be greatly appreciated.

I tried using a Java encryption example I found online and just replacing the line below with the 23 characters used in our CF app:

private static final byte[] keyValue = new byte[] {'T', 'h', 'i', 's', 'I', 's', 'A', 'S', 'e', 'c', 'r', 'e', 't', 'K', 'e', 'y' };` 

But I get the error:

java.security.InvalidKeyException: Invalid AES key length: 23 bytes

The CF code is:

Application.PasswordKey = "***********************";
Application.Algorithm = "AES";
Application.Encoding = "hex";

<cffunction name="encryptValue" access="public" returntype="string">
        <cfargument name="strEncryptThis" required="yes">

        <cfreturn Encrypt(TRIM(strEncryptThis), Application.PasswordKey, Application.Algorithm, Application.Encoding)>
</cffunction>


<cffunction name="decryptValue" access="public" returntype="string">
    <cfargument name="strDecryptThis" required="yes">

    <cfreturn Decrypt(TRIM(strDecryptThis), Application.PasswordKey, Application.Algorithm, Application.Encoding)>
</cffunction>

Solution

  • Thank you everyone for your help. I wanted to post my final solution for others to use. I am including my entire encryption package code minus the specific password key (again for security). This code creates the same hex string as the CF code listed in the question, and decrypts it back to the proper english text string.

    I found the bytesToHex and hexStringToByteArray functions in other question on stackoverflow, so my thanks to users maybeWeCouldStealAVan and Dave L. respectively also. I think I will look into other base 64 encoders/decoders in case the one from sun is ever made unavailable, but this definitely works for now. Thanks again.

    package encryptionpackage;
    
    import java.security.*;
    import java.security.spec.InvalidKeySpecException;
    import javax.crypto.Cipher; 
    import javax.crypto.spec.SecretKeySpec;
    import sun.misc.*;
    
    public class encryption 
    {
        // Note: The full CF default is "AES/ECB/PKCS5Padding"
        private static final String ALGORITHM = "AES";
        // The 24 character key from my CF app (base64 encoded)
        // typically generated with:  generateSecretKey("AES") 
        private static final String passKey = "***********************"; 
    
         public static String encrypt(String valueToEnc) throws Exception 
         {
            Key key = generateKey();
            Cipher c = Cipher.getInstance(ALGORITHM);
            c.init(Cipher.ENCRYPT_MODE, key);
            byte[] encValue = c.doFinal(valueToEnc.getBytes());
            String encryptedValue = bytesToHex(encValue);
            return encryptedValue;
        }
    
        public static String decrypt(String encryptedValue) throws Exception 
        {
            Key key = generateKey();
            Cipher c = Cipher.getInstance(ALGORITHM);
            c.init(Cipher.DECRYPT_MODE, key);
            byte[] decordedValue = hexStringToByteArray(encryptedValue);
            byte[] decValue = c.doFinal(decordedValue);
            String decryptedValue = new String(decValue);
            return decryptedValue;
        }
    
        private static Key generateKey() throws Exception 
        {
              byte[] keyValue;
              keyValue = new BASE64Decoder().decodeBuffer(passKey);
            Key key = new SecretKeySpec(keyValue, ALGORITHM);
    
            return key;
        }
    
        public static String bytesToHex(byte[] bytes) 
        { 
            final char[] hexArray = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; 
            char[] hexChars = new char[bytes.length * 2]; 
            int v; 
            for ( int j = 0; j < bytes.length; j++ ) 
            { 
                v = bytes[j] & 0xFF; 
                hexChars[j * 2] = hexArray[v >>> 4]; 
                hexChars[j * 2 + 1] = hexArray[v & 0x0F]; 
            } 
            return new String(hexChars); 
        } 
    
        public static byte[] hexStringToByteArray(String s) 
        { 
            int len = s.length(); 
            byte[] data = new byte[len / 2]; 
            for (int i = 0; i < len; i += 2) 
            { 
                data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) 
                                     + Character.digit(s.charAt(i+1), 16)); 
            } 
            return data; 
        } 
    
    }