posts:x.509-certificates: Mention openssl x509's -hash
[blog.git] / posts / X.509_certificates.mdwn
1 If you're running your own server, you're probably not shelling out
2 $400 to get an “official” Certificate Authority (CA) to sign your key.
3 Here's a quick note to myself about how to create, sign, and install
4 your own CA and key.  Depending on your application, you can use
5 either the [[GnuTLS]] or [OpenSSL][] toolchain.
6
7 GnuTLS
8 ======
9
10 Following the [GnuTLS manual][gnutls-manual], create a certificate
11 authority with [certtool][], adjusting the `cn` as you see fit:
12
13     $ certtool --generate-privkey --outfile x509-ca-key.pem
14     $ echo 'cn = GnuTLS test CA' > ca.tmpl
15     $ echo 'ca' >> ca.tmpl
16     $ echo 'cert_signing_key' >> ca.tmpl
17     $ certtool --generate-self-signed --load-privkey x509-ca-key.pem \
18         --template ca.tmpl --outfile x509-ca.pem
19
20 Now generate the *unencrypted* server key.
21
22     $ certtool --generate-privkey --outfile x509-server-key.pem
23
24 And sign the key with your CA, adjusting the `cn` as you see fit, and
25 changing `dns_name` to match your fully qualified host name.
26
27     $ echo 'organization = GnuTLS test server' > server.tmpl
28     $ echo 'cn = test.gnutls.org' >> server.tmpl
29     $ echo 'tls_www_server' >> server.tmpl
30     $ echo 'encryption_key' >> server.tmpl
31     $ echo 'signing_key' >> server.tmpl
32     $ echo 'dns_name = test.gnutls.org' >> server.tmpl
33     $ certtool --generate-certificate --load-privkey x509-server-key.pem \
34         --load-ca-certificate x509-ca.pem --load-ca-privkey x509-ca-key.pem \
35         --template server.tmpl --outfile x509-server.pem
36
37 You can also print certificates with [certtool][].
38
39     $ certtool --infile x509-server.pem --certificate-info
40
41 You can add alternate hostnames using [subject alternative
42 names][SAN].  Just add more `dns_name` entries to your template:
43
44     $ echo 'dns_name = other.gnutls.org' >> server.tmpl
45     $ certtool --generate-certificate …
46
47 You can verify a certificate if you can supply the whole certificate
48 chain.
49
50     $ certtool --verify-chain --infile x509-server.pem --infile x509-ca.pem
51
52 With versions of GnuTLS since 2.99.0 (released 2011-04-09), you can
53 verify against the global list of trusted CAs.
54
55     $ certtool --verify --load-ca-certificate /etc/ssl/certs/ca-certificates.crt --infile x509-server.pem
56
57 OpenSSL
58 =======
59
60 Use [openssl][]'s [genpkey][] to generate an *unencrypted* key.
61
62     $ openssl genpkey -algorithm RSA -out key.pem
63
64 An unencrypted key is less secure, but it allows the web server to be
65 restarted (e.g. after rebooting) without you being there to enter the
66 decryption key.  Make sure `key.pem` is only readable by `root`.
67
68 Use [req][] to generate certificate signing request.
69
70     $ openssl req -new -key key.pem -out req.pem
71
72 `-new` prompts you for new relevant field values.  You can also
73 specify the values on the command line or in an configuration file
74 (override the default with `-config filename`).
75
76 Use [x509][] to sign the certificate.
77
78     $ openssl x509 -req -days 365 -in req.pem -signkey key.pem -out cert.pem
79
80 You should keep your certificate signing request around so you can
81 re-sign your key later on (since your initial signature will
82 eventually expire).
83
84 You can add subject alternative names to the request using
85 the `openssl.cnf` [config file][x509v3_config]:
86
87     $ cp /etc/ssl/openssl.cnf openssl.cnf
88     $ emacs openssl.cnf
89     $ cat openssl.cnf
90     …
91     [ req ]
92     …
93     req_extensions = v3_req
94     …
95     [ v3_req ]
96     …
97     subjectAltName = DNS:test.gnutls.org,DNS:other.gnutls.org
98     …
99     $ openssl req -new -config openssl.cnf -key key.pem -out req.pem
100
101 You can also print certificates with [x509][].
102
103     $ openssl x509 -in cert.pem -noout -text
104
105 Or just the hash with:
106
107     $ openssl x509 -in cert.pem -noout -hash
108
109 You can verify a certificate if you can supply the whole certificate
110 chain with [verify][].
111
112     $ openssl verify cert.pem
113
114 PEM
115 ===
116
117 We've been throwing around a lot of files with a [.pem][] extension.
118 These files contain [Base64][] encoded [DER][] certificates enclosed
119 between `-----BEGIN CERTIFICATE-----` and `-----END CERTIFICATE-----`.
120 The `.crt` files requested by `update-ca-certificates` (discussed
121 below) are generally binary DER files, but can also be base64 encoded.
122
123 Downloading certificates
124 ========================
125
126 You can download certificates from remote servers using [[OpenSSL's
127 simple client|Simple_servers]]:
128
129     $ openssl s_client -showcerts -connect host:port
130
131 The PEM certificates will be printed to your terminal.
132
133 System wide certificates
134 ========================
135
136 The situation is confusing because there is currently no standardized
137 way to track trusted certificates.  Here are some things to keep in
138 mind:
139
140 ca-certificates
141 ---------------
142
143 [[Gentoo]] uses [Debian][]'s [ca-certificates][] package to manage
144 trusted CAs.  The certificates are stored under `/etc/ssl/certs` in
145 three forms:
146
147 1. As a `<filename>.pem` symlink to the external certificate (if it
148    was already base64 encoded) or an encoded version (if the external
149    certificate is binary).
150 2. As a symlink to 1 named with the certificate's hashed subject name,
151    key identifier (if present), and serial number.
152 3. As an entry in `ca-certificates.crt`, which is a concatenated list
153    of all the trusted certificates.
154
155 You can update these system certificates using
156 `update-ca-certificates`, from the the `ca-certificates` package:
157
158     # update-ca-certificates
159
160 On Fedora-based systems, `update-ca-certificates` also [updates the
161 system NSS storage][fedora] at `/etc/pki/nssdb` (more on NSS in a
162 second).
163
164 `update-ca-certificates` looks in a number of places to find trusted
165 CAs.  To add a new CA, place the certificate in
166 `/usr/local/share/ca-certificates/` as a single file ending in `.crt`
167 and run `update-ca-certificates`.
168
169 ### GnuTLS
170
171 In [[GnuTLS]], you set the list of trusted CAs using
172 [gnutls_certificate_set_x509_trust_file][].  By convention this
173 function is pointed to the `/etc/ssl/certs/ca-certificates.crt` file
174 mentioned above.
175
176 ### OpenSSL
177
178 OpenSSL loads trusted CAs with [SSL_CTX_load_verify_locations][],
179 which loads certificates from a file (like
180 `gnutls_certificate_set_x509_trust_file`) or from a directory (usually
181 `/etc/ssl/certs/`).  For efficiency, many applications prefer the
182 directory approach, as certificates can then be loaded on an as-needed
183 basis using their hashed subject name, key identifier (if present),
184 and serial number.  If you place a new CA this directory, you'll want
185 to run `c_rehash` to generate the hashed symlinks:
186
187     # c_rehash /etc/ssl/certs
188
189 OpenSSL doesn't currently provide a man page for `c_rehash`, but
190 there's one attached to [Debian bug 215618][215618].
191
192 `update-ca-certificates` (mentioned above) uses `c_rehash` internally
193 to generate hashed symlinks for OpenSSL.
194
195 NSS
196 ---
197
198 [NSS][] is the crypto library used by [Firefox][] and [Chromium][]
199 that *doesn't* use the `/etc/ssl/certs` framework discussed above.  It
200 [looks in a number of places][nss-places] depending on the package
201 type, but the system-wide `sql:/etc/pki/nssdb`.  User applications
202 will also look in `sql:~/.pki/nssdb`.  You manage the databases with
203 [certutil][].  You can install `certutil` on Gentoo by emerging
204 `dev-libs/nss` with the `utils` `USE` flag enabled.  Add your
205 certificate with something like:
206
207     $ certutil -A -n jdoe -t "C,," -d "sql:${HOME}/.pki/nssdb" -i /etc/ssl/certs/cacert.org.pem
208
209 This adds a certicate (`-A`) to the `sql:${HOME}/.pki/nssdb` database
210 (`-d`).  The certificate is named `jdoe` (`-n`), and you can use this
211 name to manage the certificate later (e.g. to delete it).  `-t "C,,"`
212 sets SSL trust to `C`, but does not grant email or object signing
213 trust.  `C` means you trust this certificate to issue SSL server
214 certificates (but not client certificates, which would be `T`), and
215 that you don't trust it for direct SSL authentication or email signing
216 (which would be `u`).
217
218 Unfortunately, many applications using NSS have a [compiled-in
219 list][certdata.txt] of trusted CAs, so you don't have complete control
220 from a sysadmin perspective unless you tweak that file at compile
221 time.
222
223
224 [gnutls-manual]: http://www.gnu.org/software/gnutls/manual/html_node/Invoking-gnutls_002dserv.html
225 [certtool]: http://www.gnu.org/software/gnutls/manual/html_node/Invoking-certtool.html#Invoking-certtool
226 [SAN]: http://tools.ietf.org/html/rfc4985
227 [OpenSSL]: http://www.openssl.org/docs/apps/openssl.html
228 [genpkey]: http://www.openssl.org/docs/apps/genpkey.html
229 [req]: http://www.openssl.org/docs/apps/req.html
230 [x509v3_config]: http://www.openssl.org/docs/apps/x509v3_config.html#Subject_Alternative_Name_
231 [x509]: http://www.openssl.org/docs/apps/x509.html
232 [verify]: http://www.openssl.org/docs/apps/verify.html
233 [Debian]: http://debian.org/
234 [ca-certificates]: http://packages.debian.org/sid/ca-certificates
235 [.pem]: http://en.wikipedia.org/wiki/X.509#Certificate_filename_extensions
236 [base64]: http://en.wikipedia.org/wiki/Base64
237 [DER]: http://en.wikipedia.org/wiki/Distinguished_Encoding_Rules
238 [fedora]: https://fedorahosted.org/update-ca-certificates/browser/update-ca-certificates.8
239 [gnutls_certificate_set_x509_trust_file]: http://www.gnu.org/software/gnutls/manual/gnutls.html#gnutls_certificate_set_x509_trust_file
240 [SSL_CTX_load_verify_locations]: http://www.openssl.org/docs/ssl/SSL_CTX_load_verify_locations.html
241 [215618]: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=215618
242 [NSS]: http://www.mozilla.org/projects/security/pki/nss/
243 [Firefox]: https://bugs.gentoo.org/325723
244 [Chromium]: http://code.google.com/p/chromium/wiki/LinuxCertManagement
245 [nss-places]: https://wiki.mozilla.org/NSS_Shared_DB_And_LINUX
246 [certutil]: http://www.mozilla.org/projects/security/pki/nss/tools/certutil.html
247 [certdata.txt]: http://comments.gmane.org/gmane.comp.mozilla.crypto/16347
248
249 [[!tag tags/linux]]
250 [[!tag tags/tools]]
251 [[!tag tags/web]]