An Architect's View

CFML, Clojure, Software Design, Frameworks and more...

An Architect's View

Help! Encryption Question

August 12, 2008 ·

Since I have a fairly large body of very smart readers, I figured I could ask you a question and have you help me for a change :) I have a bunch of data in a database encrypted via ColdFusion and I need to figure out the exact Java equivalent so that I can encrypt / decrypt across application boundaries. The ColdFusion code uses encrypt() / decrypt() with DESEDE and a hex encoding. I know the key value (duh!) but I can't figure out the exact same Java equivalent code. Anyone know?

Tags: coldfusion · j2ee

20 responses

  • 1 William Langshaw // Aug 12, 2008 at 9:49 PM

    This utility class for working with 3DES ciphers looks to be pretty straight-forward

    http://www.java2s.com/Code/Java/Security/TripleDES.htm
  • 2 Joel Stobart // Aug 12, 2008 at 11:06 PM

    I don't know precisely but it might be worth grabbing the source for openBD and seeing how they have done it? - Joel
  • 3 Kyle Perkins // Aug 12, 2008 at 11:09 PM

    I would assume it uses the JCE (1.4) or maybe the JCA (Java 6).

    I'd post links, but your comment box hates me :).
    Just look up "java crypto" and its the first two links for the two versions respectively.

    For these two versions, the classes are probably found in javax.crypto.* and recursive namespaces.

    I haven't had a need for this specific situation, so I haven't tried anything compatibility-wise, but maybe that gets you headed in the right direction.
  • 4 Anthony // Aug 12, 2008 at 11:09 PM

    I haven't worked with DESEDE before, but I have used the bouncycastle crypto providers to do PGP encryption. I looked at he main package and it has something about DESEDE. Let me know and I can send you some code I used to get the PGP working.


  • 5 Sean Corfield // Aug 12, 2008 at 11:09 PM

    @William, there are a lot of very "straight-forward" Triple DES code fragments out there but they do NOT work the same way as ColdFusion. Have you actually TRIED the code you quoted?

    @Joel, interesting idea, thank you. I hadn't thought of OpenBD working the same way as Adobe ColdFusion. I'll download it and have a look.

    In the meantime, keep the ideas coming folks but, please, actually try the code out and make sure it really does do the same as ColdFusion's encrypt() function!
  • 6 Erki Esken // Aug 12, 2008 at 11:45 PM

    Perhaps try Bouncycastle crypto library and see its DESExample sample class?

    http://www.bouncycastle.org/
  • 7 Will Tomlinson // Aug 13, 2008 at 1:28 AM

    "I figured I could ask you a question and have you help me for a change :)"

    I'm still trying to figure out when you've ever helped *me*! :)
  • 8 Jordan Clark // Aug 13, 2008 at 2:27 AM

    Sorry I haven't tried this myself, but I have two ideas. If you can include cfusion.jar in your classpath then you should be able to use the cfusion.runtime.Encryptor class which provides several overloaded static methods to encrypt and decrypt strings. If not then just unpack the archive, install the DJ Java Decompiler and see what's going on under the hood.

  • 9 David herman // Aug 13, 2008 at 3:49 AM

    I actually think that it's not "encryption" but rather more bit shifting etc. We looked into this same thing at some point and could not determine what the algo was so we ended up moving to a standard solution. We just did a onetime conversion and then stopped using the cf version and just accessed the other version through java. Granted this was before cf had more advanced solutions
  • 10 CoolJJ // Aug 13, 2008 at 4:51 AM

    Funny, I just did the same thing last week using AES. If I change the parameters to DESEDE it works with that too. Here is some test code I used to figure it out. Hopefully the formatting doesn't get too screwed. - CoolJJ

    ColdFusion test:
    <cfset message = "This is a test."/>
    <!--- the secret key was generated using generatesecretkey("DESEDE") --->
    <cfset encrypted=encrypt(message,"eoVbj51R74xw+z0fyDs38kpJc/Gzihby","DESEDE","HEX")/>
    Encrypted: <cfdump var="#encrypted#">

    Java test:
    import javax.crypto.*;
    import javax.crypto.spec.*;

    public class TestCrypto {

       public static void main(String[] args) throws Exception {

          String myMessage = new String("This is a test.");
          
          //setup secret key and convert to byte array
          String secretKeyInBase64 = new String("eoVbj51R74xw+z0fyDs38kpJc/Gzihby");
          byte[] rawSecretKey = new sun.misc.BASE64Decoder().decodeBuffer(secretKeyInBase64);
          
          //output secret key to console
          System.out.println(secretKeyInBase64);
          
          // Generate the secret key specs.
          SecretKeySpec secretkeySpec = new SecretKeySpec(rawSecretKey, "DESEDE");

          // get instance of cipher and initialize with key spec
          Cipher cipher = Cipher.getInstance("DESEDE");
          cipher.init(Cipher.ENCRYPT_MODE, secretkeySpec);
          
          //encrypt myMessage
          byte[] encrypted = cipher.doFinal(myMessage.getBytes());
          
          //convert to strings and output to console
          String sEncrypted = new sun.misc.BASE64Encoder().encode(encrypted);
          System.out.println("encrypted string Base64: " + sEncrypted);
          System.out.println("encrypted string Hex: " + asHex(encrypted));
          
          //decrypt the message
          cipher.init(Cipher.DECRYPT_MODE, secretkeySpec);
          byte[] originalraw = cipher.doFinal(encrypted);
          
          //convert to strings and output to console
          String originalmessage = new String(originalraw);
          System.out.println("The original message: " + originalmessage);
       }
       
       public static String asHex (byte buf[]) {
          StringBuffer strbuf = new StringBuffer(buf.length * 2);
          int i;
       
          for (i = 0; i < buf.length; i++) {
             if (((int) buf[i] & 0xff) < 0x10){
                strbuf.append("0");
             }
             strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
          }
       
          return strbuf.toString();
        }
    }

  • 11 Joel Cox // Aug 13, 2008 at 5:08 AM

    Instead of using encrypt()/decrypt(), could you use the native Java libraries within ColdFusion instead?
  • 12 Joe Rinehart // Aug 13, 2008 at 5:12 AM

    I've got this working - the issue is that ColdFusion's secret keys and encrypted output are Base64 encoded, and if you use raw Java, you need to convert the key from/the encrypted string to Base64 to get the same results.

    I'll e-mail you a Groovy script.
  • 13 Dan G. Switzer, II // Aug 13, 2008 at 6:09 AM

    *cough*DJ Java Decompiler*cough*
  • 14 Kevin Benore // Aug 13, 2008 at 7:51 AM

    Our java team just JAR'd their encryption/decryption routines for us to use for precisely this reason. The "key" was also encrypted so that solution was necessary for us.
  • 15 Sean Corfield // Aug 13, 2008 at 8:52 AM

    @All, if you haven't actually TRIED code, your answer isn't much help. I was well aware of the packages and had spent a fair bit of time looking at all the Java samples and building test cases.

    @CoolJJ, thank you - you and Joe were the only two people to provide a tested code sample. The key was the base64 stuff so I was extremely close by the time I gave up last night.

    To those who suggested decompilers - remember your EULA prohibits such behavior (but I was getting frustrated enough to consider trying that next :)

    Moral: build some code and test it before offering to help (you may learn something too).
  • 16 CoolJJ // Aug 13, 2008 at 9:19 AM

    Yeah, the base64 stuff threw me for a day too. That sun.misc.BASE64Encoder and sun.misc.BASE64Decoder obviously needs replaced with something in production though.

    CoolJJ
  • 17 bren // Aug 14, 2008 at 8:27 AM

    "There has been an error while trying to encrypt or decrypt your input string: Input length (with padding) not multiple of 16 bytes"

    Anyone know what this error is about using base64, normal coldfusion decrypt?

    decrypt(Data,Key,"AES","Base64")
  • 18 Sixten // Aug 14, 2008 at 8:54 AM

    By the by, I'll add another vote for the Bouncy Castle libraries. They have high-quality Open Source implementations of a lot of algorithms that the default crypto provider lacks (starting with the longer variants of SHA, and bigger key sizes for AES and Blowfish). The library also includes a lot of useful utility stuff, including hex and Base64 encode/decode functions.
  • 19 Brian // Oct 23, 2008 at 7:32 PM

    I have a noob question that I can't seem to find the answer to anywhere. I need a way to encrypt then decrypt user passwords as people register on my site. I would like to use ecrypt function to do this with generatesecretkey. However, I am unsure where to place the code to do this? If I must use the same key to encrypt and decrypt each password, does that mean I must generate and save a new key for each user who registers on the site. Example: user A registers I encrypt password with generatesitekey A. User B registers I encrypt their password with generatesitekey B. If I had only one key I don't see a way to decrypt everyone's unique password. Where would I store this key? In a DB somewhere, a cookie on the client, etc.? Thanks.
  • 20 CoolJJ // Oct 24, 2008 at 7:13 AM

    Yes, if you wish to decrypt the password you need to keep the key that the password was encrypted with. This means storing it somewhere. But before you proceed, think about the security implications of this. You need to keep that secret key hidden somewhere, either in a configuration file (should you use one key to encrypt all passwords), or in the database (one key, or unique key for each user). Also, think about why you need to be able to decrypt the password... is it really necessary? You should ask yourself this because if you don't intend to return original passwords through some 'forgot my password' mechanism, then the decrypt isn't necessary. Should someone compromise your system and read the config file somehow, or read the database tables through SQL injection, your passwords will then all be compromised and the encryption did you no good.

    An alternative is to use the hash (salt + password) method. Do a google and it will explain the method and the reason behind it being reasonably more secure, provided interesting users such as admins create good passwords.