SSL: Creating a private CAΒΆ

Title:SSL: Creating a private CA
Author:Douglas O’Leary <dkoleary@olearycomputers.com>
Description:SSL: Creating a private CA
Date created:06/2007
Date updated:06/2009
Disclaimer:Standard: Use the information that follows at your own risk. If you screw up a system, don’t blame it on me...

The steps below are outlined from the Network Security with OpenSSL book (ISBN: 0-596-00270-X) in chapter 3. It creates a CA that’s not overly robust or user friendly but is certainly useable for small environments. If you want to create your own signed certificates or if you’re doing an stunnel implementation for a client (guess where these steps came from?), than this will work.

One note: be careful on step 3, generating the self signed cert for the CA authority. I ran that command exactly as it is in the openssl book. Their example shows the private key being written to a file. Even the one I ran here shows it going to stdout:

# openssl req -x509 -newkey rsa -out cacert.pem -outform PEM
Generating a 2048 bit RSA private key
.......................................................+++
...........+++
writing new private key to stdout

You can cut/paste that into the file identified as prvate_key in your openssl.conf file. I’m reasonably certain there’s an arugment to write the key to a file, but I haven’t looked for it yet.

I ran into that little issue when I was troubleshooting key access to my CA and wanted to regenerate the keys

  1. Create the CA environment: Identify and configure the root directory for the CA environment:

    caroot=${abs_path_to_ca_root}
    cahost=${Host_that_will_be_used_as_CA}
    mkdir -p -m 755 ${caroot}
    mkdir -p -m 755 ${caroot}/certs
    mkdir -p -m 700 ${caroot}/private
    echo "01" > ${caroot}/serial.txt
    touch ${caroot}/index.txt
    
  2. Create the CA openssl.conf file. NOTE: This file should not be the openssl default configuration file. This one makes some changs to the default environment. A full example config file can be found here Specific notes for the file generation follow:

    1. Sections are identified by square braces ([]).
    2. The first section identifies the default CA. Multiple CAs can be identified; however, I would imagine that would very quickly get more complicated than this CA could easily handle.
    3. The next section starts out by identifying where the keys are located. It then goes on to identify various parameters for the certificate revocation list (CRL)
      1. default_crl_days identifies the number of days between CRLs
      2. default_days identifies how long a certificate is valid.
      3. default_md identifies the message digest algorithm used to sign the certificates.
      4. policy_key names the section that will be used for the default policy.
      5. x509_extensions: basically, this line prohibits any certs we create from being used to create other certs. There’s a more detailed explanation in the book.
    4. The policy section:
      1. Most of the entries in here say supplied. This means the information will be supplied on the command line.
      2. optional entries are just that - not required by the CA.
    5. req section:
      1. the command line used to request certs is pretty obvious. This section identifies information for that command.
      2. distinguished_name identifies the name of the section that’ll be used to supply most of the information for generating a self signed certficate (which is used to sign other certificates). Saves on typing later and keeps things consistent when you have to regenerate them.
      3. basicConstraints: this one has to be CA:true because we’re using the certificate to sign others.
  3. Create the self-signed root certificate. Once done, move or copy cacert.pem to where you designated the key in the openssl.conf file. Alternatively, you could specify that file directly:

    # export OPENSSL_CONF=${caroot}/openssl.conf
    # openssl req -x509 -newkey rsa -out cacert.pem -outform PEM
    Generating a 2048 bit RSA private key
    .......................................................+++
    ...........+++
    writing new private key to stdout  NOTE:  This is going to stdout!
    Enter PEM pass phrase: Enter passphrase here
    Verifying - Enter PEM pass phrase: Reenter passphrase here
    -----BEGIN RSA PRIVATE KEY-----
    Proc-Type: 4,ENCRYPTED
    DEK-Info: DES-EDE3-CBC,FBE415D1818FE467
    
    CYVxG9LrC83y/P6W+8W2VOFMruPAQBWrVb9CLnSV+FbBTpkAykv4B+kg4EdqSWb2
    yXbIBaJ5lzRoNS+gjZBJvh20ylW+QQxKoTCjbhNRxwcVAzvkEnwFoMGTx5O4TEsF
    BPu1ZNgmuiX8G9N+Bpf94ggOQEAxcMLDxOpe8/4hBTcsUhmRU99iUY1hA59e+FBj
    rpbJMX6OMqcHYj4ikEyE9FitTxMgLrSyPTbk399CWiJy02Ymus7Vnc5ILw1o1RM+
    vd1jNvKO/lC5MfcRCZoTqZq8/AXpJv/nKOKw47/R+4WrqF9d9a9Mx+Qd2s5/iIKa
    VWKNcsjwtvPgA0qFePcaTORFI7ssSQrv74cfMWQ7LhggnEo8yjpd0wpQZCQ4Sta5
    N+DgrAUvyGmBuEFe6Ojqu8WHWVCvNR2CipyLayRnRHHpQCErAsuPJc0DdghWFZa5
    9ORamSZSOCoPKYbOAFvwUKl3Ce9bEXvaT17LWGZR25qjLeFD9ejV8A5gycbkQEGa
    LXDsW+tWE7pZtPOFr4JTFm/ONeNGiH2cBY8P9GR+Nf8ivschvsm8ZjCX/gA4wtDu
    uhiCAPPoANo7FmUSo9O2AQ18uOzTE9bCdSoWNat+SwDrpVFLUS1h1ptu/zMDgSaE
    GOx5ESYue0ndY4c4EwmWnYUlnzwqLX3/YXFre7+N2krLVQVBO3xjVHgzd4MdlUPB
    qbSRI8BhAhDZTrL5Ws1fz8hGSGdcLIlyr6TQNDh9lcL9vfBAnXToJF0HdXNs6fqu
    d+fnkE3fa5fLH+zAdX4vbXIwJyP6ISna6k8WiEB+DJRbLZ6DpFiRoz/4xTzti/iQ
    KYh/uhiUl6NoutTxgOMFfQNr7OcO4lgUasG/3ifF+yNafU3uuxqLm8/Fj63TobR0
    X3Z6lOX3eV+D6knR/7ag+3EqoZR2A3tdM7RFkRr/+qu669VGkuffT3qYOcArOq/r
    9OqHG7MS62YgoHXT2g4zGMUvN3rKTREATHYjqTpjTfeiRzXN5basssFtw3SRY8Vr
    Do7MANxODOXDz6cwY0U/h/+WnCcoIEz+Z9sz2lV2RVVWfxB2PqoGgoGwun39OORb
    9p+PgW5Q8+JvROq6h8chryEbYF0LP3MBR+jeKfXeRYu4O7rCFQBY7aMea0FDuqUC
    3En0DwWrXK/ragKB4r0WMwkzbo9RICY38KOsHXRbH92hNKTAL5u2lZwn3srNkU/M
    omBSjh/+UW354eWrZLPZevBecuTFYHyuXZfu5Gpm5xVf+eG/FoRNIc+pP8STt49X
    gSTfm1r0iCdnhYModXnPzPbHK5aI4S+uEaH+rLIInf98+YpoZaZXOgOFDJaxQcj7
    LYSWbbH1274WcTV7eFrhwWwRMgzbV17p4IAtc5kIAA/euUOMhvfxQOo+eiRLs6sU
    /E3vJp69oc4sSdItTLxaPIpY9E7psL7QZE4dU4xzc2bKTDFULrpq2uyr8niV8Wq4
    pQIDRzm8b3C7G17OQv2OjjouguO6mwcTbpCVZKLuXqA9wqLwMJ1vN4T8E5wf1wYH
    zhl1W5TPInYaV307KwlOWM7ccQQzVeOCqIV/yQdY/L1wHSLp6UarCCKixzsFEYrx
    -----END RSA PRIVATE KEY-----
    -----
    
  4. Create a private key and a cert request. If you’re doing these commands on the same system as the one you just generated the CA, execute unset OPENSSL_CONF

    1. Create a directory for the certificates. cd into it.

      mkdir -p -m 700 /root/certs; cd $_
      
    2. Create a private key and cert request. Supply an aribitrary passphrase; we’ll remove it later. Items in bold are what you enter:

      openssl req -newkey rsa:1024 -keyout ${host}_private.pem -keyform PEM -out ${host}_req.pem
      Generating a 1024 bit RSA private key
      ....++++++
      ....................................++++++
      writing new private key to '${cahost}_private.pem'
      Enter PEM pass phrase:  <==== Enter passphrase here
      Verifying - Enter PEM pass phrase: <=== Reenter same passphrase here
      -----
      You are about to be asked to enter information that will be incorporated
      into your certificate request.
      What you are about to enter is what is called a Distinguished Name or a DN.
      There are quite a few fields but you can leave some blank
      For some fields there will be a default value,
      If you enter '.', the field will be left blank.
      -----
      Country Name (2 letter code) [AU]:US
      State or Province Name (full name) [Some-State]:IL
      Locality Name (eg, city) []:Naperville
      Organization Name (eg, company) [Internet Widgits Pty Ltd]:Myco
      Organizational Unit Name (eg, section) []:IT
      Common Name (eg, YOUR name) []:FQDN of the host
      Email Address []:YOUR email address
      
      Please enter the following 'extra' attributes
      to be sent with your certificate request
      A challenge password []:Any arbitrary word; it's not used
      An optional company name []:Myco
      
    3. Send the request to the CA directory on ${cahost}:

      scp ${host}_req.pem ${cahost}:${caroot}
      
  5. Sign the certificate

    1. Log into ${cahost} as root, cd ${caroot}

    2. The CA needs specific items in the openssl.conf file. Since these entries aren’t required for normal openssl operation, we need to use a different conf file:

      export OPENSSL_CONF=${caroot}/openssl.conf
      Sign the request:
      openssl ca -in ${host}_req.pem
      Using configuration from ${caroot}/openssl.conf
      Enter pass phrase for ${caroot}/private/cakey.pem: Enter key passphrase from step #3
      DEBUG[load_index]: unique_subject = "yes"
      Check that the request matches the signature
      Signature ok
      The Subject's Distinguished Name is as follows
      countryName           :PRINTABLE:'US'
      stateOrProvinceName   :PRINTABLE:'IL'
      localityName          :PRINTABLE:'Naperville'
      organizationName      :PRINTABLE:'Myco'
      organizationalUnitName:PRINTABLE:'IT'
      commonName            :PRINTABLE:'${cahost}.myco.com'
      emailAddress          :IA5STRING:'oleary@myco.com'
      Certificate is to be certified until Jul 11 13:54:58 2009 GMT (365 days)
      Sign the certificate? [y/n]:y
      
      
      1 out of 1 certificate requests certified, commit? [y/n]y
      Write out database with 1 new entries
      Certificate:
          Data:
              Version: 3 (0x2)
              Serial Number: 3 (0x3)
              Signature Algorithm: md5WithRSAEncryption
              Issuer: CN=Myco, ST=IL, C=US/emailAddress=oleary@myco.com, O=Root Certificate Authority
              Validity
                  Not Before: Jul 11 13:54:58 2008 GMT
                  Not After : Jul 11 13:54:58 2009 GMT
              Subject: CN=${cahost}.myco.com, ST=IL, C=US/emailAddress=oleary@myco.com, O=Myco, OU=IT
              Subject Public Key Info:
                  Public Key Algorithm: rsaEncryption
                  RSA Public Key: (1024 bit)
                      Modulus (1024 bit):
                          00:c8:f2:4d:5b:a4:8d:c9:37:66:4f:77:3d:a4:b4:
                          2e:68:84:21:e5:64:37:56:ea:e5:f0:9c:72:f5:ba:
                          1c:65:21:9a:84:21:36:06:24:86:92:56:e6:f5:14:
                          30:d6:d9:6f:ad:8d:e9:11:b8:49:e1:3e:d7:f8:3d:
                          57:9b:64:29:87:9b:9c:c3:ea:00:80:b5:03:be:72:
                          02:dc:75:56:81:59:04:bb:e7:8e:53:56:16:0c:09:
                          97:a7:ea:0a:c7:e6:55:14:cb:92:1b:79:d6:1f:dc:
                          96:49:b7:ae:7a:d1:67:73:ff:6a:ef:69:e0:15:ef:
                          1b:67:b1:90:c2:2c:fe:96:c5
                      Exponent: 65537 (0x10001)
              X509v3 extensions:
                  X509v3 Basic Constraints:
                      CA:FALSE
          Signature Algorithm: md5WithRSAEncryption
              61:c7:0b:2e:e8:65:1b:d5:7b:b0:1a:60:4b:f0:07:b7:d6:b6:
              9d:21:ea:b7:d5:3a:41:85:56:7f:ca:ed:ad:9d:06:d7:52:8c:
              9e:13:2a:ef:0f:1f:32:a7:72:12:5d:e0:00:0e:ee:44:2f:ad:
              83:06:c0:ce:94:b3:5e:5e:34:c9:eb:d1:bc:dc:bf:71:6c:e0:
              b5:65:0c:1d:64:60:e7:98:31:d4:93:18:7d:d7:4f:fc:e2:e6:
              8e:e0:06:a2:1d:ff:db:41:d0:c4:ff:8e:18:7c:8e:b8:95:1d:
              d3:59:38:73:d1:92:c1:16:f5:91:8b:1e:a3:d6:cf:04:db:24:
              84:34:28:c7:03:59:02:9c:ab:c4:31:06:dd:4b:8f:f0:64:09:
              e3:7a:13:e0:57:cf:a9:d8:81:7d:05:87:d9:a3:c4:78:03:36:
              fb:1e:58:65:a0:fd:ff:f4:8f:32:60:0a:dc:53:c8:4f:00:22:
              43:d1:dd:7a:e6:a6:63:67:87:53:9a:7a:c5:be:f0:0c:92:74:
              f5:d2:05:c6:51:60:3b:b3:83:53:40:7e:dd:44:a5:c6:32:63:
              c6:99:c4:ea:c9:36:be:f5:e9:d3:98:27:eb:59:4b:52:4c:6f:
              d2:d6:4d:df:2e:22:7c:7e:18:7b:88:8a:5a:41:6a:53:e6:6b:
              60:48:38:b8
      -----BEGIN CERTIFICATE-----
      MIIC/TCCAeWgAwIBAgIBAzANBgkqhkiG9w0BAQQFADB3MQwwCgYDVQQDEwNBTFUx
      CzAJBgNVBAgTAklMMQswCQYDVQQGEwJVUzEoMCYGCSqGSIb3DQEJARYZb2xlYXJ5
      QGFsY2F0ZWwtbHVjZW50LmNvbTEjMCEGA1UEChMaUm9vdCBDZXJ0aWZpY2F0ZSBB
      dXRob3JpdHkwHhcNMDgwNzExMTM1NDU4WhcNMDkwNzExMTM1NDU4WjCBgTEgMB4G
      A1UEAxMXdXNpbGlnbjMubmRjLmx1Y2VudC5jb20xCzAJBgNVBAgTAklMMQswCQYD
      VQQGEwJVUzEoMCYGCSqGSIb3DQEJARYZb2xlYXJ5QGFsY2F0ZWwtbHVjZW50LmNv
      bTEMMAoGA1UEChMDQUxVMQswCQYDVQQLEwJJVDCBnzANBgkqhkiG9w0BAQEFAAOB
      jQAwgYkCgYEAyPJNW6SNyTdmT3c9pLQuaIQh5WQ3Vurl8Jxy9bocZSGahCE2BiSG
      klbm9RQw1tlvrY3pEbhJ4T7X+D1Xm2Qph5ucw+oAgLUDvnIC3HVWgVkEu+eOU1YW
      DAmXp+oKx+ZVFMuSG3nWH9yWSbeuetFnc/9q72ngFe8bZ7GQwiz+lsUCAwEAAaMN
      MAswCQYDVR0TBAIwADANBgkqhkiG9w0BAQQFAAOCAQEAYccLLuhlG9V7sBpgS/AH
      t9a2nSHqt9U6QYVWf8rtrZ0G11KMnhMq7w8fMqdyEl3gAA7uRC+tgwbAzpSzXl40
      yevRvNy/cWzgtWUMHWRg55gx1JMYfddP/OLmjuAGoh3/20HQxP+OGHyOuJUd01k4
      c9GSwRb1kYseo9bPBNskhDQoxwNZApyrxDEG3UuP8GQJ43oT4FfPqdiBfQWH2aPE
      eAM2+x5YZaD9//SPMmAK3FPITwAiQ9HdeuamY2eHU5p6xb7wDJJ09dIFxlFgO7OD
      U0B+3USlxjJjxpnE6sk2vvXp05gn61lLUkxv0tZN3y4ifH4Ye4iKWkFqU+ZrYEg4
      uA==
      -----END CERTIFICATE-----
      Data Base Updated
      
  6. The generic CA puts the newly signed certificates under the ${caroot}/certs directory with a numeric filename. The new key should be the last one modified. ID and copy the newly signed cert back to the target host:

    ls -lart ${caroot}/certs | tail -1
    scp ${caroot}/certs/##.pem ${host}:/root/certs/${host}_signed.pem
    
  7. Remove the passphrase from the private key:

    Back on the target system, (not ${cahost}) run openssl command to remove the passphrase; update directories and filenames as appropriate:

    openssl rsa -in ${host}_private.pem -out ${host}_np_private.pem
    Enter pass phrase for ${host}_private.pem: <== Enter passphrase used when creating the key
    writing RSA key
    mv ${host}_np_private.pem ${host}_private.pem