Barack Obama - Change We Can Believe In

Viewing By Entry / Main
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?

Comments

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

http://www.java2s.com/Code/Java/Security/TripleDES.htm


I don't know precisely but it might be worth grabbing the source for openBD and seeing how they have done it? - Joel


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.


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.


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


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

http://www.bouncycastle.org/


"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*! :)


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.


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


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(); } }


Instead of using encrypt()/decrypt(), could you use the native Java libraries within ColdFusion instead?


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.


*cough*DJ Java Decompiler*cough*


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.


@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).


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


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


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.


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.


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.


Post Your Comments
Name:
Email Address:
Comments
*** Please note that all comments require moderation so it may be some time before your comment posts to this blog! ***
Remember My Information:
 



Hosting provided by