0

This error is already discussed in several links.

I got the similar kind of errors, But my scenario is little different than others. I need

only Decryption. not Encryption.

In my case, an encrypted message is already stored in the DB. I got that as String and now need to only decrypt it to get the original String.

Any suggestions will be very helpful.

My piece of code is as follows:

String encodedStr = "c2J7RiP1CY++gfdE7Ke/xD1fSOOdO7DvprdZZUDws9Yl8DmYJV64zGV9vvK/TMEfALqSPH8KcZik8XvmLowpjJWzYY2Of1aytHaya0ULwmopklRWlkaS5sjL80jjyhaRN2O+zQNarbAQy8g3VtXX643T2AhDTsT+NKFsCcpH4xbqmViwD1GXQQLsLwuKZx1POAtyC0UaMjQ2SrzR+eVEiSgKPDABDKIRbOyBEXRcJMK/t/P7uIk9tJ/p1X2JqQOO7GMO/1x7rvF6Pb1Fik2tmQv5qL1W6/kV97/VT5Hpi9uh6zdCFO7sstYvgkxxbs3gTyJ5raWlATVU6a/0B/Q50w==";
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(2048);
KeyPair pair = keyGen.generateKeyPair();
PrivateKey privateKey = pair.getPrivate();
PublicKey publicKey = pair.getPublic();

Cipher cipher = Cipher.getInstance("RSA");
// Encryption is not required.
//cipher.init(Cipher.ENCRYPT_MODE, privateKey);
//String ss =Base64.encodeBase64String(cipher.doFinal(encodedStr.getBytes("UTF-8")));
//System.out.println(ss);

// Only decryption is required.
cipher.init(Cipher.DECRYPT_MODE, publicKey);
String sss = new String(cipher.doFinal(Base64.decodeBase64(encodedStr)), "UTF-8");
System.out.println(sss);

And I'm getting below exception everytime at the line cipher.doFinal(Base64.decodeBase64(encodedStr) :

Exception in thread "main" javax.crypto.BadPaddingException: Decryption error
    at sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:383)
    at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:294)
    at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:356)
    at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:389)
    at javax.crypto.Cipher.doFinal(Cipher.java:2164)
    at com.sprint.neo.bc4j.util.TestMain.main(TestMain.java:20)

Though I don't require encryption, the Cipher.ENCRYPT_MODE is working fine. But incase of Cipher.DECRYPT_MODE , it's throwing exception. Please suggest me, how can I only decrypt an already existing encrypted String from DB, to get the original String value.

Jerry
  • 281
  • 4
  • 21
  • As you already have an 'encodedString' you cannot generate a NEW keypair and try to decrypt your string with the newly generated key. Asymmetric encryption is done with the PUBLIC key of the keypair and the decryption will work with the PRIVATE key of the same keypair. – Michael Fehr Sep 07 '20 at 07:54
  • Hence how can I resolve this issue here, where I have already an encrypted string. – Jerry Sep 07 '20 at 08:40
  • As part of your encryption you have previously generated a keypair. Use the public key for encryption and save both keys (private and public key) e.g. in a Java keystore. Later - when decrypting - load the private key [see below the answer of @Seema] e.g. from the keystore and use it for decryption. – Michael Fehr Sep 07 '20 at 09:19
  • Okay let me try to store the keyPair and use the private key for decryption. – Jerry Sep 07 '20 at 11:26
  • I tried but not able to store private and public key in java keystore. Can you help me with a code snippet. At the answer of @Seema, I'm getting **NullPointer**, as `Certificate cert` is null. – Jerry Sep 07 '20 at 16:48

2 Answers2

0

Here is the piece of code which works:

public static void main(String[] args) {

    byte[] txt = "message".getBytes();
    byte[] encText;
    try{

        // Load the keystore
        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
        char[] password = "keystorePassword".toCharArray();

        Key rsakey = ks.getKey("mykeyalias", password);
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");

        // Encrypt
        Certificate cert = ks.getCertificate("mykeyalias");
        try
        {
            cipher.init(Cipher.ENCRYPT_MODE, cert.getPublicKey());
            encText = cipher.doFinal(txt);
            System.out.println(encText.toString());
        }
        catch (Throwable e)
        {
            e.printStackTrace();
            return;
        }

        // Decrypt
        cipher.init(Cipher.DECRYPT_MODE, rsakey);
        String decrypted = new String(cipher.doFinal(encText));
        System.out.println(decrypted);


    } catch (Exception e) {
        System.out.println("error" + e);
    }

}

Seema
  • 84
  • 6
  • Its not resolving my issue. Here you encrypted a **message** text and then decrypt it to get the same text/string. But in my scenario, I already have an encrypted string saved in DB, which I need to decrypt to get original string. – Jerry Sep 07 '20 at 08:43
  • Can you help with a code snippet to store keyPair public-private in `Java keyStore`. – Jerry Sep 08 '20 at 05:15
  • 1
    You can have a look at this discussion: https://stackoverflow.com/questions/9890313/how-to-use-keystore-in-java-to-store-private-key – Seema Sep 08 '20 at 06:52
  • Thanks. It helps to more extent. – Jerry Sep 08 '20 at 14:29
0

Your publicKey generated will be different each time and hence the encrypted String will be different. The string generated will no longer be valid for decryption. Try to read key secret from a file and use same encrypted string to decrypt.

Seema
  • 84
  • 6