Why we need to generate duplicate certificates with OpenSSL CA?
This use case is mostly valid for lab environments or when we are using self signed CA with 1000s or servers which gets re-deployed very often. In such case we sometimes tend to generate duplicate certificates which are used for internal communication in private network. Although such exercise should not be performed when using external communication in public network.
Just to be clear, here we we use the term 'duplicate certificates' we mean 'certificates with same Common Name' as Common Name is the most important field in a certificate which is used for authentication or authorization in any communication over SSL/TLS.
Normally we either use openssl ca
or openssl x509
to sign the certificates. Now both of these commands sign and generate a certificate in different ways which we have covered in detail at openssl ca vs openssl x509 comparison [With Examples]
We will cover different examples using both the commands to generate duplicate certificates.
Setup Lab Environment
We have already installed openssl command and prepared our RootCA which we will use in this article to sign the certificates. I will just brief out the steps I have used for reference:
## navigate inside your tls path cd /root/tls ## generate rootca private key openssl genrsa -out private/cakey.pem 4096 ## generate rootCA certificate openssl req -new -x509 -days 3650 -config openssl.cnf -key private/cakey.pem -out certs/cacert.pem ## Verify the rootCA certificate content and X.509 extensions openssl x509 -noout -text -in certs/cacert.pem
You can collect my sample openssl.cnf from a different article.
Method-1: Generate duplicate certificates using openssl x509 command
The openssl x509 command doesn't maintain any database for all the certificates which is signed using the CA certificate. The command does maintain a serial number database but that doesn't contain any details about the Certificate Signing Request so it is easier to create duplicate certificates here.
Generate private key
First we would need a private key for our certificate to generate the CSR
# openssl genrsa -out server.key.pem 4096
Sample Output:
Generate Certificate Signing Request (CSR)
Next we generate the CSR required to sign the certificate. Here our Common Name would be server-1.example.com
:
# openssl req -new -key server.key.pem -out server.csr
Sample Output:
Sign and generate certificate
Next we will generate our certificate using the CSR and RootCA certificate:
# openssl x509 -req -in server.csr -CA /root/tls/certs/cacert.pem -CAkey /root/tls/private/cakey.pem -out server-1.cert.pem -CAcreateserial -days 365 -sha256
Signature ok
subject=C = IN, ST = Karnataka, L = Bengaluru, O = GoLinuxCloud, OU = Admin, CN = server-1.example.com
Getting CA Private Key
So, we have successfully created our certificate:
# ls -l
total 12
-rw-r--r-- 1 root root 1952 Sep 5 11:03 server-1.cert.pem
-rw-r--r-- 1 root root 1724 Sep 5 11:02 server.csr
-rw------- 1 root root 3243 Sep 5 11:01 server.key.pem
Generate duplicate certificate using same CSR
Now let's try to generate another certificate using the same CSR file (having same Common Name)
# openssl x509 -req -in server.csr -CA /root/tls/certs/cacert.pem -CAkey /root/tls/private/cakey.pem -out server-2.cert.pem -CAcreateserial -days 365 -sha256
Signature ok
subject=C = IN, ST = Karnataka, L = Bengaluru, O = GoLinuxCloud, OU = Admin, CN = server-1.example.com
Getting CA Private Key
List the certificate:
# ls -l
total 16
-rw-r--r-- 1 root root 1952 Sep 5 11:03 server-1.cert.pem
-rw-r--r-- 1 root root 1952 Sep 5 15:51 server-2.cert.pem
-rw-r--r-- 1 root root 1724 Sep 5 11:02 server.csr
-rw------- 1 root root 3243 Sep 5 11:01 server.key.pem
As you can see, we have two certificates using the same Common Name.
Verify duplicate certificates
Both the certificates will have different serial number:
# openssl x509 -in server-1.cert.pem -noout -serial serial=33BFBE13ED27ED780DBDA412F152D21E0A4C367D # openssl x509 -in server-2.cert.pem -noout -serial serial=33BFBE13ED27ED780DBDA412F152D21E0A4C367E
But both of them will have the same Subject field:
# openssl x509 -noout -text -in server-1.cert.pem | grep -E 'Issuer|Subject:' Issuer: C = IN, ST = Karnataka, L = Bengaluru, O = GoLinuxCloud, OU = Admin, CN = rootca.com Subject: C = IN, ST = Karnataka, L = Bengaluru, O = GoLinuxCloud, OU = Admin, CN = server-1.example.com # openssl x509 -noout -text -in server-2.cert.pem | grep -E 'Issuer|Subject:' Issuer: C = IN, ST = Karnataka, L = Bengaluru, O = GoLinuxCloud, OU = Admin, CN = rootca.com Subject: C = IN, ST = Karnataka, L = Bengaluru, O = GoLinuxCloud, OU = Admin, CN = server-1.example.com
So with openssl x509 command we can generate n number of duplicate certificates without any issues as it doesn't maintain any database apart from serial number.
Method-2: Generate duplicate certificates using openssl ca command
In this section we will cover the same steps as above but we will generate and sign the certificate using openssl ca command.
Generate private key
Let's generate another set of private keys for this section:
# openssl genrsa -out server-2.key.pem 4096
Sample Output:
Generate Certificate Signing Request
Next we need a Certificate Signing Request. Here we will use Common Name as server-2.example.com
:
# openssl req -new -key server-2.key.pem -out server-2.csr
Sample Output:
Add X.509 Extensions (Optional)
This step is not relevant for this article but as a general practice I will just add required X.509 extensions to our certificate. Although this wouldn't impact our outcome in the next steps.
# cat ext_template.cnf
basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = "OpenSSL Generated Client Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, serverAuth
Generate and sign certificate
Next we will sign and generate our certificate using RootCA as created in the Lab Environment section:
# openssl ca -config /root/tls/openssl.cnf -notext -batch -in server-2.csr -out server-2.crt -extfile ext_template.cnf
Using configuration from /root/tls/openssl.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number: 3 (0x3)
Validity
Not Before: Sep 5 04:54:24 2021 GMT
Not After : Sep 5 04:54:24 2022 GMT
Subject:
countryName = IN
stateOrProvinceName = Karnataka
organizationName = golinuxcloud
organizationalUnitName = admin
commonName = server-1.example.com
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Cert Type:
SSL Client, S/MIME
Netscape Comment:
OpenSSL Generated Client Certificate
X509v3 Subject Key Identifier:
DC:9F:78:27:9F:7F:DD:25:96:70:74:9B:EC:07:C5:DB:DE:AD:8D:DB
X509v3 Authority Key Identifier:
keyid:E4:A4:AB:AA:DC:F5:FC:58:CD:24:DB:24:28:F8:8D:77:A9:EE:B4:3E
X509v3 Key Usage: critical
Digital Signature, Non Repudiation, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Client Authentication, TLS Web Server Authentication
Certificate is to be certified until Sep 5 04:54:24 2022 GMT (365 days)
Write out database with 1 new entries
Data Base Updated
Verify the index.txt database of the rootca:
# cat /root/tls/index.txt
R 220905044447Z 210905045305Z 01 unknown /C=IN/ST=Karnataka/O=golinuxcloud/OU=admin/CN=server-1.example.com
V 220905044529Z 02 unknown /C=IN/ST=karnataka/O=golinuxcloud/OU=admin/CN=server-2.example.com
V 220905045424Z 03 unknown /C=IN/ST=Karnataka/O=golinuxcloud/OU=admin/CN=server-1.example.com
So with 02
serial, we have a new entry in our RootCA database for server-2.example.com
.
Generate duplicate certificate using the same CSR
Let us try to use the same CSR from this section i.e. server-2.csr to generate another certificate:
# openssl ca -config /root/tls/openssl.cnf -days 10 -notext -batch -in server-2.csr -out server-4.crt -extfile ext_template.cnf
Using configuration from /root/tls/openssl.cnf
Check that the request matches the signature
Signature ok
ERROR:There is already a certificate for /C=IN/ST=karnataka/O=golinuxcloud/OU=admin/CN=server-2.example.com
The matching entry has the following details
Type :Valid
Expires on :220905044529Z
Serial Number :02
File name :unknown
Subject Name :/C=IN/ST=karnataka/O=golinuxcloud/OU=admin/CN=server-2.example.com
As expected, the certificate generation has failed because we already have an entry in the index.txt
for server-2.example.com
Common Name and unless we revoke this certificate, the same can not be re-signed.
How do I fix this and generate duplicate certificates with OpenSSL?
As soon as the CA signs a certificate, it creates a new file index.txt.attr
in the same location where index.txt
resides. For us, since we are using /root/tls
as our base directory to store CA certificates and files so we can look into the same path:
]# cat /root/tls/index.txt.attr
unique_subject = yes
Change the value of unique_subject
to no
so that openssl will not check for Subject name while signing the certificates
index.txt
file and add unique_subject = no
.]# cat /root/tls/index.txt.attr
unique_subject = no
Now, let us try to sign the certificate again:
# openssl ca -config /root/tls/openssl.cnf -days 10 -notext -batch -in server-2.csr -out server-4.crt -extfile ext_template.cnf
Using configuration from /root/tls/openssl.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number: 5 (0x5)
Validity
Not Before: Sep 5 11:03:26 2021 GMT
Not After : Sep 15 11:03:26 2021 GMT
Subject:
countryName = IN
stateOrProvinceName = karnataka
organizationName = golinuxcloud
organizationalUnitName = admin
commonName = server-2.example.com
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Cert Type:
SSL Client, S/MIME
Netscape Comment:
OpenSSL Generated Client Certificate
X509v3 Subject Key Identifier:
8E:E1:06:4C:21:CA:C6:2E:8A:1D:D2:20:10:40:43:3D:51:73:C9:14
X509v3 Authority Key Identifier:
keyid:E4:A4:AB:AA:DC:F5:FC:58:CD:24:DB:24:28:F8:8D:77:A9:EE:B4:3E
X509v3 Key Usage: critical
Digital Signature, Non Repudiation, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Client Authentication, TLS Web Server Authentication
Certificate is to be certified until Sep 15 11:03:26 2021 GMT (10 days)
Write out database with 1 new entries
Data Base Updated
So, this time we were able to generate the certificate with the same Common Name. verify the ca's database:
# cat /root/tls/index.txt R 220905044447Z 210905045305Z 01 unknown /C=IN/ST=Karnataka/O=golinuxcloud/OU=admin/CN=server-1.example.com V 220905044529Z 02 unknown /C=IN/ST=karnataka/O=golinuxcloud/OU=admin/CN=server-2.example.com V 220905045424Z 03 unknown /C=IN/ST=Karnataka/O=golinuxcloud/OU=admin/CN=server-1.example.com V 100111044010Z 04 unknown /C=IN/ST=Karnataka/O=golinuxcloud/OU=admin/CN=server-3.example.com V 210915110326Z 05 unknown /C=IN/ST=karnataka/O=golinuxcloud/OU=admin/CN=server-2.example.com
Here ignore the server-3.example.com
certificate which I had created as part of different exercise. You can notice the serial 02
and 05
content and they both have the same Subject Name so we were able to generate duplicate certificates here.
Summary
In this tutorial we covered the steps to generate duplicate certificates using openssl command. As explained we normally don't create multiple certificates using the same Subject Name in production environment and specially for external communication. if any certificate is lost, compromised or expired, in such case one should first revoke the certificate in question and then generate a new one to have a secure environment.
Although for lab use cases we may need these hacks to generate multiple certificates for containers or nodes which are frequently re-deployed.