Exception in thread “main” javax.crypto.BadPaddingException: Java中的解密错误

huangapple go评论65阅读模式
英文:

Exception in thread "main" javax.crypto.BadPaddingException: Decryption error in Java

问题

我们正在Java中处理RSA加密/解密。

我们能够进行加密,但在解密时出现错误。

以下是我们正在使用的代码片段:

public class RSA_Read_Write_Key {
    
    static String plainText = "This RSA Crypto Java Code";
    
    public static void main(String[] args) throws Exception {
        byte[] cipherTextArray = encrypt(plainText, "D:\\TCE\\public.key");
        String encryptedText = Base64.getEncoder().encodeToString(cipherTextArray);
        System.out.println("Encrypted Text: " + encryptedText);
        String decryptedText = decrypt(cipherTextArray, "D:\\TCE\\private.key");
        System.out.println("Decrypted Text: " + decryptedText);    
    }

    // ...(其他方法保持不变)

    public static String decrypt(byte[] cipherTextArray, String fileName) throws Exception {
        Key privateKey = readKeyFromFile("D:\\TCE\\private.key");
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] decryptedTextArray = cipher.doFinal(cipherTextArray);
        return new String(decryptedTextArray);    
    } 
}

运行代码时,我们遇到以下错误。有人可以帮助解决这个问题吗?

Exception in thread "main" javax.crypto.BadPaddingException: Decryption error
at sun.security.rsa.RSAPadding.unpadV15(Unknown Source)
at sun.security.rsa.RSAPadding.unpad(Unknown Source)
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 RSAcrypto.RsaToy.decrypt(RsaToy.java:108)
at RSAcrypto.RsaToy.main(RsaToy.java:34)
英文:

We working on RSA encryption/Decryption in Java.

We are able to perform encryption but getting error for decryption

Below is code snippet we are using

public class RSA_Read_Write_Key {
    
    static String plainText = "This RSA Crypto Java Code";
    
    public static void main(String[] args) throws Exception {
        byte[] cipherTextArray = encrypt(plainText, "D:\\TCE\\public.key");
        String encryptedText = Base64.getEncoder().encodeToString(cipherTextArray);
        System.out.println("Encrypted Text : " + encryptedText);
        String decryptedText = decrypt(cipherTextArray, "D:\\TCE\\private.key");
        System.out.println("DeCrypted Text : " + decryptedText);    
    }

    public static Key readKeyFromFile(String keyFileName) throws IOException {
        Key key = null;
        InputStream inputStream = new FileInputStream(keyFileName);
        ObjectInputStream objectInputStream = new ObjectInputStream(new BufferedInputStream(inputStream));
        try {
            BigInteger modulus = (BigInteger) objectInputStream.readObject();
            BigInteger exponent = (BigInteger) objectInputStream.readObject();
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            if (keyFileName.startsWith("public"))
                key = keyFactory.generatePublic(new RSAPublicKeySpec(modulus, exponent));
            else
                key = keyFactory.generatePrivate(new RSAPrivateKeySpec(modulus, exponent));        
        } 
        catch (Exception e) {
            e.printStackTrace();
        } finally {
            objectInputStream.close();        
        }
        return key;    
    }
    
    public static byte[] encrypt(String plainText, String fileName) throws Exception {
        Key publicKey = readKeyFromFile("D:\\TCE\\public.key");
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] cipherText = cipher.doFinal(plainText.getBytes());
        return cipherText;   
    }

    public static String decrypt(byte[] cipherTextArray, String fileName) throws Exception {
        Key privateKey = readKeyFromFile("D:\\TCE\\private.key");
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte [] plain = new byte[100];
        byte[] decryptedTextArray = cipher.doFinal(cipherTextArray);
        return new String(decryptedTextArray);    
    } 
}

When we run the code we getting below Error. Can someone help to resolve this?

Exception in thread "main" javax.crypto.BadPaddingException: Decryption error
at sun.security.rsa.RSAPadding.unpadV15(Unknown Source)
at sun.security.rsa.RSAPadding.unpad(Unknown Source)
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 RSAcrypto.RsaToy.decrypt(RsaToy.java:108)
at RSAcrypto.RsaToy.main(RsaToy.java:34)

答案1

得分: 3

我发现了以下问题:

  • readKeyFromFile() 函数中,检查传递的文件路径是否以 public 开头。如果是,则生成公钥。但这只在路径只包含文件名的情况下有效,而通常并非如此。例如,在当前代码中使用了路径 D:\\TCE\\public.key。为了解决这个问题,最好使用 new File(keyFileName).getName().startsWith("public") 替代 keyFileName.startsWith("public")

  • encrypt()decrypt() 中传递给 readKeyFromFile() 的文件路径 fileName 应该被转发。然而实际上传递的是硬编码的路径 D:\\TCE\\public.key。这可能仅为了测试目的而更改。

通过这些改变,只要密钥以适当的格式使用,代码在我的机器上能够工作。这种格式不是像 PKCS#8、PKCS#1 或 X.508 这些典型格式之一,而是(作为 BigInteger)序列化的模数和指数(根据密钥类型是公钥还是私钥),因此两者都可以用 ObjectInputStream 进行读取。以这种格式存储密钥的一种方法是使用 ObjectOutputStream 序列化模数和指数(作为 BigInteger)。

还请注意,在某些地方进行编码(例如 plainText.getBytes())和解码(例如 new String(decryptedTextArray))时,没有指定字符集,因此会使用(与环境相关的)默认字符集(如果在不同的环境中执行加密和解密,则可能会导致问题)。

英文:

I' ve found the following problems:

  • In readKeyFromFile() it is checked whether the passed file path starts with public. If so, the public key is generated. This only works if the path consists only of the file name, which is generally not the case, e.g. in the current code the path D:\\TCE\\public.key is used. To solve this problem it would be better to apply new File(keyFileName).getName().startsWith("public") instead of keyFileName.startsWith("public").

  • The file path fileName passed in encrypt() and decrypt() should be forwarded to readKeyFromFile(). Instead the hard coded path D:\\TCE\\public.key is passed. This may have been changed for test purposes only.

With these changes, the code works on my machine as long as keys are used in an appropriate format. This is not one of the typical formats like PKCS#8, PKCS#1 or X.508, but the (as BigInteger) serialized modulus and exponent (public or private depending on the key type), so that both can be read with ObjectInputStream. One way to store a key in this format is to serialize the modulus and exponent (as BigInteger) with ObjectOutputStream.

Please also note that in some places encoding (e.g. plainText.getBytes()) and decoding (e.g. new String(decryptedTextArray)) is done without specifying a character set, so that the (environment dependent) default character set is used (which can cause problems if encryption and decryption are performed in different environments).

huangapple
  • 本文由 发表于 2020年9月10日 12:35:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/63822890.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定