2017-06-21 107 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