How to force IBM jdk to use sunjce_provider.jar

Hi,

  I am hosting an application which runs on different jvms ( jdk1.3.1_12, IBMJava2-141)

  I created a key with SUN JDK and able to encrypt and decrypt in all servers using sun jdk
  But the application is not running fine on IBM jdk servers.

 With the key generated from sun, IBM is unable to decrypt the string which was encrypted by IBM itself
throwing this error.

avax.crypto.IllegalBlockSizeException: Input length (with padding) not multiple of 8 bytes
        at com.ibm.crypto.provider.DESCipher.a(Unknown Source)
        at com.ibm.crypto.provider.DESCipher.engineDoFinal(Unknown Source)
        at com.ibm.crypto.provider.DESCipher.engineDoFinal(Unknown Source)
        at javax.crypto.Cipher.doFinal(Unknown Source)
       EncryptAndDecryptUtil.getDecryptedString

I followed the instructuions as specificed in this link

http://www.systinet.com/doc/wasp_uddi-50/html/index.html?Install.Prerequisites.html

import javax.crypto.*;
import javax.crypto.spec.*;
import java.lang.*;
import java.util.*;
import java.io.*;

public class EncryptAndDecryptUtil{
      
      private static SecretKeySpec generatedKey = null;

      public static void setSecretkey(byte[] bt){
            generatedKey = new SecretKeySpec(bt,"DES");
            System.err.println("EAD:Sending generated Key:"+generatedKey);
      }

      public static String getEncryptedString(String str){
            long t1,t2;
            t1 = System.currentTimeMillis();
            String s=null;
            try{
            Cipher desCipher = Cipher.getInstance("DES");
                  desCipher.init(Cipher.ENCRYPT_MODE, generatedKey);
                  byte[] text1 = str.getBytes();
                  byte[] text2 = desCipher.doFinal(text1);
                  s=new String(text2);
            }catch(Exception e){
            e.printStackTrace();
        }
            t2 = System.currentTimeMillis();
            System.err.println("QA:EAD:encString:"+(t2-t1));
            //System.err.println("EAD:encryptString:originalstr"+str+":size after encryption:"+s.length());
            return s;
      }

      public static String getDecryptedString(String str){
            long t1,t2;
            t1 = System.currentTimeMillis();
            String s=null;
            try{
                  Cipher desCipher = Cipher.getInstance("DES");
                  desCipher.init(Cipher.DECRYPT_MODE,generatedKey);
                byte[] text1 = desCipher.doFinal(str.getBytes());
                  s=new String(text1);
                  //System.err.println("EAD:decrypted string:"+s);
            }catch(Exception e){
            e.printStackTrace();
        }
            t2 = System.currentTimeMillis();
            System.err.println("QA:EAD:decString:"+(t2-t1));
            return s;
      }
      
      public static void main(String args[]) throws Exception{
             FileInputStream fis = new FileInputStream("profilekey.pem");
            byte[] bt = new byte[fis.available()];
            fis.read(bt);
            setSecretkey(bt);
            String str1 = "Ravindra";
            writeString(str1);
            readString();
      }
      private static void writeString(String str1) throws Exception{
            String encStr = getEncryptedString(str1);
            FileOutputStream fos = new FileOutputStream("/tmp/ravi.txt");
            fos.write(encStr.getBytes());
            fos.close();
      }
      private static void readString() throws Exception{
            FileReader fr = new FileReader("/tmp/ravi.txt");
            BufferedReader br = new BufferedReader(fr);
            String str2 = br.readLine();
            String str3 = getDecryptedString(str2) ;
            System.err.println("str3:Ravindra:equals:"+str3+":"+str3.equals("Ravindra"));
            br.close();
      }

}


I am creating the key with the following code

blic class CreateSecretKey{

    public static void main(String[] args){
        generateKey();
    }

    public static void generateKey(){
        try{
            KeyGenerator keygen = KeyGenerator.getInstance("DES");
            SecretKey desKey = keygen.generateKey();
            byte[] key = desKey.getEncoded();
            FileOutputStream fo = new FileOutputStream("profilekey.pem");
 fo.write(key);
            fo.close();
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}


Thanking u ,

Ravindra
LVL 7
Ravindra76Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Ravindra76Author Commented:
Pls have a look at

http://www.experts-exchange.com/Programming/Q_21213128.html too.

I posted here since this question is related to java. I posted it agian since i do not know how to move the question from open gruop to java group.
0
Dejan PažinHead of SW DevelopmentCommented:

I dont think this has anything to do with JVM implementation. Your program throws the same exception with sun jdk.

I think the problem is that you convert byte arrays to Strings, write that to a file and then read them back again. So I replaced that to work only with byte arrays (didnt have the time to write them to file). It works ok now, its not ibm jvm, but as I said the exception was the same here.

Here is the corrected code of EncryptAndDecryptUtil (not really nice, but lack of time...). The CreateSecretKey class stays the same.

package home;

 import javax.crypto.*;
import javax.crypto.spec.*;
import java.lang.*;
import java.util.*;
import java.io.*;

public class EncryptAndDecryptUtil{

   private static byte[] encryptedString;

     private static SecretKeySpec generatedKey = null;

     public static void setSecretkey(byte[] bt){
          generatedKey = new SecretKeySpec(bt,"DES");
          System.err.println("EAD:Sending generated Key:"+generatedKey);
     }

     public static byte[] getEncryptedString(String str){
          long t1,t2;
          t1 = System.currentTimeMillis();
        byte[] text2=null;
          String s=null;
          try{
            Cipher desCipher = Cipher.getInstance("DES");
               desCipher.init(Cipher.ENCRYPT_MODE, generatedKey);
               byte[] text1 = str.getBytes();
               text2 = desCipher.doFinal(text1);
               s=new String(text2);
          }catch(Exception e){
            e.printStackTrace();
        }
          t2 = System.currentTimeMillis();
          System.err.println("QA:EAD:encString:"+(t2-t1));
          //System.err.println("EAD:encryptString:originalstr"+str+":size after encryption:"+s.length());
          return text2;
     }

     public static byte[] getDecryptedString(){
          long t1,t2;
          t1 = System.currentTimeMillis();
          String s=null;
        byte[] text1=null;
          try{
               Cipher desCipher = Cipher.getInstance("DES");
               desCipher.init(Cipher.DECRYPT_MODE,generatedKey);
              //byte[] text1 = desCipher.doFinal(str.getBytes());
             text1 = desCipher.doFinal(encryptedString);
               s=new String(text1);
               //System.err.println("EAD:decrypted string:"+s);
          }catch(Exception e){
            e.printStackTrace();
        }
          t2 = System.currentTimeMillis();
          System.err.println("QA:EAD:decString:"+(t2-t1));
          return text1;
     }

     public static void main(String args[]) throws Exception{
            FileInputStream fis = new FileInputStream("profilekey.pem");
          byte[] bt = new byte[fis.available()];
          fis.read(bt);
          setSecretkey(bt);
          String str1 = "Ravindra";
          writeString(str1);
          readString();
     }
     private static void writeString(String str1) throws Exception{
          encryptedString = getEncryptedString(str1);
          FileOutputStream fos = new FileOutputStream("/tmp/ravi.txt");
          fos.write(encryptedString);
          fos.close();
     }
     private static void readString() throws Exception{
          FileReader fr = new FileReader("/tmp/ravi.txt");
          BufferedReader br = new BufferedReader(fr);
          String str2 = br.readLine();
          //String str3 = getDecryptedString(str2) ;
          String str3 = new String(getDecryptedString());
          System.err.println("str3:Ravindra:equals:"+str3+":"+str3.equals("Ravindra"));
          br.close();
     }

}

0
Dejan PažinHead of SW DevelopmentCommented:

BTW: If you need to put that to a file, you should work with FileOutputStream and FileInputStream instead of FileReader (to write and read bytes, not characters).
Here are the methods that do that:

     private static void writeString(String str1) throws Exception{
          encryptedString = getEncryptedString(str1);
          FileOutputStream fos = new FileOutputStream("/tmp/ravi.txt");
          fos.write(encryptedString);
          fos.close();
     }

     private static void readString() throws Exception{
          File file = new File("/tmp/ravi.txt");
          FileInputStream fis = new FileInputStream("/tmp/ravi.txt");
          BufferedInputStream bis = new BufferedInputStream(fis);
          byte[] bytes1 = new byte[(int)file.length()];

          bis.read(bytes1);

          encryptedString = bytes1;

          String str3 = new String(getDecryptedString(bytes1));
          System.err.println("str3:Ravindra:equals:"+str3+":"+str3.equals("Ravindra"));
          bis.close();
     }
0
Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

Ravindra76Author Commented:
Hi,

  My code is working fine with Suj JDK on multiple machines.
  The encrypted string generated in /tmp/ravi.txt with SUN and IBM are different.
  So decryption by IBM is failing on the encrypted string generated by SUN.

  I came to know the compatibility does not exists for SUN and IBM,especially for DES algorithm.
  Is it true?
  What is the universal algorithm for encrypting/decrypting which is compatiable among all java vendors/versions?
 
0
Dejan PažinHead of SW DevelopmentCommented:

Did you try the solution I gave you?

Its possible that your code works on some machines, but in general the code is note ok. You keep converting bytes to characters and back again (although there is no need for that) without ever knowing what encoding you are using.

Try to write the code using only byte arrays, FileOutputStream and FileInputStream (no Strings and no FileWriters, cause they are completely uncalled for in your case). Dont convert it to String in the middle of process. If nothing else, you will eliminate one possible error (but I give it a big chance that this is the error).

The fact is, that I tried your original code on my linux machine and it didnt work, but it worked on my windows machine. After I changed it, it worked fine on both.
0
Dejan PažinHead of SW DevelopmentCommented:

I got to the bottom of your problem. The bug in your code is in the method getEncryptedString(String str). Here is what you do wrong:

1. You have a String 'Ravindra'

2. Then you call writeString method which calls getEncryptedString in order to give you a String, which is encrypted. That is wrong. You should not convert the encrypted bytes into String. The line: s=new String(text2); in getEncryptedString method is the one that corrupts the encrypted bytes.

And here is why: The constructor String(byte bytes[]) constructs String by decoding the specified array of bytes using the platform's default charset. And most important part of the java specification here says :

... The behavior of this constructor when the given bytes are not valid in the default charset is unspecified....

Since the bytes you give to this constructor are just a bunch of random bytes, they dont neceseraly represent valid bytes for the charset. And from there on, the behavior is unspecified! That is why your code might sometimes work, and sometimes not.

And the solution is as I said before: Do not use Strings, FileReader and FileWriter. Use byte arrays, FileInputStream and FileOutputStream.

Since you have to start with a String, you should of course convert it to byte array (you do that already) using str.getBytes();. The next time you use String should therefore be no sooner then at the end: s=new String(text1);. But now, it will work ok, because you will only use it for the decrypted array of bytes. And since the str.getBytes(); and  s=new String(text1); are run on the same machine under the same user in the same VM, they will use the same encoding.







0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Ravindra76Author Commented:
Thanks for ur advise.

The main problem with IBM is , it is not working on the same machine I have configured.

It is not decrypting the  message which is encrypted by ibm only.

The problem is IBM is using it's own provider even though it is configured to use

security.provider.5=org.bouncycastle.jce.provider.BouncyCastleProvider

IBM uses encrypted key generated by SUN's  using the program CreateSecretKey.

Are u able to run the program with IBM 1.4 on same machine?
0
Ravindra76Author Commented:
I followed this  link to configure IBM jdk to use JCE

     http://www.systinet.com/doc/wasp_uddi-50/html/index.html?Install.Prerequisites.html

0
Dejan PažinHead of SW DevelopmentCommented:


I still dont know: did you try the solution I gave you or not? Or have you already solved the problem?

I will try to run it with IBM 1.4 later on.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Java

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.