Below is my code for getting private key from Keystore file.
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
System.err.println(KeyStore.getDefaultType());
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(new FileInputStream("src/main/resources/xxx.jks"), PASSWORD);
String alias = "xxxxxxx";
PrivateKey pk = (PrivateKey) ks.getKey(alias, PASSWORD);
System.err.println(pk);
I am giving right values for alias and password. But I am getting null in private key.
Why I am getting null, Is there any alternative approach to get private key from jks file.
Any help will be greatly appreciated!!
My question is not able to get the private key. But the mentioned question is the incorrect key
Related
void createKeyStore(String alias) throws Exception {
if(keyStoreType == null || keyStoreType.isEmpty()){
keyStoreType = KeyStore.getDefaultType();
}
keyStore = KeyStore.getInstance(keyStoreType);
KeyPair kp = generateRSAKeyPair();
Certificate[] certChain = new Certificate[1];
certChain[0] = generateCertificate(kp);
//load
char[] pwdArray = keyStorePassword.toCharArray();
keyStore.load(null, pwdArray);
keyStore.setKeyEntry(alias, kp.getPrivate(), keyStorePassword.toCharArray(), certChain);
// Save the keyStore
FileOutputStream fos = new FileOutputStream(keyStoreName,true);
keyStore.store(fos, pwdArray);
fos.close();
}
Using this function for create and write multiple alias in keystore
In the first request it create keystore file and store the alias with private key and certificate but in the second request with alias it not storing any data in same keystore file.
I am working on a Java project. I have created certificate using my function but now I have only one certificate . I am expecting to store multiple alias in the same file but it happen only with first request but not with second request.
I would like to save a X509Certificate and its private key into the Android KeyStore, I tought I should 'merge' the X509Certificate (containing the public key) and its private key. The private key is used to create a CSR and then a server party sign the certificate and return to the application, can I merge the cert and the private key into one unique cert? Also I'm using spongycastle (aka bouncycastle's android wrapper).
I have no idea about Android KeyStore, but maybe you can try something like:
PrivateKey privateKey = ... //this is what you already have
X509Certificate certificate = ... //this is what you already have
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
Certificate[] certChain = new Certificate[1];
certChain[0] = certificate;
char[] myKeyPassword = "myKeyPassword".toCharArray();
keyStore.setKeyEntry("mykeyalias", (Key)privateKey, myKeyPassword, certChain);
See https://docs.oracle.com/javase/9/docs/api/java/security/KeyStore.html#setKeyEntry-java.lang.String-java.security.Key-char:A-java.security.cert.Certificate:A- for more information about KeyStore.setKeyEntry
I wanted to load the keystore file and get the details of its root SSL Certificate.
Link to Sample
I saw the code in the above link. The code is also visible below. What is the use of keyStore.isKeyEntry(alias)?
I check JavaDocs and it says
Returns true if the entry identified by the given alias was created by a call to setKeyEntry, or created by a call to setEntry with a PrivateKeyEntry or a SecretKeyEntry.
So, What is the use of it?
boolean isAliasWithPrivateKey = false;
KeyStore keyStore = KeyStore.getInstance("JKS");
// Provide location of Java Keystore and password for access
keyStore.load(new FileInputStream(jksPath), jksPassword.toCharArray());
// iterate over all aliases
Enumeration<String> es = keyStore.aliases();
String alias = "";
while (es.hasMoreElements()) {
alias = (String) es.nextElement();
// if alias refers to a private key break at that point
// as we want to use that certificate
if (isAliasWithPrivateKey = keyStore.isKeyEntry(alias)) {
break;
}
}
if (isAliasWithPrivateKey) {
KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(alias,
new KeyStore.PasswordProtection(jksPassword.toCharArray()));
PrivateKey myPrivateKey = pkEntry.getPrivateKey();
// Load certificate chain
Certificate[] chain = keyStore.getCertificateChain(alias);
certDetails = new CertificateDetails();
certDetails.setPrivateKey(myPrivateKey);
certDetails.setX509Certificate((X509Certificate) chain[0]);
}
You have 3 types of entries in a java keystore:
privateKeyEntry, private key and associated certificate chain
trustedKeyEntry, a trusted certificate (e.g. certificate from CA like Verisign, GoDaddy ...)
secretKeyEntry, a encryption key (e.g. a symmetric key AES)
as described in the java docs, KeyStore.isKeyEntry(alias) returns true is you have secret or a private key.
The code example will fail if the entry is a secret key:
`KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(alias, new KeyStore.PasswordProtection(jksPassword.toCharArray()));`
it would be preferable to use:
`KeyStore.entryInstanceOf(alias , KeyStore.PrivateKeyEntry.class)`
I have file cert.pfx exported on Windows. This file contains my certificate. On Ubuntu i can open it with password and I see the certificate. But when I loaded this file:
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
KeyStore ks = ks = KeyStore.getInstance("pkcs12", provider.getName());
ks.load(new FileInputStream("/home/test/.cert.pfx", "xxxxxx".toCharArray());
String alias = ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, pts.getRandom());
Certificate[] chain = ks.getCertificateChain(alias);
After this operations I have null in pk and chain.
Also I have registered BC provider in java.security
I changed BouncyCastleProvider to SunJSSE. Now my correctly code is:
String providerName = "SunJSSE";
KeyStore ks = ks = KeyStore.getInstance("pkcs12", providerName);
ks.load(new FileInputStream("/home/test/.cert.pfx", "xxxxxx".toCharArray());
String alias = ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, pts.getRandom());
Certificate[] chain = ks.getCertificateChain(alias);
Now in pk is my privarte key, and in chain is certificate chain.
I don't know why in BC doesn't work. I have other certificate and BC provider work correctly.
I have the following code to export certificates and keys from a keystore, that I created with keytool in Windows:
final KeyStore keystore = KeyUtil.loadKeystore("keystore.jks", "pass");
UserInfo userinfo = new UserInfo(WSusername, WSpassword);
X509Certificate clientcert = KeyUtil.getCertificate(CLIENT_KEY_ALIAS, keystore);
X509Certificate servercert = KeyUtil.getCertificate(SERVER_KEY_ALIAS, keystore);
PrivateKey clientprivate = KeyUtil.getPrivateKey(CLIENT_KEY_ALIAS, CLIENT_KEY_PASSWORD, keystore);
Yet it fails at the last line with "unable to retrieve private key for signing"
It can retrieve the clientcert, but when it tries clientprivate, it fails.
My problem was that when I generated the keystore with keytool, it did not create the PrivateKey as a key entry. To fix this, I imported the .p12 keystore as the private key, which worked. My original code above then worked.