I've been asked to create a jks keystore based on a certificate we had created. I've read a bit on the topic, but I'm still confused on a few items:
Is the private key of a certificate supposed to be stored in a .jks keystone?
If yes - where does this get entered in? Using the keytool, it doesn't require one for creating a jks file.
If no - what is the purpose of a jks file? Why would my application need it instead of just reading in a certificate directly? And why does the keytool require a password to create a jks if it just contains a public key?
The purpose of a key store is to protect the privacy and integrity of cryptographic keys using password-based algorithms. Privacy means that the keys are kept secret; they can only be used by someone who knows the password; this is useful for private keys and secret keys. Integrity means that alteration of the keys can be detected by someone who knows the password; this is useful for public keys and secret keys.
Whether you should include the private key or not depends on what you are trying to do. If you are creating a key store for your server so that it can authenticate itself to clients, for example, then it should contain the private key. If you created a self-signed certificate, and want to give clients a key store so that they can authenticate your service, then it should not contain the private key.
If you have a pre-existing key pair, and want to import it to a JKS format key store, the easiest way might be to use OpenSSL to create a PKCS #12 format key store, then use keytool to convert that to a JKS key store. Normally, keytool expects to do key pair generation itself, and so the private key will be stored there from the beginning.
You should verify the integrity of a public key or a certificate before you use it to encrypt a message or verify a signature. Otherwise, an attacker can replace the key with one he owns and act as a man in the middle. If you simply read a public key from a file, you don't know it really belongs to your intended recipient. But if you store a password-based message authentication code with the public key, you can ensure that it hasn't been tampered with.
Is the private key of a certificate supposed to be stored in a .jks keystone?
Yes, if you own the certificate and it is stored there.
If yes - where does this get entered in? Using the keytool, it doesn't require one for creating a jks file.
That's because you can also use it as a truststore, which only contains trusted certificates.
To get the private key in there you will need to first convert it and its certificate to a PKCS#12 file using openssl, as answered in numerous questions here such as this.
If no - what is the purpose of a jks file? Why would my application need it instead of just reading in a certificate directly?
Because your application also needs the private key of the certificate.
And why does the keytool require a password to create a jks if it just contains a public key?
A keystore has a password because it is a security-related entity.
Related
In the windows personal certificate store, I am trying to programmatically install a certificate with the private key(using method setKeyEntry) using Java. But I get an exception when I do that.
Caused by: java.lang.UnsupportedOperationException: Cannot assign the key to the given alias.
at jdk.crypto.mscapi/sun.security.mscapi.CKeyStore.engineSetKeyEntry(CKeyStore.java:405)
at jdk.crypto.mscapi/sun.security.mscapi.CKeyStore$MY.engineSetKeyEntry(CKeyStore.java:57)
Code snippet:
KeyStore userCertStore = KeyStore.getInstance(getValue(CERTIFICATE_STORE_TYPE));
userCertStore.load(null,null);
for (iaik.x509.X509Certificate cert : user.getUserCertificates()) {
userCertStore.setCertificateEntry(cert.getSubjectDN().toString(), cert);
userCertStore.setKeyEntry(cert.getSubjectDN().toString(),user.getUserPrivateKey(cert),new
SecureStringBuffer(new StringBuffer(password)).toCharArray(),user.getUserCertificates());
}
The certificates are already set during setKeyEntry - do not store the certificate using setCertificateEntry.
setCertificateEntry is used to set trusted certificates (of the other party), the setKeyEntry is used to store private keys and the full certificate chain belonging to that private key.
So when you set the private key the alias is already taken by a "trusted certificate".
Is it possible to change the certificate and certificate chain for existing entry (private key) in keystore. As I understand, firstly I need to delete existing entry and then store same private key with new certificate and chain. This solution is not an option since I don't know the password for that entry in keystore.
Solution so far:
Key generation and initial storage:
KeyPair kp = generateRSAKeyPair();
X509Certificate selfSignedCert = makeSelfSignedCert(kp);
ks.load(...);
ks.setKeyEntry("entry1", kp.getPrivate(), PASSWORD, new X509Certificate[]{selfSignedCert});
ks.store(...);
After CA sends certificate I want:
ks.load(...);
ks.setCertificateEntry("entry1", caSignedCert);
ks.store(...);
The main issue is that I don't have the right certificate at the time when the key is being stored to keystore. There is a delay between the generation of keys and when CA sends signed certificates.
Another option would be to not set certificate at all, and after CA signs CSR, add the final signed certificate to keystore. Something like:
KeyPair kp = generateRSAKeyPair();
ks.load(...);
ks.setKeyEntry("entry1", kp.getPrivate(), PASSWORD);
ks.store(...);
// after some time
ks.load(...);
ks.setCertificateEntry("entry1", caSignedCert);
ks.store(...);
But I couldn't find a way to store private key without an associated certificate in keystore. Storing private key elsewhere else is also not an option.
A potential solution is to store signed certificate from CA until a user provides the password to keystore entry and then deleting existing entry & creating new entry with proper certificates. This solution is not ideal and I would like to avoid going down this road.
Any suggestions are welcome.
The solution is to first store key to keystore with the self-signed certificate. At this time, this key cannot be used because CA did not sent the proper certificate for this key yet. If one would use key at this time for signing, the associated self-signed certificate would be used (which is not desirable).
After some time CA sends the proper certificate, which must be stored somewhere (database in my case).
On the first opportunity when the password for key entry is supplied, key is retrieved from keystore and immediately gets stored again with the same password but different alias and proper certificate from CA. Then it is safe to delete original entry with self-signed certificate.
I hope this helps someone. Any better solutions are welcome.
To build an apk we need a certificate, this certificate contains the public key and also some metadata (like Company, …). The certificate itself is generated through the app signing key.
The app signing key is exactly the same as a keystore entity or? (what I think for now)
And what does one keystore entity contains exactly?
Does a keystore entity stores the „private key + public key + metadata“ inside one entity?
or the „private key + metadata (separate)“ and generates the public key through the private key?
or only a „private key“ where the metadata are written in and generates the public key through the private key?
Or otherwise? I would really like to know more technical based informations about a keystore entity/app signing key and couldn’t find a more detailed (technical based) description of storage and generation.
Thank you
Google:
"A keystore is a binary file that contains one or more private keys“
"Generate Signed APK […], select a keystore, a private key, and enter the passwords for both.“
https://developer.android.com/studio/publish/app-signing.html
A keystore is a container for keys and certificates. An Android Keystore contains the app signing key and the matching certificate.
A cryptographic key pair, public and private is generated randomly. The public key is embedded in an X509 certificate along with some additional attributes such as serial number or common name. The certificate is signed with the private key to ensure the origin and integrity. See Certificate enrollment process
Finally the private key and the certificate can be imported into a keystore file: JKS, BKS or PKCS#12
The apk is digitally signed using the private key contained in the keystore, and the certificate is also included, so you could verify the identity of the signatory and the integrity of the package
All.I am working on an android project. I need to generate a RSA keypair then use them to communicate with others.I need to store the private key and public key in a secure place and I find KeyStore could be used.
I see that KeyStore could store KeyStore.PrivateKeyEntry but it need a Certificate[] chain. I tried to create it but failed...
Is there anyone could paste some example code used to store private key and public key.
Thanks so much!
Like you said, in order to store the Private key into the keystore, you need the Private key (which you have) and the Certificate chain for the corresponding public key. What you have is just the public key, you need to obtain a certificate from an authority based on your public key. Yes, you can self-sign the certificate. But I don't think there is any built Java API to to create and self-sign a certificate programmatically.
There was similar discussion on this thread. The accepted solution describes storing private key and public key outside of keystore in a protected file.
You can read more about Java Cryptography architecture here http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html
Hope this helps.
I want to read issuer String from user's public key with Bouncy Castle. Is there example code or something from which I can learn?
If you can obtain the certificate object, then you can do the following:
((X509Certificate) certificate).getIssuerX500Principal().getName();
The public key itself does not have an issuer - only a certificate has. And you can get the public key from the certificate, but not vice-versa.
Update: Since it appears that you want to verify the validity of your users, the public key alone does not provide this info. Public keys are used for encryption / digital signature verification, but for the rest of PKI you need the certificate. Actually, verifying the issuer that is written in the certificate gives you no guarantee whatsoever. You need to check:
the certificate revocation lists - i.e. whether the certificate is not revoked. This is done either via the provided CRLs or via the ocsp protocol.
the expiration of the certificate
The public key object doesn't say who generated it. It just contains what you need to encrypt (or verify) with the public key.
If you got the public key from a certificate (java.security.cert.X509Certificate), then you can get the certificate issuer from that by using getIssuerX500Principal().
The certificate is a binding of an identity to a public key. As part of that, the certificate indicates who it was issued by. So you can verify whether you trust that issuer and, therefore, the binding.
Also, the key pair very likely wasn't generated by the certificate issuer. The subject just proved to the issuer that it did possess the associated private key.