Creating a SSL certificate is a unavoidable step of the setup of a encrypted connexion (HTTP, IMAP, FTP, etc.). This guide describe how to generate a valid SSL / TLS certificate.
This howto is tested on:
- Debian 5.0 Lenny
- Debian 6.0 Squeeze
- Debian 7.0 Wheezy
- Debian 10.0 Buster
Prerequisites
This howto recommends:
- la surveillance de l’expiration des certificats SSL/TLS, comme décrit par Mettre en place une notification par email de l’expiration des certificats SSL / TLS.
Settings
Name the group owning the SSL certificates files (for assigning access to system users):
sslGroup="ssl-cert"
To allow a software starting without “root” permissions (for example, Exim 4), add the software user to the “sslGroup” group:
# ${cmdProxy} adduser Debian-exim "${sslGroup}"
Installation
Detect if sudo is available (“command” is used if not):
cmdProxy='command'
command type -f 'sudo' &>'/dev/null' && cmdProxy='sudo'
Environment preparation
Install the software’s requisites:
${cmdProxy} apt-get install openssl ssl-cert
Create the SSL certificates folders:
while read folder; do
${cmdProxy} mkdir --parent "/etc/ssl/${folder}"
done <<< "private
requests
roots
chains
certificates
authorities
configs"
Make sure the chosen group exists:
${cmdProxy} addgroup --system "${sslGroup}"
Adjust the private keys path permissions:
${cmdProxy} chown -R root:${sslGroup} '/etc/ssl/private'
${cmdProxy} chmod 750 '/etc/ssl/private'
${cmdProxy} chmod 440 '/etc/ssl/private/'*
Creating a self-signed certificate (for local networking)
Settings
Set the fully qualified domain name (aka. FQDN, for example: “sub.domain.com”) for which the certificate is created:
sslKeyName="$(command hostname --fqdn)"
Set the group owning the created SSL certificates files (for assigning access to system users):
sslGroup="ssl-cert"
Creation
Create a self-signed certificate:
sslConfigFile="$(command mktemp)"
command sed \
-e "s/@HostName@/${sslKeyName}/" \
-e "s|privkey.pem|/etc/ssl/private/${sslKeyName}.key|" \
'/usr/share/ssl-cert/ssleay.cnf' > "${sslConfigFile}"
${cmdProxy} openssl req -config "${sslConfigFile}" -new -x509 -days 3650 \
-nodes -out "/etc/ssl/certificates/${sslKeyName}.crt" -keyout "/etc/ssl/private/${sslKeyName}.key"
command rm "${sslConfigFile}"
Set the group owning the created SSL certificates files (for assigning access to system users):
${cmdProxy} chown root:${sslGroup} "/etc/ssl/private/${sslKeyName}.key"
${cmdProxy} chmod 440 "/etc/ssl/private/${sslKeyName}.key"
Self-signed certificates are useful to encrypt connections on a private network with local domains. For connection over the Internet, “Let’s encrypt” certificates are preferred.
Note: Debian provide a tool to create self-signed certificates, but it put the private key and the public key in the same file.
# ${cmdProxy} make-ssl-cert '/usr/share/ssl-cert/ssleay.cnf' '/etc/ssl/certificates/${sslKeyName}.crt'
Creating a certified (valid) SSL / TLS certifate (for Internet)
Settings
Set the fully qualified domain name (aka. FQDN, for example: “sub.domain.com”) for which the certificate is created:
sslKeyName="domain.com"
Note: In order to create a SSL certificated valid for all sub-domains of a domain name (also known as “Wildcard”), use “*” instead of the sub-domain par of the FQDN.
# sslKeyName="*.domain.com"
Set the group owning the created SSL certificates files (for assigning access to system users):
sslGroup="ssl-cert"
Identification settings
Certificate authorities needs to validate the customer identity before acceding to a certificate signing request. Load the identity settings, if available:
if [ -e '/etc/ssl/csr-informations' ]; then
source '/etc/ssl/csr-informations'
cat '/etc/ssl/csr-informations'
else
echo "
#####################
Error: No identity informations available."
fi
If the previous command-line diplay an error, or if the loaded settings does not fit your identity, update the identity settings:
Set the code of your country:
SSL_COUNTRY="fr"
Set the name of your province:
SSL_PROVINCE="Ile-de-France"
Set the name of your city:
SSL_CITY="Paris"
Set your e-mail address:
SSL_EMAIL="user@some-domain.com"
Save the settings in a configuration file for future use:
${cmdProxy} tee '/etc/ssl/csr-informations' \
<<< "# SSL CSR informations.
SSL_COUNTRY=\"${SSL_COUNTRY}\"
SSL_PROVINCE=\"${SSL_PROVINCE}\"
SSL_CITY=\"${SSL_CITY}\"
SSL_EMAIL=\"${SSL_EMAIL}\""
Generation of the private key
Generate a RSA private key with a 2048 bits length:
${cmdProxy} openssl genrsa -out "/etc/ssl/private/${sslKeyName}.key" 2048
Set the private key access permissions:
${cmdProxy} chown root:${sslGroup} "/etc/ssl/private/${sslKeyName}.key"
${cmdProxy} chmod 440 "/etc/ssl/private/${sslKeyName}.key"
Creation of a Certificate Signing Request (CSR)
The Certificate Signing Request is sent to a certificate authority to ask it to validate (sign) the generate SSL certificate. Any error in its creation will result in the certificate authority rejecting the request. For more informations, see Certificate signing request (en) on Wikipedia.
Create the CSR:
${cmdProxy} openssl req -new \
-key "/etc/ssl/private/${sslKeyName}.key" \
-out "/etc/ssl/requests/${sslKeyName}.csr" \
<<< "${SSL_COUNTRY}
${SSL_PROVINCE}
${SSL_CITY}
${sslKeyName}
${sslKeyName}
${SSL_EMAIL}
"
Show the CSR contents:
command cat "/etc/ssl/requests/${sslKeyName}.csr"
The CSR contents should look like this:
-----BEGIN CERTIFICATE REQUEST-----
MIIC3DCCAcQCADKZgZYOEzAJBgNVBAYAXODfRYwFAYDVQQIEw1JKJDfZGUtRnJh
..... .... ....
N4QtCKIq9ZsP+FjK+h5f7Q==
-----END CERTIFICATE REQUEST-----
Obtaining the public key
The certified public key is obtained from a commercial certificate authority. The certificate authority validate the identity used to generate the CSR before issuing the certified public key.
Once the domain accepted by the certificate authority, request the signing of the certificate by sending the CSR to the authority (by sending the CSR file, or copy/pasting the content of the file in a web form):
command cat "/etc/ssl/requests/${sslKeyName}.csr"
Once the public key obtained, copy/paste it in the “sslCert” Shell variable:
sslCert="-----BEGIN CERTIFICATE-----
MIIHJzCCBg+gAwIBAgIDBNzOMXAXCDRTSIKDOWQBBQUAAGEOMMQscZfGLDVQQGEwJJ
.... .... .....
H5LYbXPAq3DpOzs=
-----END CERTIFICATE-----"
Create the public key file:
echo "${sslCert}" > "/etc/ssl/certificates/${sslKeyName}.crt"
Make sure to download the root and chains certificates for your chosen certificate authority.
For example:
# ${cmdProxy} wget "https://www.certificate-authority.com/certs/ca.crt" \
--output-document="/etc/ssl/roots/certificate-authority-root.ca"
# ${cmdProxy} wget "https://www.certificate-authority.com/certs/sca.server1.crt" \
--output-document="/etc/ssl/chains/certificate-authority.class1.server.ca.pem"
Create a symbolic link to the correct intermediate certificate of the chosen certificate authority. For example:
# ${cmdProxy} ln -s "/etc/ssl/chains/certificate-authority.class1.server.ca.pem" "/etc/ssl/chains/${sslKeyName}.ca"
Create a file containing the public, intermediate and root certificates for use by software allowing only one public certificate file:
${cmdProxy} cp "/etc/ssl/certificates/${sslKeyName}.crt"
test -e "/etc/ssl/chains/${sslKeyName}.ca" \
&& ${cmdProxy} tee -a "/etc/ssl/certificates/${sslKeyName}.crt+chain+root" < "/etc/ssl/chains/${sslKeyName}.ca"
test -e "/etc/ssl/roots/${sslKeyName}-root.ca" \
&& ${cmdProxy} tee -a "/etc/ssl/certificates/${sslKeyName}.crt+chain+root" < "/etc/ssl/roots/${sslKeyName}-root.ca"
The certificate can now be used with HTTP, IMAP, SMTP, FTP, etc. servers. Obtain the certificates files path with:
echo "Private key : \"/etc/ssl/private/${sslKeyName}.key\"
Root certificate : \"/etc/ssl/roots/${sslKeyName}-root.ca\"
Intermediate certificate : \"/etc/ssl/chains/${sslKeyName}.ca\"
Public key : \"/etc/ssl/certificates/${sslKeyName}.crt\""
Creating a local certificate authority
Settings
Set the fully qualified domain name (aka. FQDN, for example: “sub.domain.com”) of the certificate authority :
sslCaName="$(command hostname --fqdn)"
Set the group owning the created SSL certificates files (for assigning access to system users):
sslGroup="ssl-cert"
Creation of a certificate authority
Create the authority configuration file:
${cmdProxy} mkdir --parent "/etc/ssl/authorities/${sslCaName}"
confFile="/etc/ssl/authorities/${sslCaName}/${sslCaName}.conf"
${cmdProxy} sed \
-e "s/@HostName@/${sslCaName}/" \
-e "s|privkey.pem|/etc/ssl/private/${sslCaName}.cakey|" \
'/usr/share/ssl-cert/ssleay.cnf' > "${confFile}"
${cmdProxy} tee -a "${confFile}" \
<<< "[ ca ]
default_ca = CA_${sslCaName}
[ CA_${sslCaName} ]
dir = /etc/ssl
serial = \$dir/authorities/${sslCaName}/serial
database = \$dir/authorities/${sslCaName}/index.txt
new_certs_dir = \$dir/certificates
certificate = \$dir/authorities/${sslCaName}.ca
private_key = \$dir/private/${sslCaName}.cakey
default_days = 365
default_md = md5
preserve = no
email_in_dn = no
nameopt = default_ca
certopt = default_ca
policy = policy_anything
[ policy_match ]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ policy_anything ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ v3_ca ]
basicConstraints = CA:TRUE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
[ v3_req ]
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash"
Create the local certificate authority:
${cmdProxy} openssl req -config "${confFile}" -new -x509 -extensions v3_ca -days 3650 \
-nodes -out "/etc/ssl/authorities/${sslCaName}.ca" -keyout "/etc/ssl/private/${sslCaName}.cakey"
Protect the certificate authority private key:
${cmdProxy} chown root:${sslGroup} "/etc/ssl/private/${sslCaName}.cakey"
${cmdProxy} chmod 440 "/etc/ssl/private/${sslCaName}.cakey"
Create the needed files:
${cmdProxy} touch "/etc/ssl/authorities/${sslCaName}/index.txt"
${cmdProxy} tee "/etc/ssl/authorities/${sslCaName}/serial" <<< '01'
This authority can sign local certificates. It allow the validation of localy signed certificates by clients possessing the local certificate authority public key. It can be of use on a local network with a local domain non visible on Internet.
Validation of a CSR
The creation of a CSR is described in this article: Creating a certified (valid) SSL / TLS certifate (for Internet)
Accept the CSR with the local certificate authority and create the public key for the CSR:
confFile="/etc/ssl/authorities/${sslCaName}/${sslCaName}.conf"
${cmdProxy} openssl ca -config "${confFile}" -days 3650 \
-out "/etc/ssl/certificates/${sslKeyName}.crt" \
-in "/etc/ssl/requests/${sslKeyName}.csr" \
<<< 'y
y'
Bibliography
- Network Security with OpenSSL: Cryptography for Secure Communications
- Implementing SSL / TLS Using Cryptography and PKI
- Serious Cryptography: A Practical Introduction to Modern Encryption
Thanks
- Thanks to CACert (en) for VhostTaskForce (en).
- Thanks to the author and translator of Guide pratique des certificats SSL (fr).
- Thanks to Documentation technique : Debian (fr) for Création d’un Certificate Signing Request (CSR) (fr).
- Thanks to Artisan Numérique (fr) for Créer sa propre (mini) PKI (fr).
- Thanks to Phil’s Technical Pages (en) for Openssl.conf Walkthru (en).
0 Comments