java - 如何使用SubjectPublicKeyInfo加密数据?

标签 java encryption rsa bouncycastle

我对 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/

相关文章:

java - 调整按钮上背景图像的大小

java - 连接playframework和mysql(数据没有添加到表中)

javascript - 如何检查 AJAX 请求的真实性

javascript - 使用 OpenSSL 在 Ruby 中编码和字节错误?

c++ - 使用 Crypto++ 进行原始 RSA 加密和解密

Java : Rounding a decimal value to HALF_EVEN

mysql - 将加密数据从MYSQL服务器迁移到Sql服务器

java - APDU 命令中的负数

python - 使用扩展欧几里德算法创建 RSA 私钥

java - 为什么这些 Java 类名必须在 Clojure 中完全限定?