Setting up your own Certificate Authority

WARNING: This information is a bit outdated...

    This is a description of how I use OpenSSL on my various systems on (and off) the net. I have setup my own Certification Authority (CA) and I issue my own certificates that I sign with my CA certificate. Once I import my CA certificate into my favorite browsers or email clients, it's impossible to tell the difference between my SSL certificates and commercial SSL certificates that have been signed by a known commercial Certification Authority (i.e. Verisign).

    All of the information that I have collected here was taken from Nick Burch's excellent OpenSSL pages.

    Setting up your CA

    Creating your own CA self-signed certificate, entails:
    • Creating a public and a private CA key-pair.
    • Create a CA certificate request, and
    • Sign the CA certificate request with the CA private key.
    Before any of this however, you need to decide where you will store the CA private key. The CA private key must be stored VERY, VERY SECURELY! I keep my CA private key on a system behind a firewall with no entry point into it, except the console. All the certificate creation and signing takes place on this secure CA system.

    Set up the CA directory Structure

    Once on the CA system, setup a suitable directory structure. I use the following three directories (for certificates, certificate requests and private keys):

    /opt/CA/certs/
    /opt/CA/csr/
    /opt/CA/private/

    Create the CA private/public key-pair

    It's now time to create the CA key-pair. I use a 8192 bits RSA key-pair, and I ask OpenSSL to encrypt the private key with Triple-DES, using a passphrase as the Triple-DES key:

    openssl genrsa \
        -des3 \
        -out /opt/CA/private/<MyDomain>-ca.key \
        8192

    Generate the CA certificate

    Now that we have the private/public key-pair, let's go ahead and generate the self-signed certificate:

    openssl req \
         -new \
         -key /opt/CA/private/<MyDomain>-ca.key \
         -x509 \
         -days 3650 \
         -out /opt/CA/certs/<MyDomain>-ca.crt \
         -subj '/C=US/O=<MyDomain>/CN=<MyDomain> Root Certification Authority'

    Note that older versions of openssl doesn't support the subject option, -subj, so leave it out and let OpenSSL prompt you for the individual fields. See the OpenSSL manpage 'req' for a description about the subject fields. Also you might want to add some fields, like Org. Unit (OU) or email address (emailAddress).

    [Optional] Convert the CA certificate from PEM to DER format

    The certificate generated above (/opt/CA/certs/<MyDomain>-ca.crt) is in PEM format, which is good for applications (servers), OpenSSL clients, Netscape and Mozilla browsers, and newer versions of Internet Explorer. For older versions of Internet Explorer you should convert the certificate to DER format, which we can do like this:

    openssl rsa \
        -inform PEM \

        -outform DER \
        -in /opt/CA/certs/<MyDomain>-ca.crt \
        -out /opt/CA/certs/<MyDomain>-ca.der.crt

    Note that older versions of openssl, seem to have a problem converting just a certificate, as opposed to a public or a private key.

    Tell everyone about your CA certificate

    In order to use SSL certificates that you sign with you CA certificate seamless, you need to tell your SSL clients about your new fance CA certificate.

    Store your CA certificate on a web server

    In order to facilitate propagation, I keep my PEM encoded CA certificate on my web server (right here: ca.crt). Just make sure your web server have associated .crt extensions with the application/x-x509-ca-cert mime type.

    Browsers

    Click on your certificate link on your web page, or copy the certificate to the system that has the browser on it, and open the certificate in your browser as a file, using the file:// method.

    For netscape browsers, I enable all three forms of certificate use (website, email users, software signing).

    For Internet Explorer, after you click on the CA certificate, it asks you what you want to do. Click on "Open", click on "Install Certificate...", click on "Next>", select "Place all certificates in the following store", browse and select "Trusted Root Certification Authorities", click "Ok", click "Next>", click "Finish", click "Yes", and you are done.

    OpenSSL clients

    For OpenSSL clients, such as pine under unix, you need to install your CA certificate in the client system's OpenSSL certificate directory. This is usually /usr/share/ssl/certs on systems that bundle OpenSSL (Linux), otherwise it's typically /usr/local/ssl/certs or /usr/local/share/ssl/certs.

    First, copy your CA certificate (<MyDomain>-ca.crt) into the OpenSSL .../ssl/cert directory.

    Then, figure out the OpenSSL hash value for the subject in your CA certificate:

    openssl x509 \
        -hash \
        -noout \
        -in .../ssl/certs/<MyDomain>-ca.cert

    The hash value is an 8-digit hexadecimal number. You need to create a symbolic link in the OpenSSL .../ssl/certs directory using the hash value as it's name with ".0" appended to the end of the hash value. This symbolic link has to point to the CA certificate file. You can do this in one operation like this:

    cd .../ssl/certs
    ln -s <MyDomain>-ca.crt `openssl x509 -noout -hash -in <MyDomain>-ca.crt`.0

    Generating an Apache web server SSL certificate

    On the CA system again, create a new 1024 bits RSA public/private key-pair for your web server:

    openssl genrsa \
        -out /opt/CA/private/www.<MyDomain>.key \

        1024

    Then generate the certificate request using this key pair:

    openssl req \
         -new \
         -key /opt/CA/private/www.<MyDomain>.key \
         -out /opt/CA/csr/www.<MyDomain>.csr \
         -subj '/C=US/ST=New York/L=New York/O=<MyDomain>/OU=<MyDomain>/CN=www.<MyDomain>/emailAddress=hostmaster@<MyDomain>'

    Note that the commonName field (CN) has to be the virtual hostname of the web server that you are going to use this SSL certificate with.

    Note that older versions of openssl doesn't support the subject option, -subj, so leave it out and let OpenSSL prompt you for the individual fields. See the OpenSSL manpage 'req' for a description about the subject fields.

    And finally, take the certificate request and sign it using your CA private key. The result is your new web server SSL certificate:

    openssl x509 \
        -req \
        -days 365 \
        -in /opt/CA/csr/www.<MyDomain>.csr \
        -CA /opt/CA/certs/<MyDomain>-ca.crt \
        -CAkey /opt/CA/private/<MyDomain>-ca.key \
        -CAcreateserial \
        -out /opt/CA/certs/www.<MyDomain>.crt

    In order to use this SSL certificate with your apache web server, you need to copy the web server private key, the web server SSL certificate, and the CA certificate to your apache installation directory, on your web server:

    /opt/CA/certs/<MyDomain>-ca.crt --> /usr/local/apache2/conf/ssl.crt/
    /opt/CA/certs/www.<MyDomain>.crt --> /usr/local/apache2/conf/ssl.crt/
    /opt/CA/private/www.<MyDomain>.key --> /usr/local/apache2/conf/ssl.key/

    Edit the apache conf/ssl.conf file, and change:

    SSLCertificateFile /usr/local/apache2/conf/ssl.crt/www.<MyDomain>.crt
    SSLCertificateKeyFile /usr/local/apache2/conf/ssl.key/www.<MyDomain>.key
    SSLCertificateChainFile /usr/local/apache2/conf/ssl.crt/<MyDomain>-ca.crt

    and restart apache.

    Generating a mail server certificate

    This certificate will work both with UW's imapd and postfix.

    The steps to create a key-pair, generate the certificate request, and signing it with the CA private key for imapd/postfix is identical to how we did it for apache above.

    So in rapid sequence, we do:

    openssl genrsa \
         -out /opt/CA/private/mail.<MyDomain>.key \
         1024

    openssl req \
         -new \
         -key /opt/CA/private/mail.<MyDomain>.key \
         -out /opt/CA/csr/mail.<MyDomain>.csr \
         -subj '/C=US/ST=New York/L=New York/O=<MyDomain>/OU=<MyDomain>/CN=mail.<MyDomain>/emailAddress=hostmaster@<MyDomain>'

    openssl x509 \
         -req \
         -days 365 \
         -in /opt/CA/csr/mail.<MyDomain>.csr \
         -CA /opt/CA/certs/<MyDomain>-ca.crt \
         -CAkey /opt/CA/private/<MyDomain>-ca.key \
         -CAcreateserial \
         -out /opt/CA/certs/mail.<MyDomain>.crt

    Note that older versions of openssl doesn't support the subject option, -subj, so leave it out and let OpenSSL prompt you for the individual fields. See the OpenSSL manpage 'req' for a description about the subject fields.

    Imapd/postfix needs the private key and the certificate to be in the same file, so we can just concatenate both of them like this:

    cat /opt/CA/private/mail.<MyDomain>.key > /opt/CA/private/mail.<MyDomain>.key.crt
    echo "" >> /opt/CA/private/mail.<MyDomain>.key.crt
    cat /opt/CA/certs/mail.<MyDomain>.crt >> /opt/CA/private/mail.<MyDomain>.key.crt

    For UW's imapd, copy the joint private key and certificate PEM encoded file to your mailserver in the OpenSSL .../ssl/certs directory, and call it "imapd.pem".

    Postfix


    For postfix, copy the joint private key and certificate PEM encoded file to your mailserver in /etc/postfix, and call it "smtp.pem".

    And at a minimum, add the following configuration directives in /etc/postfix/main.cf:

    smtpd_tls_cert_file = /etc/postfix/smtp.pem
    smtpd_tls_key_file = $smtpd_tls_cert_file
    smtpd_use_tls = yes


    Also enable the postfix smtps daemon program in /etc/postfix/master.cf, and make sure you define the smtps service in /etc/services (465/tcp).

    In addition, once SSL is working, if you want to turn on SMTP authentication (using SASL), and disable cleartext passwords unless SSL is used, add the following to main.cf:

    smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination

    smtpd_sasl_auth_enable = yes

    smtpd_sasl_security_options = noanonymous, noplaintext
    smtpd_sasl_tls_security_options = noanonymous

    Note that we just added the 'permit_sasl_authenticated' to 'smtpd_recipient_restrictions', the other two options are present by default.
    Comments