Exception in thread "main" java.security.spec.InvalidKeySpecException: Only RSAPublicKeySpec and X509EncodedKeySpec supported for RSA public keys
at sun.security.rsa.RSAKeyFactory.generatePublic(RSAKeyFactory.java:306)
at sun.security.rsa.RSAKeyFactory.engineGeneratePublic(RSAKeyFactory.java:201)
at java.security.KeyFactory.generatePublic(KeyFactory.java:334)
at com.asymmetric.rsa.TestRSA.testDecrypt(TestRSA.java:77)
at com.asymmetric.rsa.TestRSA.main(TestRSA.java:32)
at sun.security.rsa.RSAKeyFactory.generatePublic(RSAKeyFactory.java:306)
at sun.security.rsa.RSAKeyFactory.engineGeneratePublic(RSAKeyFactory.java:201)
at java.security.KeyFactory.generatePublic(KeyFactory.java:334)
at com.asymmetric.rsa.TestRSA.testDecrypt(TestRSA.java:77)
at com.asymmetric.rsa.TestRSA.main(TestRSA.java:32)
一直不明白,为什么不能用PKCS8EncodedKeySpec 作RSA解密的格式,今天就尝试了一下,报错很明显是java底层 RSA公钥只支持X509EncodedKeySpec这种格式
测试代码:
package com.asymmetric.rsa; import java.security.InvalidKeyException; import java.security.Key; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.Base64; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; public class TestRSA { public static String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQgEoj3z9JrdPNI23DbMQkl3gkGuDke7iBr5yrYyqolkTyxuBLWFwHNuGv4VKOj9fXg61QxpaJ/fxDBvMvmkBSRowHBloGFceVTx8wV/8u0DcjvTCu0IZ1zp6wjG6xBn5j66Sg/q+9hvaY2p7fkKmsvcW6VoNPgQHU1Cf01DLZmQIDAQAB+oXcINOiE3AsuZ4VJmwNZg9Y/7fY+OFRS2JAh5YMsrv2qyoGP+Z9ksre26NYR+Lt91B2lhdwJHLpQpziaANZm/ONb31fj/lwIDAQAB"; public static String privateKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBANCASiPfP0mt080jbcNsxCSXeCQa4OR7uIGvnKtjKqiWRPLG4EtYXAc24a/hUo6P19eDrVDGlon9/EMG8y+aQFJGjAcGWgYVx5VPHzBX/y7QNyO9MK7QhnXOnrCMbrEGfmPrpKD+r72G9pjant+Qqay9xbpWg0+BAdTUJ/TUMtmZAgMBAAECgYBSozY/Z4FW+31h5fPgK+DFu/8TGFAgXuTvCaJnz2Md9IkZTDejxT6cYWUr53toI5zhvz/XLw6FXNQ54KxMJq/s9PiZYUgq/PMrnyU4gBSTm5BmiWjdaGicVEZ1lofHjpkAchPNW/CzwxD8AeKI7QaObE+EkWbLAi6sa+nRdHKgrQJBAOwYLD2DncU15XCKS0RNzTrNohdBQcisOPHdtQO0CGZlxx3xjuU4WL6/EpdmbjTeYbOSDKCmY5vyVbYZdOWfEs8CQQDiFIwWpvW2WLxLVw3i2P55WmMMXuecwEzg++ae3Ht7nW0zNcWSsyvHh40sM8XqEzmWOzMY6JOePbkuVfWTc4cXAkBRzf5mQhiEoKwjVofF3v9hhKbJT/8vPR1uENgLtHHEqTdZFL3ihqeZUDNs6jz9bKCFy/E8KOsSueEg+6kZdwjZAkEAj2RW4fstd2VasDJb5ViaNqAEmJENOBej60L6KCJR07qqy0M8t+oaR2iLOtDvo6Jj8QxFQXQqRMCDVodAxjANKwJAL3KuaqA6kdy9RxdV3uP8nRXLY7C/1ZIK6U0pyZqKXEwpD+7Ar3hwwhPz9TeuoqjB/cCknZjw70BQFQ0/VUHW2g=="; private static String algorithm = "RSA"; //$NON-NLS-1$ private static String data = "这是一个test"; //$NON-NLS-1$ public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException { byte[] test = testEncrypt(privateKey,data); String testDecrypt = testDecrypt(publicKey, test); System.out.println(testDecrypt); } /** * 加密 * @param key * @param data * @return * @throws NoSuchAlgorithmException * @throws InvalidKeySpecException * @throws NoSuchPaddingException * @throws IllegalBlockSizeException * @throws BadPaddingException * @throws InvalidKeyException */ public static byte[] testEncrypt(String key,String data) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException{ byte[] decode = Base64.getDecoder().decode(key); PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(decode); KeyFactory kf = KeyFactory.getInstance(algorithm); PrivateKey generatePrivate = kf.generatePrivate(pkcs8EncodedKeySpec); Cipher ci = Cipher.getInstance(algorithm); ci.init(1, generatePrivate); byte[] doFinal = ci.doFinal(data.getBytes()); // return Base64.getEncoder().encodeToString(doFinal); return doFinal; } /** * 解密 * @param key * @param data * @return * @throws NoSuchAlgorithmException * @throws InvalidKeyException * @throws NoSuchPaddingException * @throws InvalidKeySpecException * @throws BadPaddingException * @throws IllegalBlockSizeException */ public static String testDecrypt(String key,byte[] data) throws NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, InvalidKeySpecException, IllegalBlockSizeException, BadPaddingException{ byte[] decode = Base64.getDecoder().decode(key); PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(decode); //java底层 RSA公钥只支持X509EncodedKeySpec这种格式 //X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(decode); KeyFactory kf = KeyFactory.getInstance(algorithm); PublicKey generatePublic = kf.generatePublic(pkcs8EncodedKeySpec); Cipher ci = Cipher.getInstance(algorithm); ci.init(1,generatePublic); // byte[] doFinal = ci.doFinal(Base64.getDecoder().decode(data)); byte[] doFinal = ci.doFinal(Base64.getDecoder().decode(data)); return Base64.getEncoder().encodeToString(doFinal); } }
解决方法:
将解密时的PKCS8EncodedKeySpec 转换成X509EncodedKeySpec 就可以了,其实rsa公钥也支持RSAPublicKeySpec 但是构造方法不同,没有直接传入字节数组的构造