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]

Publish your 'C' code and your keys and test data with encrypted result.
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.
> 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.
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.
> 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.
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);
}
}
What encrypted value do you get? Result in Hex would be best.
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?
JAVA O0pX9fJlK4soXPMGgQekE4IH6l0+GaX9C褯4哥铥?Y絢n烪?
You use ("DESede/ECB/NoPadding")Why?
How can I convert to Hex as easy as you do?
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.
> How can I convert to Hex as easy as you do?Print each encrypted byte with something like printf("%02x",...)
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.
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.
> 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.
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?
> 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);
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);
}
}
Im talking about this in this topic http://forum.java.sun.com/thread.jspa?messageID=4496927
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.