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.
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.
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.