I have a single rootCA
certificate in the resource
folder (along with its private key) of my project.
When the software starts, it initialises the SSLManager
object, which in turn:
- Loads the rootCA into an
x509Certificate
- Loads the rootCA private key
- Generates a server keypair and certificate
- Signs the certificate using the rootCA
I would like to store the rootCA and server certificate into a keystore, that I can later use to setup an SSLContext, and for more secure storage.
I know how to store a single keypair/certificate into a keystore, but how would I correctly go about this for a chain?
I presume:
keyStore.setKeyEntry(ALIAS, privateKey, password.toCharArray, Array(rootCA, serverCert))
However, if true, which private key do I use (rootCA vs server)?
A full example would be much appreciated.
I have a single rootCA
certificate in the resource
folder (along with its private key) of my project.
When the software starts, it initialises the SSLManager
object, which in turn:
- Loads the rootCA into an
x509Certificate
- Loads the rootCA private key
- Generates a server keypair and certificate
- Signs the certificate using the rootCA
I would like to store the rootCA and server certificate into a keystore, that I can later use to setup an SSLContext, and for more secure storage.
I know how to store a single keypair/certificate into a keystore, but how would I correctly go about this for a chain?
I presume:
keyStore.setKeyEntry(ALIAS, privateKey, password.toCharArray, Array(rootCA, serverCert))
However, if true, which private key do I use (rootCA vs server)?
A full example would be much appreciated.
Share edited Feb 10 at 17:54 Gaël J 15.3k5 gold badges22 silver badges44 bronze badges asked Feb 10 at 12:56 Kris RiceKris Rice 11 Answer
Reset to default 3I presume:
keyStore.setKeyEntry(ALIAS, privateKey, password.toCharArray, Array(rootCA, serverCert))
Close
However, if true, which private key do I use (rootCA vs server)?
Use the privatekey of the server, and the cert-array must have the server cert FIRST, followed by its chain cert(s) preferably in upward sequence but possibly omitting the root.
This is because JSSE will send this cert-array as the cert-chain in the SSL/TLS handshake. The original standards required that the cert-chain sent by a server begin with the server cert, followed the chain CA certs in strict upward sequence -- "Each following certificate must directly certify the one preceding it." In practice, quite a few servers due to miscoding or misconfiguration got certs after the first out of order, and since they can be sorted out given only the first one is correct, SSL/TLS clients were coded to tolerate this; the latest standard, RFC8446 for TLS1.3, now recommends support for "potentially extraneous certificates and arbitrary orderings" EXCEPT that "the end-entity cert[] MUST be first".
In addition, all standards have allowed the root cert to be omitted from the transmitted chain, because it isn't needed; a client can safely validate the cert and chain, and thus the server's identity, only using a root cert (or possibly a nonroot anchor) already configured/stored local to that client (for Java typically in JRE/lib/security/cacerts, for other software in comparable ways), so having the server send another copy is a waste of bandwidth -- though a fairly small one. Java keytool
does not like to create a PrivateKeyEntry with a chain that omits the root, but code you write can, and JSSE will happily send either.
For your simple case, this means an array of (servercert, rootcacert)
or optionally just (servercert)