Creating X.509 Certificates with OpenSSL
This guide describes how to create X.509 certificates with OpenSSL.
Prerequisites
- OpenSSL CLI.
- Last tested with version 3.0.4 21 Jun 2022.
Hardware Constraints
For nearly every production scenario, Peridio recommends storing your sensitive credentials in a hardware security module. It is common for hardware security modules to impose constraints on the credentials they store. For example, Microchip's ATECC608B stores certificates in a novel fashion. One can use this guide to create certificates that are compatible with the ATECC608B so long as the start dates have a resolution of hours (minute and second must be 0) and end dates are a set number of years from the issue date (must have identical month, day, hour, minute and second as corresponding issue date).
While this guide is useful for quickly creating certificates for non-production runs, one should be mindful that the choices you make with respect to production hardware, firmware, and software can impose constraints upon your public key infrastructure. To avoid unexpected delays in development and manufacturing and ensure you have the time and resources available to operate securely, it is best to make the decisions that dictate these constraints as soon as possible.
Private and Public Keys
Every X.509 certificate has a public key within it. The public key is derived from a private key. When considered together they are referred to as an asymetric key pair. Generally, this field is refered to as public-key cryptography or asymmetric cryptography.
To create an asymmetric key pair, one must first decide on a public key algorithm to use, this choice dictates:
- The cryptographic properties of the keys and in turn their capabilities and security guarantees.
- The processes required to create and interact with the keys.
This guide will use the ECDSA public key algorithm, but RSA and DSA are other common choices.
Effective security requires keeping the private key private; the public key can be openly distributed without compromising security.
WARNING: Private keys are sensitive components of a public key infrastructure. If they are leaked the entire downstream chain of trust is fundamentally compromised.
Inspect a Private Key
To inspect any private key created later in this guide:
openssl ecparam \
-in key.pem \
-text \
-noout
Create Certificates
Some of the commands below will reference an openssl.cnf
file, you must create this with the contents described at Appendix A.
The aforementioned config requires one additional file to track created certificates and one additional directory to store certificates historically. You must create them:
touch database.txt
mkdir certificates
Note that when creating certificates with the openssl ca
command that it will write the same created certificate file twice, once to the certificates
directory where the name will be the serial number in hex with .pem appended, and once to the calling directory with the name specified by the -out
option of the command.
Inspect a Certificate Signing Request
To inspect any certificate signing request created later in this guide:
openssl req \
-in certificate-signing-request.pem \
-text \
-noout
Inspect a Certificate
To inspect any certificate created later in this guide:
openssl x509 \
-in certificate.pem \
-text \
-noout
Root
Generally speaking, a root certificate authority is a certificate that:
- is self-signed
- is capable of signing certificates
Create a Private Key
Reference openssl-ecparam.
openssl ecparam \
-genkey \
-name prime256v1 \
-out root-private-key.pem
WARNING: Private keys are sensitive components of a public key infrastructure. If they are leaked the entire downstream chain of trust is fundamentally compromised.
Create a Certificate Signing Request
Reference openssl-req.
openssl req \
-config openssl.cnf \
-key root-private-key.pem \
-new \
-out root-certificate-signing-request.pem \
-section root_certificate_authority_req \
-subj "/CN=unique-root-name"
Create a Certificate
Reference openssl-ca.
You must fill in the -startdate
and -enddate
values.
openssl ca \
-batch \
-config openssl.cnf \
-enddate YYYYMMDDHHMMSSZ \
-extensions root_certificate_authority_extensions \
-in root-certificate-signing-request.pem \
-keyfile root-private-key.pem \
-out root-certificate.pem \
-selfsign \
-startdate YYYYMMDDHHMMSSZ
WARNING: The -startdate
and -enddate
options should be specified cautiously as they dictate when the certificate will be valid for. The impact of a certificate not being valid yet or having already expired is dependent on the parties interacting with it. For information regarding how Peridio interacts with certificates reference CA Certificates and Device Certificates. It is also common for hardware security modules to require these dates to be specified in a very particular manner, see Hardware Constraints.
You may retain or delete the certificate signing request depending on your use case.
The certificate can be openly distributed without compromising security.
Intermediate
Generally speaking, an intermediate certificate authority is a certificate that:
- is not self signed
- is signed either by an intermediate certificate authority or a root certificate authority
- is capable of signing certificates
Create a Private Key
Reference openssl-ecparam.
openssl ecparam \
-genkey \
-name prime256v1 \
-out intermediate-private-key.pem
WARNING: Private keys are sensitive components of a public key infrastructure. If they are leaked the entire downstream chain of trust is fundamentally compromised.
Create a Certificate Signing Request
Reference openssl-req.
openssl req \
-key intermediate-private-key.pem \
-new \
-out intermediate-certificate-signing-request.pem \
-subj "/CN=unique-intermediate-name"
Create a Certificate
Reference openssl-ca.
You must fill in the -startdate
and -enddate
values.
openssl ca \
-batch \
-cert root-certificate.pem \
-config openssl.cnf \
-enddate YYYYMMDDHHMMSSZ \
-extensions intermediate_certificate_authority_extensions \
-in intermediate-certificate-signing-request.pem \
-keyfile root-private-key.pem \
-out intermediate-certificate.pem \
-startdate YYYYMMDDHHMMSSZ
WARNING: The -startdate
and -enddate
options should be specified cautiously as they dictate when the certificate will be valid for. The impact of a certificate not being valid yet or having already expired is dependent on the parties interacting with it. For information regarding how Peridio interacts with certificates reference CA Certificates and Device Certificates. It is also common for hardware security modules to require these dates to be specified in a very particular manner, see Hardware Constraints.
You may retain or delete the certificate signing request depending on your use case.
The certificate can be openly distributed without compromising security.
End-entity Certificate
Generally speaking, an end-entity certificate is a certificate that:
- is not self signed
- is signed by either an intermediate certificate authority or a root certificate authority
- is not capable of signing certificates
Create a Private Key
Reference openssl-ecparam.
openssl ecparam \
-genkey \
-name prime256v1 \
-out end-entity-private-key.pem
WARNING: Private keys are sensitive components of a public key infrastructure. If they are leaked the entire downstream chain of trust is fundamentally compromised.
Create a Certificate Signing Request
Reference openssl-req.
openssl req \
-key end-entity-private-key.pem \
-new \
-out end-entity-certificate-signing-request.pem \
-subj "/CN=unique-end-entity-name"
Create a Certificate
Reference openssl-ca.
You must fill in the -startdate
and -enddate
values.
openssl ca \
-batch \
-cert intermediate-certificate.pem \
-config openssl.cnf \
-enddate YYYYMMDDHHMMSSZ \
-extensions end_entity_certificate_extensions \
-in end-entity-certificate-signing-request.pem \
-keyfile intermediate-private-key.pem \
-out end-entity-certificate.pem \
-startdate YYYYMMDDHHMMSSZ
WARNING: The -startdate
and -enddate
options should be specified cautiously as they dictate when the certificate will be valid for. The impact of a certificate not being valid yet or having already expired is dependent on the parties interacting with it. For information regarding how Peridio interacts with certificates reference CA Certificates and Device Certificates. It is also common for hardware security modules to require these dates to be specified in a very particular manner, see Hardware Constraints.
You may retain or delete the certificate signing request depending on your use case.
The certificate can be openly distributed without compromising security.
Appendix
A - openssl.cnf
When creating certificates and certificate signing requests there is often a set of common extensions you wish to include. It is convenient to enumerate these extensions in a config file for ease of maintenance and referenceability.
In this guide, we use the following config referenced as openssl.cnf
.
#
# ca
#
[ ca ]
default_ca=default_ca
[ default_ca ]
database=database.txt
default_days=0
default_md=SHA256
email_in_dn=no
new_certs_dir=certificates
policy=default_policy
rand_serial=yes
unique_subject=no
x509_extensions=root_certificate_authority_extensions
[ default_policy ]
countryName = optional
stateOrProvinceName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
#
# extensions
#
[ root_certificate_authority_extensions ]
basicConstraints=critical,CA:TRUE,pathlen:1
extendedKeyUsage=serverAuth,clientAuth
keyUsage=critical,digitalSignature,keyCertSign,cRLSign
subjectKeyIdentifier=hash
[ intermediate_certificate_authority_extensions ]
authorityKeyIdentifier=keyid:always
basicConstraints=critical,CA:TRUE,pathlen:0
extendedKeyUsage=serverAuth,clientAuth
keyUsage=critical,digitalSignature,keyCertSign,cRLSign
subjectKeyIdentifier=hash
[ end_entity_certificate_extensions ]
authorityKeyIdentifier=keyid:always
extendedKeyUsage=clientAuth
keyUsage=critical,digitalSignature
subjectKeyIdentifier=hash
For a comprehensive understanding of what the above configuration is doing, one should exhaustively read all of this guide's References.
References
config
OpenSSL's CONF library configuration files, reference https://www.openssl.org/docs/man3.0/man5/config.html.
openssl-ca
OpenSSL's sample minimal CA application, reference https://www.openssl.org/docs/man3.0/man1/openssl-ca.html.
openssl-ecparam
OpenSSL's EC parameter manipulation and generation command, reference https://www.openssl.org/docs/man3.0/man1/openssl-ecparam.html.
openssl-req
OpenSSL's PKCS#10 certificate request and certificate generating command, reference https://www.openssl.org/docs/man3.0/man1/openssl-req.html.
openssl-x509
OpenSSL's certificate display and signing command, reference https://www.openssl.org/docs/man3.0/man1/openssl-x509.html.
RFC 4158
Internet X.509 Public Key Infrastructure: Certification Path Building, reference https://datatracker.ietf.org/doc/html/rfc4158.
RFC 5280
Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile, reference https://datatracker.ietf.org/doc/html/rfc5280.
x509v3_config
OpenSSL's X509 V3 certificate extension configuration format, reference https://www.openssl.org/docs/man3.0/man5/x509v3_config.html.