Skip to content

Instantly share code, notes, and snippets.

@wolever
Last active August 16, 2019 13:42
Show Gist options
  • Select an option

  • Save wolever/5762823 to your computer and use it in GitHub Desktop.

Select an option

Save wolever/5762823 to your computer and use it in GitHub Desktop.

Revisions

  1. wolever renamed this gist Jul 15, 2013. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  2. wolever revised this gist Jul 15, 2013. 6 changed files with 1 addition and 341 deletions.
    90 changes: 0 additions & 90 deletions README.rst
    Original file line number Diff line number Diff line change
    @@ -1,90 +0,0 @@
    SSL Helpers
    ===========

    These scripts can be used to generate different kinds of SSL keys and
    certificates.

    Usage
    -----

    1. Create a certificate authority::

    $ ./mkca <ca_name>
    .............++++++
    .....++++++
    writing new private key to '<ca_name>/cakey.pem'
    -----

    #. Trust the CA's certificate, which will be stored at
    ``<ca_name>/cacert.crt``. On Windows and Mac, this can be done by double
    clicking the file then adding it to the list of "Trusted Root Certification
    Authorities", or similar.

    #. Create an SSL certificate (where ``<cert_cn>`` will be the common name used
    on the certificate)::

    $ ./mkcert <ca_name> <cert_cn>
    --- creating key ---
    Generating a 1024 bit RSA private key
    .........++++++
    ......++++++
    writing new private key to '<cert_cn>-temp-private.pem'
    -----
    Using configuration from ./openssl.cfg
    Check that the request matches the signature
    Signature ok
    The Subject's Distinguished Name is as follows
    commonName :T61STRING:'<cert_cn>'
    Certificate is to be certified until Jun 3 17:21:15 2031 GMT (7300 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
    Data Base Updated
    <ca_name>/certs/<cert_cn>.pem created.

    #. Use the ``certcat`` script to verify that the certificate is correct::

    $ ./certcat <ca_name>/certs/<cert_cn>.pem
    Private-Key: (1024 bit)
    modulus:
    00:b4:8c:01:20:52:a5:f1:11:d1:d1:52:bd:ec:7b:
    a6:12:d6:c6:5f:ef:ff:fc:bf:86:06:bc:51:be:8c:
    30:6b:09:15:c0:de:ab:9a:b3:85:cc:1d:a1:63:b1:
    ...
    Certificate:
    Data:
    Version: 3 (0x2)
    Serial Number: 1 (0x1)
    Signature Algorithm: sha1WithRSAEncryption
    Issuer: CN=<ca_name>
    Validity
    Not Before: Jun 8 17:21:15 2011 GMT
    Not After : Jun 3 17:21:15 2031 GMT
    Subject: CN=<cert_cn>
    Subject Public Key Info:
    Public Key Algorithm: rsaEncryption
    RSA Public Key: (1024 bit)
    Modulus (1024 bit):
    00:b4:8c:01:20:52:a5:f1:11:d1:d1:52:bd:ec:7b:
    ...
    01:b2:e3:37:12:0f:21:9e:bb
    Exponent: 65537 (0x10001)
    X509v3 extensions:
    X509v3 Basic Constraints:
    CA:FALSE
    X509v3 Subject Key Identifier:
    36:BA:81:45:68:E0:19:41:DC:7A:B0:A8:DE:8D:82:C1:46:41:8F:EE
    X509v3 Authority Key Identifier:
    keyid:AD:E7:D8:50:3E:A7:9D:26:D9:92:4D:44:46:D7:88:95:CF:CC:C1:3E
    DirName:/CN=<ca_name>
    serial:F0:3C:D7:80:54:DD:15:9B

    Signature Algorithm: sha1WithRSAEncryption
    11:33:24:56:32:72:0c:a8:b6:b4:5d:06:02:3e:7d:2f:82:67:
    ...
    04:73

    #. Copy the new key and certificate (which has been signed by ``<ca_name>``)
    into place::

    $ scp <ca_name>/certs/<cert_cn>.pem host:/etc/ssl/private/<cert_cn>.pem
    1 change: 1 addition & 0 deletions README.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1 @@
    This gist has been migrated to a real repository: https://github.com/wolever/openssl-x509-scripts
    6 changes: 0 additions & 6 deletions certcat
    Original file line number Diff line number Diff line change
    @@ -1,6 +0,0 @@
    #!/bin/bash
    # from http://dv-zeuthen.desy.de/security/examples_for_usage_of_openssl_command/

    openssl rsa -noout -text -in "$1" | head -n5
    echo "..."
    openssl x509 -noout -text -in "$1"
    74 changes: 0 additions & 74 deletions mkca
    Original file line number Diff line number Diff line change
    @@ -1,74 +0,0 @@
    #!/bin/bash
    set -e

    nodes="-nodes"
    if [[ "$1" == "-des" ]]; then
    nodes=""
    shift
    fi

    if [[ ! "$1" || ! "$2" || "$1" =~ "^-" ]]; then
    echo "usage: $0 [-des] CommonName directory"
    exit 2
    fi

    name="$1"
    dir="$2"

    subj="/C=CA/ST=Ontario/L=Toronto/O=Luminautics Inc./CN=$name"

    cakey="ca.key"
    if [[ ! "$nodes" ]]; then
    cakey="$cakey-encrypted"
    fi

    if [[ -d "$dir" ]]; then
    echo "error: $dir/ exists"
    exit 1
    fi

    mkdir "$dir"
    cat "`dirname "$0"`"/openssl.default.cfg | sed -e "s/{{CAKEY}}/$cakey/" > "$dir/openssl.cfg"
    cd "$dir"

    # Because we want to explicitly set the default start and end dates (see
    # default_startdate, default_enddate in openssl.cfg), some hoops need to be
    # jumped through:
    # - A key + self-signed cert must be created
    # - A CSR must be generated from that key
    # - Then the self-signed cert must be used to sign the CSR

    # First create a key + self-signed certificate
    openssl req -new -x509 -config ./openssl.cfg \
    -keyout "$cakey" \
    -out "temp_cert.crt" \
    -subj "$subj" \
    $nodes \
    -extensions "standard_ca"

    mkdir "certs"
    touch "database"
    echo "0001" > "serial"

    # Generate a new CSR from the private key
    openssl req -new -config ./openssl.cfg \
    -key "$cakey" \
    -out "temp_csr.csr" \
    -subj "$subj" \
    $nodes \
    -extensions "standard_ca"

    # Use the self-signed certificate to sign the CSR, producing the final
    # certificate.
    openssl ca -config ./openssl.cfg \
    -batch \
    -cert "temp_cert.crt" \
    -out "ca.crt" \
    -in "temp_csr.csr" \
    -extensions "standard_ca"

    # Optionally, export the cert in pkcs12 format
    openssl pkcs12 -export -in "$cakey" -out "ca.p12"

    # Cleanup!
    rm temp_*
    91 changes: 0 additions & 91 deletions mkcert
    Original file line number Diff line number Diff line change
    @@ -1,91 +0,0 @@
    #!/bin/bash

    set -e

    usage() {
    echo "usage: $0 [-server] [-des] ca keyname"
    echo " -server include 'nsCertType=server' in the certificate"
    echo " (for use with OpenVPN's 'ns-cert-type' option)"
    echo " -des also include an encrypted private key"
    }

    extensions="standard"
    nodes="-nodes"

    while :; do
    if [[ $# -eq 2 ]]; then
    break
    fi
    case "${1-}" in
    "-server")
    extensions="server"
    shift
    ;;
    "-des")
    nodes=""
    shift
    ;;
    **)
    usage
    exit 2
    ;;
    esac
    done


    ca="${1%/}"
    keyname="$2"

    subj="/C=CA/ST=Ontario/L=Toronto/CN=$keyname"

    if [[ ! -d "$ca" ]]; then
    echo "error: can't find $ca/"
    exit 1
    fi

    cd "$ca/"

    echo "--- creating key ---"

    keyfile="$keyname-temp.key"
    reqfile="$keyname-temp.csr"
    crtfile="$keyname-temp.crt"

    openssl req -new -config ./openssl.cfg \
    -keyout "$keyfile" \
    -out "$reqfile" \
    -subj "$subj" \
    -nodes \
    -extensions "$extensions"

    if [[ -f "passphrase" ]]; then
    echo "=========="
    echo "PASSWORD: `cat passphrase`"
    echo "=========="
    fi

    openssl ca -config ./openssl.cfg \
    -batch \
    -noemailDN \
    -in "$reqfile" \
    -out "$crtfile" \
    -extensions "$extensions"

    pemfile="certs/$keyname.pem"
    if [[ "$nodes" ]]; then
    cat "$crtfile" "$keyfile" > "$pemfile"
    echo "$ca/$pemfile created."
    else
    # Store an encrypted copy of the certificate in the CA's store
    openssl rsa '-in' "$keyfile" -des3 -out "$keyfile-encrypted"
    cat "$crtfile" "$keyfile-encrypted" > "$pemfile-encrypted"
    echo "$ca/$pemfile-encrypted created."

    # And stick an unencrypted copy of the certificate in /tmp/
    touch "/tmp/$keyname.pem"
    chmod 600 "/tmp/$keyname.pem"
    cat "$crtfile" "$keyfile" > "/tmp/$keyname.pem"
    echo "/tmp/$keyname.pem created"
    fi

    rm "$keyname-temp"*
    80 changes: 0 additions & 80 deletions openssl.default.cfg
    Original file line number Diff line number Diff line change
    @@ -1,80 +0,0 @@
    #
    # OpenSSL configuration file.
    #

    # Establish working directory.
    dir = .

    [ ca ]
    default_ca = CA_default

    [ CA_default ]
    serial = $dir/serial
    database = $dir/database
    new_certs_dir = $dir/certs
    certificate = $dir/ca.crt
    private_key = $dir/{{CAKEY}}
    default_md = sha1
    preserve = no
    nameopt = default_ca
    certopt = default_ca
    policy = policy_match
    default_days =
    default_startdate = 700101000001Z
    default_enddate = 300101000000Z

    [ policy_match ]
    countryName = optional
    stateOrProvinceName = optional
    localityName = optional
    organizationName = optional
    organizationalUnitName = optional
    commonName = supplied
    emailAddress = optional

    [ req ]
    default_bits = 1024 # Size of keys
    default_keyfile = key.pem # name of generated keys
    default_md = sha1 # message digest algorithm
    string_mask = nombstr # permitted characters
    distinguished_name = req_distinguished_name

    [ req_distinguished_name ]
    #0.organizationName = Organization Name (company)
    #organizationalUnitName = Organizational Unit Name (department, division)
    #emailAddress = Email Address
    #emailAddress_max = 40
    #localityName = Locality Name (city, district)
    #stateOrProvinceName = State or Province Name (full name)
    #countryName = Country Name (2 letter code)
    #countryName_min = 2
    #countryName_max = 2
    #commonName = commonName (hostname)
    #commonName_max = 64

    #0.organizationName_default = David Wolever
    #organizationalUnitName_defaul =
    #emailAddress_default = david@wolever.net
    #localityName_default = Toronto
    #stateOrProvinceName_default = Ontario
    #countryName_default = CA

    #
    # Custom extension definitions
    #

    [ standard_ca ]
    basicConstraints = CA:TRUE
    subjectKeyIdentifier = hash
    authorityKeyIdentifier = keyid:always

    [ standard ]
    basicConstraints = CA:FALSE
    subjectKeyIdentifier = hash
    authorityKeyIdentifier = keyid:always,issuer:always

    [ server ]
    basicConstraints = CA:FALSE
    subjectKeyIdentifier = hash
    authorityKeyIdentifier = keyid:always,issuer:always
    nsCertType = server
  3. wolever revised this gist Jun 12, 2013. 1 changed file with 6 additions and 2 deletions.
    8 changes: 6 additions & 2 deletions README.rst
    Original file line number Diff line number Diff line change
    @@ -8,6 +8,7 @@ Usage
    -----

    1. Create a certificate authority::

    $ ./mkca <ca_name>
    .............++++++
    .....++++++
    @@ -21,6 +22,7 @@ Usage

    #. Create an SSL certificate (where ``<cert_cn>`` will be the common name used
    on the certificate)::

    $ ./mkcert <ca_name> <cert_cn>
    --- creating key ---
    Generating a 1024 bit RSA private key
    @@ -40,8 +42,9 @@ Usage
    Data Base Updated
    <ca_name>/certs/<cert_cn>.pem created.

    #. Use the ``dump_ssl`` script to verify that the certificate is correct::
    $ ./dump_ssl <ca_name>/certs/<cert_cn>.pem
    #. Use the ``certcat`` script to verify that the certificate is correct::

    $ ./certcat <ca_name>/certs/<cert_cn>.pem
    Private-Key: (1024 bit)
    modulus:
    00:b4:8c:01:20:52:a5:f1:11:d1:d1:52:bd:ec:7b:
    @@ -83,4 +86,5 @@ Usage

    #. Copy the new key and certificate (which has been signed by ``<ca_name>``)
    into place::

    $ scp <ca_name>/certs/<cert_cn>.pem host:/etc/ssl/private/<cert_cn>.pem
  4. wolever created this gist Jun 12, 2013.
    86 changes: 86 additions & 0 deletions README.rst
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,86 @@
    SSL Helpers
    ===========

    These scripts can be used to generate different kinds of SSL keys and
    certificates.

    Usage
    -----

    1. Create a certificate authority::
    $ ./mkca <ca_name>
    .............++++++
    .....++++++
    writing new private key to '<ca_name>/cakey.pem'
    -----

    #. Trust the CA's certificate, which will be stored at
    ``<ca_name>/cacert.crt``. On Windows and Mac, this can be done by double
    clicking the file then adding it to the list of "Trusted Root Certification
    Authorities", or similar.

    #. Create an SSL certificate (where ``<cert_cn>`` will be the common name used
    on the certificate)::
    $ ./mkcert <ca_name> <cert_cn>
    --- creating key ---
    Generating a 1024 bit RSA private key
    .........++++++
    ......++++++
    writing new private key to '<cert_cn>-temp-private.pem'
    -----
    Using configuration from ./openssl.cfg
    Check that the request matches the signature
    Signature ok
    The Subject's Distinguished Name is as follows
    commonName :T61STRING:'<cert_cn>'
    Certificate is to be certified until Jun 3 17:21:15 2031 GMT (7300 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
    Data Base Updated
    <ca_name>/certs/<cert_cn>.pem created.

    #. Use the ``dump_ssl`` script to verify that the certificate is correct::
    $ ./dump_ssl <ca_name>/certs/<cert_cn>.pem
    Private-Key: (1024 bit)
    modulus:
    00:b4:8c:01:20:52:a5:f1:11:d1:d1:52:bd:ec:7b:
    a6:12:d6:c6:5f:ef:ff:fc:bf:86:06:bc:51:be:8c:
    30:6b:09:15:c0:de:ab:9a:b3:85:cc:1d:a1:63:b1:
    ...
    Certificate:
    Data:
    Version: 3 (0x2)
    Serial Number: 1 (0x1)
    Signature Algorithm: sha1WithRSAEncryption
    Issuer: CN=<ca_name>
    Validity
    Not Before: Jun 8 17:21:15 2011 GMT
    Not After : Jun 3 17:21:15 2031 GMT
    Subject: CN=<cert_cn>
    Subject Public Key Info:
    Public Key Algorithm: rsaEncryption
    RSA Public Key: (1024 bit)
    Modulus (1024 bit):
    00:b4:8c:01:20:52:a5:f1:11:d1:d1:52:bd:ec:7b:
    ...
    01:b2:e3:37:12:0f:21:9e:bb
    Exponent: 65537 (0x10001)
    X509v3 extensions:
    X509v3 Basic Constraints:
    CA:FALSE
    X509v3 Subject Key Identifier:
    36:BA:81:45:68:E0:19:41:DC:7A:B0:A8:DE:8D:82:C1:46:41:8F:EE
    X509v3 Authority Key Identifier:
    keyid:AD:E7:D8:50:3E:A7:9D:26:D9:92:4D:44:46:D7:88:95:CF:CC:C1:3E
    DirName:/CN=<ca_name>
    serial:F0:3C:D7:80:54:DD:15:9B

    Signature Algorithm: sha1WithRSAEncryption
    11:33:24:56:32:72:0c:a8:b6:b4:5d:06:02:3e:7d:2f:82:67:
    ...
    04:73

    #. Copy the new key and certificate (which has been signed by ``<ca_name>``)
    into place::
    $ scp <ca_name>/certs/<cert_cn>.pem host:/etc/ssl/private/<cert_cn>.pem
    6 changes: 6 additions & 0 deletions certcat
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,6 @@
    #!/bin/bash
    # from http://dv-zeuthen.desy.de/security/examples_for_usage_of_openssl_command/

    openssl rsa -noout -text -in "$1" | head -n5
    echo "..."
    openssl x509 -noout -text -in "$1"
    74 changes: 74 additions & 0 deletions mkca
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,74 @@
    #!/bin/bash
    set -e

    nodes="-nodes"
    if [[ "$1" == "-des" ]]; then
    nodes=""
    shift
    fi

    if [[ ! "$1" || ! "$2" || "$1" =~ "^-" ]]; then
    echo "usage: $0 [-des] CommonName directory"
    exit 2
    fi

    name="$1"
    dir="$2"

    subj="/C=CA/ST=Ontario/L=Toronto/O=Luminautics Inc./CN=$name"

    cakey="ca.key"
    if [[ ! "$nodes" ]]; then
    cakey="$cakey-encrypted"
    fi

    if [[ -d "$dir" ]]; then
    echo "error: $dir/ exists"
    exit 1
    fi

    mkdir "$dir"
    cat "`dirname "$0"`"/openssl.default.cfg | sed -e "s/{{CAKEY}}/$cakey/" > "$dir/openssl.cfg"
    cd "$dir"

    # Because we want to explicitly set the default start and end dates (see
    # default_startdate, default_enddate in openssl.cfg), some hoops need to be
    # jumped through:
    # - A key + self-signed cert must be created
    # - A CSR must be generated from that key
    # - Then the self-signed cert must be used to sign the CSR

    # First create a key + self-signed certificate
    openssl req -new -x509 -config ./openssl.cfg \
    -keyout "$cakey" \
    -out "temp_cert.crt" \
    -subj "$subj" \
    $nodes \
    -extensions "standard_ca"

    mkdir "certs"
    touch "database"
    echo "0001" > "serial"

    # Generate a new CSR from the private key
    openssl req -new -config ./openssl.cfg \
    -key "$cakey" \
    -out "temp_csr.csr" \
    -subj "$subj" \
    $nodes \
    -extensions "standard_ca"

    # Use the self-signed certificate to sign the CSR, producing the final
    # certificate.
    openssl ca -config ./openssl.cfg \
    -batch \
    -cert "temp_cert.crt" \
    -out "ca.crt" \
    -in "temp_csr.csr" \
    -extensions "standard_ca"

    # Optionally, export the cert in pkcs12 format
    openssl pkcs12 -export -in "$cakey" -out "ca.p12"

    # Cleanup!
    rm temp_*
    91 changes: 91 additions & 0 deletions mkcert
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,91 @@
    #!/bin/bash

    set -e

    usage() {
    echo "usage: $0 [-server] [-des] ca keyname"
    echo " -server include 'nsCertType=server' in the certificate"
    echo " (for use with OpenVPN's 'ns-cert-type' option)"
    echo " -des also include an encrypted private key"
    }

    extensions="standard"
    nodes="-nodes"

    while :; do
    if [[ $# -eq 2 ]]; then
    break
    fi
    case "${1-}" in
    "-server")
    extensions="server"
    shift
    ;;
    "-des")
    nodes=""
    shift
    ;;
    **)
    usage
    exit 2
    ;;
    esac
    done


    ca="${1%/}"
    keyname="$2"

    subj="/C=CA/ST=Ontario/L=Toronto/CN=$keyname"

    if [[ ! -d "$ca" ]]; then
    echo "error: can't find $ca/"
    exit 1
    fi

    cd "$ca/"

    echo "--- creating key ---"

    keyfile="$keyname-temp.key"
    reqfile="$keyname-temp.csr"
    crtfile="$keyname-temp.crt"

    openssl req -new -config ./openssl.cfg \
    -keyout "$keyfile" \
    -out "$reqfile" \
    -subj "$subj" \
    -nodes \
    -extensions "$extensions"

    if [[ -f "passphrase" ]]; then
    echo "=========="
    echo "PASSWORD: `cat passphrase`"
    echo "=========="
    fi

    openssl ca -config ./openssl.cfg \
    -batch \
    -noemailDN \
    -in "$reqfile" \
    -out "$crtfile" \
    -extensions "$extensions"

    pemfile="certs/$keyname.pem"
    if [[ "$nodes" ]]; then
    cat "$crtfile" "$keyfile" > "$pemfile"
    echo "$ca/$pemfile created."
    else
    # Store an encrypted copy of the certificate in the CA's store
    openssl rsa '-in' "$keyfile" -des3 -out "$keyfile-encrypted"
    cat "$crtfile" "$keyfile-encrypted" > "$pemfile-encrypted"
    echo "$ca/$pemfile-encrypted created."

    # And stick an unencrypted copy of the certificate in /tmp/
    touch "/tmp/$keyname.pem"
    chmod 600 "/tmp/$keyname.pem"
    cat "$crtfile" "$keyfile" > "/tmp/$keyname.pem"
    echo "/tmp/$keyname.pem created"
    fi

    rm "$keyname-temp"*
    80 changes: 80 additions & 0 deletions openssl.default.cfg
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,80 @@
    #
    # OpenSSL configuration file.
    #

    # Establish working directory.
    dir = .

    [ ca ]
    default_ca = CA_default

    [ CA_default ]
    serial = $dir/serial
    database = $dir/database
    new_certs_dir = $dir/certs
    certificate = $dir/ca.crt
    private_key = $dir/{{CAKEY}}
    default_md = sha1
    preserve = no
    nameopt = default_ca
    certopt = default_ca
    policy = policy_match
    default_days =
    default_startdate = 700101000001Z
    default_enddate = 300101000000Z

    [ policy_match ]
    countryName = optional
    stateOrProvinceName = optional
    localityName = optional
    organizationName = optional
    organizationalUnitName = optional
    commonName = supplied
    emailAddress = optional

    [ req ]
    default_bits = 1024 # Size of keys
    default_keyfile = key.pem # name of generated keys
    default_md = sha1 # message digest algorithm
    string_mask = nombstr # permitted characters
    distinguished_name = req_distinguished_name

    [ req_distinguished_name ]
    #0.organizationName = Organization Name (company)
    #organizationalUnitName = Organizational Unit Name (department, division)
    #emailAddress = Email Address
    #emailAddress_max = 40
    #localityName = Locality Name (city, district)
    #stateOrProvinceName = State or Province Name (full name)
    #countryName = Country Name (2 letter code)
    #countryName_min = 2
    #countryName_max = 2
    #commonName = commonName (hostname)
    #commonName_max = 64

    #0.organizationName_default = David Wolever
    #organizationalUnitName_defaul =
    #emailAddress_default = david@wolever.net
    #localityName_default = Toronto
    #stateOrProvinceName_default = Ontario
    #countryName_default = CA

    #
    # Custom extension definitions
    #

    [ standard_ca ]
    basicConstraints = CA:TRUE
    subjectKeyIdentifier = hash
    authorityKeyIdentifier = keyid:always

    [ standard ]
    basicConstraints = CA:FALSE
    subjectKeyIdentifier = hash
    authorityKeyIdentifier = keyid:always,issuer:always

    [ server ]
    basicConstraints = CA:FALSE
    subjectKeyIdentifier = hash
    authorityKeyIdentifier = keyid:always,issuer:always
    nsCertType = server