RSA-AES 解密问题 - javax.crypto.BadPaddingException:解密错误

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

我需要将 python 代码转换为 java 代码以用于 RSA-AES 解密逻辑。他们提供了 PEM 文件格式的 RSA 加密字符串和私钥。我们需要在 java 代码中实现相同的解密。

这里,我已经包含了python代码,(这个我们必须转换成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 + '[=11=]' * (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)

我在 java 代码中尝试 "to convert the encrypted text to RSA decryption" 时遇到以下错误,

我使用 "io.netty"、"BouncyCastle" 提供程序、apache BASE64、JavaUtil Base64 等尝试了很多东西。

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;

    }

}

这是我在尝试将加密文本转换为 RSA 解密时遇到的错误。

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)

这里我给出了解密文本的私钥(PEM)文件格式

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

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

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

如果我们在 python 代码中使用相同的键,它将起作用。 有人可以帮忙吗?

正如评论中已经提到的,填充有问题:

  • 虽然创建了一个 OAEPParameterSpec-实例 (oaepParams),但它没有在任何地方使用! oaepParams 必须作为 Cipher#init 调用中的第三个参数传递。

  • OAEP 使用 标签 ,默认情况下它是一个空的 byte-array (PSource.PSpecified.DEFAULT)。虽然这很不寻常,但 Python-code 不使用默认值(即空的 byte-array),而是使用自定义的 byte-sequence(更准确地说,字符串 OAEP Encrypted,UTF -8 编码)。因此,在 OAEPParameterSpec- constructor-call PSource.PSpecified.DEFAULT 必须替换为 new PSource.PSpecified("OAEP Encrypted".getBytes(StandardCharsets.UTF_8))

有关 OAEP 和 PSource.PSpecified 的更详细说明,请参见例如here and here。如果两个错误都得到修复,Java-code 的 RSA-decryption 对应于 Python-code (UQQtMe0oUzkguQLzvcBcJMAvmsx2XWU6G-CMZtV1dR0qtu2LXwE=)。顺便说一下,Java-code 只包含 Python-code.

的 RSA-decryption 部分