Generating a Signing Cert using certutil

Imagine a locked room with a big window. If I am the only person with a key to room, and I tape a poster up inside the window, everyone can read it, and everyone can state with a pretty high degree of certainty that I was the person that I put up the poster. This is analogy to how you can use PKI to sign a document.


UPDATE: I’ve taken Kashyap’s advice and cleanup the following steps.

In order for the message signature to be verifiable, we generate a pair of keys, one that is kept private, and one that is made public. Data encrypted with the private key can then be decrypted with only the corresponding public key. So, to sign a message, it is encrypted with the private key.

There are ways to make this more efficient, such as signing a hash of the message, but the principal is the same.

I am going to use the same set of cryptographic tools that Mozilla provides for securing web traffic. These tools fall under then name Network Security Services or NSS for short.

The first step is to provide a Certificate Authority (CA) Certificate. This is a certificate used to sign other certificates. This is actually supposed to be part of a chain. In the browser, there are a list of CA certs that are accepted by default. For our purposes here, I am going to self sign one. Figuring out how to set this up for your organization has been left as an exercise to the reader.

We need a place to put the certificate. For NSS, this is called an NSS database. I am going to create one in a directory I call alias, because that is the name of the NSS database used in Apache HTTPD. To generate:

mkdir alias
certutil -N -d ./alias/

Now create a self-signed CA certificate. Type the command:

certutil -S -s "CN=CA Issuer" -n CACert -x -t "CT,C,C" -v 120 -m 1234 -d alias/

You will be prompted to type. This is used to generate entropy, or randomness, for the underlying cryptography.

The security conscious folks out there are squirming in their seats reading this, because a self-signed CA cert is BAD under most circumstances. However, this is proof-of-concept type stuff. You always need to get a certificate signed by a CA…this is just the simple way to do it for development.

Now that we have a CA cert, we need to generate a Key. With NSS, you can generate the Key and the certificate signing request in one step:

 certutil -R -s "CN=Adam Young, O=RedHat , L=Westford, ST=MA, C=US" -p "617-555-1212" -o mycert.req -d alias

You see the same entropy generation prompt as before.

You can list the keys using:

certutil -K -d ./alias/ 

Which produces output along the lines of:

certutil: Checking token "NSS Certificate DB" in slot "NSS User Private Key and Certificate Services"
< 0> rsa      99f6d153a007f8fb2d79312d454749eb92e4db99   NSS Certificate DB:myissuer
< 1> rsa      b8472a65af1c2da900fb0eb953d9c278d615a580   NSS Certificate DB:ayoung

Note that there is one in there for the CA certificate we produced before.

To sign the key run the following:

 certutil -C -m 2345 -i mycert.req -o mycert.crt -c myissuer -d ./alias/ -6

The -6 option allows to add extensions to the certificate, specifically the ones that we need to sign email. The private and public keys are held in the NSS database.

Now that we have a useful certificate and key pair that we can use to sign a document. To Sign auth_token.json run:

cmsutil -S -d alias -N ayoung -i signme.txt -o signed.p7s

The signed message is put into signed.p7s. The file extension alludes to the PKCS 7 standard that CMS grew out of.

Here is everything as a single Makefile.

TARGETS = alias mycert.req noise.dat mycert.crt

all: $(TARGETS)


alias : noise.dat
	mkdir alias
	certutil -N -d alias
	certutil -S -s "CN=CA Issuer" -n CACert -x -t "CT,C,C" -v 120 -m 1234 -d alias/ -z noise.dat


mycert.req : alias
	certutil -R -s "CN=Joe Admin, O=RedHat , L=Westford, ST=MA, C=US" -p "617-555-1212" -o mycert.req -d alias -n joeadmin -z noise.dat


mycert.crt : mycert.req
	certutil -C -m 2345 -i mycert.req -o mycert.crt -c CACert -d ./alias --extKeyUsage  "clientAuth,emailProtection"
	certutil -A -d ./alias/ -i mycert.crt -n joeadmin -t "u,u,u"

noise.dat :
	head -c 20 /dev/urandom > noise.dat



clean:
	rm -rf $(TARGETS)


It is possible I’ve typeo’d some things, but the Makefile ran after a “make clean” so I should have generated everything from scratch.

5 thoughts on “Generating a Signing Cert using certutil

  1. Heya Adam,
    Just a couple of observations:

    1/ You could create a self-signed CA in one go w/o manual intervention (w/o explicitly providing the cert extensions like -1, -2 , -5 )

    certutil -S -n “IPA ROOTCA certificate” -s “cn=CAcert” -x -t “CT,,” -m 1000 -v 120 -d .

    Also, perhaps, you could avoid a couple of prompts in your request. You used trust attributes “C,C,C” — where ‘C’ means “Trusted CA to issue server certificates (SSL only)” . And, haven’t provided ‘T’ attribute there ( like — “CT,C,C”) , where ‘T’ would mean “Trusted CA to issue client certificates (implies c) ”

    2/ You could also create the entropy (or ‘noise’ file) and pass it with the flag(‘-z’) to avoid manual intervention.

    #Certutil -S ………. -z noise.txt

    If you omitted the all above things just to make your illustration more explicit and clear, please disregard me 🙂

  2. Thanks, Kashyap….I was going by trial and error, and so I am not surprised that there are more efficient ways to do these tasks. I don’t think my explanation is any more clear due to the details.

  3. Hi Adam! just a question – if a certificate is issued using the cmd prompt (using certutil), is it logged anywhere?

  4. How to generate the CSR request with SAN name using certutil.

    Can you please provide the command?

    I did not find in certutil options.

    Thanks
    Anand

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.