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.
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=My Issuer" -n myissuer -x -t "C,C,C" -1 -2 -5 -m 1234 -d alias/
You will be prompted to type. This is used to generate entropy, or randomness, for the underlying cryptography.
Then you will be prompted to select aspects of the certificate. A menu of options like this:
0 - Digital Signature
1 - Non-repudiation
2 - Key encipherment
3 - Data encipherment
4 - Key agreement
5 - Cert signing key
6 - CRL signing key
Other to finish
Type each number in order. 0 1 2 3 4 5 6. The menu will reappear after each.
Yes, it is annoying. I didn’t write the tool.
then type any number to finish
So the number 9 works.
9
Is this a critical extension [y/N]?
y
Is this a CA certificate [y/N]?
y
Enter the path length constraint, enter to skip [<0 for unlimited path]: >
Is this a critical extension [y/N]?
y
Not done yet: Next menu.
0 - SSL Client
1 - SSL Server
2 - S/MIME
3 - Object Signing
4 - Reserved for future use
5 - SSL CA
6 - S/MIME CA
7 - Object Signing CA
Other to finish
For this we want 5 6 7 then again pick 9 to exit.
> 9
Is this a critical extension [y/N]?
y
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
Here is the menu you are presented:
0 - Server Auth
1 - Client Auth
2 - Code Signing
3 - Email Protection
4 - Timestamp
5 - OCSP Responder
6 - Step-up
Other to finish
The import options are 1 and 3, as we are going to use the same mechanism as we would use to sign email. The private and public keys are held in the NSS database. OK, we finally 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.