I read this article on how to use keytool to generate CSRs for your organization. It was simple and easy, but left me with a few questions that I couldn't find clear, descriptive answers to:
What is Java's concept of a CSR alias and why would you want to use one? Where is this alias field stored and what other tools/APIs have access to it?
What is the difference between a key and a keystore?
What is Java's concept of a CSR alias and why would you want to use one? Where is this alias field stored and what other tools/APIs have access to it?
First of all, java uses keystores to keep keys (and certificates) inside. Single keystore can hold many certificates, so you need a way to differentiate them. That's what aliases are for. Having a keystore, an alias (and a password if needed) you can get the certificate from the keystore using Java Crypto API (specifically classes like Keystore). Here, you have a an example of how the Crypto API can be used to load a key from keystore
What is the difference between a key and a keystore?
The keystore is a container. The keys are kept inside keystores.
A keystore is a file format used to hold certificates and private keys, and alias is used to identify each entry in the keystore.
Related
I'm implementing a mutual authentication with a web server in Java on Windows.
I have a certificate on a SmartCard which is supposed to be used to authenticate me (or other user).
So far I've figured out that I can access the certificates using Windows-MY key store.
I do it like that:
KeyStore keyStore = KeyStore.getInstance("Windows-MY");
keyStore.init(null, null);
This works. I can see all certificates inside keystoreSpi (in debugger). One of them is the one which I need to use - I confirmed that.
The problem is as follows:
KeyStore api allows me to get a certificate only by using it's alias. e.g. keyStore.getCertificate("alias") or keystore.getCertificateChain("alias")
I noticed that there are multiple different certificates with the same alias in this keystore. I cannot change the aliases. I just physicaly got the smartcard with given certificates.
When I call one of the mentioned methods, keystore returns just the first certificate in the list with given alias. (generally, in the implementation there is a map where aliases are it's keys, so all duplicated aliases are ignored).
Unfortunately first certificate's purpose is "email encryption", etc. The second certificate's purpose is "SmartCard Logon" and this one I need to use. I confirmed that by going into debugger and manually hacking the list of certificates.
The question is: how do I get a proper certificate using the API (eg. the second one) when there are duplicated aliases?
If this can be done by external libraries, I can opt for that.
More details which may be useful:
I use KeyStore, then create KeyStoreManager.
I initialize SSLContext with given keyStoreManager sslContext.init(keyManagerFactory.getKeyManagers(), ...)
I create HttpsUrlConnection with given ssl context, which is my objective.
This has been fixed a while ago. Just update to a recent JRE. For more information see here: https://bugs.java.com/bugdatabase/view_bug.do?bug_id=6483657
By looking at the file java.security of my JRE, I see that the keystore type to use by default is set to JKS. Here, there is a list of the keystore types that can be used.
Is there a recommended keystore type? What are the pros/cons of the different keystore types?
There are a few more types than what's listed in the standard name list you've linked to. You can find more in the cryptographic providers documentation. The most common are certainly JKS (the default) and PKCS12 (for PKCS#12 files, often with extension .p12 or sometimes .pfx).
JKS is the most common if you stay within the Java world. PKCS#12 isn't Java-specific, it's particularly convenient to use certificates (with private keys) backed up from a browser or coming from OpenSSL-based tools (keytool wasn't able to convert a keystore and import its private keys before Java 6, so you had to use other tools).
If you already have a PKCS#12 file, it's often easier to use the PKCS12 type directly. It's possible to convert formats, but it's rarely necessary if you can choose the keystore type directly.
In Java 7, PKCS12 was mainly useful as a keystore but less for a truststore (see the difference between a keystore and a truststore), because you couldn't store certificate entries without a private key. In contrast, JKS doesn't require each entry to be a private key entry, so you can have entries that contain only certificates, which is useful for trust stores, where you store the list of certificates you trust (but you don't have the private key for them).
This has changed in Java 8, so you can now have certificate-only entries in PKCS12 stores too. (More details about these changes and further plans can be found in JEP 229: Create PKCS12 Keystores by Default.)
There are a few other keystore types, perhaps less frequently used (depending on the context), those include:
PKCS11, for PKCS#11 libraries, typically for accessing hardware cryptographic tokens, but the Sun provider implementation also supports NSS stores (from Mozilla) through this.
BKS, using the BouncyCastle provider (commonly used for Android).
Windows-MY/Windows-ROOT, if you want to access the Windows certificate store directly.
KeychainStore, if you want to use the OSX keychain directly.
Here is a post which introduces different types of keystore in Java and the differences among different types of keystore. http://www.pixelstech.net/article/1408345768-Different-types-of-keystore-in-Java----Overview
Below are the descriptions of different keystores from the post:
JKS, Java Key Store. You can find this file at
sun.security.provider.JavaKeyStore. This keystore is Java specific, it
usually has an extension of jks. This type of keystore can contain
private keys and certificates, but it cannot be used to store secret
keys. Since it's a Java specific keystore, so it cannot be used in
other programming languages.
JCEKS, JCE key store. You can find this file at
com.sun.crypto.provider.JceKeyStore. This keystore has an extension of
jceks. The entries which can be put in the JCEKS keystore are private
keys, secret keys and certificates.
PKCS12, this is a standard keystore type which can be used in Java and
other languages. You can find this keystore implementation at
sun.security.pkcs12.PKCS12KeyStore. It usually has an extension of p12
or pfx. You can store private keys, secret keys and certificates on
this type.
PKCS11, this is a hardware keystore type. It servers an interface for
the Java library to connect with hardware keystore devices such as
Luna, nCipher. You can find this implementation at
sun.security.pkcs11.P11KeyStore. When you load the keystore, you no
need to create a specific provider with specific configuration. This
keystore can store private keys, secret keys and cetrificates. When
loading the keystore, the entries will be retrieved from the keystore
and then converted into software entries.
If you are using Java 8 or newer you should definitely choose PKCS12, the default since Java 9 (JEP 229).
The advantages compared to JKS and JCEKS are:
Secret keys, private keys and certificates can be stored
PKCS12 is a standard format, it can be read by other programs and libraries1
Improved security: JKS and JCEKS are pretty insecure. This can be seen by the number of tools for brute forcing passwords of these keystore types, especially popular among Android developers.2, 3
1 There is JDK-8202837, which has been fixed in Java 11
2 The iteration count for PBE used by all keystore types (including PKCS12) used to be rather weak (CVE-2017-10356), however this has been fixed in 9.0.1, 8u151, 7u161, and 6u171
3 For further reading:
Mind Your Keys? A Security Evaluation of Java Keystores (PDF)
Java KeyStores – the gory details
Java 11 offers the following types of KeyStores:
jceks: The proprietary keystore implementation provided by the SunJCE provider.
jks: The proprietary keystore implementation provided by the SUN provider.
dks: A domain keystore is a collection of keystores presented as a single logical keystore. It is specified by configuration data whose syntax is described in the DomainLoadStoreParameter class.
pkcs11: A keystore backed by a PKCS #11 token.
pkcs12: The transfer syntax for personal identity information as defined in PKCS #12.
Source: https://docs.oracle.com/en/java/javase/11/docs/specs/security/standard-names.html#keystore-types
I'm interested in Java-NSS libraries, and I'm reading the Sun's P11 Guide. I am confused on the following:
What is the difference between using a PKCS12 keystore and a PKCS11 keystore?
A keystore is just a keystore, right? Are there some differences? Can they be used interchangeably in any aspect?
PKCS#12 is a file format (often called .p12 or .pfx) where you can store a private key and certificates. It's used for converting/transporting keys and certificates, mainly. If you export a private key + certificate from your browser, it's likely going to be in that format.
PKCS#11 is an interface, usually used to talk to hardware cryptographic tokens (often smart-cards or USB-tokens, which effectively are smart-cards embedded in a reader). This interface has a number of operations to make use of the keys and certificates. Some tokens are able to sign using the private key they contain, without the key being able to leave the device.
The point of this interface is to treat what handles the keys and certificates as a separate entity, without having to do the cryptographic operations that PKCS#11 offer (more specifically, the ones related to the private key).
When you use PKCS#11 with NSS, you're effectively using NSS as a black-box wrapped behind the PKCS#11 layer (it's effectively a software provider for what a PKCS#11 hardware token would be). There is a slight difference in the way Java uses NSS via PKCS#11 in that it doesn't require a PKCS#11 shared library (compared to other PKCS#11 libraries), so as such, it's not PKCS#11 strictly speaking, although it's very similar.
In Java, you may be able to get an RSAPrivateKey instance from a PKCS#11 store, use it to sign and decipher, without ever being able to get anything from its modulus. The security provider handling it will do the signing/deciphering via the library (and thus via the token, if that library is supported by a hardware token).
Coming back to the KeyStore in Java, it's an API that can allow you to load and use keys and certificates from files (you get various files formats such as JKS, PKCS#12, PEM, depending on your security provider) or from other underlying APIs (such as PKCS#11, more or less merged with NSS in the Sun provider, or the KeychainStore if you're on OSX and want to use the KeyChain as a KeyStore).
From Different types of keystore in Java -- Overview, the differences between PKCS12 and PKCS11 can be described as following
PKCS12, this is a standard keystore type which can be used in Java and
other languages. You can find this keystore implementation at
sun.security.pkcs12.PKCS12KeyStore. It usually has an extension of p12
or pfx. You can store private keys, secret keys and certificates on
this type. Unlike JKS, the private keys on PKCS12 keystore can be
extracted in Java. This type is portable and can be operated with
other libraries written in other languages such as C, C++ or C#.
Currently the default keystore type in Java is JKS, i.e the keystore
format will be JKS if you don't specify the -storetype while creating
keystore with keytool. However, the default keystore type will be
changed to PKCS12 in Java 9 because its enhanced compatibility
compared to JKS. You can check the default keystore type at
$JRE/lib/security/java.security file:
PKCS11, this is a hardware keystore type. It provides an interface for
the Java library to connect with hardware keystore devices such as
SafeNet's Luna, nCipher or Smart cards. You can find this
implementation at sun.security.pkcs11.P11KeyStore. When you load the
keystore, you no need to create a specific provider with specific
configuration. This keystore can store private keys, secret keys and
certificates. When loading the keystore, the entries will be retrieved
from the keystore and then converted into software entries.
Can we load multiple Certificates & Keys in a Key Store?
Is it always required to load only Pairs (i.e. Certificates & Keys together)?
If a Key Store has multiple Certificates and Keys, which one will get selected when Java SSL tries to establish connection as a Server?
Although this depends on the KeyStore type, generally, you can store multiple private keys and certificates in a single store.
Which key and certificate combination is used for a Java-based server will depend on how the application was implemented. A number of applications let you select a given certificate using the alias name. The key and certificate getters in KeyStore take an alias parameter to make this choice. Usually, when this is not specified in the configuration, the application or framework will use the first suitable one it finds based on the KeyStore.aliases() enumeration.
Tomcat, for example, uses the keyAlias attribute in its Connector configuration:
keyAlias: The alias used to for the server
certificate in the keystore. If not
specified the first key read in the
keystore will be used.
Regarding key pairs, some KeyStores (again, depending on the type) can be used to store SecretKeys (e.g. DES), that is shared keys, as well as public-private key pairs.
You can have a keystore with as many certificates and keys as you like.
If there are multiple certificates in a keystore a client uses as its truststore, all certificates are being looked at until one is found that fits. You can look at the preinstalled certificates, they are in /lib/security/cacerts. It's just a big collection of root CAs' certificates.
Regarding the keys I don't know. I'd reckon the client uses a key that is signed by the same CA as the certificate that is provided by the server and if there are multiple, the first is used. But I can't say that for sure.
I have a Certificate that has been added to a keystore using a KeyTool. I have also been provided private keys for use in Production / Test environment. I understand that the certificate is using a public key. Where do i place the keystore and the private keys to be able to be read by the command line programme. The following key reads the keystore.
System.setProperty("javax.net.ssl.keyStore", "xxx.ks");
System.setProperty("javax.net.ssl.keyStorePassword", "xxx_4ps!");
System.setProperty("javax.net.ssl.trustStore", "xxx.ks");
System.setProperty("javax.net.ssl.trustStorePassword", "xxx!");.
Where do i have to place the private keys to be read by the programme. I am new to public/private key encryption so any help would be appreciated.
Kind Regards,
Mateen
The private key and its corresponding certificate go in the javax.net.ssl.keyStore.
Certificates that you want to trust go in the javax.net.ssl.trustStore. Often you don't have one of your own, just use the default supplied with the JDK, in which case you don't specify this property at all.
These properties are pointing to certificates and just indirectly to keys. So, first you have to get certificates and put them into keystores.
"javax.net.ssl.keyStore" is used for keystore with certificate which is used to identify your system. By default, without any additional code, you can use just one identity certificate per keystore. To create a certificate, you have two options - one is to create self-signed certificate, another one is to create CSR and send it to certificate authority to sign.
See
http://download.oracle.com/javase/1.3/docs/tooldocs/win32/keytool.html#selfcertCmd and
http://download.oracle.com/javase/1.3/docs/tooldocs/win32/keytool.html#certreqCmd commands.
Once certificate is created, there will be private and public keys associated to it.
"javax.net.ssl.trustStore" points to the keystore with certificates which you trust. It means that your system will accept SSL connections only with certificates from this keystore or signed by the certificates from this keystore. These certificated can be added into the keystore using following command:
http://download.oracle.com/javase/1.3/docs/tooldocs/win32/keytool.html#importCmd
You can put your keystores anywhere you like. Just ensure that java process has an access to them.