I am trying to read an ECPrivateKey (including a certificate chain) from the JKS KeyStore, as shown in the code below.
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(); FileInputStream inputStream = new FileInputStream(storePath); KeyStore keyStore2 = KeyStore.getInstance(storeType); keyStore2.load(inputStream, storePass.toCharArray()); Key privateKey2 = keyStore2.getKey("eckey", storePass.toCharArray());
The curve I use is not supported by the Sun / Oracle security provider, so I use Bouncy Castle. BC is inserted at position 0 on my list of security providers. Storage works fine, reading fails:
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)
Apparently, the JKS KeyStore implementation does not go through the list of security providers. However, this works great for other types of KeyStore supported by BC: PKCS12 and BKS . Is there a way to use JKS as a KeyStore type when using BC to restore a key?
The createX509Certificate method used in the above code is defined:
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; }