You are here: Home / Debian GNU/Linux / Servers / HTTP / Create a SSL / TLS certificate on Debian

Create a SSL / TLS certificate on Debian

by Pierre-Yves Landuré last modified Mar 02, 2018 06:04

The creation of a SSL certificate is a major step when setting up a encrypted connection. Whether to implement HTTPS, to encrypt your IMAP server or FTP server, this guide helps you generate a valid SSL certificate.

This howto is tested on:

  • Debian 5.0 Lenny
  • Debian 6.0 Squeeze
  • Debian 7.0 Wheezy

Prerequisites

This howto recommends:

    Environment preparation

    Install the needed software:

    command apt-get install openssl ssl-cert

    Create the folders that will contain the certificate:

    command mkdir --parent '/etc/ssl/private'
    command mkdir --parent '/etc/ssl/requests'
    command mkdir --parent '/etc/ssl/roots'
    command mkdir --parent '/etc/ssl/chains'
    command mkdir --parent '/etc/ssl/certificates'
    command mkdir --parent '/etc/ssl/authorities'
    command mkdir --parent '/etc/ssl/configs'

    Make sure that the system group "ssl-cert" exists:

    command addgroup --system 'ssl-cert'

    Adjust the permissions on the private keys folder:

    command chown -R root:ssl-cert '/etc/ssl/private'
    command chmod 710 '/etc/ssl/private'
    command chmod 440 '/etc/ssl/private/'*

    Creation of a self-signed SSL / TLS certificate (for local networking)

    Parameters

    Provide the fully qualified host name (sub-domain.domain) of the generated certificate:

    SSL_KEY_NAME="$(command hostname --fqdn)"

    Creation of the self-signed certificate

    Create a self-signed certificate:

    CONF_FILE="$(command mktemp)"
    command sed \
    -e "s/@HostName@/${SSL_KEY_NAME}/" \
    -e "s|privkey.pem|/etc/ssl/private/${SSL_KEY_NAME}.pem|" \
    '/usr/share/ssl-cert/ssleay.cnf' > "${CONF_FILE}"
    command openssl req -config "${CONF_FILE}" -new -x509 -days 3650 \
    -nodes -out "/etc/ssl/certificates/${SSL_KEY_NAME}.crt" -keyout "/etc/ssl/private/${SSL_KEY_NAME}.key"
    command rm "${CONF_FILE}"

    Protect the private key:

    command chown root:ssl-cert "/etc/ssl/private/${SSL_KEY_NAME}.key"
    command chmod 440 "/etc/ssl/private/${SSL_KEY_NAME}.key"

    This method can be used to create a non-valid SSL certificate for a web site. The use of self-signed certificates trigger the display of error messages in web browsers.

    Note : Debian provide a tool to create self-signed certificates, but it does not allow to separate private key from public key.

    # command make-ssl-cert '/usr/share/ssl-cert/ssleay.cnf' '/etc/ssl/certificates/${SSL_KEY_NAME}.crt'

    Creating a valid SSL / TLS certificate (for Internet)

    Parameters

    Provide the complete domain name (sub-domain included) which for you want to generate a certificate (free with StartSSL authority):

    SSL_KEY_NAME="www.domain.com"

    Note: To obtain a SSL certificate that match all of a domain sub-domains (also known as Wildcard certificate), replace the sub-domain part by a star ("*") (wildcard certificate cost: US $ 59.90 with StartSSL authority):

    SSL_KEY_NAME="*.domain.com"

    Personal informations

    Some personal data are needed to create a SSL certificate. Load this informations if possible:

    if [ -e '/etc/ssl/csr-informations' ]; then
    source '/etc/ssl/csr-informations'
    cat '/etc/ssl/csr-informations'
    else
    echo "

    #####################
    Error: No SSL informations available."
    fi

    If the command above display an error, or if the loaded data does not fit, update the data:

    Provide your country code (edit the bold value):

    SSL_COUNTRY="us"

    Provide your state / province (edit the bold value):

    SSL_PROVINCE="Florida"

    Provide your city (edit the bold value):

    SSL_CITY="Miami"

    Provide your e-mail address (edit the bold value):

    SSL_EMAIL="user@some-domain.com"

    Save this informations in a configuration file for future use:

    echo "# SSL CSR informations.
    SSL_COUNTRY=\"${SSL_COUNTRY}\"
    SSL_PROVINCE=\"${SSL_PROVINCE}\"
    SSL_CITY=\"${SSL_CITY}\"
    SSL_EMAIL=\"${SSL_EMAIL}\"" \
    > '/etc/ssl/csr-informations'

    Creating the private key

    Generate the RSA private key with a 2048 bits length:

    command openssl genrsa -out "/etc/ssl/private/${SSL_KEY_NAME}.key" 2048

    Protect the private key access:

    command chown root:ssl-cert "/etc/ssl/private/${SSL_KEY_NAME}.key"
    command chmod 440 "/etc/ssl/private/${SSL_KEY_NAME}.key"

    Creating the Certificate Signing Request (CSR)

    The Certificate Signing Request is to be sent to the certification authority in order to obtain the signed (aka. checked) SSL certificate. It is important to make no mistake when creating it: invalid requests are rejected. For more information, read the Wikipedia article: Certificate signing request.

    Generate the CSR:

    command openssl req -new \
    -key "/etc/ssl/private/${SSL_KEY_NAME}.key" \
    -out "/etc/ssl/requests/${SSL_KEY_NAME}.csr" \
    <<< "${SSL_COUNTRY}
    ${SSL_PROVINCE}
    ${SSL_CITY}
    ${SSL_KEY_NAME}

    ${SSL_KEY_NAME}
    ${SSL_EMAIL}

    "

    Display the CSR contents:

    cat "/etc/ssl/requests/${SSL_KEY_NAME}.csr"

    The displayed contents must look like:

    -----BEGIN CERTIFICATE REQUEST-----
    MIIC3DCCAcQCADKZgZYOEzAJBgNVBAYAXODfRYwFAYDVQQIEw1JKJDfZGUtRnJh
    ..... .... ....
    N4QtCKIq9ZsP+FjK+h5f7Q==
    -----END CERTIFICATE REQUEST-----

    Obtaining the public key

    The public key is obtained from a certification authority. If you have no preference, you can use the StartSSL certification authority.

    Once registered, and after your domain name has been validated by the authority, request the validation of the CSR displayed by:

    cat "/etc/ssl/requests/${SSL_KEY_NAME}.csr"

    For the StartSSL certification authority, the validation process is available in your account "Certificate Wizard" tab.

    Once the public key obtained, copy/paste it in the Shell variable SSL_CERT (replace the bold value with your public key):

    SSL_CERT="-----BEGIN CERTIFICATE-----
    MIIHJzCCBg+gAwIBAgIDBNzOMXAXCDRTSIKDOWQBBQUAAGEOMMQscZfGLDVQQGEwJJ
    .... .... .....
    H5LYbXPAq3DpOzs=
    -----END CERTIFICATE-----
    "

    Create the public key file:

    echo "${SSL_CERT}" > "/etc/ssl/certificates/${SSL_KEY_NAME}.crt"

    If you choose to use the StartSSL certification authority, download the authority root and intermediate certificate:

    command wget "http://www.startssl.com/certs/ca.pem" \
    --output-document="/etc/ssl/roots/startssl-root.ca"
    command wget "http://www.startssl.com/certs/sub.class1.server.ca.pem" \
    --output-document="/etc/ssl/chains/startssl-sub.class1.server.ca.pem"
    command wget "http://www.startssl.com/certs/sub.class2.server.ca.pem" \
    --output-document="/etc/ssl/chains/startssl-sub.class2.server.ca.pem"
    command wget "http://www.startssl.com/certs/sub.class3.server.ca.pem" \
    --output-document="/etc/ssl/chains/startssl-sub.class3.server.ca.pem"

    If you choose to use the StartSSL certification authority, install the root certificate of this authority:

    command ln -s "/etc/ssl/roots/startssl-root.ca" "/etc/ssl/roots/${SSL_KEY_NAME}-root.ca"

    If you choose to use the StartSSL certification authority, install the intermediate certificate of this authority:

    if [ "${SSL_KEY_NAME}" = "$(echo "${SSL_KEY_NAME}" | command tr '*' '.')" ]; then
    command ln -s "/etc/ssl/chains/startssl-sub.class1.server.ca.pem" "/etc/ssl/chains/${SSL_KEY_NAME}.ca"
    else
    command ln -s "/etc/ssl/chains/startssl-sub.class2.server.ca.pem" "/etc/ssl/chains/${SSL_KEY_NAME}.ca"
    fi

    Create a file containing the public, intermediate and root certificates for software that does not have the needed configuration options:

    command cp "/etc/ssl/certificates/${SSL_KEY_NAME}.crt" "/etc/ssl/certificates/${SSL_KEY_NAME}.crt+chain+root"
    test -e "/etc/ssl/chains/${SSL_KEY_NAME}.ca" \
    && command cat "/etc/ssl/chains/${SSL_KEY_NAME}.ca" >> "/etc/ssl/certificates/${SSL_KEY_NAME}.crt+chain+root"
    test -e "/etc/ssl/roots/${SSL_KEY_NAME}-root.ca" \
    && command cat "/etc/ssl/roots/${SSL_KEY_NAME}-root.ca" >> "/etc/ssl/certificates/${SSL_KEY_NAME}.crt+chain+root"

    The SSL certificate is now available to be used by your HTTP, IMAP, FTP, etc. servers. Get the names of its key and certificates files:

    echo "Private key :        \"/etc/ssl/private/${SSL_KEY_NAME}.key\"
    Root certificate : \"/etc/ssl/roots/${SSL_KEY_NAME}-root.ca\"
    Intermediate certificate : \"/etc/ssl/chains/${SSL_KEY_NAME}.ca\"
    Public key : \"/etc/ssl/certificates/${SSL_KEY_NAME}.crt\""

    Creating a local certification authority

    Parameters

    Provide the complete domain name (sub-domain included) which for you want to generate a certification authority:

    SSL_CA_NAME="$(command hostname --fqdn)"

    Creating a certification authority

    Create the authority configuration file:

    command mkdir --parent "/etc/ssl/authorities/${SSL_CA_NAME}"
    CONF_FILE="/etc/ssl/authorities/${SSL_CA_NAME}/${SSL_CA_NAME}.conf"
    command sed \
    -e "s/@HostName@/${SSL_CA_NAME}/" \
    -e "s|privkey.pem|/etc/ssl/private/${SSL_CA_NAME}.cakey|" \
    '/usr/share/ssl-cert/ssleay.cnf' > "${CONF_FILE}"
    command echo "[ ca ]
    default_ca = CA_${SSL_CA_NAME}
    [ CA_${SSL_CA_NAME} ]
    dir = /etc/ssl
    serial = \$dir/authorities/${SSL_CA_NAME}/serial
    database = \$dir/authorities/${SSL_CA_NAME}/index.txt
    new_certs_dir = \$dir/certificates
    certificate = \$dir/authorities/${SSL_CA_NAME}.ca
    private_key = \$dir/private/${SSL_CA_NAME}.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" \
    >> "${CONF_FILE}"

    Create the local certification authority:

    command openssl req -config "${CONF_FILE}" -new -x509 -extensions v3_ca -days 3650 \
    -nodes -out "/etc/ssl/authorities/${SSL_CA_NAME}.ca" -keyout "/etc/ssl/private/${SSL_CA_NAME}.cakey"

    Protect the private key:

    command chown root:ssl-cert "/etc/ssl/private/${SSL_CA_NAME}.cakey"
    command chmod 440 "/etc/ssl/private/${SSL_CA_NAME}.cakey"

    Create the authority index and serial files:

    command touch "/etc/ssl/authorities/${SSL_CA_NAME}/index.txt"
    command echo '01' > "/etc/ssl/authorities/${SSL_CA_NAME}/serial"

    This authority is used to sign certificates localy created. It has almost no value, other than allow clients with its public key installed to validate local certificates signed by it.

    Obtaining a certificate public key by validating a CSR

    Note: the CSR creation process is described higher in this page.

    Sign a public certificate by accepting the Certificate Signing Request with the local authority:

    echo 'y
    y' > '/tmp/ca.input'
    CONF_FILE="/etc/ssl/authorities/${SSL_CA_NAME}/${SSL_CA_NAME}.conf"
    command openssl ca -config "${CONF_FILE}" -days 3650 \
    -out "/etc/ssl/certificates/${SSL_KEY_NAME}.crt" \
    -in "/etc/ssl/requests/${SSL_KEY_NAME}.csr" \
    < '/tmp/ca.input'
    command rm '/tmp/ca.input'

    Allowing the use of SSL / TLS certificates

    If the server software does not start with root user permissions (it is the case for Exim 4), add the server user to the "ssl-cert" group. For example, to enable the use of SSL / TLS certificates by Exim 4:

    command adduser Debian-exim ssl-cert

    References

    These books can help you:

    Thanks