How to create a Certificate Signing Request (CSR) for HTTPS (TLS/SSL) RSA PEMsPublished 2015-1-27
Watch on YouTube: youtu.be/r92gqYHJc5c
Free, Automatic SSL Certificates
Starting sometime in the summer of 2015 Mozilla will be giving everyone the cheap-o ($7-$40) basic SSL certificates for free. They'll be short term, but they'll automatically renew all on their own (via the appropriate npm, gem, egg, etc).
See Let's Encrypt for details.
If you want the double green bar platinum all-star (but still not actually verified) certificates for $300, you'll still have to pay for those.
Inexpensive SSL from name.com
Until Let's Encrypt is up and running, you'll still need to buy a basic certificate from an SSL provider.
1. Create a 2048-bit RSA Private Key for SSL
If you're on Windows, you're gonna need to get on a real computer for a few minutes to run commands.
For everyone else, just open up Terminal and copy/paste the following:
mkdir -p certs/server openssl genrsa \ -out certs/server/my-server.key.pem \ 2048
2. Create a CSR with your Domain Info
There are two ways to go about this:
- Run the command bare and type answers to a lot of questions
- Run the command with the questions already filled out
I prefer the latter because, well, I'm lazy and it's a lot faster.
mkdir -p certs/tmp openssl req -new \ -sha256 \ -key certs/server/my-server.key.pem \ -out certs/tmp/my-server.csr.pem \ -subj "/C=US/ST=Utah/L=Provo/O=ACME App Client/CN=www.example.com"
A quick rundown of the options.
Note: These all apply in the context of the business or person requesting the certificate. So if your domain is florida-nicknacks.com, but you live in Georgia and operate your business in South Carolina... it's one of the latter two, not Florida.
|Thingy||What it means||What it really means|
|C||Country||The country (or Indian Reservation?) in which you reside|
|ST*||State||State, Province, Region - whatever your country calls a state|
|L||Locality||City, Locality, District - whatever your country calls a city|
|O||Organization||The business or organization name - i.e. ACME, Inc|
|OU||Organizational Unit||(optional) i.e. ACME Sales Dept|
|CN*||Cananical Name||either www.example.com (assumes bare domain example.com also) or foo.example.com|
- C should be the TWO DIGIT country code
- ST must be ALL SPELLED OUT: Utah, not UT
- CN GET IT RIGHT. If you put the wrong domain you'll have to contact customer support and stuff to get it cancelled and fixed
- WWW. vs BARE DOMAIN name.com requires a subdomain, but using
wwwwill also validates your cert for the bare domain.
- (P.S. don't let anyone tell you different, www. looks retarded. If you have cookie issues, get a second domain for your CDN, usercontent, or whatever)
- WWW. vs BARE DOMAIN name.com requires a subdomain, but using
Also, sometimes you'll see in the instructions to not use a passphrase, but it doesn't really matter whether you do or you don't.
If you do, you'll end up hard-coding the passphrase into your server - and if someone can gain access to the directory where you're storing your certs, they can almost certainly also gain access to the file that has the passphrase hard-coded into it.
Passphrases are more useful for Trusted Peer SSL or other situations where you might have a device that prompts the user for their passphrase.
Even in that case you're just as well to use the biometric (fingerprint) scanner or device passcode to AES-256 encrypt the private key... wait... that's what the passphrase is doing.
Yeah, so doesn't much matter, might as well not.
3. Test Run before you Spend $$
If you followed my steps above then you have a directory that looks like this:
certs ├── server │ └── my-server.key.pem └── tmp └── my-server.csr.pem 2 directories, 2 files
I have a test repository (nodejs-ssl-example) so that you can
- copy your certs into the directory
- sign your CSR with my bogus Root CA
- fire up the webserver and make sure the darn thing works
git clone https://github.com/coolaj86/nodejs-ssl-example.git rsync -av certs/ nodejs-ssl-example/certs/ pushd nodejs-ssl-example/ bash bin/sign-csr.sh npm install node ./server.js
Open your browser to https://helloworld3000.com:8043.
You will see an error message in your browser informing you that:
- Your connection is not private
- The Server's certificate does not match the URL.
- The Server's certificate is not trusted.
That's okay for this example. Click on your browsers SSL icon (normally a lock or key of some sort) and verify that your domain name is represented correctly. If that looks good, make sure you can get through to your site.
If your domain is correct (i.e. www.my-site.com and not www.sucky-typo.com), then you're good to proceed to the next step.
If you get a different kind of error such as when starting the server (i.e.
or the connection error that won't allow you to view the test page in the example repo,
then you may need to hone your copy and paste skills a little and try again after you've worked on that.
4. Go exchange your dollars for SSL
Head over to https://www.name.com/ssl and pick the cheapest (or pay extra money to get the same certificate with a special directive in the comment field that tells the browser to give you the double extra platinum green-lock ultra icon, if that's your thing).
You'll need to copy and paste the contents of your CSR into their form and off you go.
5. Hunt down the Intermediate Root CA
You may notice that when you only pay $10 ~ $30 for a certificate, you'll be told that you need to download an intermediate certificate.
Intermediate certificates are like... one of the 6 degrees of friends between you and Kevin Bacon.
See, the certificate you were issued is untrusted, because it was signed by an untrusted intermediate certificate that generally expires in 1-3 years (at least as long as the one you purchased). However, that cert is signed by a trusted Root CA (that generally won't expire for several years later) - but the browser won't know that unless you bundle them both together (or it's just a really really old browser or device that hasn't gotten any security updates in the past few years).
Take a look at the code of
serve.js for an example of how to add a intermediate
It's a one-liner. No biggie.
6. If io.js / node.js, use root-ssl-cas
Unfortunately the method for adding a Root CA in io.js / node.js exclusively causes the installed certificates to be ignored. I wasn't sure how to reach the right ears to solve this problem but, fortunately, it's another one-line fix.
Many people won't experience any SSL problems if you choose not to use
because your app doesn't connect to 3rd party services, but if you're using
oauth (facebook connect, etc), or
s3, then it very likely that you will get cert
errors and that
ssl-root-cas will make them disappear.
Some sites require the
-sha256 option to be used during the CSR generation.
I don't think that any sites will fail to work without it, but if you do happen
to get an error about your CSR you could try running the command without that
By AJ ONeal
Did I make your day?
Buy me a coffee
(you can learn about the bigger picture I'm working towards on my patreon page )