java javax.crypto.BadPaddingException:解密错误

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/41872614/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 06:12:35  来源:igfitidea点击:

javax.crypto.BadPaddingException: Decryption error

javaencryptioncryptographyrsa

提问by jenny kenith

Here is the error I have got when run my Encode & Decode Class.

这是我在运行编码和解码类时遇到的错误。

javax.crypto.BadPaddingException: Decryption error
    at sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:380)
    at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:291)
    at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:365)
    at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:391)
    at javax.crypto.Cipher.doFinal(Cipher.java:2087)
    at RSAEncDecDemo.decryptData(RSAEncDecDemo.java:64)
    at RSAEncDecDemo.main(RSAEncDecDemo.java:47)
java.lang.NullPointerException
    at java.lang.String.<init>(String.java:556)
    at RSAEncDecDemo.decryptData(RSAEncDecDemo.java:70)
    at RSAEncDecDemo.main(RSAEncDecDemo.java:47)

Here is the source code of RSAEncDecDemo.java class file.

这里是 RSAEncDecDemo.java 类文件的源代码。

public class RSAEncDecDemo {

    private static final String PUBLIC_KEY_FILE = "lk.public.key";
    private static final String PRIVATE_KEY_FILE = "lk.private.key";

    @SuppressWarnings("restriction")
    public static void main(String[] args) throws IOException {

        try {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            keyPairGenerator.initialize(2048);
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
            PublicKey publicKey = keyPair.getPublic();
            PrivateKey privateKey = keyPair.getPrivate();

            writeStringkey(PUBLIC_KEY_FILE,new BASE64Encoder().encode(publicKey.getEncoded()));
            writeStringkey(PRIVATE_KEY_FILE,new BASE64Encoder().encode(privateKey.getEncoded()));

            String demoString = "123346"; 
            RSAEncDecDemo rsa = new RSAEncDecDemo();
            String decrypted = rsa.decryptData(demoString);
            String msisdn = decrypted.substring(0,decrypted.indexOf("|"));

        } catch (Exception e) {
            e.printStackTrace();

        }
    }

    private String decryptData(String strData) throws IOException {
        byte[] data = DatatypeConverter.parseHexBinary(strData);
        byte[] descryptedData = null;

        try {
            PrivateKey privateKey = readPrivateKeyFromFile(PRIVATE_KEY_FILE);
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            descryptedData = cipher.doFinal(data);

        } catch (Exception e) {
            e.printStackTrace();
        }

        return new String(descryptedData);
    }


    @SuppressWarnings("restriction")
    public PrivateKey readPrivateKeyFromFile(String fileName)throws IOException, NoSuchAlgorithmException,InvalidKeySpecException {

        String publicK = readStringKey(fileName);
        byte[] keyBytes = new BASE64Decoder().decodeBuffer(publicK);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory fact = KeyFactory.getInstance("RSA");
        return fact.generatePrivate(keySpec);
    }

    public PrivateKey readPrivateKeyFromFileold(String fileName)throws IOException {
        FileInputStream fis = null;
        ObjectInputStream ois = null;
        try {
            fis = new FileInputStream(new File(fileName));
            ois = new ObjectInputStream(fis);

            BigInteger modulus = (BigInteger) ois.readObject();
            BigInteger exponent = (BigInteger) ois.readObject();

            RSAPrivateKeySpec rsaPrivateKeySpec = new RSAPrivateKeySpec(modulus, exponent);
            KeyFactory fact = KeyFactory.getInstance("RSA");
            PrivateKey privateKey = fact.generatePrivate(rsaPrivateKeySpec);

            return privateKey;

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (ois != null) {
                ois.close();
                if (fis != null) {
                    fis.close();
                }
            }
        }
        return null;
    }

    public static void writeStringkey(String fileName, String data) {
        try {
            FileWriter out = new FileWriter(new File(fileName));
            out.write(data);
            out.close();
        } catch (IOException e) {
        }
    }

    public static String readStringKey(String fileName) {

        BufferedReader reader = null;
        StringBuffer fileData = null;
        try {

            fileData = new StringBuffer(2048);
            reader = new BufferedReader(new FileReader(fileName));
            char[] buf = new char[1024];
            int numRead = 0;
            while ((numRead = reader.read(buf)) != -1) {
                String readData = String.valueOf(buf, 0, numRead);
                fileData.append(readData);
                buf = new char[1024];
            }

            reader.close();

        } catch (Exception e) {
        } finally {
            if (reader != null) {
                reader = null;
            }
        }
        return fileData.toString();

    }
}

Where is mistaken point.? Decryption part is give that error.
Whole class uploaded here LINK TO SOURCE CODE

错点在哪里。?解密部分给出了那个错误。
全班在这里上传 链接到源代码

-Thanks

-谢谢

回答by Maarten Bodewes

In principle a ciphertext should be indistinguishable from random. That said, ciphers do place constraints on the domain (size and possible values). In the case of RSA PKCS#1 - which is the default mode for "RSA" within the Oracle provider - the output must be precisely the key size (in bytes). Furthermore, the value must be smaller than the modulus.

原则上,密文应该与随机无法区分。也就是说,密码确实对域(大小和可能的值)施加了限制。在 RSA PKCS#1 的情况下 - 这是 Oracle 提供程序中“RSA”的默认模式 - 输出必须恰好是密钥大小(以字节为单位)。此外,该值必须小于模数。

Now assume that you've just shown us a demo value (because the exception doesn't match the input) and the size of the ciphertext is correct. In that case you would get an unpadding exception when either:

现在假设您刚刚向我们展示了一个演示值(因为异常与输入不匹配)并且密文的大小是正确的。在这种情况下,您将在以下任一情况下获得取消填充异常:

  • the private key doesn't match the public key used;
  • the wrong padding mode (e.g. OAEP) was used to create the ciphertext;
  • the ciphertext was altered (e.g. due to an invalid conversion to a string).
  • 私钥与使用的公钥不匹配;
  • 使用错误的填充模式(例如 OAEP)来创建密文;
  • 密文被更改(例如,由于向字符串的无效转换)。

You would have to try until you find the culprit, without the required information we cannot test this for you.

您必须尝试直到找到罪魁祸首,如果没有所需的信息,我们将无法为您测试。