在安卓上使用 RSA 算法加密了一个字符串,然后 Base64 了一下;
在 Mac 上使用 Java 先转码再解密这个加密后转码的字符串,遇到了如下错误:
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:363)
at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:389)
at javax.crypto.Cipher.doFinal(Cipher.java:2165)
at RSAUtils.decryptData(RSAUtils.java:97)
at Decrypt.main(Decrypt.java:62)
其中,加密使用的模块如下:
public static byte[] encryptData(byte[] data, PublicKey publicKey) {
try {
Cipher cipher = Cipher.getInstance(RSA);
// 编码前设定编码方式及密钥
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
// 传入编码数据并返回编码结果
return cipher.doFinal(data);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
解密使用的模块如下:
public static byte[] decryptData(byte[] encryptedData, PrivateKey privateKey) {
try {
Cipher cipher = Cipher.getInstance(RSA);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(encryptedData);
} catch (Exception e) {
e.printStackTrace();
//System.out.println(e.printStackTrace());
return null;
}
}
解密过程使用了 BC 模块来读取 pem 格式( pkcs8 )的私钥文件(加解密过程中均使用了同一模块进行 Base64 操作),调用解密的代码如下:
KeyFactory factory = KeyFactory.getInstance("RSA", "BC");
PrivateKey privateKey = generatePrivateKey(factory, "private_key.pem");
String encryptContent = "xxxxx";
byte[] decryptByte = RSAUtils.decryptData(Base64Utils.decode(encryptContent), privateKey);
String decryptStr = new String(decryptByte);
System.out.println(decryptStr);
已经谷歌了一下,但是没有找到合适的办法,不知哪位有接触过这个,希望不吝赐教,感谢。
1
ipeony 2017-09-04 17:16:50 +08:00 1
试了下这样可以的,看有没有帮助
<script src="https://gist.github.com/dongfg/cba825a96a416924698b6be02b34c054.js"></script> |
2
linuxchild OP @ipeony 先感谢,回头试一下看看行不行
|
3
linuxchild OP |
4
ipeony 2017-09-07 14:31:53 +08:00
@linuxchild #3 我试了下用 BC 读也是可以的,你的密钥对怎么生成的
|
5
linuxchild OP |
6
ipeony 2017-09-07 20:09:06 +08:00
@linuxchild #5 我没看出问题~感觉跟 BC 那个关系不大,可能是公钥私钥格式上的问题,我理解也不深
这是我生成密钥对的命令 ---- openssl genrsa -out key_private.pem 4096 openssl rsa -pubout -in key_private.pem -out key_public.pem openssl pkcs8 -topk8 -in key_private.pem -inform pem -outform pem -out key_private_pkcs8.pem -nocrypt ---- String privateKeyStr = FileUtils.readFileToString(new File("key_private_pkcs8.pem"), UTF_8); String publicKeyStr = FileUtils.readFileToString(new File("key_public.pem"), UTF_8); privateKeyStr = privateKeyStr.replaceAll("\\n", "").replace("-----BEGIN PRIVATE KEY-----", "").replace("-----END PRIVATE KEY-----", ""); publicKeyStr = publicKeyStr.replaceAll("\\n", "").replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLIC KEY-----", ""); if (Security.getProvider("BC") == null) { Security.addProvider(new BouncyCastleProvider()); } KeyFactory kf = KeyFactory.getInstance("RSA","BC"); PKCS8EncodedKeySpec keySpecPKCS8 = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyStr)); PrivateKey privateKey = kf.generatePrivate(keySpecPKCS8); X509EncodedKeySpec keySpecX509 = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyStr)); RSAPublicKey publicKey = (RSAPublicKey) kf.generatePublic(keySpecX509); System.out.println(publicKey.getFormat()); System.out.println(privateKey.getFormat()); String rawString = "aaa"; byte[] encryptData = encryptData(rawString.getBytes(), publicKey); byte[] decryptData = decryptData(encryptData, privateKey); Assert.assertNotNull(decryptData); String decryptString = new String(decryptData); Assert.assertEquals(rawString, decryptString); |
7
linuxchild OP @ipeony
感谢给这么详细耐心的回复。 试了一下这段代码,用的自己的私钥和公钥,一串明文进行加解密没问题。 但是如果用这段代码去解密之前的密文就出现所述的问题了… 另外,我之前用 Python 试过,同样的密文,同样的密钥,就可以解出来,擦 我看看再找个人问一下,等解决了告诉你一下。 再次感谢 |
8
linuxchild OP @ipeony
hello,问题解决了,是将解密的代码改动了一行: ``` public static byte[] decryptData(byte[] encryptedData, PrivateKey privateKey) { try { Cipher cipher = Cipher.getInstance(RSA, new org.bouncycastle.jce.provider.BouncyCastleProvider()); cipher.init(Cipher.DECRYPT_MODE, privateKey); return cipher.doFinal(encryptedData); } catch (Exception e) { e.printStackTrace(); //System.out.println(e.printStackTrace()); return null; } } ``` 前提是把 bc 包引入,我使用动办法是 > 1. edit jre\lib\security\java.security > add security.provider.10=org.bouncycastle.jce.provider.BouncyCastleProvider > 2. copy bc*.jar to jre\lib\ext 摘自: https://stackoverflow.com/questions/13721579/jce-cannot-authenticate-the-provider-bc-in-java-swing-application 然后再进行解密就可以了。 至于原因,我猜测在加密动时候可能就使用了这个模块。 |
9
ipeony 2017-09-08 17:00:23 +08:00
@linuxchild #8 学习了
|