我对 RSA 比较陌生,并且使用 BC 从公钥中获取SubjectPublicKeyInfo。
String key = "-----BEGIN RSA PUBLIC KEY-----\n" +
"........\n" +// Multiple lines here
"-----END RSA PUBLIC KEY-----\n";
Security.addProvider(new BouncyCastleProvider());
PEMParser reader = new PEMParser(new StringReader(key));
SubjectPublicKeyInfo subjectPublicKeyInfo = (SubjectPublicKeyInfo) reader.readObject();
然后我想要加密数据。我发现有人使用 RSAEngine 来做到这一点:
AsymmetricKeyParameter aKey = (RSAKeyParameters) PublicKeyFactory.createKey(subjectPublicKeyInfo);
AsymmetricBlockCipher engine = new RSAEngine();
engine.init(false, aKey);
byte[] dataEncrypted = engine.processBlock(data, 0, data.length);
运行这些代码后,我发现结果与预期不符。 所以我想知道我的代码是否有错误?
最佳答案
我终于找到了出路。
如果有人熟悉 BouncyCaSTLe
,他可以指出我的低级错误。
首先,要加密数据,应在 init
函数中首先将 Engine
参数设置为 true。
其次,我的公钥以“-----BEGIN RSA PUBLIC KEY-----”开头。它是 PKCS#1 格式的 RSA 公钥,应使用 BouncyCaSTLe
读入,但加密数据应具有 padding
。因此,我不应该直接使用 RSAEngine
,而是使用 PKCS1Encoding
。
最后贴出我的加密代码和解密代码:
加密:
Security.addProvider(new BouncyCastleProvider());
PEMParser reader = new PEMParser(new StringReader(key));
SubjectPublicKeyInfo subjectPublicKeyInfo = (SubjectPublicKeyInfo) reader.readObject();
RSAKeyParameters rsaKeyParameters = (RSAKeyParameters)
PublicKeyFactory.createKey(subjectPublicKeyInfo);
PKCS1Encoding engine = new PKCS1Encoding(new RSAEngine());
engine.init(true, rsaKeyParameters);
return engine.processBlock(data, 0, data.length);
解密:
public static byte[] decryptByPublicKey(String data, String key) throws Exception {
byte[] rawData = Base64.decode(data);
Security.addProvider(new BouncyCastleProvider());
PEMParser reader = new PEMParser(new StringReader(key));
PEMKeyPair pemKeyPair = (PEMKeyPair) reader.readObject();
SubjectPublicKeyInfo publicKeyInfo = pemKeyPair.getPublicKeyInfo();
PrivateKeyInfo privateKeyInfo = pemKeyPair.getPrivateKeyInfo();
RSAKeyParameters rsaKeyParameters = (RSAKeyParameters)
PrivateKeyFactory.createKey(privateKeyInfo);
PKCS1Encoding engine = new PKCS1Encoding(new RSAEngine());
engine.init(false, rsaKeyParameters);
return engine.processBlock(rawData, 0, rawData.length);
}
对于加密,您可以使用模数和公共(public)指数来创建 JDK 支持的 key :
Security.addProvider(new BouncyCastleProvider());
PEMParser reader = new PEMParser(new StringReader(key));
PemObject obj = reader.readPemObject();
org.bouncycastle.asn1.pkcs.RSAPublicKey rsaPublicKey = org.bouncycastle.asn1.pkcs.RSAPublicKey.getInstance(obj.getContent());
BigInteger modulus = rsaPublicKey.getModulus();
BigInteger publicExponent = rsaPublicKey.getPublicExponent();
KeyFactory keyFactory = KeyFactory.getInstance("RSA", "BC");
RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(modulus, publicExponent);
PublicKey pubKey = keyFactory.generatePublic(pubKeySpec);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "BC");//This line should use right padding.For PKCS#1 format RSA key , it should be this.
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
return cipher.doFinal(data);
另请参阅:Basic RSA example.
关于java - 如何使用SubjectPublicKeyInfo加密数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27517883/