opensslcode-signingcode-signing-certificate

How to create a self-signed code signing certificate from a CSR?


The title says it all. All the articles I could find was either about generating a self-signed SSL certificate, or not considering a CSR. My requirement is simple: generate a self-signed code signing certificate that I can use with signtool.exe from a CSR for testing.


Solution

  • I expect this question to be a duplicate but I could not find a concise answer so I am offering this as a more complete one using OpenSSL to generate x509 self signed certificates for code signing (or any other purpose).

    Steps:

    1. Generate a CA (Certificate Authority) key
    2. Generate an x509 CA certificate (DER encoding)
    3. Create a CSR (Certificate Signing Request) template
    4. Generate a CSR using the CSR template
    5. Create a signing certificate template
    6. Generate an x509 signing certificate and key pair (DER enconding)
    7. (optional) Convert DER to PKCS12 format (Windows needs this)
    8. (optional) View your work

    I will use a fake company (The Company Ltd) that is not related in any way to a real organisation

    See Wikipedia for a clarification of BER, DER and CER formats. Note .cer is often used as a file extension for a DER file - Doh! Also see Wikipedia about PKCS12 format

    1 - Generate a CA key

    openssl genrsa -des3 -out rootCA.key 4096
    

    Give the root CA key a password and don't forget it!!

    2 - Create an x509 CA certificate (DER encoding)

    openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 1024 -out rootCA.crt
    

    Enter details for: [example]

    3 - Edit CSR Template : code_sign_csr.conf

    [ req ]
    default_bits  = 2048      # RSA key size
    encrypt_key   = yes       # Protect private key
    default_md    = sha256    # MD to use
    utf8          = yes       # Input is UTF-8
    string_mask   = utf8only  # Emit UTF-8 strings
    prompt        = yes       # Prompt for DN
    distinguished_name = codesign_dn # DN template
    req_extensions     = codesign_reqext # Desired extensions
    
    [ codesign_dn ]
    commonName      = the-company.com
    commonName_max  = 64
    
    [ codesign_reqext ]
    keyUsage             = critical,digitalSignature
    extendedKeyUsage     = critical,codeSigning
    subjectKeyIdentifier = hash
    

    4 - Generate a CSR using the template

    openssl req -new -newkey rsa:2048 -keyout testsign.key -sha256 -nodes -out testsign.csr -subj "/CN=The Company Engineering Code Sign Cert" -config code_sign_csr.conf
    

    5 - Create a signing certificate template: code_sign_cert.conf

    authorityKeyIdentifier = keyid,issuer
    basicConstraints       = CA:FALSE
    subjectAltName         = @alt_names
    extendedKeyUsage       = codeSigning
    
    [alt_names]
    DNS.1 = the-company.com
    

    6 - Generate a x509 signing cert and key pair by signing the CSR with the CA certificate

    openssl x509 -req -CA rootCA.crt -CAkey rootCA.key -in testsign.csr -out testsign.crt -days 365 -CAcreateserial -extfile code_sign_cert.conf
    

    The same process in (5) and (6) is used to generate further certificates.

    7 - (optional) convert x509 certs to PKCS12

    openssl pkcs12 -export -out testsign.p12 -inkey testsign.key -in testsign.crt
    openssl pkcs12 -export -out rootCA.p12 -inkey rootCA.key -in rootCA.crt
    

    8 - (optional) view your work

    openssl x509 -in testsign.crt -noout -text
    openssl x509 -in rootCA.crt -noout -text
    

    Note and verify the Issuer and Subject

    Now supply the rootCA certificate to the clients that need to validate the certificate.

    Supply the rootCA certificate and generated certificate(s) to the server, code author, emailer, etc.

    Store the CA signing key in a very safe place and don't share it or forget where you put it..... (I always find that bit the hardest).

    A note on Subject Alt Name