?
Solved

How to force IBM jdk to use sunjce_provider.jar

Posted on 2004-11-19
9
Medium Priority
?
2,223 Views
Last Modified: 2013-11-23
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
0
Comment
Question by:Ravindra76
  • 5
  • 4
9 Comments
 
LVL 7

Author Comment

by:Ravindra76
ID: 12625437
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
 
LVL 17

Expert Comment

by:Dejan Pažin
ID: 12626496

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
 
LVL 17

Expert Comment

by:Dejan Pažin
ID: 12626634

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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 7

Author Comment

by:Ravindra76
ID: 12627785
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
 
LVL 17

Expert Comment

by:Dejan Pažin
ID: 12630804

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
 
LVL 17

Accepted Solution

by:
Dejan Pažin earned 2000 total points
ID: 12633666

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
 
LVL 7

Author Comment

by:Ravindra76
ID: 12634313
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
 
LVL 7

Author Comment

by:Ravindra76
ID: 12634319
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
 
LVL 17

Expert Comment

by:Dejan Pažin
ID: 12634744


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

Featured Post

[Webinar] Cloud and Mobile-First Strategy

Maybe you’ve fully adopted the cloud since the beginning. Or maybe you started with on-prem resources but are pursuing a “cloud and mobile first” strategy. Getting to that end state has its challenges. Discover how to build out a 100% cloud and mobile IT strategy in this webinar.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

An old method to applying the Singleton pattern in your Java code is to check if a static instance, defined in the same class that needs to be instantiated once and only once, is null and then create a new instance; otherwise, the pre-existing insta…
By the end of 1980s, object oriented programming using languages like C++, Simula69 and ObjectPascal gained momentum. It looked like programmers finally found the perfect language. C++ successfully combined the object oriented principles of Simula w…
Viewers learn about the scanner class in this video and are introduced to receiving user input for their programs. Additionally, objects, conditional statements, and loops are used to help reinforce the concepts. Introduce Scanner class: Importing…
The viewer will learn how to implement Singleton Design Pattern in Java.
Suggested Courses
Course of the Month14 days, 17 hours left to enroll

839 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question