从RSA .pem文件中获取私钥

7
给定这个使用openssl生成并加密密码的.pem文件:
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,AC009672952033EB

2wegzxf3MtncXS1CY3c.....
....
....
-----END RSA PRIVATE KEY-----

如何在Java中获取一个PrivateKey对象?我编写了以下代码,但是我找不到正确的方法来获取KeySpec

PrivateKey readFromPem(File keyFile, String password){
    PemReader r = new PemReader(new InputStreamReader(new FileInputStream(keyFile)));
    PemObject pemObject = r.readPemObject();
    byte[] encodedKey = pemObject.getContent();

    KeySpec keySpec = ???? // how to get this?

    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    PrivateKey key = keyFactory.generatePrivate(keySpec);
    return key;
}

我想我应该构建一个RSAPrivateKeySpec,但我不知道怎么做。 我尝试了这个答案这个其他答案中的方法,但在解析字节数组时都会导致错误。

2个回答

7
我正在使用BouncyCastle 1.57(bcprov-jdk15on、bcmail-jdk15on和bcpkix-jdk15on)和Java 7
您可以使用JcaPEMKeyConverter类读取私钥。下面的代码适用于有密码和无密码的密钥:
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMDecryptorProvider;
import org.bouncycastle.openssl.PEMEncryptedKeyPair;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder;

// don't forget to add the provider
Security.addProvider(new BouncyCastleProvider());
String password = "your password";

// reads your key file
PEMParser pemParser = new PEMParser(new FileReader(keyFile));
Object object = pemParser.readObject();
JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");

KeyPair kp;
if (object instanceof PEMEncryptedKeyPair) {
    // Encrypted key - we will use provided password
    PEMEncryptedKeyPair ckp = (PEMEncryptedKeyPair) object;
    // uses the password to decrypt the key
    PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder().build(password.toCharArray());
    kp = converter.getKeyPair(ckp.decryptKeyPair(decProv));
} else {
    // Unencrypted key - no password needed
    PEMKeyPair ukp = (PEMKeyPair) object;
    kp = converter.getKeyPair(ukp);
}

// RSA
KeyFactory keyFac = KeyFactory.getInstance("RSA");
RSAPrivateCrtKeySpec privateKey = keyFac.getKeySpec(kp.getPrivate(), RSAPrivateCrtKeySpec.class);

System.out.println(privateKey.getClass());

privateKey的类将是java.security.spec.RSAPrivateCrtKeySpec(它继承自RSAPrivateKeySpec)。


1
PEMKeyPair ukp = (PEMKeyPair) object; 在没有密码的情况下抛出错误:org.bouncycastle.asn1.pkcs.PrivateKeyInfo 无法转换为 org.bouncycastle.openssl.PEMKeyPair。使用版本1.60。 - Sasha Bond
如果你想要PKCS#1编码的私钥,那么上面的答案会给你PKCS#8编码的私钥。请按照这个答案操作 - https://dev59.com/LVXTa4cB1Zd3GeqPyh5u#39363008 - Anurag_BEHS

6
使用Bouncy Castle的bcpkix依赖项,它知道如何处理OpenSSL密钥。
<dependency>
  <groupId>org.bouncycastle</groupId>
  <artifactId>bcpkix-jdk14</artifactId>
  <version>1.57</version>
</dependency>

然后像这样尝试:

private PrivateKey readFromPem(File keyFile, String password) throws IOException {
    Security.addProvider(new BouncyCastleProvider());

    PEMParser pemParser = new PEMParser(new InputStreamReader(new FileInputStream(keyFile)));
    PEMEncryptedKeyPair encryptedKeyPair = (PEMEncryptedKeyPair) pemParser.readObject();
    PEMDecryptorProvider decryptorProvider = new JcePEMDecryptorProviderBuilder().build(password.toCharArray());
    PEMKeyPair pemKeyPair = encryptedKeyPair.decryptKeyPair(decryptorProvider);

    JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
    return converter.getPrivateKey(pemKeyPair.getPrivateKeyInfo());
}

嗨,使用上述方法从受密码保护的pfx文件中读取私钥时遇到了NPE错误。 - mahi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接