L0090 Certificate Extensions Part 1

When we read a certificate, we can see the version of the certificate specification at the top. Currently all certificates are using the version No. 3. Each new version had some new features. To avoid creating a new version every time a new feature is needed, extensions are introduced. When we want to add a new feature, we just add a new extension, we don't have to change certificate specification.

We will take a look at Reddit certificate. In the section "x509v3 extensions", we can find many extensions and their values. We will look at them one by one.  
openssl s_client -connect reddit.com:443 </dev/null | openssl x509 -text -noout

Reddit Certificate Extensions

Authority Key Identifier and Subject Key Identifier

Reddit certificate is signed by DigiCert CA. DigiCert has its public key. SHA1 hash of that public key is calculated and we can see it here in this field.
Subject key identifier is SHA1 hash of the Reddit public key.
The purpose of these fields is to identify certificates that make a chain. If we take a look at Reddit certificate chain, we will see three certificates. The first two belongs to DigiCert root and intermediate certificates.

We can use "-showcerts" to export the certificate chain to a file. Inside of that file, we will find intermediate and leaf certificate. Root certificate is in the folder with other root certificates that our OS trust "/etc/ssl/certs".  

openssl s_client -showcerts -connect reddit.com:443 </dev/null > reddit.chain

I will copy these two certificates into two separate files with names "Digicert1.cert" and "Digicert2.cert". Then we can read the content of these files. I am only interested into AKI and SKI fields.
cd /home/fff/Desktop
openssl x509 -in DigiCert1.crt -text -noout
openssl x509 -in DigiCert2.crt -text -noout

DigiCert1 is a leaf certificate.
DigiCert2 is intermediate certificate.
Notice that leaf AIK is the same as intermediate SKI.Now, we only miss connection between root and intermediate certificate.
I will find the root certificate in my Linux OS certificate store.
cd /etc/ssl/certs
ls | grep DigiCert_Global_Root_G2.pem

I will read AKI and SKI from the root certificate.
openssl x509 -in DigiCert_Global_Root_G2.pem -text -noout
This is self-signed certificate, so there is no AKI, only SKI.

Root certificate SKI is the same as AKI for intermediate certificate.

Now we can reconstruct the whole certificate chain.

Reading of AKI and SKI

We can read only AKI and SKI extensions, not the whole certificate.
openssl s_client -connect reddit.com:443 </dev/null  | openssl x509 -noout -ext authorityKeyIdentifier,subjectKeyIdentifier

Subject Alternative Name

When we connect to some web site and we download that site certificate, inside of that certificate we must find the URL of that site. That is how clients verify certificates.
We can verify that certificate is valid for our web site with this OpenSSL command.
openssl s_client -connect www.reddit.com:443 -verify_hostname www.reddit.com

Todays web browsers are only checking this SAN field. They are never verifying CN field.

I will remind you that for URL we can use domain, wildcard domain and multidomain.

example.com – valid only for that URL.*.example.com – valid for the first level subdomains. It will match any address like "users.example.com" or "info.example.com". It will not match two or more levels subdomains like "info.users.example.com".
DNS:example.com, DNS:google.com – now we can use the same certificate for multi domains.DNS:example.com, DNS:*.example.com, DNS:*.*.example.com – we can set our certificate to be valid for multidomans, wildcard domains with different subdomain levels, so any combination is possible.

SAN is not only for web sites addresses. We can also use:
email:               URI:               RID:                 otherName:
RID  is "registered object identifier". "otherName" is for custom identifiers.
X509v3 Subject Alternative Name:
       email:admin@example.com,
       URI:https://example.com/service

We can read only the SAN field, with option "subjectAltName".
openssl s_client -connect reddit.com:443 </dev/null  | openssl x509 -noout -ext subjectAltName

Certificate Policies

Here, we can see web page with CPS ( Certification Practice Statement ). There we can find legal/technical PDFs published by the CA that describes in detail how they protect private keys, how they verify identities, what is procedure for revocation.

This certificate was issued according to policy 2.23.140.1.2.2. This is not CA's policy. This is official policy issued by the "CA/Browser Forum". This organization have members that are major stakeholders in the PKI infrastructure. It includes CAs, web browser vendors, OS creators, email server providers and others.

These policies mostly explain how thoroughly the identity of the certificate owner was vetted before issuance. We already talked about OV, EV, DV certificates. These policies refer to these different kinds of verification. Some of the most popular policies are:

2.23.140.1.2.2 2.23.140.1.2.1  2.23.140.1.2.3  2.23.140.1.1     2.23.140.1.4.1  
Organization ValidatedDomain ValidatedIndividual ValidationExtended ValidationCode Signing

We can extract certificate policies from a certificate with this option.
openssl s_client -connect reddit.com:443 </dev/null  | openssl x509 -noout -ext certificatePolicies

Key Usage

The Key Usage extension specifies what cryptographic operations the certificate's public key is allowed to perform. Our key can only be used for signing. This extension is marked as "critical". If a client doesn't understand this "critical" extension, it should reject the certificate with this extension.

"Key Encipherment" means that the key can be used for signing other keys. This is only important and useful for RSA keys.

There are many different usages that we can provide in this extension:

Digital SignatureFor signing certificates, code, files.Content CommitmentSigning can not be later denied. For legal documents.
Data EnciphermentFor signing data directly. Rarely used.Key AgreementThe key can participate in key agreement protocols ( DH of ECDH ).
Certificate SignCan sign certificates.CRL SignCan sign certificate black lists.
Encipher OnlyOnly for encryption.Decipher OnlyOnly for decryption.

Key usage options are usually used in these combinations.

Signatures → Digital Signature, Content CommitmentEncryption → Key Encipherment, Data Encipherment
Key exchange → Key Agreement, Encipher Only, Decipher OnlyCA operations → Certificate Sign, CRL Sign

We will only read key usage option from a certificate.
openssl s_client -connect reddit.com:443 </dev/null  | openssl x509 -noout -ext keyUsage

Extended Key Usage

The Extended Key Usage extension specifies for what scenarios a key may be used. Our key can only be used to authenticate a TLS/HTTPS server.

These are possible application scenarios that we can use the key for.

TLS Web Server AuthenticationFor server authentication.TLS Web Client AuthenticationFor client authentication.
Code SigningFor signing code.E-mail ProtectionFor email certificates.
Time StampingServer that proves the time of signing.OCSP SigningFor signing certificate white lists.

We can read only the data about extended key usage.
openssl s_client -connect reddit.com:443 </dev/null  | openssl x509 -noout -ext extendedKeyUsage

CRL Distribution Points

Sometimes certificates get revoked. That can happen because the private key is compromised or domain ownership changed. The problem is how to inform a client that some certificate is no more valid. This can be done with certificate revocation lists.

This extension will give us URL through which we can download a list of revoked certificates. This list is refreshed by the CA every few hours. We should not trust the certificates that are on this list.

There will be usually two URLs for redundancy. The URLs do not use HTTPS, but HTTP because their content is public, and it is signed by a CA so that no one can compromise the integrity of such a list. Let's learn a little bit more about certificate revocation lists ( CRL ).

How to Get onto Revocation List?

When you feel that something is wrong with your certificate, you can contact your CA and declare that your certificate should be revoked. Another possibility is that the CA revokes your certificate if there is evidence that some suspicious activity is being performed with that certificate.

Sometimes it is a good idea to purchase a certificate and then immediately try to revoke it. It is possible that the CA does not offer certificate revocation. It is also possible that the clients we use cannot read CRL services or are misconfigured. We want to test that.

Some modern environments don't use CRLs because the downloaded file is big in megabytes, and because the list is refreshed every few hours, the data in these lists is stale. Today, we have a better technology, OCSP, which we will discuss later.

How to Download CRL List?

CRLs are typically downloaded every few hours and then cached. I will download CRL file using URL from Reddit certificate.
wget http://crl3.digicert.com/DigiCertGlobalG2TLSRSASHA2562020CA1-1.crl
I will get a file with this name. The file size is 9.7 MB.
DigiCertGlobalG2TLSRSASHA2562020CA1-1.crl
                                                                                              

We can read this file with "crl" command. This is usually a binary file with DER format. Because this file is long, I will read only the first 100 lines. Most lines will be serial numbers of a certificates.  
openssl crl -in DigiCertGlobalG2TLSRSASHA2562020CA1-1.crl -inform DER -text -noout  | head -100

If we look for Reddit certificate serial number, we will not find it inside of this list, so that certificate is not revoked.
openssl crl -in DigiCertGlobalG2TLSRSASHA2562020CA1-1.crl -inform DER -text -noout | grep "0e:9e:4f:5d:82:fc:c4:14:5f:d8:8f:d3:9c:2a:31:11"

Getting Only the CRL Extension

With option "crlDistributionPoints", we can separately read only the CRL list addresses.
openssl s_client -connect reddit.com:443 </dev/null  | openssl x509 -noout crlDistributionPoints

L0080 Keys

Different Formats

Base64

Secret keys (RSA, EC, AES) are just big numbers. Any number can be represented in binary as a string of ones and zeros. For example, the number 199 can be represented as "11000111". For historical reasons, we don't want to store and share our keys as binary numbers.

Many historical technologies were built only for text exchange. Such as email, text editors, terminals. Some technologies can work with binary data, but are better suited for text (such as XML and JSON). This is why we want to store our private and public keys as text.

For better compatibility, we want to limit ourselves to only those letters and other characters that are universally understood. Base64 uses an alphabet of only 64 characters ("A-Z, a-z, 0-9, +, /"). If we do not practice text simplicity with a limited number of characters, we risk our keys becoming corrupted and invalid during manipulation.

Base64 works by simple substitution, so number 199199199, which is "11000111 11000111 11000111" in binary format, can be represented as "x8fH" in base64 encoding. That is why the keys look like a sequence of random letters.

000000000001000010011010011011011100110100111101111110111111110001111100011111000111
ABCabc09+/x8fH

PEM Format

When we create a new key, it will be in base64 format.
openssl genpkey -algorithm ed25519 -out private.key

We can easily send and copy this key. Inside of the file, we also have text that is telling where is the start and end of our key. If we see such file, the file is in the PEM format ( Privacy-enhanced Mail ). This is the most used format for storing and sending cryptographic files.

DER Format

DER file format is a binary format. We can easily transform PEM file into DER file in 2 steps:
– First we remove "BEGIN/END PRIVATE KEY" text.
– Then we decode base64 into zeros and ones.

DER ( "Distinguished Encoding Rules" ) is much more than pure binary format. While keys are just big numbers, certificates contain text, dates, fields and structure. Certificates are also base64 encoded, while in PEM format. To get a readable format, we must base64 decode them into binary format and then to encode them again into English language format.

Mapping between binary format and English language must be deterministic and precise. That is why DER format is important. This format tells us how fields are encoded, how strings/dates are encoded, how the structure is encoded. There is no place for ambiguity and obscurity.

DER file format is used by software, it is not for humans. For software DER files are smaller and easier than PEM files.

PKCS#12 Format

PKCS#12 is a standardized file format for storing and transporting cryptographic material in a single file. This file can contain a private key and the whole chain of certificates. It is cumbersome to manage a key and all of the certificates separately. It is much more convenient to pack everything into one "suitcase". That makes importing, distributing, backing up, much more convenient.

PKCS#12 files are usually encrypted. Encryption protects the content and integrity of a file.

PKCS#12 files are used by organizations to provide authentication of the users. Users add those files into browsers, email clients, smart cards. Windows heavily uses PKCS#12. Some servers, like Microsoft IIS, prefer cryptography files in PKCS#12 format. Mobile device management (MDM) systems distribute client certificates to phones and tablets as ".p12" files.

PKCS#12 files contain keys and certificates in DER format. All of them are encrypted together for safety and convenience. The full name of this format is "Public-Key Cryptography Standards #12".

File Format Extensions

.pemFiles with this extension can store private keys or certificates. They are in the PEM format.
.keyExtension KEY is used for private keys. This extension is used no matter if the keys are in PEM or DER format.
.crtCertificates in PEM format are saved in files with CRT extension.
.cerCertificates in DER format are saved in files with CER file extension.
.pfxThis file format extension is used for PKCS#12 files. These files can contain keys and certificates together, or separately.
.p12Same as above. ".pfx" and ".p12" are the same binary format.
.pubIs used for public keys in PEM format.
.csrIs used for certificate signing requests in PEM format.

File format extensions are not important for OpenSSL. For OpenSSL is important that content of a file is correctly formatted. We can name our files anyway we want if we work with OpenSSL, but some other programs can be picky.

We said that PKCS#12 standard files are always in binary format. Contrary to that, PKCS#8 and PKCS#10 files are in the PEM format. When we see a key file presented as PEM, internally it is following PKCS#8 standard. Similar to that, ".csr" files are following PKCS#10 standard.

Veryfication of a Key

I will create one private key. It will be in the PEM format.
cd /home/fff/Desktop
openssl genpkey -algorithm ed25519 -out private.key
This is how we can check whether the key is correct.
openssl pkey -in private_key.pem -check

Format Conversions

Key Format Conversions

PEM to DER

We have PEM key. Let's convert it into DER format.
openssl pkey -inform PEM -in private.key -outform DER -out privateDER.key
This is binary format DER.

DER to PEM

We can transform our key back to its original format PEM.
openssl pkey -inform DER -in privateDER.key -outform PEM -out privatePEM.key

PEM to PKCS#12

We can place PEM key into P12 container. We must provide a password for PKCS#12 container.
openssl pkcs12 -inkey privatePEM.key -export -nocerts -out P12key.p12 -passout pass:1234

This is how we can read P12 key.
openssl pkcs12 -noenc -info -in P12key.p12 -passin pass:1234

DER to PKCS#12

It is not possible to directly transform a DER key into PKCS#12. We can do this by using the PEM format as an intermediary.

Certificate Conversion

Certificate Creation

We already now how to create a certificate. Certificate is made by signing CSR file with a private key.

openssl req -new -subj "/CN=Root CA" -addext "basicConstraints=critical,CA:TRUE" -key privatePEM.key -out RootCSR.csrWe create CSR.
openssl x509 -req -in RootCSR.csr -copy_extensions copyall -key privatePEM.key -days 365 -out RootCert.crtWe make certificate.

PEM to DER

This is how we can transform PEM certificate into DER certificate.  
openssl x509 -inform PEM -in RootCert.crt -outform DER -out RootCertDER.crt  
We can read DER certificates with x509 command.  
openssl x509 -in RootCertDER.crt -inform der -text -noout

DER to PEM

We can transform DER format into PEM format, of a certificate.  
openssl x509 -inform DER -in RootCertDER.crt -outform PEM -out RootCertPEM.crt

PEM to PKCS#12

We use option "-nokeys" to export PKCS#12 certificate from PEM certificate. We must provide a password.
openssl pkcs12 -in RootCertPEM.crt -export -nokeys -out RootCert.p12 -passout pass:1234

If we provide a certificate and a key, we can export them both into PKCS#12 format.
openssl pkcs12 -in RootCertPEM.crt -inkey privatePEM.key -export -out KeyPlusCert.p12 -passout pass:1234

We are working with a self signed certificate. If we had CA signed certificate, then we can add CA certificate inside of the PKCS#12 file too. For that we use "-certfile ca.crt" option.
# openssl pkcs12 -in RootCertPEM.crt -inkey privatePEM.key -export -out KeyPlusCert.p12 -passout pass:1234 -certfile ca.crt

We can export only the key. I will use "-nocerts" to exclude certificates.
openssl pkcs12 -inkey privatePEM.key -export -nocerts -out NocertsP12key.p12 -passout pass:1234

PKCS#12 to PEM

These commands will convert PKCS#12 files back into PEM format.
openssl pkcs12 -in RootCert.p12 -nokeys -out NoKeysRootCertPEM.crt -passin pass:1234    # get certificate
openssl pkcs12 -in KeyPlusCert.p12 -nokeys -out OnlyRootCertPEM.crt -passin pass:1234   # get only the certificate, without the key
When exporting the key, we will be asked for a password to unencrypt the key. Our key is unencrypted, so I will use "-noenc" to avoid the question.
openssl pkcs12 -in KeyPlusCert.p12 -nocerts -noenc -out NoCertsprivatePEM.key -passin pass:1234 # get only the key, without certificate

It is possible to export both the key end the certificate. The exported file will have both the certificate and the private key.  

openssl pkcs12 -in KeyPlusCert.p12 -noenc -out Everything.pem -passin pass:1234

PKCS#12 vs DER

It is not possible to convert directly between PKCS#12 and DER files. We can do the conversion indirectly using a PEM file as an intermediary.

PKCS#12 and Certificate Chain

We will download certificate chain from the website www.facebook.com. We will not get root certificate ( it is already on our computer ), but we will get leaf and intermediate certificate.
openssl s_client -connect www.facebook.com:443 -showcerts </dev/null > facebook-chain.pem
We will create PKCS#12 file that has the whole certificate chain.
openssl pkcs12 -in facebook-chain.pem -export -nokeys -out facebook-chain.p12 -passout pass:1234

Now we will transform this chain back. We can get both certificates, only leaf certificate, or only intermediate certificates.

This command will return the whole certificate chain. It will include both the leaf and intermediate certificate.
openssl pkcs12 -in facebook-chain.p12 -nokeys -out facebook-chain2.pem -passin pass:1234  
This command should return the leaf certificate. OpenSSL will return the blank file. OpenSSL can not recognize what certificate is leaf certificate. To assert that, OpenSSL must know the private key. The certificate that matches the private key is leaf certificate. Because we do not have the private key, we will get a blank file.
openssl pkcs12 -in facebook-chain.p12 -clcerts -nokeys -out facebook-leaf.crt -passin pass:1234 # get leaf ( client ) certificate
If OpenSSL can not recognize the leaf certificate, then all of the certificates will be considered intermediate. That is why this command will return both certificates, although we asked only for intermediate certificate.
openssl pkcs12 -in facebook-chain.p12 -cacerts -nokeys -out facebook-intermediates.crt -passin pass:1234 # get intermediate certificates

How to Recognize Cryptography File Format?

We made 3 certificate files.RootCertPEM.crtRootCertDER.crtRootCert.p12

To test their format, we must try to open them.

openssl x509 -in RootCertPEM.crtIf this succeed, this is a PEM file.
openssl x509 -in RootCertDER.crt -inform DERThis would be DER file.
openssl pkcs12 -in RootCert.p12 -noencThis will show us that we have PKCS#12 file.

L0070 Certification Chain

A certificate chain is a sequence of digital certificates where each certificate is signed by the previous certificate in the chain. That allows a client to verify that a server's certificate is trustworthy, by tracing it back to a root CA.

This structure doesn't have to be linear, it can have a shape of a tree.

Creation of a Certification Chain

We will make our own certificate chain. We will create three certificates, just like on the image above.

Root Certificate

I will create root private key. This is RSA private key.cd /home/fff/Desktop
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out RootCA.key

We will use the CA private key to generate CSR file. We will add one extension. Extensions are those special elements in a certificate. The name of extension is "basicConstraints". Here we say whether the private key can be used to sign other keys. For root and intermediate certificates, we must set this setting to true ( CA:TRUE ). For leaf certificates it will be FALSE.
critical – this is severity of our setting. Possible values are critical and non-critical. Default is non-critical. If the setting is critical then a client must obey that setting. If a client doesn't understand the critical setting, then it must reject connection. For "basicConstraints" extension we must always use critical.
openssl req -new -subj "/CN=Root CA" -addext "basicConstraints=critical,CA:TRUE" -key RootCA.key -out RootCSR.csr

Inside of the CSR file, we can see our extension.  

openssl req -in RootCSR.csr -noout -text

CA will sign its own key. "RootCSR.csr" will be signed by "RootCA.key". The result is certificate "RootCert.crt".
openssl x509 -req -in RootCSR.csr -copy_extensions copyall -key RootCA.key -days 365 -out RootCert.crt

openssl x509 -in RootCert.crt -noout -text
Issuer and Subject of the self signed certificate are the same. Validity of this certificate is 365 days.
By default, extensions will not be copied from the CSR file to the certificate. We need to use the option "-copy_extensions copyall" to make that happen.

Intermediate Certificate

We will create elliptic private key for intermediate certificate.openssl genpkey -algorithm ED448 -out Intermediate.key

After that, we will create intermediate certificate signing request, based on that key.
openssl req -new -subj "/CN=Intermediate CA" -addext "basicConstraints=critical,CA:TRUE" -key Intermediate.key -out Intermediate.csr

The next step is to sign CSR file. For signing process we must provide both root private key and root certificate. Private key is used for encryption, but certificate is used for information. Data about root CA will be copied from root CA certificate into intermediate certificate.
openssl x509 -req -in Intermediate.csr -copy_extensions copyall -CAkey RootCA.key -CA RootCert.crt -days 365 -out Intermediate.crt

Intermediate certificate is issued by "Root CA" to "Intermediate CA".  
openssl x509 -in Intermediate.crt -noout -text

Leaf Certificate

The last piece of the puzzle is leaf certificate. No matter the certificate, we always follow the same steps.

We will generate elliptic leaf key.openssl genpkey -algorithm ED448 -out LeafKey.key

Based on the private key, we will create CSR file. "basicConstraint" is set to FALSE for the leaf CSR.
openssl req -new -subj "/CN=Leaf" -addext "basicConstraints=critical,CA:FALSE" -key LeafKey.key -out LeafCSR.csr

We will use intermediate key to sign leaf CSR file. We will transfer Issuer data from intermediate certificate to leaf certificate.
openssl x509 -req -in LeafCSR.csr -copy_extensions copyall -CAkey Intermediate.key -CA Intermediate.crt -days 365 -out LeafCert.crt

The leaf certificate is issued by "Intermediate CA". "basicConstraint" is set to FALSE.  
openssl x509 -in LeafCert.crt -noout -text  

As a result, we ended up with 9 files. The CSR files can be deleted, but we will still have 6 other files. Key proliferation is something we need to take seriously. In large organizations, the number of keys can grow dramatically, and this requires meticulous key management.

Certificate Verification

This is how we can verify certificate chain. We have trust in the root certificate, but not into intermediate certificate. Because, this is a chain of certificates, we only need one certificate we trust.  

openssl verify -verbose -show_chain -trusted RootCert.crt -untrusted Intermediate.crt LeafCert.crt

We can also use option "-CAfile" to designate the root certificate.  
openssl verify -show_chain -CAfile RootCert.crt -untrusted Intermediate.crt LeafCert.crt
We would get the same result.

Certification Chain with Long Commands

Root CA

We can run this long command to get self signed root certificate.
openssl req -new -newkey rsa:2048 -noenc -keyout RootCA.key -x509 -subj "/CN=Root CA" -addext "basicConstraints=critical,CA:TRUE" -days 365 -out RootCert.crt

Intermediate Level

This command will create private key and CSR for intermediate level.
openssl req -new -newkey ED448 -noenc -keyout Intermediate.key -subj "/CN=Intermediate CA" -addext "basicConstraints=critical,CA:TRUE" -out Intermediate.csr

We will sign the CSR, to get intermediate certificate.
openssl x509 -req -in Intermediate.csr -copy_extensions copyall -CAkey RootCA.key -CA RootCert.crt -days 365 -out Intermediate.crt

Leaf Level

We will repeat the same steps as from intermediate level, to create a key and CSR for leaf level. First, we will get private key and CSR file.
openssl req -newkey ED448 -noenc -keyout LeafKey.key -subj "/CN=Leaf" -addext "basicConstraints=critical,CA:FALSE" -out LeafCSR.csr

The last step is to sign leaf CSR file, and to get leaf certificate.
openssl x509 -req -in LeafCSR.csr -copy_extensions copyall -CA Intermediate.crt -CAkey Intermediate.key -days 365 -out LeafCert.crt

Usage of a Chain

We will test chain of certificates with an OpenSSL server. We will start the server, and we will provide private key and certificate of the leaf. We must also provide an intermediate certificate.
openssl s_server -port 4433 -key LeafKey.key -cert LeafCert.crt -cert_chain Intermediate.crt

On the side of the client, we will provide certificate of the root.openssl s_client -connect localhost:4433 -CAfile RootCert.crt

The client is waiting to communicate with the server using the root certificate. The client only needs that certificate to authenticate the server. The server needs to prove its identity, and to do that, it needs the entire chain. That's why the server has both a leaf and an intermediate certificate. The server will send both certificates to the client. The client will then have all three chained certificates. The client trusts the root CA certificate, and because of that, it will trust the intermediate and leaf certificates. That's how a certificate chain works.

Client and server can now have their protected conversation.

Why do We Need Certificate Chains?

If we look at the certificate chain for the Facebook website, we see at the top the DigiCert certificate. Below that is the intermediate certificate, also from DigiCert. At the bottom is Facebook.

The purpose of certificate chains is to reduce the risk of a CA's private key being compromised. The CA will use its private key to sign a number of intermediate keys. These intermediate keys will be used to sign user certificates. The root key will be hidden, where no one can find or access it. No one will be able to steal the root private key, but the CA will still be able to sign user certificates normally.

If the intermediate private key is compromised, it will only affect some users and will not destroy the CA's business. Certificate chains are a solution for CAs to protect themselves and their users.

Where Does Root Certificates Come From?

When we browse the Internet, we use TLS. When we download some programs to our computer, the program installation files are signed using asymmetric keys. The question is how we can trust web sites and downloaded files if we have never downloaded a certificate from a certification authority.

The answer is that these CA certificates are already on our computer. Trusted root certificates are already determined by the platform creator. A platform can be an operating system, a web browser, a web server, a VPN server. When we install Ubuntu, we will get all the root certificates that Ubuntu trusts. When we install a web browser, that web browser will have many certificates in it. When we trust some servers or some websites, it is because Ubuntu and Chrome already have pre-installed certificates that provide trust to those servers/sites.

Ubuntu has its certificate store on this location:
/etc/ssl/certs

Inside of this folder we can see many certificates in PEM file format.

Content of one PEM file.

I have Brave browser installed. Its certificates are at the location "~/.local/share/pki/nssdb".

When we connect to some server, the server will send us certificate chain ( without the root certificate ). We will then search our local certificate store to find CA certificate that is valid for that certificate chain. Because we trust CA certificates from the local repository, then we will able to trust other certificates in the certificate chain.

L0060 Certificate Signing Request (CSR)

Self signed certificates are great for communication between nodes that we have full control of. If we want to make our servers available over the internet, and make them exposed to users, then mutual trust and security must include Certificate Authority. We need CA to sign our certificate.

What is CSR?

If we need CA to sign our certificate, we first must send it what to sign. That is CSR. A CSR (Certificate Signing Request) is essentially an application you submit to a Certificate Authority asking them to issue you a signed certificate. This is one file that we send to CA, CA will verify information from that file, and after successful verification, it will send us back signed certificate.

First, we create a private key, we type identity information, and from them we create a CSR request.
After that, we send CSR ( and some money ) to Certification Authority, and then we wait for their answer.

During that time, CA will verify the data that we have send them.

What CSR Contains?

CSR is, in many ways similar, to selfsigned certificate. It has the same three sections.Data:Signature Algorithm:Signature Value:

In the Data: section we have identity data and we have our public key. We used algorithm from the Signature Algorithm: to create that public key and accompanied private key.

Signature Value: is the same as in the self signed key. We used our private key to sign everything from the Data: and Signature Algorithm:  sections.. Signature Value: section contains other two sections signed with our private key.

Signature Value: is used to prove that we control the private key that match the public key from the Data: section. Without this anyone would be able to create CSR with our public key.

There are some things that are missing compared with self signed certificate. It has no Issuer filed, no validity period ( "not before" / "not after" ). CSR is unsigned certificate that is incomplete until CA sign it.

The CSR does not contain a private key. The private key is never shared with anyone. Our CA doesn't have to know our private key.

CSR Verification

Certification Authority will check whether Signature Value: match the public key. Beside that, verification depends on the type of the certificate. There are 3 kinds of certificates: DV, OV, EV. There are also IV certificates.

Domain Validated ( DV )  
                       
These are the cheapest certificates. They will only validate that we control some internet domain.
Organization Validated ( OV )  

Beside domain validation, CA will check does our organization really exist. They will search for it in the government business registries and official company databases. They will visit its web site, and will call phone numbers of the organization.
Extended Validation ( EV )  

EV is similar to OV, but it is much more expensive and the validation process is more complex. CA will check the physical location of the company. They can send someone for a visit. They will ask government about legal status of the company. They will ask for identity of the person sending a CSR, and they will check if that person has authority to request a certificate in the name of the company. This kind of a certificate is usually an overkill and even big corporation will use OV certificate instead of it.

Individual Validation (IV) is a type of certificate used to verify a person. The CA will verify your personal identity (passport, ID card, driver's license), verify your physical address, and verify your phone number. This type of certificate is sometimes used to prove that someone owns an internet domain or email address. It is sometimes used to sign documents or software code.

Creation of an RSA Key

Before we create a CSR, we must create a private key.openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out private.key
                                                                                                                                                                 
Private key will have PEM format.



We can read content of this PEM file with "pkey" command =>
openssl pkey -in private.key -text -noout

Creation of a CSR File

Based on the private key we will create a CSR file. We use req command to create CSR file.  
openssl req -new -key private.key -out request.csr  
Just like for a certificate, we will be asked to provide Country, State, City, Department and other data. I will just type Enter each time and I will go through all of the question without providing any data.  

On the image above we can see two unfamiliar prompts. At the bottom we will be asked for a "challenge password" and an "optional company name". These are the fields that today don't have any purpose and we should ignore them. They are not used anymore.

CSR file will have familiar PEM format.

For request we use "req" command. We can use it to read text of the CSR file.
                                                                            
openssl req -in request.csr -noout -text
Notice that fields "C,ST,O" are filled with default values. We have a country, state and organization. This will happen any time we use Enter to walk through CSR prompts. Default values will be used.To make these fields empty we must type dots.

I will create the same CSR file again, but this time I will type dots.

We will get an error, because we must provide at least one field value.
I will run it again, but this time with I will provide a Country.
We can now read from the request. We will see that only the field for a Country has a value.
openssl req -in request.csr -noout -text

How to Create a Key and CSR File with One Command?

It is possible to simplify creation of a key and CSR. We use this command line. We also used "subj" option to avoid getting questions.
openssl req -new -newkey rsa:2048 -noenc -keyout private.key -out request.csr -subj "/C=AU"

Encryption

When we use "req" command to create a key and a CSR file, we must provide "-noenc" to avoid encryption of a key. When we use "genpkey" command to create standalone key, then we don't have to provide "-noenc" option, because the key will be unencrypted.

openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out private.key -aes-128-cbc  
To encrypt the key, we must provide encryption algorithm. Password must be over 4 characters.

If you want to use some other cipher for key encryption, you can search for it with this command. The cipher we used is also here.  
openssl list -cipher-algorithms | grep "AES-128-CBC"

Creation of an EC Key

We can create EC private key with "genpkey" command.openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:prime256v1 -out private.key
We already learned that instead of providing a curve, we can provide algorithm name. Algorithm will assume the curve used.openssl genpkey -algorithm ed25519 -out private.key
                                                                                                                                                                            

I will read the content of a private key.  
openssl pkey -in private.key -text -noout  
Interesting thing is that we will get both Private and Public key. Opposite from RSA keys, EC public keys are directly derived from the private keys. We get both keys because EC keys are short and it is easy to derive public key from a private key.

Verification of a CSR File

Public key and Signature Value: in CSR file must match. We can verify that with this command.
openssl req -in request.csr -verify -noout

Extraction of a Public Key

We have already saw how to extract public key from a private key.openssl pkey -in private.key -pubout
By using redirection we can save this key into a file:  

openssl pkey -in private.key -pubout > public.pub
We can do the same with "-out" option.openssl pkey -in private.key -pubout -out public.pub

I will remind you that we can extract public key from a certificate. We did this in an article about self-signed keys.# openssl x509 -in certificate.crt -pubkey -noout
The last extraction is from a CSR file.
openssl req -in request.csr -pubkey -noout
                      

L0050 Self Signed Key

Self signed key is useful when we want to protect communication between two devices that are under our control. In this case there is no "mutual friend" ( Certificate Authority ) that will sign our certificate.

As a result, we will get one private key and 1 certificate. Our private key will be used to sign a certificate.

Self Signed RSA Key

This is OpenSSL command that will create RSA private key and self signed certificate. Let's dissect this command.
cd /home/fff/Desktop
openssl req -x509 -sha256 -noenc -days 365 -newkey rsa:2048 -keyout private.key -out certificate.crt

req -x509This command is asking for creation of a self signed certificate.
-sha256Certificate data hash will be made by using SHA algorithm.
-noencPrivate key will not be encrypted. This is needed if we want to use our key automatically.
-days 365Our certificate will be valid from today ( 20.06.2026. ) till 20.06.2027.
-newkey rsa:2048We will create RSA asymmetric key with size of 2048 bits.
-keyout private.keyIn the current directory we will get a file with a private key.
-out certificate.crtIn the same directory we will get certificate file.

In terminal, we will now get a list of questions about certificate owner.
"RS" – 2 code abbreviation of a country name.
"Belgrade" – state or province.
"Belgrade" – city.
"Example Corp" – the name of the organization.
"Analytics Department" – department inside of the organization.
"Polychronis Hikari" – personal name. This is certificate for a person.
"hikari@gmail.com" – email address of that person.

Reading of Private Key and Certificate

We will use "x509" command to read our certificate:          openssl x509 -in certificate.crt -text -noout

We can notice that Issuer and Subject are the same. That is because this is self signed certificate. Algorithm used is SHA256 and RSA. The certificate is valid for 365 days from today.

For reading the private key, we use "pkey" command with similar options as for a certificate.
openssl pkey -in private.key -text -noout

The result will have a list of hexadecimal numbers. All of these numbers belong to RSA key. We can notice Modulus (N), Private (E) and Public (D) exponents, Prime 1 (P) and Prime 2 (Q). We used letters N, E, D, P, Q as variables for the explanation how RSA calculation works.

For reading of this key, we don't have to provide a password because the key is not encrypted.

CN Property Clarification

CN means "common name". CN is a text property. CN Property exists in the Subject and Issuer elements of the certificate.

Issuer:   CN = Let's Encrypt R12This is the name of a certification authority.
Subject: CN = example.com
               CN = Polychronius Hikari
               CN = My Root CA
Here we write domain name, or a person name, or the purpose of a key. The goal is to identify for what purpose will this key be used.

Long ago, CN for Subject was important because this was the place where we wrote a domain name. Internet browser would then verify this domain name with URL that client is trying to connect to. Long ago CN was one of the most important parts of a certificate.

The problem with CN is that was accepting only one domain. Users were not able to have many domains signed by the same certificate. Today the CN is not validated by modern internet browsers. Instead of CN we use SAN ( "Subject Alternative Name" ). SAN is part of extensions in a certificate. SAN has ability to accept several domain names.

Providing CN and SAN Value in "req -x509" Command

We can provide "C,ST,L,O,OU,CN,emailAddress" data with "-subj" option. We can provide SAN data with "-addtext" option.
openssl req -x509 -sha256 -noenc -days 365 -newkey rsa:2048 \
-subj "/C=RS/ST=Belgrade/L=Belgrade/O=Example Corp/OU=Analytics Department/CN=Polychronis Hikari/emailAddress=hikari@gmail.com" \
-addext "subjectAltName=email:hikari@gmail.com,DNS:polychronis.example.com,IP:127.0.0.1" \
-keyout private.key -out certificate.crt

For SAN data, we must define type of the protocol ( "email, DNS, IP" ). I will run the command above. This time we will not get prompts to provide "C,ST,L,O,OU,CN,emailAddress" data. We can read our certificate.

At the bottom of "Data:" section we have extensions. Here we can see the value of SAN extension.
SAN is not the only extensions that can be defined with "-addext" option. All extensions can be provided this way.

Root Domain, Wildcard Domain, Multidomain

-addext "subjectAltName=DNS:www.example.com"
                                                                     
This is valid for "https://www.example.com", but not for "https://example.com" and                                                                                                        "https://shop.example.com".

DNS:www.example.comRoot domains are only valid for the specific domain with precisely the same name.
DNS:www.example.com,DNS:maps.google.comMultidomain is set of several domains. We can use the certificate for all of them.
DNS:*.example.comThis is wild card domain. It is only useful for one level subdomain. Think about it as "<anything>.example.com". This wildcard domain will not work for "example.com" and "a.b.example.com", but it will work for "www.example.com" and "shop.example.com".

We can combine these domain names in different ways.DNS:www.example.com,DNS:maps.google.com,DNS:*.*.example.com

Encryption

I will create private key with encryption. I will use "-subj" option to avoid getting questions.
openssl req -x509 -sha256 -subj "/C=RS" -days 365 -newkey rsa:2048 -keyout private.key -out certificate.crt

This time I will get prompts for a password. Password must have at least 4 characters.
For reading this private key we must provide password.
openssl pkey -in private.key -text -noout

When a key is encrypted, the header of the key is changed. It says ENCRYPTED.We can decrypt private key like this:
openssl pkey -in private.key -out unencrypted.key

We can encrypt the key again.
openssl pkey -in unencrypted.key -aes256 -out private.key

Password

openssl pkey -in private.key -out unencrypted.key -passin pass:"pass123"
openssl pkey -in unencrypted.key -aes256 -out private.key -passout pass:"pass123"

                                                                                                                              
We can encrypt and decrypt the key again, but this time, we can provide a password inside of the OpenSSL command.

Important thing is that we must provide the source of a password. Source can be stdin, a file or a an environ.

echo "pass123" > pass.txt
export MYPASSWORD="pass123"
I will create a file with a password, and I will also create one environ with a password.

We can decrypt the key with the password from the file.
openssl pkey -in private.key -out unencrypted.key -passin file:"pass.txt"
We can encrypt it with the password from an environ.
openssl pkey -in unencrypted.key -aes256 -out private.key -passout env:MYPASSWORD

Self Signed Eliptic Key

The command that will create EC keys is similar. This time we have another option "-pkeyopt".
openssl req -x509 -sha256 -subj "/C=RS" -noenc -days 365 -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -keyout private.key -out certificate.crt

For EC keys we must choose a "curve". This is parameter that is deciding the strength of the key.ec_paramgen_curve:prime256v1           # most popular for web sites ec_paramgen_curve:secp384r1            # stronger, for governments and banks ec_paramgen_curve:secp521r1            # strongest, but rarely used
openssl ecparam -list_curvesWe can list all of the curves by using this command. There are dozens of these curves.

When we use "-pkeyopt", we choose a curve. Instead of that we can choose algorithm directly. Algorithm already has a curve specified. These are newer algorithms. For algorithms we are using option "-algorithm". These are two used the most.-algorithm X25519
                              
-algorithm ED25519
                              

EC keys are much smaller than RSA keys. On the image we can see the whole key. That is why EC is faster than RSA.

Exporting a Public Key

We can get a public key based on the private key.
openssl pkey -in private.key -pubout  

-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE12P1PRoujnQCWgwCvPyN8q1CR/Pl
tCoegq6+OAQ6iqRe9R0SNtnml3FBPUijajZwLXv9IkGJIJ2BrvXkALBe/w==
-----END PUBLIC KEY-----
We can get public key from the certificate.
openssl x509 -in certificate.crt -pubkey -noout  

-----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE12P1PRoujnQCWgwCvPyN8q1CR/Pl tCoegq6+OAQ6iqRe9R0SNtnml3FBPUijajZwLXv9IkGJIJ2BrvXkALBe/w==
-----END PUBLIC KEY-----

Linking Private Key and the Certificate

We can see above that exported public keys, from the private key and from the certificate, are the same. We can use that fact to detect linked private keys and certificates. Because public keys can be long, we will create digest from them, so we can easily compare those digests.

openssl pkey -in private.key -pubout | openssl sha256  

SHA2-256(stdin)= 0a44ba248fa6ca1ba6d392f93f00858d6abc84b4c8ffa59471d9ee8c003e63b7
openssl x509 -in certificate.crt -pubkey -noout | openssl sha256  

SHA2-256(stdin)= 0a44ba248fa6ca1ba6d392f93f00858d6abc84b4c8ffa59471d9ee8c003e63b7

Now we can eyeball that this private key and this certificate are linked together.

Exporting and Reading Public Key

This is how we can export public key to a file.
openssl pkey -in private.key -pubout -out public.pub
Pkey is a command for reading a private key. If we use option "-pubin", we can also use it to read public keys.
openssl pkey -in public.pub -noout -text -pubin