2017-06-21 108 views
5

一个专用密钥鉴于这种.pem文件(与OpenSSL的生成,并用密码加密):获得来自RSA的.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,但我不知道怎么办。我尝试了this answerthis other answer中的方法,但它们在解析字节数组时都会导致错误。

回答

5

我使用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)。

4

使用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()); 
} 
+0

嗨,借助上述方法从密码保护的pfx文件读取私钥时获取NPE。 – mahi