2012-12-28 54 views
4

我試圖從JKS KeyStore讀回ECPrivateKey(包括證書鏈),如下面的代碼所示。從JKS KeyStore回讀ECPrivateKey

String storeType = "JKS", storePass = "secret", storePath = "c:/keystore.ks"; 
ECNamedCurveParameterSpec bcParamSpec = ECNamedCurveTable.getParameterSpec("brainpoolp224r1"); 
ECNamedCurveSpec jceParamSpec = new ECNamedCurveSpec(bcParamSpec.getName(), bcParamSpec.getCurve(), bcParamSpec.getG(), bcParamSpec.getN(), bcParamSpec.getH(), bcParamSpec.getSeed()); 

KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC"); 
keyPairGenerator.initialize(jceParamSpec); 
KeyPair keyPair = keyPairGenerator.generateKeyPair(); 
ECPublicKey publicKey = (ECPublicKey)keyPair.getPublic(); 
ECPrivateKey privateKey = (ECPrivateKey)keyPair.getPrivate(); 

Certificate trustCert = createX509Certificate("CN=CA", "CN=CA", publicKey, privateKey, "SHA224withECDSA"); 
Certificate[] chain = { createX509Certificate("CN=Client", "CN=CA", publicKey, privateKey, "SHA224withECDSA"), trustCert }; 

KeyStore keyStore = KeyStore.getInstance(storeType); 
keyStore.load(null, storePass.toCharArray()); 
keyStore.setKeyEntry("eckey", privateKey, storePass.toCharArray(), chain); 

FileOutputStream outputStream = new FileOutputStream(storePath); 
keyStore.store(outputStream, storePass.toCharArray()); 
outputStream.close(); 

/* Now read it back */ 
FileInputStream inputStream = new FileInputStream(storePath); 
KeyStore keyStore2 = KeyStore.getInstance(storeType); 
keyStore2.load(inputStream, storePass.toCharArray()); 

Key privateKey2 = keyStore2.getKey("eckey", storePass.toCharArray()); 

我使用的曲線不受Sun/Oracle安全提供程序支持,所以我使用Bouncy Castle。 BC在我的安全提供商列表中的0位插入。存儲工作正常,回讀失敗:

java.security.UnrecoverableKeyException: Unknown named curve: 1.3.36.3.3.2.8.1.1.5 
    at sun.security.provider.KeyProtector.recover(KeyProtector.java:338) 
at sun.security.provider.JavaKeyStore.engineGetKey(JavaKeyStore.java:138) 
at sun.security.provider.JavaKeyStore$JKS.engineGetKey(JavaKeyStore.java:55) 
at java.security.KeyStore.getKey(KeyStore.java:792) 

顯然,JKS密鑰庫實現通過安全提供者列表不循環。但是,對於BC支持的其他KeyStore類型,此工作正常:PKCS12BKS在使用BC恢復密鑰時,有沒有使用JKS作爲KeyStore類型的方法?

代碼中使用的createX509Certificate上述方法由下式給出:

private static X509Certificate createX509Certificate(String dn, String issuer, PublicKey publicKey, PrivateKey privateKey, String sigAlg) throws Exception { 
    X509V3CertificateGenerator certGenerator = new X509V3CertificateGenerator(); 
certGenerator.setSerialNumber(BigInteger.valueOf(Math.abs(new Random().nextLong()))); 
certGenerator.setIssuerDN(new X509Name(issuer)); 
    certGenerator.setSubjectDN(new X509Name(dn)); 
    certGenerator.setNotBefore(Calendar.getInstance().getTime()); 
certGenerator.setNotAfter(Calendar.getInstance().getTime()); 
certGenerator.setPublicKey(publicKey); 
certGenerator.setSignatureAlgorithm(sigAlg); 
X509Certificate certificate = (X509Certificate)certGenerator.generate(privateKey, "BC"); 
return certificate; 
} 
+0

我甚至不能通過'keyPairGenerator.initialize(jceParamSpec);',除非我在第一個位置安裝BC。 –

回答

2

我唯一的想法是,以實現自己的Provider是既可以代理「的KeyFactory」請求,BouncyCastle的供應商,其餘的另一個知道JKS或代理所有請求到BouncyCastle的「KeyStore」請求除外。 Here's關於如何實現提供者的文檔。

+0

謝謝。要麼,要麼將格式切換爲PKCS12。 – martijno