This page looks best with JavaScript enabled

Public Key Certificate Pt. 2

 ·  β˜• 7 min read

Create a public/private key

openssl genrsa <algorithm> -out <keyfile> <key-size:2048>
# man genrsa for more details
openssl  genrsa -aes256 -out private_key.pem
#Generating RSA private key, 2048 bit long modulus (2 primes)
#........................................+++++
#.........+++++
#e is 65537 (0x010001)
#Enter pass phrase for private_key.pem:
#Verifying - Enter pass phrase for private_key.pem:

Now you need to generate a public key to obtain a certificate. Having the private key you can derive the public key:

openssl rsa -in private_key.pem -pubout -out public_key.pem

The certificate, in addition to containing the public key, contains additional information such as issuer and other types of metadata such supposed usage of the certificate.

Typically, a certificate is itself signed by a certificate authority (CA) using CA’s private key. This verifies the authenticity of the certificate.

A self-signed certificate can only provide secure communications but cannot prove the identity of the owner of the certificate.

Having a public key there are two ways to obtain a certificate:

  • sign your own certificate
  • generate a certificate request and pass it to a certification authority

CSR Certificate Signing Request

A CSR consists mainly of the public key and some additional information that will be inserted into the certificate when it is signed.

You can sign youself a certificate whith your private key. In case you need to sign a lot of certificates maybe it’s a good idea to generate your own CA so you can trust internally in your network.

openssl x509 manual page

CRS Generation

Mode 1

# req -new

openssl req -new -key private_key.pem -out cert.csr -sha256

This command will generate the CSR from your private key asking you some information to insert in the certificate.

Remember that to be a valid certificate Common Name (CN) field should be the exactly the Fully Qualified Domain Name (FQDN) of your webserver.

You can bypass the input of the informations in 2 ways:

Mode 2

# req -new

# with subject
openssl req -new -key private_key.pem -out cert.csr \
    -subj "/C=IT/O=MyOrg/OU=DeveloperUnit/CN=test/L=Noplace/ST=Nowhere" \
    -sha256

Mode 3

or with a config file name csr-conf.txt

[ req ]
default_md = sha256
prompt = no
distinguished_name = req_distinguished_name

[ req_distinguished_name ]
commonName = test
countryName = IT
stateOrProvinceName = Nowhere
localityName = Noplace
organizationName = MyOrg

and then issuing the command

# req -new

openssl req -new -key private_key.pem \
    -config csr-conf.txt -out cert.csr -sha256

Mode 4

You can do all the stuff with only one command very similar to the previous ones, this is useful if you have a lot of vhosts and you want a new private key for each one.

This command will generate also the private key private_key.pem with rsa and lenght od 2048 with no passphrase -nodes and a csr cert.csr

# req -new
openssl req -new -newkey rsa:2048 -nodes -keyout private_key.pem \
    -config csr-conf.txt -out cert.csr -sha256

It is clear that you need the change data in the csr-conf.txt every time, because it will generate a new private key for each host.

Congratulations: now You have a valid CSR.

Check a CSR

Check your newly generate certificate signing request CSR cert.csr

openssl req -in cert.csr -noout -text

Signing a CSR (Self Signed)

# x509 -req

openssl x509 -req -days 365 -in cert.csr \
    -signkey private_key.pem -out cert.pem

This will sign the certificate request cert.csr with your private key private_key.pem returning a certificate cert.pem valid 365 days.

All in One

You finally can use a very useful command to issue all the previous steps.

Create a new private key with no passphrase and generate directly certificate valid 356 days using the csr-conf.txt configuration

# req -new -x509

openssl req -new -x509 -days 365 -nodes \
    -config csr-conf.txt -out cert.pem -keyout private_key.key

Verify the content of a certificate

openssl x509 -noout -text -in cert.pem

Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number:
            07:49:53:05:a3:bf:10:58:8b:3d:cf:1c:26:d4:68:7b:51:e0:7e:17
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = IT, O = MyOrg, OU = DeveloperUnit, CN = test, L = Noplace, ST = Nowhere
        Validity
            Not Before: Sep 12 20:02:08 2020 GMT
            Not After : Sep 12 20:02:08 2021 GMT
        Subject: C = IT, O = MyOrg, OU = DeveloperUnit, CN = test, L = Noplace, ST = Nowhere
# to get only end of validy
openssl X509 -noout -enddate -in cert.pem

# notAfter=Sep 12 20:02:08 2021 GMT

Real CA

Passing this file to a CA and paying (in most of the cases) will give you a valide certificate.

Test Online Certificate

You can check a certificate from a given web server with this command

openssl s_client -connect <host>:443

Test Certificate

You can check a certificate from a given web server with this command

openssl s_client -connect <host>:443
# expiration date
openssl s_client -connect <host>:443 2>/dev/null | \
    openssl x509 -noout –enddate

Subject Alternative Name

Subject Alternative Name (SAN) is an extension to X.509 that allows various values to be associated with a security certificate using a subjectAltName field. These values are called Subject Alternative Names (SANs). Names include:

  • Email addresses
  • IP addresses
  • URIs
  • DNS names: this is usually also provided as the Common Name RDN within the Subject field of the main certificate.
  • Directory names: alternative Distinguished Names to that given in the Subject.
  • Other names, given as a General Name or Universal Principal Name: a registered object identifier followed by a value.

A Subject Alternative Name or SAN certificate can be used on multiple domain names like a-site.dev, b-site.dev and example.com where the domain names are completely different, but they can share the same certificate.

SAN

ssl.conf
[ req ]
default_md = sha256
default_bits       = 4096
distinguished_name = req_distinguished_name
distinguished_name = req_distinguished_name
req_extensions     = req_ext

[ req_distinguished_name ]
countryName                 = Country Name (2 letter code)
countryName_default         = IT
stateOrProvinceName         = State or Province Name (full name)
stateOrProvinceName_default = Italy
localityName                = Locality Name (eg, city)
localityName_default        = Nowhere
organizationName            = Organization Name (eg, company)
organizationName_default    = MyOrg
organizationalUnitName      = Organizational Unit Name (eg, section)
organizationalUnitName_default = DEV
commonName                  = Common Name (e.g. server FQDN or YOUR name)
commonName_max              = 64
commonName_default          = localhost

[ req_ext ]
subjectAltName = @alt_names

[alt_names]
DNS.1   = a-site.dev
DNS.2   = b-site.dev
DNS.3   = example.com

or without prompt

[ req ]
prompt = no
default_bits       = 4096
default_md = sha256
distinguished_name = req_distinguished_name
req_extensions     = req_ext

[ req_distinguished_name ]

countryName            = IT
stateOrProvinceName    = Italy
localityName           = Nowhere
organizationName       = MyOrg
commonName             = localhost
organizationalUnitName = DEV

[ req_ext ]
subjectAltName = @alt_names

[alt_names]
DNS.1   = a-site.dev
DNS.2   = b-site.dev
DNS.3   = example.com

and generate all the previous stuff

# private key
openssl genrsa -out private.key 4096

# cert req
openssl req -new -sha256 \
    -out private.csr \
    -key private.key \
    -config ssl.conf

openssl req -text -noout -in private.csr

# Requested Extensions:
#     X509v3 Subject Alternative Name:
#         DNS:a-site.dev, DNS:b-site.dev, DNS:example.com

# sign cert req.
openssl x509 -req \
    -sha256 \
    -days 3650 \
    -in private.csr \
    -signkey private.key \
    -out cert.crt \
    -extensions req_ext \
    -extfile ssl.conf

-extensions section
-reqexts section
These options specify alternative sections to include certificate extensions (if the -x509 option is present) or certificate request extensions. This allows several different sections to be used in the same configuration file to specify requests for a variety of purposes.

One command with SAN

openssl req -x509 -new -sha256 -newkey rsa:4096 \
    -keyout private.key -nodes -out cert.crt  \
    -config ssl.conf -extensions req_ext

Final note

You have may notice that the public key derived from the private is never used, but I’ve said also that a cerficate is build using a public key.

In all the examples the CSR is built using a private key not the public key.

WHY?

The Reason is simple: you must prove to have a private key to build a certificate. It is used to sign the information in it.

So you cannot generate a CSR without a private key.