How does create Intermediate certificate with openssl?
It is difficult to understand this intermediate certificate. I wonder why this intermediate is necessary?. I have found this documentation over Internet.
The purpose of using an intermediate CA is primarily for security. The root key can be kept offline and used as infrequently as possible. If the intermediate key is compromised, the root CA can revoke the intermediate certificate and create a new intermediate cryptographic pair. |
I studied about the chain concept. I focused if the encryption with private key of root certificate and decryption with public key of child certificate are possible, reverse versa?. (The answer is "Not Possible"). The reason is to hide the root CA for security.
1. Prerequisite
This is the default directory structure to generate intermediate certificate.
# mkdir /root/ca
# cd /root/ca # mkdir certs crl newcerts private # chmod 700 private # touch index.txt # echo 1000 > serial |
To generate "Key", "CSR" (Certificate Signing Reqeust) and. CRT (Certificate), I need configuration for each case, In reference documentation, there are 2 types of configuration for Root CA and Intermediate CA. At this time, I need Root CA configuration. It looks like below.
# vi /root/ca/openssl.cnf
# OpenSSL root CA configuration file. # Copy to `/root/ca/openssl.cnf`.
[ ca ] # `man ca` default_ca = CA_default
[ CA_default ] # Directory and file locations. dir = /root/ca certs = $dir/certs crl_dir = $dir/crl new_certs_dir = $dir/newcerts database = $dir/index.txt serial = $dir/serial RANDFILE = $dir/private/.rand
# The root key and root certificate. private_key = $dir/private/ca.key.pem certificate = $dir/certs/ca.cert.pem
# For certificate revocation lists. crlnumber = $dir/crlnumber crl = $dir/crl/ca.crl.pem crl_extensions = crl_ext default_crl_days = 30
# SHA-1 is deprecated, so use SHA-2 instead. default_md = sha256
name_opt = ca_default cert_opt = ca_default default_days = 375 preserve = no policy = policy_strict
[ policy_strict ] # The root CA should only sign intermediate certificates that match. # See the POLICY FORMAT section of `man ca`. countryName = match stateOrProvinceName = match organizationName = match organizationalUnitName = optional commonName = supplied emailAddress = optional
[ policy_loose ] # Allow the intermediate CA to sign a more diverse range of certificates. # See the POLICY FORMAT section of the `ca` man page. countryName = optional stateOrProvinceName = optional localityName = optional organizationName = optional organizationalUnitName = optional commonName = supplied emailAddress = optional
[ req ] # Options for the `req` tool (`man req`). default_bits = 2048 distinguished_name = req_distinguished_name string_mask = utf8only
# SHA-1 is deprecated, so use SHA-2 instead. default_md = sha256
# Extension to add when the -x509 option is used. x509_extensions = v3_ca
[ req_distinguished_name ] # See <https://en.wikipedia.org/wiki/Certificate_signing_request>. countryName = Country Name (2 letter code) stateOrProvinceName = State or Province Name localityName = Locality Name 0.organizationName = Organization Name organizationalUnitName = Organizational Unit Name commonName = Common Name emailAddress = Email Address
# Optionally, specify some defaults. countryName_default = GB stateOrProvinceName_default = England localityName_default = 0.organizationName_default = Alice Ltd organizationalUnitName_default = emailAddress_default =
[ v3_ca ] # Extensions for a typical CA (`man x509v3_config`). subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always,issuer basicConstraints = critical, CA:true keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ v3_intermediate_ca ] # Extensions for a typical intermediate CA (`man x509v3_config`). subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always,issuer basicConstraints = critical, CA:true, pathlen:0 keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ usr_cert ] # Extensions for client certificates (`man x509v3_config`). basicConstraints = CA:FALSE nsCertType = client, email nsComment = "OpenSSL Generated Client Certificate" subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment extendedKeyUsage = clientAuth, emailProtection
[ server_cert ] # Extensions for server certificates (`man x509v3_config`). basicConstraints = CA:FALSE nsCertType = server nsComment = "OpenSSL Generated Server Certificate" subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer:always keyUsage = critical, digitalSignature, keyEncipherment extendedKeyUsage = serverAuth
[ crl_ext ] # Extension for CRLs (`man x509v3_config`). authorityKeyIdentifier=keyid:always
[ ocsp ] # Extension for OCSP signing certificates (`man ocsp`). basicConstraints = CA:FALSE subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer keyUsage = critical, digitalSignature extendedKeyUsage = critical, OCSPSigning |
There are lots of options in there. I can not explain all of things. For the reproduction of this test, I check the directory path at first.
[ CA_default ] # Directory and file locations. dir = /root/ca |
In this post, I create "/root/ca" directory before, therefore I do not need to change this value. However, it need to be changed if I want to work on other directory.
2. Create root key and root certificate
I generate RSA private key which is most used with "openssl genrsa" command. (Please, note that If there is no option like "-aes256", there is no process to enter the password)
# cd /root/ca # openssl genrsa -aes256 -out private/ca.key.pem 4096
Enter pass phrase for ca.key.pem: secretpassword Verifying - Enter pass phrase for ca.key.pem: secretpassword
# chmod 400 private/ca.key.pem |
And then, I create Root CA certificate with the Private key which is generated earlier. (In this case, I do not use the CSR). The "-x509" option is the option which is necessary when I create certificate
# cd /root/ca # openssl req -config openssl.cnf -key private/ca.key.pem -new -x509 -days 7300 -sha256 -extensions v3_ca -out certs/ca.cert.pem
Enter pass phrase for ca.key.pem: secretpassword You are about to be asked to enter information that will be incorporated into your certificate request. ----- Country Name (2 letter code) [XX]:GB State or Province Name []:England Locality Name []: Organization Name []:Alice Ltd Organizational Unit Name []:Alice Ltd Certificate Authority Common Name []:Alice Ltd Root CA Email Address []:
# chmod 444 certs/ca.cert.pem |
In this case, Root CA is not changed for a long time. So "-days 7300" (almost 20 years) is defined. Because of this, the Private key of Root should be secret. I can see more detail information with "verification" command. In the result, I can see the "issuer" and "validity" information. Also I can see the certificate include the Public Key Info.
# openssl x509 -noout -text -in certs/ca.cert.pem Certificate: Data: Version: 3 (0x2) Serial Number: Signature Algorithm: sha256WithRSAEncryption Issuer: C=GB, ST=England, O=Alice Ltd, OU=Alice Ltd Certificate Authority, CN=Alice Ltd Root CA Validity Not Before: Oct 19 00:53:19 2018 GMT Not After : Oct 14 00:53:19 2038 GMT Subject: C=GB, ST=England, O=Alice Ltd, OU=Alice Ltd Certificate Authority, CN=Alice Ltd Root CA Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (4096 bit) Modulus: Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Key Identifier: X509v3 Authority Key Identifier: X509v3 Basic Constraints: critical CA:TRUE X509v3 Key Usage: critical Digital Signature, Certificate Sign, CRL Sign Signature Algorithm: sha256WithRSAEncryption |
Therefore, I can extract the Public key.
# mkdir public
# openssl x509 -pubkey -in certs/ca.cert.pem -noout > public/pub.ca.cert.pem -----BEGIN PUBLIC KEY----- Something ................ xxxxxxxxxxxxxxxxxxxxxxx -----END PUBLIC KEY----- |
3. Create intermediate pair
To generate the Intermediate certificate, I need to make sub-directory under the root directory.
# mkdir /root/ca/intermediate
# cd /root/ca/intermediate # mkdir certs crl csr newcerts private # chmod 700 private # touch index.txt # echo 1000 > serial # echo 1000 > /root/ca/intermediate/crlnumber |
"echo 1000 > /root/ca/intermediate/crlnumber" is used for tracking certificate revocation lists. In this post, I do not handle about this. I also need configuration for intermediate certificate. Most of the contents are same with Root's configuration. 5 things are different.
[ CA_default ] dir = /root/ca ==> /root/ca/intermediate private_key = $dir/private/ca.key.pem ==> $dir/private/intermediate.key.pem certificate = $dir/certs/ca.cert.pem ==> $dir/certs/intermediate.cert.pem crl = $dir/crl/ca.crl.pem ==> $dir/crl/intermediate.crl.pem policy = policy_strict ==> policy_loose |
I generate RSA Private key. this key is independent with Root Private key. This intermediate certificate is usually not used for end-point such as the server and client. I think it is kinds of sub-Root certificate. (However, this is one of cases. I can use intermediate certificate on server and client also.)
# cd /root/ca # openssl genrsa -aes256 -out intermediate/private/intermediate.key.pem 4096
Enter pass phrase for intermediate.key.pem: secretpassword Verifying - Enter pass phrase for intermediate.key.pem: secretpassword
# chmod 400 intermediate/private/intermediate.key.pem |
Now I need to generate certificate signing request (CSR) at this time. During this step, The Common Name must be different. CSR includes several information such as "common Name". I can create certificate without this CSR. (In the Root case, I did not create CSR at that time.
# cd /root/ca # openssl req -config intermediate/openssl.cnf -new -sha256 -key intermediate/private/intermediate.key.pem -out intermediate/csr/intermediate.csr.pem
Enter pass phrase for intermediate.key.pem: secretpassword You are about to be asked to enter information that will be incorporated into your certificate request. ----- Country Name (2 letter code) [XX]:GB State or Province Name []:England Locality Name []: Organization Name []:Alice Ltd Organizational Unit Name []:Alice Ltd Certificate Authority Common Name []:Alice Ltd Intermediate CA Email Address []: |
Now, I will generate intermediate certificate with this CSR. Please, note that I will use root certificate and configuration to create intermediate
# cd /root/ca # openssl ca -config openssl.cnf -extensions v3_intermediate_ca -days 3650 -notext -md sha256 -in intermediate/csr/intermediate.csr.pem -out intermediate/certs/intermediate.cert.pem Using configuration from openssl.cnf Enter pass phrase for /root/ca/private/ca.key.pem: Check that the request matches the signature Signature ok Certificate Details: Serial Number: 4096 (0x1000) Validity Not Before: Oct 19 01:20:29 2018 GMT Not After : Oct 16 01:20:29 2028 GMT Subject: countryName = GB stateOrProvinceName = England organizationName = Alice Ltd organizationalUnitName = Alice Ltd Certificate Authority commonName = Alice Ltd Intermediate CA X509v3 extensions: X509v3 Subject Key Identifier: X509v3 Authority Key Identifier: X509v3 Basic Constraints: critical CA:TRUE, pathlen:0 X509v3 Key Usage: critical Digital Signature, Certificate Sign, CRL Sign Certificate is to be certified until Oct 16 01:20:29 2028 GMT (3650 days) Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y Write out database with 1 new entries Data Base Updated
# chmod 444 intermediate/certs/intermediate.cert.pem |
During creation, I can see the detail information. Also, I can see mote detail with "verification" command.
# # openssl x509 -noout -text -in intermediate/certs/intermediate.cert.pem Certificate: Data: Version: 3 (0x2) Serial Number: 4096 (0x1000) Signature Algorithm: sha256WithRSAEncryption Issuer: C=GB, ST=England, O=Alice Ltd, OU=Alice Ltd Certificate Authority, CN=Alice Ltd Root CA Validity Not Before: Oct 19 01:20:29 2018 GMT Not After : Oct 16 01:20:29 2028 GMT Subject: C=GB, ST=England, O=Alice Ltd, OU=Alice Ltd Certificate Authority, CN=Alice Ltd Intermediate CA Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (4096 bit) Modulus: Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Key Identifier: X509v3 Authority Key Identifier: X509v3 Basic Constraints: critical CA:TRUE, pathlen:0 X509v3 Key Usage: critical Digital Signature, Certificate Sign, CRL Sign Signature Algorithm: sha256WithRSAEncryption |
This certificate also include the public key, therefore I can extract the public key from certificate
# mkdir intermediate/public
# openssl x509 -pubkey -in intermediate/certs/intermediate.cert.pem -noout > intermediate/public/pub.intermediate.cert.pem -----BEGIN PUBLIC KEY----- Something ........ xxxxxxxxxxxxxxxxxxxxxxxx -----END PUBLIC KEY----- |
4. Verify the intermediate certificate
I obtain "Private key", "CSR" and "Certificate" files for intermediate. I have some question how does this cert guarantee?. "openssl verfify -CAfile" command show intermediate cert is certified by root certificate.
# openssl verify -CAfile certs/ca.cert.pem intermediate/certs/intermediate.cert.pem intermediate/certs/intermediate.cert.pem: OK |
4-1. [Optional] The relationship between Root Key and Intermediate Key.
Someone can think like me, the intermediate certificate inherit from the root certification. Therefore, I can encrypt with intermediate public key and decrypt with root private key or reverse versa. The answer is "No" (RSA operation error is happend)
# echo "welecom ssl world" > message
[ Intermediate public encrypt + Root private decrypt ] # openssl rsautl -encrypt -inkey intermediate/public/pub.intermediate.cert.pem -pubin -in message -out encrypted-message # openssl rsautl -decrypt -inkey private/ca.key.pem -in encrypted-message -out decrypted-message RSA operation error
[ Root public encrypt + Intermediate private decrypt ] # openssl rsautl -encrypt -inkey public/pub.ca.cert.pem -pubin -in message -out encrypted-message # openssl rsautl -decrypt -inkey intermediate/private/intermediate.key.pem -in encrypted-message -out decrypted-message RSA operation error |
5. Create the certificate chain file
In the documentation, there are reason why the chain file is necessary.
When an application (eg, a web browser) tries to verify a certificate signed by the intermediate CA, it must also verify the intermediate certificate against the root certificate. |
Thus, it is necessary to confirm if the intermediate certificate come from root certificate. To create chain, I will merge both certificate into single file.
# cat intermediate/certs/intermediate.cert.pem certs/ca.cert.pem > intermediate/certs/ca-chain.cert.pem # chmod 444 intermediate/certs/ca-chain.cert.pem |
6. Sign server and client certificates
Before, I do this step. I need to know what is difference between server certificate and client certificate. Before, I write this post, I only consider web server such as Apache. In this Apache case, the server certificate is necessary. Server certificate focus if this server is safe or not. Client certificate focus if my request to the server is safe or not. So usually, client certificate is doing after server certificate. In this post, I will handle server certificate.
I think this intermediate certificate is kinds of sub-root certificate. So this intermediate should be hidden for the security. (Don't worry, if this intermediate certificate is stolen, I can delete and re-create with Root certificate again) Anyway, I can create certificate for end-point.
# cd /root/ca # openssl genrsa -aes256 -out intermediate/private/www.example.com.key.pem 2048 # chmod 400 intermediate/private/www.example.com.key.pem |
The reason why I use 2048 bit to create RSA key. Usually, the certificate for end-point should be short expiration day. So, 2048 bit is much efficient. After this, I create the CSR with private key. And I use intermediate configuration file to generate. (At this time, it looks like another intermediate certificate). Note that the Common Name cannot be the same as either your root or intermediate certificate.
# cd /root/ca # openssl req -config intermediate/openssl.cnf -key intermediate/private/www.example.com.key.pem -new -sha256 -out intermediate/csr/www.example.com.csr.pem
Enter pass phrase for www.example.com.key.pem: secretpassword You are about to be asked to enter information that will be incorporated into your certificate request. ----- Country Name (2 letter code) [XX]:US State or Province Name []:California Locality Name []:Mountain View Organization Name []:Alice Ltd Organizational Unit Name []:Alice Ltd Web Services Common Name []:www.example.com Email Address []: |
Now, I will create the certificate. Please note, I used "server_cert" option, because I suppose I create certificate for web-server. However if I want the certificate for client, I use "user_cert"
To create a certificate, use the intermediate CA to sign the CSR. If the certificate is going to be used on a server, use the server_cert extension. If the certificate is going to be used for user authentication, use the usr_cert extension. Certificates are usually given a validity of one year, though a CA will typically give a few days extra for convenience. |
# cd /root/ca # openssl ca -config intermediate/openssl.cnf -extensions server_cert -days 375 -notext -md sha256 -in intermediate/csr/www.example.com.csr.pem -out intermediate/certs/www.example.com.cert.pem # chmod 444 intermediate/certs/www.example.com.cert.pem |
I can verify this certificate. At this time, I do not verify with the certificate of the intermediate. I verify with ca-chain which are generated earlier.
# openssl x509 -noout -text -in intermediate/certs/www.example.com.cert.pem # openssl verify -CAfile intermediate/certs/ca-chain.cert.pem intermediate/certs/www.example.com.cert.pem |
I will deploy my web server with these certificate and chain. At this time, I do not need to merge again the ca-chain.cert.pem.
ca-chain.cert.pem www.example.com.key.pem www.example.com.cert.pem |
I compare the configuration. In "-config" option of "openssl ca", it decide the "issuer". Therefore, intermediate's issuer is root and server's issuer is intermediate. In "extension" option, it decide the rule or type of certificate. Becuase of this, the server handle another type of intermediate certificate which is issued by (sub-root) intermediate certificate.
Therefore, the certification does not need to merge at this time. I do test again to check the relationship between intermediate certifications. In the result, I can not encrypt and decrypt.
# openssl rsautl -encrypt -inkey intermediate/public/pub.www.example.com.cert.pem -pubin -in message -out encrypt-message # openssl rsautl -decrypt -inkey intermediate/private/intermediate.key.pem -in encrypt-message -out decrypt-message RSA operation error |
Reference
[ 1 ] https://jamielinux.com/docs/openssl-certificate-authority/index.html#openssl-certificate-authority
[ 2 ] https://jamielinux.com/docs/openssl-certificate-authority/appendix/root-configuration-file.html
[ 3 ] https://www.websecurity.symantec.com/security-topics/client-certificates-vs-server-certificates