posts:x.509-certificates: Use --outfile with --generate-privkey
[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 You can verify a certificate if you can supply the whole certificate
106 chain with [verify][].
107
108     $ openssl verify cert.pem
109
110 PEM
111 ===
112
113 We've been throwing around a lot of files with a [.pem][] extension.
114 These files contain [Base64][] encoded [DER][] certificates enclosed
115 between `-----BEGIN CERTIFICATE-----` and `-----END CERTIFICATE-----`.
116 The `.crt` files requested by `update-ca-certificates` (discussed
117 below) are generally binary DER files, but can also be base64 encoded.
118
119 Downloading certificates
120 ========================
121
122 You can download certificates from remote servers using [[OpenSSL's
123 simple client|Simple_servers]]:
124
125     $ openssl s_client -showcerts -connect host:port
126
127 The PEM certificates will be printed to your terminal.
128
129 System wide certificates
130 ========================
131
132 The situation is confusing because there is currently no standardized
133 way to track trusted certificates.  Here are some things to keep in
134 mind:
135
136 ca-certificates
137 ---------------
138
139 [[Gentoo]] uses [Debian][]'s [ca-certificates][] package to manage
140 trusted CAs.  The certificates are stored under `/etc/ssl/certs` in
141 three forms:
142
143 1. As a `<filename>.pem` symlink to the external certificate (if it
144    was already base64 encoded) or an encoded version (if the external
145    certificate is binary).
146 2. As a symlink to 1 named with the certificate's hashed subject name,
147    key identifier (if present), and serial number.
148 3. As an entry in `ca-certificates.crt`, which is a concatenated list
149    of all the trusted certificates.
150
151 You can update these system certificates using
152 `update-ca-certificates`, from the the `ca-certificates` package:
153
154     # update-ca-certificates
155
156 On Fedora-based systems, `update-ca-certificates` also [updates the
157 system NSS storage][fedora] at `/etc/pki/nssdb` (more on NSS in a
158 second).
159
160 `update-ca-certificates` looks in a number of places to find trusted
161 CAs.  To add a new CA, place the certificate in
162 `/usr/local/share/ca-certificates/` as a single file ending in `.crt`
163 and run `update-ca-certificates`.
164
165 ### GnuTLS
166
167 In [[GnuTLS]], you set the list of trusted CAs using
168 [gnutls_certificate_set_x509_trust_file][].  By convention this
169 function is pointed to the `/etc/ssl/certs/ca-certificates.crt` file
170 mentioned above.
171
172 ### OpenSSL
173
174 OpenSSL loads trusted CAs with [SSL_CTX_load_verify_locations][],
175 which loads certificates from a file (like
176 `gnutls_certificate_set_x509_trust_file`) or from a directory (usually
177 `/etc/ssl/certs/`).  For efficiency, many applications prefer the
178 directory approach, as certificates can then be loaded on an as-needed
179 basis using their hashed subject name, key identifier (if present),
180 and serial number.  If you place a new CA this directory, you'll want
181 to run `c_rehash` to generate the hashed symlinks:
182
183     # c_rehash /etc/ssl/certs
184
185 OpenSSL doesn't currently provide a man page for `c_rehash`, but
186 there's one attached to [Debian bug 215618][215618].
187
188 `update-ca-certificates` (mentioned above) uses `c_rehash` internally
189 to generate hashed symlinks for OpenSSL.
190
191 NSS
192 ---
193
194 [NSS][] is the crypto library used by [Firefox][] and [Chromium][]
195 that *doesn't* use the `/etc/ssl/certs` framework discussed above.  It
196 [looks in a number of places][nss-places] depending on the package
197 type, but the system-wide `sql:/etc/pki/nssdb`.  User applications
198 will also look in `sql:~/.pki/nssdb`.  You manage the databases with
199 [certutil][].  You can install `certutil` on Gentoo by emerging
200 `dev-libs/nss` with the `utils` `USE` flag enabled.  Add your
201 certificate with something like:
202
203     $ certutil -A -n jdoe -t "C,," -d "sql:${HOME}/.pki/nssdb" -i /etc/ssl/certs/cacert.org.pem
204
205 This adds a certicate (`-A`) to the `sql:${HOME}/.pki/nssdb` database
206 (`-d`).  The certificate is named `jdoe` (`-n`), and you can use this
207 name to manage the certificate later (e.g. to delete it).  `-t "C,,"`
208 sets SSL trust to `C`, but does not grant email or object signing
209 trust.  `C` means you trust this certificate to issue SSL server
210 certificates (but not client certificates, which would be `T`), and
211 that you don't trust it for direct SSL authentication or email signing
212 (which would be `u`).
213
214 Unfortunately, many applications using NSS have a [compiled-in
215 list][certdata.txt] of trusted CAs, so you don't have complete control
216 from a sysadmin perspective unless you tweak that file at compile
217 time.
218
219
220 [gnutls-manual]: http://www.gnu.org/software/gnutls/manual/html_node/Invoking-gnutls_002dserv.html
221 [certtool]: http://www.gnu.org/software/gnutls/manual/html_node/Invoking-certtool.html#Invoking-certtool
222 [SAN]: http://tools.ietf.org/html/rfc4985
223 [OpenSSL]: http://www.openssl.org/docs/apps/openssl.html
224 [genpkey]: http://www.openssl.org/docs/apps/genpkey.html
225 [req]: http://www.openssl.org/docs/apps/req.html
226 [x509v3_config]: http://www.openssl.org/docs/apps/x509v3_config.html#Subject_Alternative_Name_
227 [x509]: http://www.openssl.org/docs/apps/x509.html
228 [verify]: http://www.openssl.org/docs/apps/verify.html
229 [Debian]: http://debian.org/
230 [ca-certificates]: http://packages.debian.org/sid/ca-certificates
231 [.pem]: http://en.wikipedia.org/wiki/X.509#Certificate_filename_extensions
232 [base64]: http://en.wikipedia.org/wiki/Base64
233 [DER]: http://en.wikipedia.org/wiki/Distinguished_Encoding_Rules
234 [fedora]: https://fedorahosted.org/update-ca-certificates/browser/update-ca-certificates.8
235 [gnutls_certificate_set_x509_trust_file]: http://www.gnu.org/software/gnutls/manual/gnutls.html#gnutls_certificate_set_x509_trust_file
236 [SSL_CTX_load_verify_locations]: http://www.openssl.org/docs/ssl/SSL_CTX_load_verify_locations.html
237 [215618]: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=215618
238 [NSS]: http://www.mozilla.org/projects/security/pki/nss/
239 [Firefox]: https://bugs.gentoo.org/325723
240 [Chromium]: http://code.google.com/p/chromium/wiki/LinuxCertManagement
241 [nss-places]: https://wiki.mozilla.org/NSS_Shared_DB_And_LINUX
242 [certutil]: http://www.mozilla.org/projects/security/pki/nss/tools/certutil.html
243 [certdata.txt]: http://comments.gmane.org/gmane.comp.mozilla.crypto/16347
244
245 [[!tag tags/linux]]
246 [[!tag tags/tools]]
247 [[!tag tags/web]]