I'm trying to get certificates and private keys from windows certificate store using MSCAPI provider, then i need to store them in a Java Keystore object, but i'm facing a problem of private keys format, the error says:
java.security.KeyStoreException: Cannot get key bytes, not PKCS#8 encoded
Here's my code:
SunMSCAPI providerMSCAPI = new SunMSCAPI();
Security.addProvider(providerMSCAPI);
KeyStore ks = KeyStore.getInstance("Windows-MY");
ks.load(null, null);
PrivateKey privateKey = null;
X509Certificate cert = null;
cert = (X509Certificate) ks.getCertificate("ALIAS");
if (ks.isKeyEntry("ALIAS")) {
privateKey = (PrivateKey) ks.getKey("ALIAS", null);
}
KeyStore newKs = null;
...
...
newKs .setKeyEntry("pvKey", privateKey , "pwd".toCharArray(), certifChain);
Also, the privateKey.getEncoded()
returns null.
I have exactly the same issue when programatically importing a pfx file into the windows certificate store and then attempting to read this certificate and key again later. I believe the answer lies in http://www.oracle.com/technetwork/articles/javase/security-137537.html and I quote: "...the resulting PKCS#12 keystore may not be imported into applications that use only a single password for the keystore and all its key entries". Earlier in the document it also states: "Note that keys produced by the SunMSCAPI provider are wrapper objects for the native handles. Thus, they may not be accepted by other providers and may behave somewhat differently than keys produced by pure-Java providers, such as SunJCE. In particular, the RSA private keys generated by the SunMSCAPI provider cannot be serialised". Upon trying to read the private key results in null algorithm and null encoded data as you note above, though reading the certificate works fine. Alternatively you could save the PrivateKey in a separate RSA encrypted file instead of the windows certificate store or just work of the original pfx file instead of importing the pfx into the windows certificate store.
I use command such like:
Runtime.getRuntime().exec("openssl pkcs8 -topk8 -nocrypt -in "+ privateKeyPath + " -out " + pkcs8PrivateKeyPath)