Чтение ECPrivateKey из JKS KeyStore

Я пытаюсь прочитать ECPrivateKey (включая цепочку сертификатов) из хранилища ключей JKS, как показано в приведенном ниже коде.

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 KeyStore не проходит через список поставщиков безопасности. Однако это прекрасно работает для других типов KeyStore, поддерживаемых BC: PKCS12 и BKS. Есть ли способ использовать JKS в качестве типа KeyStore при использовании BC для восстановления ключа?

Метод 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;
}

person martijno    schedule 28.12.2012    source источник
comment
Я даже не могу пройти мимо keyPairGenerator.initialize(jceParamSpec);, если не установлю BC на первое место.   -  person President James K. Polk    schedule 02.01.2013


Ответы (1)


Моей единственной мыслью было реализовать свой собственный Provider который может либо проксировать запрос «KeyFactory» к провайдеру BouncyCastle, а остальные — другому, который знает о JKS, либо проксировать все запросы к BouncyCastle, за исключением запроса «KeyStore». здесь документация о том, как реализовать провайдер.

person Staros    schedule 04.01.2013