Tuesday, September 09, 2008

Java Triple DES example

I had to do this recently, and the examples that I found through Google seemed a little lacking. So a pointer to others:



UPDATE

Changed to use a gist on github. That will probably dilute the search ranking of this post (which is reasonably popular) but gives me nicer formatting!

14 comments:

Anonymous said...

Very Helpful! Thanks James.

Anand Koppal said...

thanks a lot..it was great

Tahir Akram said...

Hi;

Will you please post the import section of this code too. Like I am getting compilation exception for these PLAIN_TEXT Hex CIPHER_TEXT SHARED_KEY.

James Abley said...

@Tahir: Hex is from Apache Commons Codec.

The constants will vary according to your needs. SHARED_KEY is what you and the 3rd party that you are exchanging data with have agreed. PLAIN_TEXT and CIPHER_TEXT are hopefully tests that have been similarly agreed / defined in sample documentation. If you don't have any, then I would suggest defining some, so that with the common shared key, the String "Hello World" results in the cipher text ????.

jundat said...

I must try to encrypt a password: 888888 by 3DES.
Key is a String like : 256EE615CB64085E0E1386895E5E6BC28A621F7C314016DC
and then after encrypting password with this key is : D2C9AA1103116499
But I search and try many times, but don't have any associated with it. Can u help me ?

Glenn Grabbe said...

Great job dude! This was exactly what I was looking for.

James Abley said...

@jundat: I get a different result. In your case, do you know whether you should be using a particular initialization vector?

Vijaya said...

@James - It was a very helpful one. Here is the complete class for the same. (just adding upto the example).

import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.spec.InvalidKeySpecException;

import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;

public class CryptoUtil {

private Cipher ecipher;
private Cipher dcipher;
private String algorithm = "DESede";
private String transformation = "DESede/CBC/PKCS5Padding";
private String keyPhrase = "123456789012345678901234"; //your keyphrase 24 bit
private SecretKey key;
private IvParameterSpec iv;

private static CryptoUtil cryptoUtil;

public static CryptoUtil getInstance() { //Singleton
if (cryptoUtil == null)
cryptoUtil = new CryptoUtil();

return cryptoUtil;
}

private CryptoUtil() {
try {
DESedeKeySpec keySpec = new DESedeKeySpec(keyPhrase.getBytes());
key = SecretKeyFactory.getInstance(algorithm).generateSecret(keySpec);
iv = new IvParameterSpec(new byte[8]);
ecipher = Cipher.getInstance(transformation);
dcipher = Cipher.getInstance(transformation);
ecipher.init(Cipher.ENCRYPT_MODE, key, iv);
dcipher.init(Cipher.DECRYPT_MODE, key, iv);

} catch (InvalidKeySpecException e) {
} catch (javax.crypto.NoSuchPaddingException e) {
} catch (java.security.NoSuchAlgorithmException e) {
} catch (java.security.InvalidKeyException e) {
} catch (InvalidAlgorithmParameterException e) {
}
}


@SuppressWarnings({"restriction", "hiding"})
public String encrypt(String str) {
try {
// Encode the string into bytes using utf-8
byte[] utf8 = str.getBytes("UTF8");

// Encrypt
byte[] enc = ecipher.doFinal(utf8);

// Encode bytes to base64 to get a string
return new sun.misc.BASE64Encoder().encode(enc);
} catch (javax.crypto.BadPaddingException e) {
} catch (IllegalBlockSizeException e) {
} catch (UnsupportedEncodingException e) {
} catch (java.io.IOException e) {
}
return null;
}

@SuppressWarnings("restriction")
public String decrypt(String str) {
try {
// Decode base64 to get bytes
byte[] dec = new sun.misc.BASE64Decoder().decodeBuffer(str);

// Decrypt
byte[] utf8 = dcipher.doFinal(dec);

// Decode using utf-8
return new String(utf8, "UTF8");
} catch (javax.crypto.BadPaddingException e) {
} catch (IllegalBlockSizeException e) {
} catch (UnsupportedEncodingException e) {
} catch (java.io.IOException e) {
}
return null;
}
}

James Abley said...

@Vijay - I'll probably update this post to use github for better code formatting. You might want to watch out for the sun.misc imports that you're using though.

Oleksandr said...

In Windows there is algId ALG_SID_3DES_112
Is it the same algorithm as "DESede" in Java?
I think not.. Could you help me with algorithm id in Java that is exactly the same as ALG_SID_3DES_112?

Thanks

James Abley said...

@Oleksandr: does the code as is not work on Windows for you? I don't have access to a Windows machine myself, but I think it should work?

Santhros ibn Shinu said...

@Jim:

Many thanks, really.

I feel so thankful, that if you had the Starbucks plugin, I would give you a coffee, pal.

sudha said...

HI;

I am facing some problem while encoding and decoding the data. The requirement is Triple DES algorithm in CBC mode and right padding with ‘0’. I was developed the Code based in the CBC algorithm base.
My Code :
private static Key genarateKey() throws Exception {
final Key key;
final String UNICODE_FORMAT = "UTF8";
final String DESEDE_ENCRYPTION_SCHEME = "DESede";
final String myEncryptionKey = "CF54F07BF324646BC5D3D62A651B21D20BD322EBAE238985";
key = SecretKeyFactory.getInstance(DESEDE_ENCRYPTION_SCHEME).generateSecret(new DESedeKeySpec(myEncryptionKey.getBytes(UNICODE_FORMAT)));
return key;
}
public static byte[] encryptData(String message,byte cipherIv[]) throws Exception {
final Key key = genarateKey();
Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
//final IvParameterSpec iv = new IvParameterSpec(new byte[8]);
final IvParameterSpec iv = new IvParameterSpec(cipherIv);
cipher.init(Cipher.ENCRYPT_MODE, key, iv);
byte[] bytesData = message.getBytes("UTF8");
byte[] raw = cipher.doFinal(bytesData);
/*BASE64Encoder encoder = new BASE64Encoder();
String encryptData = encoder.encode(raw);
return encryptData;*/
return raw;
}
public static void main(String args[]) throws Exception{
String dec = "2#2#purchase##1#1";
System.out.println("Before padding:"+dec);
int count = dec.length()%8;
if(count != 0 ){
while(count != 8)
{
dec=dec+"0";
count++;
}
}
System.out.println("After padding:"+dec);
int j = 0;
byte [] cipherIv = new byte[8];
for(int i =0;i<dec.length()/8;i++){
String blockMsg = dec.substring(j, (j+=8)-1);
cipherIv = TripleDSE.encryptData(blockMsg,cipherIv);
System.out.println("Encrypted data:"+cipherIv);
}
String hexValue = new String(Hex.encodeHex(cipherIv));
System.out.println("Hexadecimal Value:"+hexValue);
}
Please give the Solution for this.

madhuram said...

Hi I am new to Cryptography, I have question in triple des(3des): encryption is done in Oracle function DBMS_OBFUSCATION_TOOLKIT.DES3Encrypt , is that possible I can decrypt same in using java API.
I have only key and encrypted password to decrypt. I have tried couple of examples, when I decrypt in java , Ii am getting different value.
Is that possible if something is encrypted in oracle and can be decrypt in java