简体   繁体   English

BadPaddingException RSA加密,然后在Java中解密

[英]BadPaddingException RSA Encrypt then decrypt in java

I have been given an RSA public Key and an RSA private key with OAEP SHA-256 padding. 我获得了带有OAEP SHA-256填充的RSA公钥和RSA私钥。 I am attempting to simply encrypt a random string and then decrypt it to assert the result is equalt to the original. 我试图简单地加密一个随机字符串,然后解密它以断言结果等于原始字符串。

This is the public key i have been given: 这是我得到的公钥:

-----BEGIN RSA PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq8tiBtDmkeS/ruY3rrkq
dz6Lc6XWFRbI/GjPtIokrtpM+Ujyv6wX8TBqY8e03gzh+eE7VUyEVPapDnceAqgJ
ZQah2h+N5AEQKqNDM4/1to1V0F+m1ISR7CIUU8dvU+bPk67DU5VkEtLxf+mW8/es
hy0u6oSB04WCDPNnh+9GDF7tN7lOzBH1FxKPWIb5Gqg6GoXS+KgvQhYEk0TajIBk
+mefzTv1D4HJlhFYybgY+/p3k4P2kM5HnbEtoVpz/PL9+94YVp5RBHTQHmk/3SAX
RkPP34IjY6LZqTJGWQGxc64Qci54ZJsq4wSTXvfdHgUWz7eX+v1jA+GLjFExNcYZ
nQIDAQAB
-----END RSA PUBLIC KEY-----

This is the private key I have been given: 这是我得到的私钥:

-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDAUQiHdHuMBCnF
P/7RQoRWrp62dGWQLDLP9l+3KUMlSPheN2R5jHDZ/WEGJGF2WYKxaQvv5XCocdnt
uxVZTNM1PVyduokJaJzrSIj+jGWDd4hTWvVoS3vhds8u6W0jD3M4ayrF6c7NYuHc
tE5YLLIgK1DTn+ZZCr3VGbScISDJ/WPx3+1YTNQDvm+T7MfjhetJqqzWIsunMUiw
nQOQvkdjCVWpk+L10SaMrezixtIS5wfpOTjGIZ0w5VunvtsPxg1TkuvGURa9S3rS
7D3uhDPY+V8UDMpBPso3j7TGD5axlBJcpavWeF8qde3sWztmqUFQ3JDypZWGSAe2
d8e4mY65AgMBAAECggEAal8nwYxbHZnb5L892U7aVfuly7Nbzb+0pzRVwsBu5DuV
LL+kslpMvTYZqUUMJ2LhF/HLaXhVtMWsTYLSDx+gHu1+wbtAOtUDHlxzcaAEMhA2
dix0WqiNr6qAdCkmdWMBTu5vrSJigVW1KdcNElY+e+6ZeUQTK6L2Vt0t+cGVGkM4
K5PdHcGLR1BiAf3k4BguHE4TGGnqN9dF5Rn9nPP6C7QihWzGn15efD2dAXn3Kbho
dMIRgyYiO7uXPm2LrIjtldYb8tPus+V9SWT4hcgnJZrtd9atkqZrJ3dhQf9ZetGs
UwTCzHJ169NNbVyrjCbcy4Uht8Na+t/94Im9hI8n0QKBgQDO6tYnwh1hPg3E+4DY
xCiDAp7v3afJIvC9a1sBtif8KkzZTYH31ww+PRcfDPQUlk/MIDie0u6xIawnBYkC
oN1u9erojcvQbBP0GFylP5hNxYZbI7gPA/7AiGRxyezZPOiVMwdd5fCM7Wv4kucr
c1JCcvtPoDQcFFZOfI+wqqdWnQKBgQDt745Pvckt7/XL7wbfv4BV+cwpLNjc4/3k
ajOLtasgpT8mc0gUH2ejHhpkuhjSUpSTrlFB8EN1kAwmBYy0GOoO9967hm6twmqk
Q5L3OHJ96pYkf1rbyXNE1N7inh5Z3M1H5ONIaliAYLHXOzKsZvI5eUdKAJdSqFLo
uvVCwr4PzQKBgG6W3rzDJ9a4Rr24OgYg2RIkTXQgALQko4xpm2tPwxEoPoiJv2QK
ILYHCpuC3dU+/Qk5U2m3jPFI8OyuLask9RSABPwkBQGxMfztJF8BnVI7tvJxJceI
uBiJDT4v0RHOVvSfIFnUMnvvzRw+z6TObvGq6JyHIDK9v98U/etLWkKVAoGAIIxF
lmjqzUrm/8ep1A+5OYmbQQKug8D4aTeR54mpaCTSt6rLcF0/axPiHmdKn/LF+lG9
MdzxDXLwBn952OUTl4qWwGZKW6Cdv+yyfPkOyGS/tyxovGoZR5ArESr6Eebfefc4
lB5gDuerTDr/2o+WkQAjHV9pU9hMxyNUC5biMv0CgYEAiDlw8lBf3cQs6FxNXs9t
whWpfL0yY7WAONvhfFB0Dpsz52gGDCYRvJekGRz6jOlKDuXJ+Mm1AX4BaufMETI5
QseZxtVPIn+BXm0A1x8w/DifmE1JqQZmPCQPOh3eLx5nSn9LKGIbMgd17mfH3HhU
8WX2mzWjmRA3C/CzdGfCKSk=
-----END PRIVATE KEY-----

I am reading this key from a pem file "crypt_pkcs8.pem" but recive the public key as a byte array from a gRPC call. 我正在从pem文件“ crypt_pkcs8.pem”中读取此密钥,但是从gRPC调用中将公共密钥作为字节数组接收。

Here is my Java code: 这是我的Java代码:

public class Encryption{
public static void main(String args){
    ByteString publicKey = client.getPublicKey(nonce).getRSAEncryptionKey();

    String strKeyPEM = "";
    BufferedReader br = new BufferedReader(new FileReader("crypt_pkcs8.pem"));
    String line;
    while ((line = br.readLine()) != null) {
        strKeyPEM += line+"\n";
    }
    br.close();
    byte[] pt;
    try {
        pt = "h".getBytes("UTF-8");
        byte[] ct =encrypt(publicKey, pt);
        byte[] response= decrypt(strKeyPEM, ct);

        assertEquals(pt, response);
    } catch (UnsupportedEncodingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
public static byte[] encrypt(ByteString rawKey ,byte[] message){
    String strippedKey=stripKey(rawKey.toStringUtf8());

    byte[] keyBytes = Base64.getDecoder().decode(strippedKey);
    System.out.println(keyBytes.length);

    Cipher cipher_RSA;
    try {
        cipher_RSA = Cipher.getInstance("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING");
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
        PublicKey pk = keyFactory.generatePublic(spec);
        System.out.println(pk.getAlgorithm()+" format : "+pk.getFormat());

        cipher_RSA.init(Cipher.ENCRYPT_MODE, pk); 
        return cipher_RSA.doFinal(message);
    } catch (NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException |
            BadPaddingException | InvalidKeyException | InvalidKeySpecException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        return null;
    }

}

public static byte[] decrypt(String rawKey ,byte[] message){
    String strippedKey=stripPrivateKey(rawKey);

    byte[] keyBytes = Base64.getDecoder().decode(strippedKey);
    System.out.println(keyBytes.length);

    Cipher cipher_RSA;
    try {
        cipher_RSA = Cipher.getInstance("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING");
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
        PrivateKey pk = keyFactory.generatePrivate(spec);
        System.out.println(pk.getAlgorithm()+" format : "+pk.getFormat());

        cipher_RSA.init(Cipher.DECRYPT_MODE, pk); 
        return cipher_RSA.doFinal(message);
    } catch (NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException |
            BadPaddingException | InvalidKeyException | InvalidKeySpecException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        return null;
    }
}
public static String stripKey(String key){
    key = key.replace("-----BEGIN RSA PUBLIC KEY-----\n", "");
    key = key.replace("-----END RSA PUBLIC KEY-----", "");
    key = key.replace("\n", "");
    return key;
}

public static String stripPrivateKey(String key){
    key = key.replace("-----BEGIN PRIVATE KEY-----", "");
    key = key.replace("-----END PRIVATE KEY-----", "");
    key = key.replace("\n", "");
    return key;
}


}

I cannot find anything obviously wrong with my actaul code so I believe this is to do with the keys not matching. 我找不到我的actaul代码有任何明显错误的内容,因此我相信这与键不匹配有关。

I also notice the header/footer is different on the public key and private key. 我还注意到公钥和私钥的页眉/页脚不同。 From looking online this is because the public key is in PKCS#8 format. 从网上看这是因为公共密钥是PKCS#8格式。

Will I need to change the public key to pkcs#8 format as well? 我是否还需要将公钥更改为pkcs#8格式? If so what is the easiest way to do this? 如果是这样,最简单的方法是什么?

I have also been told I should be able to extract the public key (in pkcs8 format) from the private key given above. 我还被告知我应该能够从上面给出的私钥中提取公钥(以pkcs8格式)。 Can this be done easily? 能容易做到吗?

If you can get a valid public key then the key is not in PKCS#8 format, it will be in X.509 (SubjectPublicKeyInfo) format as Java expects. 如果您可以获取有效的公共密钥,则该密钥不是PKCS#8格式的,而是Java期望的X.509(SubjectPublicKeyInfo)格式。 However, your public and private keys do indeed not match. 但是,您的公钥和私钥确实匹配。 You can use the answer here to create the correct public key file from the private key file. 您可以在此处使用答案以根据私钥文件创建正确的公钥文件。


Java doesn't directly contain code to retrieve the public exponent from an RSAPrivateKey without CRT parameters. Java没有直接包含RSAPrivateKey带CRT参数的RSAPrivateKey检索公共指数的代码。 However, if you want a Java only solution you could cast the PrivateKey even further to RSAPrivateCrtKey which does contain a getPublicExponent method to retrieve the public exponent. 但是,如果您只希望使用Java解决方案,则可以将PrivateKey进一步转换为RSAPrivateCrtKey ,后者确实包含用于检索公共指数的getPublicExponent方法。 Then you can use an RSA KeyFactory to generate a public key using RSAPublicKeySpec . 然后,您可以使用RSA KeyFactory通过RSAPublicKeySpec生成公共密钥。


You could also parse the PEM file to retrieve the public key in Java using eg the Bouncy Castle API. 您也可以使用例如Bouncy Castle API来解析PEM文件以检索Java中的公钥。 But expect a steep learning curve if you do. 但是如果您愿意的话,可以期望学习曲线陡峭。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM