Compatibility wtih 3DES

I want to encrypt wtih 3DES in java and decryt in C. The same in the other way. The problem is that when I encrypt the same word with the same key in both languages, I get a different cipher test.

Can anybody help me?

I use this code to encrypt in JAVA:

publicclass Encriptador{

//Generamos la clave

/*private static final byte[] _3desData = {

(byte)0x76, (byte)0x6F, (byte)0xBA, (byte)0x39, (byte)0x31, (byte)0x2F,

(byte)0x0D, (byte)0x4A, (byte)0xA3, (byte)0x90, (byte)0x55, (byte)0xFE,

(byte)0x55, (byte)0x65, (byte)0x61, (byte)0x13, (byte)0x34, (byte)0x82,

(byte)0x12, (byte)0x17, (byte)0xAC, (byte)0x77, (byte)0x39, (byte)0x19 };*/

static String clave ="012345678901234567890123";

privatestaticfinalbyte[] _3desData = clave.getBytes();//{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

privatestatic SecretKeySpec _key =new SecretKeySpec(_3desData,"DESede");

// private static SecretKeySpec _key = Generador.clave();

//Tenemos funciones de encriptar y desencriptar con cadenas y bytes

publicstatic String encrypt(String text){

byte[] plaintext = text.getBytes();

try{

// Cogemos el objeto 3DES Cipher

Cipher cipher = Cipher.getInstance("DESede");// Triple-DES encryption

// Modo encriptar

cipher.init(Cipher.ENCRYPT_MODE, _key);

// Encriptamos, pero pasamos a ASCII primero

byte[] cipherText = cipher.doFinal(plaintext);

BASE64Encoder b64 =new BASE64Encoder();

return b64.encode(cipherText);

}catch (Exception e){

thrownew java.lang.RuntimeException(e);

}

}

publicstatic String decrypt(String text){

try{

BASE64Decoder b64 =new BASE64Decoder();

byte[] cipherText = b64.decodeBuffer(text);

// Cogemos el objeto 3DES Cipher

Cipher cipher = Cipher.getInstance("DESede");// Triple-DES encryption

// Modo desencriptar

cipher.init(Cipher.DECRYPT_MODE, _key);

// Desencriptamos

String plainText =new String(cipher.doFinal(cipherText));

return plainText;

}catch (Exception e){

thrownew java.lang.RuntimeException(e);

}

[4119 byte] By [jorgiria] at [2007-10-3 11:02:17]
# 1
Publish your 'C' code and your keys and test data with encrypted result.
sabre150a at 2007-7-15 6:29:12 > top of Java-index,Security,Cryptography...
# 2
the C code are some .h from my work and a prueba.c that I磛e made. I can磘 upoload all the code now, but if anyone have the 3DES implemented in C, coud give me the code or try to compare wtih the java code?Thanks.
jorgiria at 2007-7-15 6:29:12 > top of Java-index,Security,Cryptography...
# 3

> the C code are some .h from my work and a prueba.c

> that I磛e made. I can磘 upoload all the code now, but

> if anyone have the 3DES implemented in C, coud give

> me the code or try to compare wtih the java code?

>

The problem we have is that we can't compare your Java with you 'C' without knowing which 'C' library you have used and how you have used it. It is no use me providing a 'C' DES library because, although I would expect the DES part to be the same, the method of specifying the key and the padding to be used may be different from your library.

sabre150a at 2007-7-15 6:29:12 > top of Java-index,Security,Cryptography...
# 4

This is for 3DES:

void algorithms_3DES_ECB(

UCHAR *pucClaveA,

UCHAR *pucClaveB,

UCHAR *pucDatoEntrada,

UCHAR *pucDatoCifrado )

/*============================================================================*/

{

UCHAR ucAux[8];

memcpy( ucAux, pucDatoEntrada, 8 );

algorithms_DES( DEST_CIFR, ucAux, pucClaveA );

algorithms_DES( DEST_DESC, ucAux, pucClaveB );

algorithms_DES( DEST_CIFR, ucAux, pucClaveA );

memcpy( pucDatoCifrado, ucAux, 8 );

} //end of function

/*============================================================================*/

algorithms_DES is a typical DES function, if you want I could upload it.

To do the test I use as clave 12345678 in all the cases. And as plaintext hello.

jorgiria at 2007-7-15 6:29:12 > top of Java-index,Security,Cryptography...
# 5

> algorithms_DES is a typical DES function, if you want

> I could upload it.

Good idea.

>

> To do the test I use as clave 12345678 in all the

> cases. And as plaintext hello.

How are you padding "hello" to make it a compete block of 8 bytes?

You do realise that by using the same key for each phase you are in effect doing just single DES encryption.

sabre150a at 2007-7-15 6:29:12 > top of Java-index,Security,Cryptography...
# 6

Excuse me, I磎 using as plaintext 0000111122220000.

Yes, I磎 now that use this keys make it a DES encrypt, but it only is to simplify yhe test.

This is the C code. I can磘 change it because it works in other aplications.

void algorithms_DES (char tipo,UCHAR *d,UCHAR *c)

{

int i,j;

UCHAR k,val_car,d_i1[65],d_i2[65];

UCHAR Edato[65],Eclave[65],Fresu[33],DatoR[33],Iclave[49];

UCHAR permut_ini[65] = { 64,58,50,42,34,26,18,10, 2,60,52,44,36,28,20,12, 4,

62,54,46,38,30,22,14, 6,64,56,48,40,32,24,16, 8,57,

49,41,33,25,17, 9, 1,59,51,43,35,27,19,11, 3,61,53,

45,37,29,21,13, 5,63,55,47,39,31,23,15, 7

};

UCHAR permut_fin[65] = { 64,40, 8,48,16,56,24,64,32,39, 7,47,15,55,23,63,31,

38, 6,46,14,54,22,62,30,37, 5,45,13,53,21,61,29,36,

4,44,12,52,20,60,28,35, 3,43,11,51,19,59,27,34, 2,

42,10,50,18,58,26,33, 1,41, 9,49,17,57,25

};

ST(Edato,0,sizeof(Edato));

ST(Eclave,0,sizeof(Eclave));

ST(d_i1,0,sizeof(d_i1));

ST(d_i2,0,sizeof(d_i2));

ST(Fresu,0,sizeof(Fresu));

ST(Iclave,0,sizeof(Iclave));

ST(DatoR,0,sizeof(DatoR));

Edato[0]=sizeof(Edato)-1;

Eclave[0]=sizeof(Eclave)-1;

d_i1[0]=sizeof(d_i1)-1;

d_i2[0]=sizeof(d_i2)-1;

Fresu[0]=sizeof(Fresu)-1;

Iclave[0]=sizeof(Iclave)-1;

DatoR[0]=sizeof(DatoR)-1;

for (i=0,j=1 ; i<8 ; i++)

{

val_car=d[i];

for (k=0x80 ; k>0 ; k/=2)

{

if ((k & val_car)!=0) Edato[j]=1;

j++;

}

}

for (i=0,j=1 ; i<8 ; i++)

{

val_car=c[i];

for (k=0x80 ; k>0 ; k/=2)

{

if ((k & val_car)!=0) Eclave[j]=1;

j++;

}

}

for (i=1 ; i<=permut_ini[0] ; i++) d_i1[i]=Edato[permut_ini[i]];

for (i=1;i<=16;i++)

{

ST(&d_i2[1],0,d_i2[0]);

if (tipo==DEST_CIFR) algorithms_calc_Ki((UCHAR)i,Eclave,Iclave);

else

if (tipo==DEST_DESC) algorithms_calc_Ki((UCHAR)(17-i),Eclave,Iclave);

else return;

CP(&DatoR[1],&d_i1[33],DatoR[0]);

algorithms_calc_F(Fresu,DatoR,Iclave);

CP(&d_i2[1],&d_i1[33],32);

for (j=1 ; j<=d_i2[0]/2 ; j++) d_i2[j+32]=(d_i1[j] ^ Fresu[j]);

CP(&d_i1[1],&d_i2[1],d_i2[0]);

}

CP(&d_i2[1], &d_i1[33],32);

CP(&d_i2[33],&d_i1[1], 32);

for (i=1 ; i<=permut_fin[0] ; i++) Edato[i]=d_i2[permut_fin[i]];

ST(d,0,8);

for (i=1 ; i<=Edato[0] ; i+=8)

{

d[(i-1)/8] = (UCHAR)(Edato[i ]*0x80)+(UCHAR)(Edato[i+1]*0x40)+

(UCHAR)(Edato[i+2]*0x20)+(UCHAR)(Edato[i+3]*0x10)+

(UCHAR)(Edato[i+4]*0x08)+(UCHAR)(Edato[i+5]*0x04)+

(UCHAR)(Edato[i+6]*0x02)+(UCHAR)(Edato[i+7]*0x01);

}

}

jorgiria at 2007-7-15 6:29:12 > top of Java-index,Security,Cryptography...
# 7
What encrypted value do you get? Result in Hex would be best.
sabre150a at 2007-7-15 6:29:12 > top of Java-index,Security,Cryptography...
# 8

Using

import javax.crypto.*;

import javax.crypto.spec.*;

import org.apache.commons.codec.binary.*;

public class TestEncryption_1_1

{

private static final Hex hexEncoder = new Hex();

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

{

String partA = "12345678";

String partB = "12345678";

String keyAsString = partA + partB + partA;

SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");

DESedeKeySpeckeySpec = new DESedeKeySpec(keyAsString.getBytes("ASCII"));

SecretKey key = keyFactory.generateSecret(keySpec);

Cipher cipher = Cipher.getInstance("DESede/ECB/NoPadding");

cipher.init(Cipher.ENCRYPT_MODE, key);

byte[] bytesToEncrypt = "0000111122220000".getBytes("ASCII");

byte[] encryptedBytes = cipher.doFinal(bytesToEncrypt);

String encryptedBytesAsHexString = new String(hexEncoder.encode(encryptedBytes));

System.out.println("Encrypted = [" + encryptedBytesAsHexString + "]");

cipher.init(Cipher.DECRYPT_MODE, key);

byte[] decryptedBytes = cipher.doFinal(encryptedBytes);

String decryptedBytesAsString = new String(decryptedBytes, "ASCII");

System.out.println("Decrypted = [" + decryptedBytesAsString + "]");

}

}

I get

Encrypted = [d19b34b8e7eefbd91459bd6b6e9f48f1]

Decrypted = [0000111122220000]

Whant does your C code give?

sabre150a at 2007-7-15 6:29:12 > top of Java-index,Security,Cryptography...
# 9
JAVA O0pX9fJlK4soXPMGgQekE4IH6l0+GaX9C褯4哥铥?Y絢n烪?
jorgiria at 2007-7-15 6:29:12 > top of Java-index,Security,Cryptography...
# 10
You use ("DESede/ECB/NoPadding")Why?
jorgiria at 2007-7-15 6:29:12 > top of Java-index,Security,Cryptography...
# 11
How can I convert to Hex as easy as you do?
jorgiria at 2007-7-15 6:29:12 > top of Java-index,Security,Cryptography...
# 12
Print the C value out in hex so that one can compare properly. I use ECB No Padding because that is what you seem to be using since you have not had to pad your input to a block boundary and you have not used anything like CBC block mode.
sabre150a at 2007-7-15 6:29:12 > top of Java-index,Security,Cryptography...
# 13
> How can I convert to Hex as easy as you do?Print each encrypted byte with something like printf("%02x",...)
sabre150a at 2007-7-15 6:29:12 > top of Java-index,Security,Cryptography...
# 14
My boss is calling me, if I can I will put the hex cipher in C today, if not, tomorrow.Lot of thanks for your help.
jorgiria at 2007-7-15 6:29:12 > top of Java-index,Security,Cryptography...
# 15

This is my C code: d19b34b8e7eefbd91459bd6b6e9f48f1

Thanks a lot!!!!!!!!!!!!!!

Ive now two little questions:'

1-. What are the diferents types of DESede/ECB/NoPadding" and the others? where can I get information about?

2.- You use import org.apache.commons.codec.binary.*; Ive done functions to convert in hex. How can I use this import?

Thanks again, all my Duke dollars for you.

jorgiria at 2007-7-21 13:36:21 > top of Java-index,Security,Cryptography...
# 16

> This is my C code: d19b34b8e7eefbd91459bd6b6e9f48f1

>

> Thanks a lot!!!!!!!!!!!!!!

:-) Great!

>

> Ive now two little questions:'

>

> 1-. What are the diferents types of

> DESede/ECB/NoPadding" and the others? where can I get

> information about?

The field is split at the '/' character. The first field is the algorithm which in your case is DESede meaning tripple DES. The second field is the block mode which normally indicates how block are combined. In your case you don't combine any block so Electronic Code Book (ECB) mode is used. The third field indicates the padding to use. If your data length is not an integral of the block size (in your case 8) then it needs to be padded. Your test data is 8 bytes but you will need to know what how your C code pads and then create a Java equivalent.

>

> 2.- You use import org.apache.commons.codec.binary.*;

> Ive done functions to convert in hex. How can I use

> this import?

I don't understand? Do you ask how you can use the apache module or how you can use your own module. If the first then just as I have done. If the second then, since I don't have access to your source, it is impossible for me to say. What I will say is that I would use the apache module unless the license stops it being used with your code.

sabre150a at 2007-7-21 13:36:21 > top of Java-index,Security,Cryptography...
# 17

I put this on your code:

/////////////////////////////////////////////////////

System.out.println(encryptedBytes);

Object tmp = (hexEncoder.decode(encryptedBytesAsHexString));

System.out.println(tmp);

/////////////////////////////////////////////////////

And I get this:

Encrypted = [d19b34b8e7eefbd91459bd6b6e9f48f1]

[B@d2906a

[B@72ffb

Decrypted = [0000111122220000]

Why?

jorgiria at 2007-7-21 13:36:21 > top of Java-index,Security,Cryptography...
# 18

> Encrypted = [d19b34b8e7eefbd91459bd6b6e9f48f1]

> [B@d2906a

> [B@72ffb

> Decrypted = [0000111122220000]

>

> Why?

Because printing an array of bytes like this does not print the content of the array; it prints a pseudo reference to that array. If you want to get a String representation of the bytes then use java.util.Arrays.toString(encryptedBytes);

sabre150a at 2007-7-21 13:36:21 > top of Java-index,Security,Cryptography...
# 19

The last question(Or almost the last). I want to take an output in plain tetxt. My class work perfectly in Hexadecimal and in ASCII, but if I want plain text, it dont get the expected output: I put the code

import javax.crypto.*;

import javax.crypto.spec.*;

public class Encriptador {

//Generamos la clave

private SecretKey Generador(String partA, String partB) throws Exception {

String keyAsString = partA + partB + partA;

SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");

DESedeKeySpeckeySpec = new DESedeKeySpec(keyAsString.getBytes("ASCII"));

return keyFactory.generateSecret(keySpec);

}

//Ahora funciones de desencriptar y encriptar

public String encrypt(String key1, String key2, String text){

try{

//Cogemos el objeto 3DES Cipher

Cipher cipher = Cipher.getInstance("DESede/ECB/NoPadding"); // Triple-DES encryption

// Modo encriptar

cipher.init(Cipher.ENCRYPT_MODE, this.Generador(key1,key2));

byte[] bytesToEncrypt = text.getBytes();

//byte[] bytesToEncrypt = text.getBytes("ASCII"); asi pondriamos en ASCII

byte[] encryptedBytes = cipher.doFinal(bytesToEncrypt);

String Ciphertext = new String(encryptedBytes);

//String Ciphertext = new String(encryptedBytes, "ASCII");

return Ciphertext;

}catch (Exception e){

throw new java.lang.RuntimeException(e);

}

}

public String decrypt(String key1, String key2,String cipherText){

try{

byte[] encryptedBytes = cipherText.getBytes();

// Cogemos el objeto 3DES Cipher

Cipher cipher = Cipher.getInstance("DESede/ECB/NoPadding"); // Triple-DES encryption

// Modo desencriptar

cipher.init(Cipher.DECRYPT_MODE, this.Generador(key1,key2));

//Desencriptamos

byte[] decryptedBytes = cipher.doFinal(encryptedBytes);

String plainText = new String(decryptedBytes);

//String plainText = new String(decryptedBytes, "ASCII");

return plainText;

}catch (Exception e){

throw new java.lang.RuntimeException(e);

}

}

}

And the class to test

public class Encriptar {

public static void main(String[] args){

//prueba con texto e imprimiendo en hexadecimal

Encriptador UtilidadEncriptar = new Encriptador();

String key1="12345678";

String key2="87654321";

String cadena = "0000111122223333";

System.out.println("cadena a encriptar: " + cadena);

String encrypted = UtilidadEncriptar.encrypt(key1, key2, cadena);

System.out.println("cadena encriptada: " + encrypted);

String decrypted = UtilidadEncriptar.decrypt(key1, key2,encrypted);

System.out.println("cadena desencriptada: " +decrypted);

}

}

jorgiria at 2007-7-21 13:36:21 > top of Java-index,Security,Cryptography...
# 20
Im talking about this in this topic http://forum.java.sun.com/thread.jspa?messageID=4496927
jorgiria at 2007-7-21 13:36:21 > top of Java-index,Security,Cryptography...
# 21
This - byte[] encryptedBytes = cipher.doFinal(bytesToEncrypt);String Ciphertext = new String(encryptedBytes); is never a good idea. That is why you use Base64 or Hex encoding.Just scan though this forum to see dozens o posts on this topic.
sabre150a at 2007-7-21 13:36:21 > top of Java-index,Security,Cryptography...