Tag Archives: ssl - Page 3

Code Signing for Mac OS X and Windows

Code signing is rapidly becoming an important part of application deployment on many platforms. On OS X it suppresses the keychain warnings when you update your application and on Windows it can bypass numerous UAC notifications as well as the initial application launch dialog. This can (sometimes drastically) improve the customer experience and reduce friction associated with your application. But how do you actually do it?

You can purchase a code signing certificate from any major CA, but for today we’re going to use the OpenSSL Self-Signed CA we created in a previous article.

First let’s create a code signing certificate (if you purchased a certificate you will not need to perform these steps):

 openssl req -newkey rsa:1024 -nodes -out codesign.csr -keyout codesign.key

This will write out a codesign.key and codesign.csr after you choose the fields you desire. Since we are making a code signing certificate the common name should be your company name. You can also leave the challenge password blank.

Generating a 1024 bit RSA private key
..........++++++
..................++++++
writing new private key to 'req.key'
-----
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) [GB]:US
State or Province Name (full name) [Berkshire]:Illinois
Locality Name (eg, city) [Newbury]:Chicago
Organization Name (eg, company) [My Company Ltd]:End Entity, Inc.
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:End Entity, Inc.
Email Address []:
 
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

Now that we’ve created the CSR, we need to modify the myca.conf file to flag certificates for code signing. Find this line

extendedKeyUsage = serverAuth

and change it to

extendedKeyUsage = codeSigning

Now we’re all set to sign the certificate.

 openssl ca -batch -config /path/to/myca.conf -notext -in codesign.csr -out /path/to/codesign.cer

At this point we should have a codesign.cer and a codesign.key file and we’re ready for the actual signing process.

Code Signing on OS X

In OS X the codesign binary is used to sign applications. Codesign cannot accept the private key/certificate pair as a command line parameter, so you must place them in your Keychain. To do this you need to convert your CER + RSA private key into a PKCS12 (PFX) file. Luckily there’s already a post here about that, so check out Generating a PKCS12 (PFX) Via OpenSSL for more information.
Once you have it in the proper format, simply double click to import. Now to sign your application:

codesign -s 'End Entity, Inc.' Whatever.app

Inside the single quotes you’ll want to choose the name (CN) of the certificate as seen in Keychain Access.
If you chose to sign the application with a self-signed cert, please note that OS X won’t trust it unless you add the created root to your Keychain. If you do not you will receive this warning:

Whatever.app/: CSSMERR_TP_NOT_TRUSTED

Code Signing XP/Vista/Windows 7

To code sign in Windows you should have an SPC (aka PKCS7/P7B) or CER file along with a pvk formatted private key. To take a standard RSA private key and convert to PVK you should use PVK Tool (Download link is under the conversion tools heading)
Convert your private key to PVK format

pvk.exe -topvk -nocrypt -in codesign.key -out codesign.pvk

Once you have the files in the format you require execute SignTool from a windows command prompt.

 signtool.exe signwizard


And we’re done! If you chose to sign the application with a self-signed cert, please note that Windows won’t trust it unless you add the created root to your certificate store.

Generating a PKCS12 (PFX) Via OpenSSL

Sometimes there are cases when you have a separate private key/certificate pair (perhaps with an intermediate or two) that need to be combined into a single file.  This merge can be performed on the command line using OpenSSL.

openssl pkcs12 -export -in my.cer -inkey my.key -out mycert.pfx

This is the most basic use case and assumes that we have no intermediates, the private key has no password associated, my.cer is a PEM encoded file, and that we wish to supply a password interactively to protect the output file.  Great, but what if that’s not true?

Common Optional Flags

-passin If your private key has a password, you can supply it via this flag (Example: -passin pass:mypass).  Note: This flag is not necessary as OpenSSL will ask you for the password interactively if it detects that the private key is passworded, but can be useful for automation.

-in You can add extra certificates via additional -in parameters. (Example: -in anothercert.cer)

-inform If your certificates are DER (binary) encoded rather than PEM (base64) use this flag (Example: -inform DER)

-password You can use this flag to specify the output file’s password in a non-interactive fashion (Example: -password pass:mypass).  Note: Again, this is useful primarily to reduce interactivity and increase automation/scripting capability.

Much more advanced behavior is available, but if you need that it’s probably time to check the man page.

OpenSSL Self-Signed CA

Setting up a basic CA for development certificate issuance via OpenSSL is fairly simple, but most of the tutorials available online don’t show every step. This guide attempts to be as clear as possible, but if you spot anything that could use more explanation don’t hesitate to leave a comment.

If you don’t have a copy of OpenSSL on your machine, download it now.  Linux and OS X users should already have it on their systems, but Windows users can get the latest binaries here.  Please note that if you are running a version of OpenSSL prior to 0.9.8 that signing the same CSR multiple times will cause an error (due to lack of support for unique_subject=no).  RHEL4 ships with 0.9.7a.

Creating a Self-Signed Root Certificate

First we must create a signing cert (a certificate with basicConstraints set to CA:True) for use.  This will write out a privkey.pem file (base64 encoded RSA private key) as well as a root.cer file containing the self-signed public key with a 3650 day validity period.

openssl req -newkey rsa:2048 -days 3650 -x509 -nodes -out root.cer

You will see output in the following form.  Fill in the fields as you desire.  Example choices are filled in below.

Generating a 2048 bit RSA private key
............................................+++
.................................................+++
writing new private key to 'privkey.pem'
 
----
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) [GB]:US
State or Province Name (full name) [Berkshire]:Illinois
Locality Name (eg, city) [Newbury]:Chicago
Organization Name (eg, company) [My Company Ltd]:My Company
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:My Development CA
Email Address []:

Setting Up a Custom Openssl.conf

Create a new file named “myca.conf” save the following configuration into it substituting the proper private key, certificate (public key), and new_certs_dir (random temp dir) paths.  On Windows if you choose to use backslash delimited paths, please note that you will need to escape the backslashes with an additional backslash (e.g. C:pathtocert becomes C:\path\to\cert).

[ ca ]
default_ca = myca
 
[ crl_ext ]
# issuerAltName=issuer:copy  #this would copy the issuer name to altname
authorityKeyIdentifier=keyid:always
 
[ myca ]
new_certs_dir = /tmp
unique_subject = no
certificate = /path/to/root.cer
database = /path/to/certindex
private_key = /path/to/privkey.pem
serial = /path/to/serialfile
default_days = 365
default_md = sha1
policy = myca_policy
x509_extensions = myca_extensions
 
[ myca_policy ]
commonName = supplied
stateOrProvinceName = supplied
countryName = supplied
emailAddress = optional
organizationName = supplied
organizationalUnitName = optional
 
[ myca_extensions ]
basicConstraints = CA:false
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always
keyUsage = digitalSignature,keyEncipherment
extendedKeyUsage = serverAuth
crlDistributionPoints = URI:http://path.to.crl/myca.crl

You will also need to create empty files located at /path/to/certindex and /path/to/serialfile.  For the serialfile add “000a” (without the quotes) as a hexadecimal seed for the serial number. 

Create a CSR and Issue A Cert

 We now have our CA infrastructure configured so let’s create a CSR (certificate signing request) and issue our first certificate. 

 openssl req -newkey rsa:1024 -nodes -out ourdomain.csr -keyout ourdomain.key

  This will write out a req.key and req.csr after you choose the fields you desire.  If you are setting up a serverAuth certificate the common name should be the FQDN of your server.  You can also leave the challenge password blank. 

Generating a 1024 bit RSA private key
..........++++++
..................++++++
writing new private key to 'req.key'
-----
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) [GB]:US
State or Province Name (full name) [Berkshire]:Illinois
Locality Name (eg, city) [Newbury]:Chicago
Organization Name (eg, company) [My Company Ltd]:End Entity, Inc.
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:www.examplefqdn.com
Email Address []:
 
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

Now we’re ready to issue the certificate!  We will let our configuration file do most of the heavy lifting.  Just specify the path to the config and the path for the output certificate.

 openssl ca -batch -config /path/to/myca.conf -notext -in req.csr -out /path/to/ourdomain.cer

Your certificate should now be written to the path you specified.  To verify the contents of the certificate:
 

 openssl x509 -noout -text -in /path/to/ourdomain.cer

Browser Trust Configuration

To be trusted a certificate must have a root at the top of its chain inside the certificate store of whatever client you are attempting to use. This means you will need to import your self-signed public key (root.cer) into the store.  While each browser/OS is different, let’s demonstrate via Firefox 3.

SSL Is Not Broken

This morning an important and ingenious method of compromising the chain of trust for PKI was published. Naturally the internet is in a tizzy about the implications of this break, but misinformation rules the day.

SSL is in no way broken, but CAs still issuing MD5 certificates simply MUST stop as soon as possible. There are really two components to this (extremely clever) break:

1) a further reduction in the time required to compute a useful MD5 collision which the authors of the paper have not yet detailed.

2) CAs not using randomized serials to increase the entropy provided to the hash function.

If #2 is immediately rectified by the CAs then the difficulty of this attack increases dramatically. Of course, if they have any sanity they will switch to both SHA-1 and randomized serials.

It’s important to note, for those who don’t have the patience to read through the paper, that this describes a method of issuing a new subordinate CA from1 a trusted CA that can, in turn, issue any certificate without proper vetting. These certs would be trusted by every browser2 and OS containing the cert used for the initial issuance. This is not a compromise of MD5 certificates in the wild.

That distinction may seem inconsequential in view of the potential for a completely broken chain of trust, but it is important. Provided that the potentially vulnerable3 CAs (RapidSSL, possibly others) remedy their issues then this attack is completely neutered until such time as SHA1 is compromised to a similar extent. If those CAs take quick action then drastic steps (such as the revocation of whole root CAs and mass reissuance to all affected customers) should not be necessary.

 

Update (1/11/09): For future reference, RapidSSL ceased using MD5 signatures in their certificates within a day of the release of this paper.

  1. The actual subordinate CA is not being signed by the CA, only a valid cert, so saying it’s “from” the CA is misleading.
  2. With the exception of Opera, which requires a valid CRL/OCSP response from every link in the chain. As described in the paper the authors were unable to include a crlDistributionPoint node in their ASN.1 structure so while browsers such as IE, Firefox, and Safari would simply trust the cert, Opera would explicitly deny trust.
  3. Being vulnerable to this attack requires both the active use of MD5 in new certificates, an exactly guessable validity via automated issuance or other means, and sequential or otherwise predictable serial numbers.