Search code examples
javapythonencryptionaesrsa

RSA-AES Decryption Issue - javax.crypto.BadPaddingException: Decryption error


I am in need to convert the python code to java code for RSA-AES Decryption logic. They have provided RSA Encrypted string and private key as a PEM file format. we need to implement the same decryption in java code.

Here , I have included the python code, (this we have to convert into java)

import base64

from Crypto.Cipher import AES

from cryptography.hazmat.primitives import hashes

from cryptography.hazmat.primitives.asymmetric import padding

from Crypto.PublicKey import RSA

from Crypto.Cipher import PKCS1_v1_5

from cryptography.hazmat.backends import default_backend

from cryptography.hazmat.primitives import serialization

encrypted = 'gBTI3T5KP8CG23_DLM7lVo9--pEQcoHaL2YxuhHqmv_guahHuOeDPQQiV3-yxXK4JXacIjqv7BL7QpTzq9v8HyK4P_f0PYFTH4RjnM_IYnAQPZt0ey2m2ckkvfuuAqeXvPEFoQtPfLPqqAokYzhH2O5K-VYth0tfTEjWGGNH7ukQjcjh3fUDneFBH4MVYuzGACRtG3gPTvCHnAuzAkA6UWfErXbh-17ZsBxpw-9wdcRtJ2DTE8rOZcpcT4NwXtURLDL6fl3eXaQFQA6BMZ2k1Iv19zjUD7WyN6NUZwQYdtMBq3PUMBd-uMNmB8YEb9sV4fEixbiZIS4j0y2gFCf0JrZXq7n9Jtv7_WTL0_jxoeysVauc2u3rc31jRtzHS6m1vTlg4qAcq390nk4m_QJyLq1RrvsWnyg6HjVpjSwSCEgZj441WWENWAaH0Tb2JhWosu53eiRTbjGivAKa0SUxpYW6b85DqW9jmYs9D9JrMwzVllmF6KaFa6lL3C97VZGmPZChUihqCvzp8tpxx7EPuPXloyFJaH3_oMW8PgQL0uBuCLfFt5pdxAp4QqEOe_z19IS27PSdJfFwZrk8DM3cLQEn__30EsnVC1e1fGrqz3Xh_Yvw-1kBZuer3YBpw43lIachaATy43EuVvM2gl1ppasBZQwMQWTWkJqrTyQBUmQ='

decoded = base64.urlsafe_b64decode(encrypted)

print('decode : ', decoded)

print('--------------- Started RSA Decryption ----------------------')

with open("./t2.pem", "rb") as key_file:

private_key = serialization.load_pem_private_key(

key_file.read(),

password=None,

backend=default_backend()

)

original_message = private_key.decrypt(

decoded,

padding.OAEP(

mgf=padding.MGF1(algorithm=hashes.SHA256()),

algorithm=hashes.SHA256(),

label="OAEP Encrypted"

)

)

print("RSA Decrypted Message",original_message)

print('--------------- Started AES Decryption ----------------------')

value = str(original_message)

key = b'1004063899047190'

value = base64.b64decode(value + '=' * (4 - len(value) % 4), '-_')

iv, value = value[:AES.block_size], value[AES.block_size:]

remainder = len(value) % 16

padded_value = value + '\0' * (16 - remainder)

cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128)

msg = cipher.decrypt(padded_value)[:len(value)]

print("message -- ",msg)


print("message -- ",msg)

I am getting the following error while tried "to convert the encrypted text to RSA decryption" in java code,

I have tried many things using "io.netty" ,"BouncyCastle" provider, apache BASE64, JavaUtil Base64.. etc all those stufs.

package MMDemo.TarCopyJen2Master;

import java.io.BufferedReader;

import java.io.FileReader;

import java.io.IOException;

import java.security.GeneralSecurityException;

import java.security.KeyFactory;

import java.security.KeyPair;

import java.security.KeyPairGenerator;

import java.security.PrivateKey;

import java.security.PublicKey;
import java.security.Security;
import java.util.Base64;

import java.security.interfaces.RSAPrivateKey;

import java.security.spec.MGF1ParameterSpec;

import java.security.spec.PKCS8EncodedKeySpec;

import javax.crypto.Cipher;

import javax.crypto.SecretKey;

import javax.crypto.spec.OAEPParameterSpec;

import javax.crypto.spec.PSource;

import javax.crypto.spec.SecretKeySpec;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class PublickeyTest1 {

    public static void main(String[] args) throws Exception {

        Security.addProvider(new BouncyCastleProvider());
        String rsaEncrypted1 = "gBTI3T5KP8CG23_DLM7lVo9--pEQcoHaL2YxuhHqmv_guahHuOeDPQQiV3-yxXK4JXacIjqv7BL7QpTzq9v8HyK4P_f0PYFTH4RjnM_IYnAQPZt0ey2m2ckkvfuuAqeXvPEFoQtPfLPqqAokYzhH2O5K-VYth0tfTEjWGGNH7ukQjcjh3fUDneFBH4MVYuzGACRtG3gPTvCHnAuzAkA6UWfErXbh-17ZsBxpw-9wdcRtJ2DTE8rOZcpcT4NwXtURLDL6fl3eXaQFQA6BMZ2k1Iv19zjUD7WyN6NUZwQYdtMBq3PUMBd-uMNmB8YEb9sV4fEixbiZIS4j0y2gFCf0JrZXq7n9Jtv7_WTL0_jxoeysVauc2u3rc31jRtzHS6m1vTlg4qAcq390nk4m_QJyLq1RrvsWnyg6HjVpjSwSCEgZj441WWENWAaH0Tb2JhWosu53eiRTbjGivAKa0SUxpYW6b85DqW9jmYs9D9JrMwzVllmF6KaFa6lL3C97VZGmPZChUihqCvzp8tpxx7EPuPXloyFJaH3_oMW8PgQL0uBuCLfFt5pdxAp4QqEOe_z19IS27PSdJfFwZrk8DM3cLQEn__30EsnVC1e1fGrqz3Xh_Yvw-1kBZuer3YBpw43lIachaATy43EuVvM2gl1ppasBZQwMQWTWkJqrTyQBUmQ=";
        PrivateKey privateKey = getPrivateKey("D:/Infosys/Decrpyt/EncryptDec/private_key.pem");
        String rsaDecrypted = decrypt(rsaEncrypted1, privateKey);
        System.out.println("RSA Decrypted Text == " + rsaDecrypted);
    }

    public static String decrypt(String cipherText, PrivateKey privateKey)
            throws IOException, GeneralSecurityException {
        byte[] decodedCipherText = Base64.getUrlDecoder().decode(cipherText);

        System.out.println("Decoded Cipher text == " + decodedCipherText.toString());

        OAEPParameterSpec oaepParams = new OAEPParameterSpec(

                "SHA-256", "MGF1", new MGF1ParameterSpec("SHA-256"), PSource.PSpecified.DEFAULT);

        Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");

        cipher.init(Cipher.DECRYPT_MODE, privateKey);

        // cipher.init(Cipher.DECRYPT_MODE, privateKey);

        System.out.println("algo " + cipher.getAlgorithm());

        System.out.println("cipherText == " + cipherText);

        return new String(cipher.doFinal(decodedCipherText), "UTF-8");

    }

    private static String getKey(String filename) throws IOException {

        // Read key from file

        String strKeyPEM = "";

        BufferedReader br = new BufferedReader(new FileReader(filename));

        String line;

        while ((line = br.readLine()) != null) {

            strKeyPEM += line;// + "n";

        }

        br.close();

        return strKeyPEM;

    }

    public static RSAPrivateKey getPrivateKey(String filename) throws IOException, GeneralSecurityException {

        String privateKeyPEM = getKey(filename);

        System.out.println("PrivateKeyPem == " + privateKeyPEM);

        return getPrivateKeyFromString(privateKeyPEM);

    }

    public static RSAPrivateKey getPrivateKeyFromString(String key) throws IOException, GeneralSecurityException {

        String privateKeyPEM = key;

        // Remove the first and last lines

        privateKeyPEM = privateKeyPEM.replace("-----BEGIN RSA PRIVATE KEY-----", "");

        privateKeyPEM = privateKeyPEM.replace("-----END RSA PRIVATE KEY-----", "");

        privateKeyPEM = privateKeyPEM.replace("-----BEGIN PRIVATE KEY-----", "");

        privateKeyPEM = privateKeyPEM.replace("-----END PRIVATE KEY-----", "");

        System.out.println("privatekey pem after removal == " + privateKeyPEM);

        byte[] encoded = Base64.getDecoder().decode(privateKeyPEM); // for util base64

        KeyFactory kf = KeyFactory.getInstance("RSA");

        RSAPrivateKey privKey = (RSAPrivateKey) kf.generatePrivate(new PKCS8EncodedKeySpec(encoded));

        System.out.println("RSA Private Key after encoded: " + privKey);
        return privKey;

    }

}

This is error I am getting while try to convert the encrypted text to RSA Decryption.

Exception in thread "main" javax.crypto.BadPaddingException: Decryption error
    at sun.security.rsa.RSAPadding.unpadOAEP(RSAPadding.java:502)
    at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:296)
    at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:363)
    at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:389)
    at javax.crypto.Cipher.doFinal(Cipher.java:2164)
    at com.infy.rsaaes.RSAAESEncryptDecrypt.PublickeyTest1.decrypt(PublickeyTest1.java:129)
    at com.infy.rsaaes.RSAAESEncryptDecrypt.PublickeyTest1.main(PublickeyTest1.java:79)

here I have given the private key (PEM) file format to decrypt the text.

-----BEGIN PRIVATE KEY-----

MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQCDJekby5SEjN2VYlNByHlom8pmoxb1osQ9Mmp+FWEWCcvNnpeAE9ND1Kavm4H/EqgCNjg1JSNodhpCGXEcpOL4o67oTf8ToV6VFIg44IB8zoaGtlRRDkAY0hP276G+3Wj8EftxHnj60GbuQYmzkwjdww+3Gjf9kL+22UE9a/Xq6ALhfz6w+9NHsjDxtiorXkpDFZhhkZt0BszisVEcOp/8G5hMW39nspvj1HHjys5p8/x7vTIHzois1ldrQ3xATY02KwkEIpUE0VwcPcXLfAm1sc8CzJvi02Tnp0+Co0WEOj82dxFKtqAQSdoaaCQGwNKwC61HwhLe+jxEd4omkSFgD2uE+5GPMsVVs3EciVNJzzxGh59JPTIMExrEsI7Z4a5U5Vc2TamSM7LwCD93bbZijwWB0rYTTtvZ4LvqNWg7xXxCVSd8ZVBaxFNPtUfju0i79d0PP+aF18+OGU5naPfV8kYNxrLrTt1P24gsD8hibp0l7ZmcLNSLX764mssvQtNXnJipVpxCXAdoL6ZC/2BRPlYiK/MHz4Up+bc0bJa6TEXcggPQI8r9B0xqEzvNdjikMo7KwMlZAMT1SfSS3Tem+oe7xUGmavDa/Mf89EASYy9uCjAlSH8Srahrjdi5gCz+xrbUPbjOh6ekIum3HWG1j7r1lEmtGs3kOUMgcub3GQIDAQABAoICAEihizr4gRTzipf7r05EP3C+rtYuxj1dWj7mF/Ih1vXEkRkcFp043Yy4TWP9xH3GEEPBUVmlarmkhqBKxMjvTEAVLn27DGQLv3zitRqCwsXb/sbGXWXSdY8JcUMVrUcuCcFoGA+qp6eIGSkkJKXN7WAbci2emJmWO4aBRU9F5hilS0slFEwh+v2+4rpKf4orGweSAyUt5aDZT0jQmLIAia+ufKb1GVcNpKYFdtmH7M7i79Z7jiSirjDCOAHQixR1npn8NW8T0+GqLM/7KfqqhBobEiFjvYVeO4jLsQ4RbCNxuqZoRKxS/cxniiGLwT/4M/aJUPrnsVnJzezBI0J+p7Ndqgwq7iprNd6Kc3A7s2vWtGZIUONQQMrYJVrDlJd0n/mTNzRSzrDFRFg0PmyoDROcu9Q9LRM7+2WT/bUmAXJgQ4V4sWbqOCc1hpgRXE99U3YkiErXDuZEvN3nPeWvDbna6sDQ+mt0haTXHMW6vj8kvKnmHaHinHSetUFgcB7oqVmb+ied2LgjohLCoFJ7Fan6m3G3F6g2OHDSg5s1tz/aTGXW/FzJUvNBVaeDVGYf53OAHMX/Eo8Oq8WslaNyHq2kB/rKELDN6YVxBAnlJH4v2N/Bpt6WFFb3vb0P3kRaHauKQAYjpVDDxwTnX085xcr8vjqf+1UwnD710gPI1IxtAoIBAQD54j7azS3vwmILqO4pFhCpueUAROHdV0ASZ+IppHAaU2LCtVqMoKhBBcgh/Nud4zt9LosOJcar1RVe02QqyN8VjEMXYkyhwX0wV4zwjbukrrZV3PvEQQgg3x7R/FPL0N0sOFowKR4wolQMtZ55vbWrgSg9ifn2zMe0I1SaS+PbdN+suJ2GcOhMEI4d5kszTyMJaS7Db4BcC3zKqJmJ/ksnntBKx6EOa5D0kcsu7xOxic4saSp9kZlqenJyDJGKMQPfTlD+ewTo6ABjlJQv7o1Y+A/FTQgrk7bMLyEMZRPBlxHCx0DYrtKKz0xfvSmGFAoc+Zjjs+bQlKOEaQ0ipuwnAoIBAQCGW6zqhIm1uX5HaaXYDmR5YOnAWYny4yW22WO5FybwpG7SiVDuPxfkvsr5lsFf2SoW/+bMkSSS13igC4rVLOQiUmDmYz1vloBSSID0TmA/1B+1TFkW9Ic3zWHa+eAeNC0cm4Ruda6ghLzRBM8dY0zvml4ksq2SfWQMI7dqpWax0J4O0AuH8Oh8yAIMtMfYiU4V9zJu0Rs51L3Ud+RLMyw7SOuXa3FWZFzJYAsIhrGR+P3g2N0yfY3aQD0yStJmfDJGy5daZCyzaZvXYSLx4U5jcLUZRaky/V2dhGbByF7K4SF1EvWg5bL+Bka4BXAxNq9GQSMlug478Ac+Hdbjisq/AoIBAQDNKaTRoISGxeIaEKj5stQbhjUu818+i9RfSEu4RPqFotEDbELcE0wRlt2qiiEGkPrW3M/u3bUwf9L7+DPVrPb8ihzLpjmk1WgjuL5PAw99NrUd6kIL8BjsZES5w6JJRUNSezIROLFA3QaFKNjku43dMj4HyLEioR+WFyvvQz/hfyPme+1Z5HnVegI1Kk+z4NWzdFigvXt2Fzhua98kHVU3Qn1h6GWjoU1ygAGCl2hj6/ELJY1ta426jq5IVWlpPLUhMvvs9LQjRdiL6gGBGSuUUJciNwzuOmlrW4aW1qZR2+cJNO9Y+LCEp47dTEI7g1iKUaPl0F9CAcf/fwD54nMhAoIBAF1sbYX8dsz3mEkLuxfKmi6UJrVrDTLooxbLfj37TUZS8ARRGwcus+yIhhaarwd4t32ant9rpSS90tBmdjjYqCD9aweHxfZLjhqo85Hs1ZxMYWftGJ2Pll5E32AmE6Ks4RldQe6UwcI3yhsE3wcuPxb0HbYiz/JmYiTWyPjM3eWSi/T80KfL6byqTlKLedKlVriLVHQdznKd7QlJ/GIVyRHIGJkHSp2p16Lmt4VMMzivC8lGwjgTeYli1aqcwEQm48a6VhmyQirWqlhO4L+TzK/0dNiHyaj86BVZNSJVsyQa+uqvLkCct6NOtenLTkHKJoIRVOEsyC0BL+gPU5aQsX0CggEAC+d4/Ygggraoocq1mw3xwk0+eU3eWyiKcn4YS567npcTYBgXNTzFrrSGrhsPIGGoYAKPZysYKLcmCgHa4EtnSWZRU7pSdJtT9N9SwJjk591KSgGC9Qb1HYcPots9HX5wi/Lz4CKRaXSmkuk9u7RKivKitcB6LNAeq0JFCKBJ9gHtIMEEARwyWPGVHWUVtuGKzQ2GVzDESJxdXwI54epzYtaZYBsdMJFq3eiUYf15SNjxJTckGCT25Be+LTHc1EjWMtlOleGvpN6rscvsqOywhJ7I4zOrL+iCkqVaBvcGGAJjZ+pPPXUEwHyacIWOtrKSzIz6C+2CIwV0DBb0poIZDQ==

-----END PRIVATE KEY-----

If we use the same key in that python code, It will work. Could anyone help on this?


Solution

  • As already mentioned in the comment, there is something wrong with the padding:

    • Although an OAEPParameterSpec-instance (oaepParams) is created, it is not used anywhere! oaepParams must be passed as third parameter in the Cipher#init-call.

    • OAEP uses a label that by default is an empty byte-array (PSource.PSpecified.DEFAULT). Although it is rather unusual, the Python-code doesn't use that default (i.e. the empty byte-array), but a custom byte-sequence (more precisely, the string OAEP Encrypted, UTF-8 encoded). Therefore, in the OAEPParameterSpec- constructor-call PSource.PSpecified.DEFAULT must be replaced by new PSource.PSpecified("OAEP Encrypted".getBytes(StandardCharsets.UTF_8)).

    For a more detailed description of OAEP and PSource.PSpecified see e.g. here and here. If both bugs are fixed, the RSA-decryption of the Java-code corresponds to that of the Python-code (UQQtMe0oUzkguQLzvcBcJMAvmsx2XWU6G-CMZtV1dR0qtu2LXwE=). By the way, the Java-code contains only the RSA-decryption portion of the Python-code.