PBE encryption shows different output on IBMJCE and SunJCE providers
PBE encryption shows different output on IBMJCE and SunJCE providers - when I ran the following program on Sun JDK and IBM JDK, I got different results. Can anybody tell me the reason or give me a solution ?
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.io.*;
public class PbeEncryption{
public static void main(String args[]) throws Exception{
String MYPBEALG = "PBEWithSHA1AndDESede" ;
byte[] salt = new byte[] {103 , -73 , -94 , 12 , -73 , -33 , 1 , 109};
int count = 10;
String password = "password" ;
PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, count);
PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray());
SecretKeyFactory keyFac = SecretKeyFactory.getInstance(MYPBEALG);
SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);
MYPBEALG = MYPBEALG + "/CBC/PKCS5PADDING";
Cipher pbeCipher = Cipher.getInstance(MYPBEALG);
pbeCipher.init(Cipher.ENCRYPT_MODE, pbeKey, pbeParamSpec);
byte[] abyte0 = pbeCipher.doFinal(password.getBytes());
String encoded = new String(abyte0, "UTF-8");
FileOutputStream fos = new FileOutputStream("encrypted.txt");
fos.write(abyte0);
fos.close();
System.out.println("********* E N C O D E D B Y T E S **********");
for(int i=0; i<abyte0.length;i++){
System.out.print((int)abyte0 + " ");
}
System.out.println("********************************************");
System.out.println("ENCRYPTION SUCCESSFULL .......");
}
}
Thanks in advance>
[1637 byte] By [
Mkarattua] at [2007-10-2 23:50:35]

> byte[] abyte0 =
> = pbeCipher.doFinal(password.getBytes());
>
> String encoded = new String(abyte0, "UTF-8");
>
An example of just about the most common problem posted on this forum. This about as wrong as you can get. It is almost always wrong to convert arbitrary byte to a String, even with utf-8, because not all byte sequences create valid characters and it almost certainly will not be reversible.
If you must have a String version of encrypted bytes then use Base64 or Hex encoding.
I dont think encoding is the problem here.if so, atleast the following piece of code should show similar results on both platformsfor(int i=0; i<abyte0.length;i++){ System.out.print((int)abyte0 + " ");}>
Plz consider this code...
I have removed encoding related snipplets from the code.
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.io.*;
public class PbeEncryption{
public static void main(String args[]) throws Exception{
String MYPBEALG = "PBEWithSHA1AndDESede" ;
byte[] salt = new byte[] {103 , -73 , -94 , 12 , -73 , -33 , 1 , 109};
int count = 10;
char[] pwd = {103 , 123 , 84 , 92 , 63 , 83 , 40 , 100};
PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, count);
PBEKeySpec pbeKeySpec = new PBEKeySpec(pwd);
SecretKeyFactory keyFac = SecretKeyFactory.getInstance(MYPBEALG);
SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);
MYPBEALG = MYPBEALG + "/CBC/PKCS5PADDING";
Cipher pbeCipher = Cipher.getInstance(MYPBEALG);
pbeCipher.init(Cipher.ENCRYPT_MODE, pbeKey, pbeParamSpec);
byte[] abyte0 = pbeCipher.doFinal(new byte[]{103 , 23 , 84 , 92 , 23 , 83 , 10 , 100});
System.out.println("********* E N C O D E D B Y T E S **********");
for(int i=0; i<abyte0.length;i++){
System.out.print((int)abyte0 + " ");
}
System.out.println("********************************************");
}
}>
> I dont think encoding is the problem here.
It may not be THE problem but it will be A problem.
>
> if so, atleast the following piece of code should
> show similar results on both platforms
>
> for(int i=0; i<abyte0.length;i++){
>System.out.print((int)abyte0 + " ");
Rather than looping yourself, use Arrays.toString(bByteArray) to do this.
I can run this on Sun JDK but until I can find out how to download the IBM unlimted strength policy files I cannot run it on IBM!
import java.util.*;
import javax.crypto.*;
import javax.crypto.spec.*;
public class PbeEncryption
{
public static void main(String args[]) throws Exception
{
String MYPBEALG = "PBEWithSHA1AndDESede" ;
byte[] salt = new byte[] {103 , -73 , -94 , 12 , -73 , -33 , 1 , 109};
int count = 10;
char[] pwd = {103 , 123 , 84 , 92 , 63 , 83 , 40 , 100};
PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, count);
PBEKeySpec pbeKeySpec = new PBEKeySpec(pwd);
SecretKeyFactory keyFac = SecretKeyFactory.getInstance(MYPBEALG);
SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);
MYPBEALG = MYPBEALG + "/CBC/PKCS5PADDING";
Cipher pbeCipher = Cipher.getInstance(MYPBEALG);
pbeCipher.init(Cipher.ENCRYPT_MODE, pbeKey, pbeParamSpec);
byte[] abyte0 = pbeCipher.doFinal(new byte[]{103 , 23 , 84 , 92 , 23 , 83 , 10 , 100});
System.out.println("********* E N C O D E D B Y T E S **********");
System.out.println(Arrays.toString(abyte0));
System.out.println("********************************************");
}
}
produces
********* E N C O D E D B Y T E S **********
[-48, 0, 75, -35, -18, 52, -121, -30, -7, -120, 11, 14, 23, -8, 40, -42]
********************************************
You can get unlimited jurisdiction policy files for IBM JDK
from the following site:
http://www.ibm.com/developerworks/java/jdk/security/index.html
(You need to register with IBM to download the policy files.)
Then-->
Click J2SE 5.0
Click IBM SDK Policy files
The Unrestricted JCE Policy files Web site is displayed.
Select Unrestricted JCE Policy files for SDK 1.4.2[this is same for java 1.5
also]
Then download Unrestricted JCE policy files for use with IBM's SDK for Java
1.4
unrestrict142.zip .
Extract this file and replace local_policy.jar and
US_export_policy.jar in the $JAVA_HOME/jre/lib/security
I have installed the IBM unlimited files and it would seem that there is a mismatch between IBM and Sun. Looks like a bug report needs to be raised but I hav enot idea where!At some point I will try to compare IBM, Sun and BC PBE implementations.
I have just established tha the key bytes are the same for both IBM and Sun so it has (almost certainly) to be a problem with the Ciperh and it's initialization.
Probably ignore the above since the key byes have only length 8 and not 16 or 24 as required by DESede!
Message was edited by:
sabre150
Short sighted of me! It gives the ASCII byters presented as the char array!
Message was edited by:
sabre150
I am now convinced you have a found a real problem. If I use MD5 rather than SHA1 then the two give the same results
Java vendor : IBM Corporation
Algorithm: PBEWithMD5AndTripleDES
class com.ibm.crypto.provider.PBEKey [103, 123, 84, 92, 63, 83, 40, 100]
********* E N C R Y P T E DB Y T E S **********
[-104, 58, -113, -77, 58, -8, -92, 82, 76, 44, 126, 90, 62, 34, 120, -73]
**************************************************
Java vendor : Sun Microsystems Inc.
Algorithm: PBEWithMD5AndTripleDES
class com.sun.crypto.provider.PBEKey [103, 123, 84, 92, 63, 83, 40, 100]
********* E N C R Y P T E DB Y T E S **********
[-104, 58, -113, -77, 58, -8, -92, 82, 76, 44, 126, 90, 62, 34, 120, -73]
**************************************************
Did u change anything otherthan Algorithm in the code? I am getting java.security.InvalidKeyException: Illegal key size on Sun JDK.
> Did u change anything otherthan Algorithm in the
> code? I am getting java.security.InvalidKeyException:
> Illegal key size on Sun JDK.
Quite a bit of simplification (my view anyway)
import java.util.*;
import javax.crypto.*;
import javax.crypto.spec.*;
public class PbeEncryption
{
public static void main(String args[]) throws Exception
{
String MYPBEALG = "PBEWithMD5AndTripleDES" ;
System.out.println("Java vendor : " + System.getProperty("java.vendor"));
System.out.println("Algorithm: " + MYPBEALG);
byte[] salt = new byte[] {103 , -73 , -94 , 12 , -73 , -33 , 1 , 109};
int count = 10;
char[] pwd = {103 , 123 , 84 , 92 , 63 , 83 , 40 , 100};
PBEKeySpec pbeKeySpec = new PBEKeySpec(pwd);
PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, count);
SecretKey pbeKey = SecretKeyFactory.getInstance(MYPBEALG).generateSecret(pbeKeySpec);
System.out.println(pbeKey.getClass() + " " + Arrays.toString(pbeKey.getEncoded()));
Cipher pbeCipher = Cipher.getInstance(MYPBEALG);
pbeCipher.init(Cipher.ENCRYPT_MODE, pbeKey, pbeParamSpec);
byte[] abyte0 = pbeCipher.doFinal(new byte[]{103 , 23 , 84 , 92 , 23 , 83 , 10 , 100});
System.out.println("********* E N C R Y P T E DB Y T E S **********");
System.out.println(Arrays.toString(abyte0));
System.out.println("**************************************************");
}
}
My requirement is to decrypt a file on IBM JDK which is encrypted on Sun JDK. I couldnt do it even with PBEWithMD5AndTripleDES, though both shows same output while encryption...
> My requirement is to decrypt a file on IBM JDK which
> is encrypted on Sun JDK. I couldnt do it even with
> PBEWithMD5AndTripleDES, though both shows same output
> while encryption...
So what does your decryption code look like and how are you shipping teh encrypted data from the encrypting process to the decrypting process?
I write the encrypted bytes into a file and try to decrypt the file using IBM JDK.
PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, count);
PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray());
SecretKeyFactory keyFac = SecretKeyFactory.getInstance(MYPBEALG);
SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);
Cipher pbeCipher = Cipher.getInstance(MYPBEALG);
pbeCipher.init(Cipher.DECRYPT_MODE, pbeKey, pbeParamSpec);
File file = new File("encrypted.txt");
byte[] toRead = new byte[(int)file.length()];
FileInputStream fis = new FileInputStream(file);
fis.read(toRead);
fis.close();
System.out.println("read =" + Arrays.toString(toRead));
byte[] abyte0 = pbeCipher.doFinal(toRead);
I have not problem encryption with one an ddecryption with the other using algorithm "PBEWithMD5AndTripleDES".
I use this to encrypt for both IBM and Sun
import java.util.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.io.*;
public class PbeEncryption
{
public static void main(String args[]) throws Exception
{
String MYPBEALG = "PBEWithMD5AndTripleDES" ;
String dataToEncrypt = "The quick brown fox jumps over the lazy dog.";
System.out.println("Java vendor : " + System.getProperty("java.vendor"));
System.out.println("Algorithm: " + MYPBEALG);
byte[] salt = new byte[] {103 , -73 , -94 , 12 , -73 , -33 , 1 , 109};
int count = 10;
char[] pwd = {103 , 123 , 84 , 92 , 63 , 83 , 40 , 100};
PBEKeySpec pbeKeySpec = new PBEKeySpec(pwd);
PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, count);
SecretKey pbeKey = SecretKeyFactory.getInstance(MYPBEALG).generateSecret(pbeKeySpec);
System.out.println(pbeKey.getClass() + " " + Arrays.toString(pbeKey.getEncoded()));
Cipher pbeCipher = Cipher.getInstance(MYPBEALG);
pbeCipher.init(Cipher.ENCRYPT_MODE, pbeKey, pbeParamSpec);
byte[] abyte0 = pbeCipher.doFinal(dataToEncrypt.getBytes("UTF-8"));
System.out.println("********* E N C R Y P T E DB Y T E S **********");
System.out.println(Arrays.toString(abyte0));
System.out.println("**************************************************");
DataOutputStream dostrm = new DataOutputStream(new FileOutputStream(System.getProperty("user.home") + "/zz"));
dostrm.writeShort(abyte0.length);
dostrm.write(abyte0);
dostrm.flush();
dostrm.close();
}
}
and this to decrypt using IBM or Sun
import java.util.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.io.*;
public class PbeDecryption
{
public static void main(String args[]) throws Exception
{
String MYPBEALG = "PBEWithMD5AndTripleDES" ;
System.out.println("Java vendor : " + System.getProperty("java.vendor"));
System.out.println("Algorithm: " + MYPBEALG);
byte[] salt = new byte[] {103 , -73 , -94 , 12 , -73 , -33 , 1 , 109};
int count = 10;
char[] pwd = {103 , 123 , 84 , 92 , 63 , 83 , 40 , 100};
PBEKeySpec pbeKeySpec = new PBEKeySpec(pwd);
PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, count);
SecretKey pbeKey = SecretKeyFactory.getInstance(MYPBEALG).generateSecret(pbeKeySpec);
System.out.println(pbeKey.getClass() + " " + Arrays.toString(pbeKey.getEncoded()));
Cipher pbeCipher = Cipher.getInstance(MYPBEALG);
pbeCipher.init(Cipher.DECRYPT_MODE, pbeKey, pbeParamSpec);
DataInputStream distrm = new DataInputStream(new FileInputStream(System.getProperty("user.home") + "/zz"));
int len = distrm.readShort();
byte[] encryptedBytes = new byte[len];
distrm.readFully(encryptedBytes);
distrm.close();
byte[] decryptedBytes = pbeCipher.doFinal(encryptedBytes);
System.out.println(new String(decryptedBytes,"UTF-8"));
}
}
Note that I do not convert encrypted data to Java Strings.
Hi,PBEWithMD5AndTripleDES worked fine for me too...Plz let me know if you get any solution for the other algorithm..
Just a thought. Could it be that IBM and Sun are using different key lengths? Maybe one DES approach uses the same key for both DES encryption phases and the other uses a different key for each encryption phase.I don't see how to test this hypothesis.
From SUN security team
The PKCS12 PBEWithSHA1AndDESede implementations between SunJCE and IBMJCE providers are interoperable. However, its name is not, i.e.
"PBEWithSHA1AndDESede" for SunJCE provider and
"PBEWithSHAAnd3KeyTripleDES" for IBMJCE provider.
Use:
String MYPBEALG = "PBEWithSHA1AndDESede" ;
try{
Provider[] providers = Security.getProviders("Cipher.OID.1.2.840.113549.1.12.1.3");
MYPBEALG = (String)providers[0].get("Alg.Alias.Cipher.OID.1.2.840.113549.1.12.1.3");
}catch(Exception e){}
See the solution here http://forum.java.sun.com/thread.jspa?threadID=749835&messageID=4320560#4320560
solution at http://forum.java.sun.com/thread.jspa?threadID=749835&messageID=4320560#4320560