Forum Stats

  • 3,826,763 Users
  • 2,260,705 Discussions
  • 7,897,072 Comments

Discussions

RSA Encryption in JAVA

imation3m
imation3m Member Posts: 177
edited Feb 15, 2017 7:16AM in Java Programming

I am calling a SOAP Webservice to fetch the public key in the form of byte[] .

I want to encrypt some input text with this public key using RSA Encryption in java.

I am using the below class:

public class CryptographyUtil {    private static final String ALGORITHM = "RSA";    public static byte[] encrypt(byte[] publicKey, byte[] inputData)            throws Exception {        PublicKey key = KeyFactory.getInstance(ALGORITHM).generatePublic(new X509EncodedKeySpec(publicKey));        Cipher cipher = Cipher.getInstance(ALGORITHM);        cipher.init(Cipher.PUBLIC_KEY, key);        byte[] encryptedBytes = cipher.doFinal(inputData);        return encryptedBytes;    }}

I am calling the above:

String text = "1234";            byte[] c = CryptographyUtil.encrypt(publickKey.getBytes(), text.getBytes() );

But i am getting  the below exception

java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: invalid key format

  at sun.security.rsa.RSAKeyFactory.engineGeneratePublic(RSAKeyFactory.java:188)

How can i resolve this?

rpc1

Answers

  • Unknown
    edited Feb 10, 2017 2:35PM
    How can i resolve this?

    The EASIEST way to 'resolve' it is to start with a working example from the internet. Their are plenty of them available. Here is just one:

    Asymmetric (Public-key) Encryption Using RSA, Java and OpenSSL | Brian Reindel

    Notice how that example FIRST creates the factory (line #25) before using the key with it.

    And when you ask for  help you have to provide ALL of the info needed to help you. You need to provide EXACTLY the exception posted and that would have included full stack trace or at least the portion that shows the line number of YOUR code. It also means providing enough info/code so people can try to reproduce the problem.

    Take ONLY the code you posted and try to reproduce the problem. It isn't possible because there are pieces of code and data missing.

    Next, in order to troubleshoot you need to be able to examine things ONE STEP at a time.

    That means when you are trying/learning new things you have to code with that in mind and often need to write the code DIFFERENTLY.

    1. PublicKeykey=KeyFactory.getInstance(ALGORITHM).generatePublic(newX509EncodedKeySpec(publicKey));

    See how you are doing THREE things in that one line of code using dot notation? Dot notation is a nice convenience but you now have three things that can go wrong. The problem is that you will only get ONE EXCEPTION message. That is NOT the ratio  you want when you troubleshoot - you want one for one.

    Remember how that example in the link got the factory first? They used ONE LINE OF CODE. If that line of code produced an exception you would know EXACTLY what code caused the exception.

    But i am getting the below exceptionjava.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: invalid key format at sun.security.rsa.RSAKeyFactory.engineGeneratePublic(RSAKeyFactory.java:188)

    Except that doesn't show the line number of YOUR code.

    I suggest you FIRST try to reproduce that example code from the link (or from other sources).

    Then when that works for you copy the project it and modify the new project to produce your own example.

    Break that one line of code into three: one for each step being done. Then you will know which step is causing the error.

    There are NO SHORTCUTS - that is the same thing anyone else would have to do to find the problem.

    rpc1
  • imation3m
    imation3m Member Posts: 177
    edited Feb 10, 2017 3:12PM

    Okay i have broken the code

    public class CryptographyUtil {    private static final String ALGORITHM = "RSA";    public static byte[] encrypt(byte[] publicKey, byte[] inputData)            throws Exception {        X509EncodedKeySpec enKeySpec = new X509EncodedKeySpec(publicKey);        KeyFactory kf = KeyFactory.getInstance(ALGORITHM);        PublicKey key = kf.generatePublic(enKeySpec);        Cipher cipher = Cipher.getInstance(ALGORITHM);        cipher.init(Cipher.PUBLIC_KEY, key);        byte[] encryptedBytes = cipher.doFinal(inputData);        return encryptedBytes;    }}

    The below line is throwing exception:

    PublicKey key = kf.generatePublic(enKeySpec);

    Trace below:

    java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: invalid key format  at sun.security.rsa.RSAKeyFactory.engineGeneratePublic(RSAKeyFactory.java:188)  at java.security.KeyFactory.generatePublic(KeyFactory.java:304)  at soapuitester.CryptographyUtil.encrypt(CryptographyUtil.java:25)  at soapuitester.SOAPUITester.main(SOAPUITester.java:43)Caused by: java.security.InvalidKeyException: invalid key format  at sun.security.x509.X509Key.decode(X509Key.java:370)  at sun.security.x509.X509Key.decode(X509Key.java:386)  at sun.security.rsa.RSAPublicKeyImpl.<init>(RSAPublicKeyImpl.java:66)  at sun.security.rsa.RSAKeyFactory.generatePublic(RSAKeyFactory.java:281)  at sun.security.rsa.RSAKeyFactory.engineGeneratePublic(RSAKeyFactory.java:184)  ... 3 more

    My main class below:

    public static void main(String[] args) {        String publickKey = "";        // TODO code application logic here        VeripakWebserviceTester veripakWebserviceTester =                new VeripakWebserviceTester();        try {            publickKey = veripakWebserviceTester.getPublickKey();            System.out.println("publickKey=" + publickKey);            String pinText = "1234";                        byte[] c = CryptographyUtil.encrypt(publickKey.getBytes(), pinText.getBytes() );            //System.out.println("cipher=" + (new String(c, "UTF-8")) );                    } catch (MalformedURLException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        } catch (Exception ex) {            Logger.getLogger(SOAPUITester.class.getName()).log(Level.SEVERE, null, ex);        }

  • Unknown
    edited Feb 10, 2017 4:25PM
    Okay i have broken the code

    That's a start.

    And did you TRY the example in the link I posted?

    I'm not sure you understand what I was trying to tell you. YOU are the one that has to do the work. Otherwise you won't learn anything.

    Now that you split the code out you were able to identify the line causing the problem.

    PublicKey key = kf.generatePublic(enKeySpec);

    And you have the exception telling you the problem:

    java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: invalid key format  

    Just put the two together and it should be clear that: 'enKeySpec' is an 'invalid key format'.

    So now your problem is to determine where the value of 'enKeySpec' came from and why it is in an invalid format for the 'generatePublic' method call.

    Look at the Java API for that method:

    https://docs.oracle.com/javase/7/docs/api/java/security/KeyFactory.html

    At the top of that API is sample code 'similar' to yours

    X509EncodedKeySpec bobPubKeySpec = new X509EncodedKeySpec(bobEncodedPubKey); KeyFactory keyFactory = KeyFactory.getInstance("DSA"); PublicKey bobPubKey = keyFactory.generatePublic(bobPubKeySpec);

    See how you can tell where 'bobPubKeySpec' came from? See how it is using 'bobEncodedPubKey'. See how it is NOT just using a public key - it is using an 'encoded' public key?

    This is your code

            X509EncodedKeySpec enKeySpec = new X509EncodedKeySpec(publicKey);          KeyFactory kf = KeyFactory.getInstance(ALGORITHM);          PublicKey key = kf.generatePublic(enKeySpec);  

    See how your code uses 'publicKey'?

    1. public static byte[] encrypt(byte[] publicKey, byte[] inputData) 

    See how that value comes from a byte array passed to the method?

    So where does that byte array come from?

                publickKey = veripakWebserviceTester.getPublickKey();              System.out.println("publickKey=" + publickKey);              String pinText = "1234";  byte[] c = CryptographyUtil.encrypt(publickKey.getBytes(), pinText.getBytes() );  

    It comes from 'publickKey.getBytes() there at line 4 above.

    And where does that 'invalid' value come from?

    It comes from line 1 above.

    And where and how does that line 1 get its value.

    We have  NO IDEA because YOU DIDN'T POST THE CODE!

    I will now leave it to others to try to help you. I also suggest if you want help from others that you reread what I told before but that you chose NOT to do:

    And when you ask for  help you have to provide ALL of the info needed to help you. You need to provide EXACTLY the exception posted and that would have included full stack trace or at least the portion that shows the line number of YOUR code. It also means providing enough info/code so people can try to reproduce the problem.Take ONLY the code you posted and try to reproduce the problem. It isn't possible because there are pieces of code and data missing.

    Reread that last paragraph above until it sinks in.

    We were trying to help you. But it just is NOT possible if you don't provide the info needed.

    Good luck with your problem.

  • imation3m
    imation3m Member Posts: 177
    edited Feb 11, 2017 2:17AM

    I am just calling a webservice method and the value returned from veripakWebserviceTester.getPublickKey()

    is below

    MIIB/DCCAWmgAwIBAgIQpbarEXfe8rVDlWlg2T+ixzAJBgUrDgMCHQUAMBgxFjAUBgNVBAMTDUJBTktESE9GQVIwMDEwIBcNMTMwNzEwMDkxMjU5WhgPMjA5OTEyMjkyMDAwMDBaMBgxFjAUBgNVBAMTDUJBTktESE9GQVIwMDEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALZTB/2vKxWwCGhUdywVvikj8klvlzpZTJbVd0bRIN82bTTzp53SDXczc7mkto4vsqelGqnyjZcigyhj5y60SWYggc83d89I+i2Vo77am6aW8tfx1p/x9Op6bDLIN8V0uyoBK8IhRbuiugHmbP69Fyq4vXQ4+D2EzmmOuPRQfg4BAgMBAAGjTTBLMEkGA1UdAQRCMECAEAMkZd7uwQQG7803GjCmF7yhGjAYMRYwFAYDVQQDEw1CQU5LREhPRkFSMDAxghCltqsRd97ytUOVaWDZP6LHMAkGBSsOAwIdBQADgYEAhau3OD9QPoJm+H8v70WQmGUwJaS2IZORo/f8sMgUnVA6qoiD7BRkv8VVT0No4H+77YnYR2mtlCkU1BenKM3bC4WQXsXawMDSOoJcqBVLBFpYzl/8xpNrRyA8yyLUX37kXmH6mdioGLiNSKhQvX/XBYkTeOnsS2umt+zjS2JDS+g=

    I am not sure how to encode the above public key so I can pass to X509EncodedKeySpec(bobEncodedPubKey)

    I tried another sample program from internet, when i pass a small text as public key it works, but when i try my public key string it gives error:

    public class AESUtils {  static String INITIALIZATIO_VECTOR = "AODVNUASDNVVAOVF";    public static byte[] encrypt(String plainText, String encryptionKey) throws Exception {    Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding", "SunJCE");    SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");    cipher.init(Cipher.ENCRYPT_MODE, key,new IvParameterSpec(INITIALIZATIO_VECTOR.getBytes("UTF-8")));    return cipher.doFinal(plainText.getBytes("UTF-8"));  }  public static String decrypt(byte[] cipherText, String encryptionKey) throws Exception{    Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding", "SunJCE");    SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");    cipher.init(Cipher.DECRYPT_MODE, key,new IvParameterSpec(INITIALIZATIO_VECTOR.getBytes("UTF-8")));    return new String(cipher.doFinal(cipherText),"UTF-8");  }}

    Main

    public class RSAEncrypter {    static String PLAIN_TEXT = "Java Code Geeks Rock!\0\0\0\0\0\0\0\0\0\0\0";    //static String ENCRYPTION_KEY = "0123456789abcdef";    static String  ENCRYPTION_KEY = "MIIB/DCCAWmgAwIBAgIQpbarEXfe8rVDlWlg2T+ixzAJBgUrDgMCHQUAMBgxFjAUBgNVBAMTDUJBTktESE9GQVIwMDEwIBcNMTMwNzEwMDkxMjU5WhgPMjA5OTEyMjkyMDAwMDBaMBgxFjAUBgNVBAMTDUJBTktESE9GQVIwMDEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALZTB/2vKxWwCGhUdywVvikj8klvlzpZTJbVd0bRIN82bTTzp53SDXczc7mkto4vsqelGqnyjZcigyhj5y60SWYggc83d89I+i2Vo77am6aW8tfx1p/x9Op6bDLIN8V0uyoBK8IhRbuiugHmbP69Fyq4vXQ4+D2EzmmOuPRQfg4BAgMBAAGjTTBLMEkGA1UdAQRCMECAEAMkZd7uwQQG7803GjCmF7yhGjAYMRYwFAYDVQQDEw1CQU5LREhPRkFSMDAxghCltqsRd97ytUOVaWDZP6LHMAkGBSsOAwIdBQADgYEAhau3OD9QPoJm+H8v70WQmGUwJaS2IZORo/f8sMgUnVA6qoiD7BRkv8VVT0No4H+77YnYR2mtlCkU1BenKM3bC4WQXsXawMDSOoJcqBVLBFpYzl/8xpNrRyA8yyLUX37kXmH6mdioGLiNSKhQvX/XBYkTeOnsS2umt+zjS2JDS+g=";    /**     * @param args the command line arguments     */    public static void main(String[] args) {        try {                        System.out.println("length of pkey="+ENCRYPTION_KEY.getBytes().length);            System.out.println("Plain text:" + PLAIN_TEXT);            byte[] cipherText = AESUtils.encrypt(PLAIN_TEXT, ENCRYPTION_KEY);            System.out.print("Cipher Text:  ");            for (int i = 0; i < cipherText.length; i++) {                System.out.print(String.format("%02X ", cipherText[i]));            }            System.out.println("");            String decrypted = AESUtils.decrypt(cipherText, ENCRYPTION_KEY);            System.out.println("Decrypted Text: " + decrypted);        } catch (Exception e) {            e.printStackTrace();        }    }}

    Error when i try my string is

    length of pkey=684Plain text:Java Code Geeks Rock!java.security.InvalidKeyException: Invalid AES key length: 684 bytes  at com.sun.crypto.provider.AESCrypt.init(AESCrypt.java:87)  at com.sun.crypto.provider.CipherBlockChaining.init(CipherBlockChaining.java:91)  at com.sun.crypto.provider.CipherCore.init(CipherCore.java:591)  at com.sun.crypto.provider.AESCipher.engineInit(AESCipher.java:346)  at javax.crypto.Cipher.init(Cipher.java:1394)  at javax.crypto.Cipher.init(Cipher.java:1327)  at rsaencrypter.AESUtils.encrypt(AESUtils.java:23)  at rsaencrypter.RSAEncrypter.main(RSAEncrypter.java:29)
  • imation3m
    imation3m Member Posts: 177
    edited Feb 11, 2017 2:24AM

    I also downloaded the local_policy.jar and US_export_policy.jar and replaced in <span style="color: #333333; font-family: Tahoma, Arial, Verdana, sans-serif; font-size: 15px;">directory </span><code>JAVA_HOME/jre{version_number}/lib/security

  • imation3m
    imation3m Member Posts: 177
    edited Feb 15, 2017 3:01AM

    Awaiting response from someone.

  • imation3m
    imation3m Member Posts: 177
    edited Feb 15, 2017 7:16AM

    The public key for asymmetric encryption in the form of DER (Distinguished Encoding Rules) encoded binary data, which is a restricted form of the ASN.1 (Abstract Syntax Notation One) encoding.

This discussion has been closed.