If you're running your own server, you're probably not shelling out $400 to get an “official” Certificate Authority (CA) to sign your key. Here's a quick note to myself about how to create, sign, and install your own CA and key. Depending on your application, you can use either the [[GnuTLS]] or [OpenSSL][] toolchain. GnuTLS ====== Following the [GnuTLS manual][gnutls-manual], create a certificate authority with [certtool][], adjusting the `cn` as you see fit: $ certtool --generate-privkey --outfile x509-ca-key.pem $ echo 'cn = GnuTLS test CA' > ca.tmpl $ echo 'ca' >> ca.tmpl $ echo 'cert_signing_key' >> ca.tmpl $ certtool --generate-self-signed --load-privkey x509-ca-key.pem \ --template ca.tmpl --outfile x509-ca.pem Now generate the *unencrypted* server key. $ certtool --generate-privkey --outfile x509-server-key.pem And sign the key with your CA, adjusting the `cn` as you see fit, and changing `dns_name` to match your fully qualified host name. $ echo 'organization = GnuTLS test server' > server.tmpl $ echo 'cn = test.gnutls.org' >> server.tmpl $ echo 'tls_www_server' >> server.tmpl $ echo 'encryption_key' >> server.tmpl $ echo 'signing_key' >> server.tmpl $ echo 'dns_name = test.gnutls.org' >> server.tmpl $ certtool --generate-certificate --load-privkey x509-server-key.pem \ --load-ca-certificate x509-ca.pem --load-ca-privkey x509-ca-key.pem \ --template server.tmpl --outfile x509-server.pem You can also print certificates with [certtool][]. $ certtool --infile x509-server.pem --certificate-info You can add alternate hostnames using [subject alternative names][SAN]. Just add more `dns_name` entries to your template: $ echo 'dns_name = other.gnutls.org' >> server.tmpl $ certtool --generate-certificate … You can verify a certificate if you can supply the whole certificate chain. $ certtool --verify-chain --infile x509-server.pem --infile x509-ca.pem With versions of GnuTLS since 2.99.0 (released 2011-04-09), you can verify against the global list of trusted CAs. $ certtool --verify --load-ca-certificate /etc/ssl/certs/ca-certificates.crt --infile x509-server.pem OpenSSL ======= Use [openssl][]'s [genpkey][] to generate an *unencrypted* key. $ openssl genpkey -algorithm RSA -out key.pem An unencrypted key is less secure, but it allows the web server to be restarted (e.g. after rebooting) without you being there to enter the decryption key. Make sure `key.pem` is only readable by `root`. Use [req][] to generate certificate signing request. $ openssl req -new -key key.pem -out req.pem `-new` prompts you for new relevant field values. You can also specify the values on the command line or in an configuration file (override the default with `-config filename`). Use [x509][] to sign the certificate. $ openssl x509 -req -days 365 -in req.pem -signkey key.pem -out cert.pem You should keep your certificate signing request around so you can re-sign your key later on (since your initial signature will eventually expire). You can add subject alternative names to the request using the `openssl.cnf` [config file][x509v3_config]: $ cp /etc/ssl/openssl.cnf openssl.cnf $ emacs openssl.cnf $ cat openssl.cnf … [ req ] … req_extensions = v3_req … [ v3_req ] … subjectAltName = DNS:test.gnutls.org,DNS:other.gnutls.org … $ openssl req -new -config openssl.cnf -key key.pem -out req.pem You can also print certificates with [x509][]. $ openssl x509 -in cert.pem -noout -text Or just the hash with: $ openssl x509 -in cert.pem -noout -hash You can verify a certificate if you can supply the whole certificate chain with [verify][]. $ openssl verify cert.pem PEM === We've been throwing around a lot of files with a [.pem][] extension. These files contain [Base64][] encoded [DER][] certificates enclosed between `-----BEGIN CERTIFICATE-----` and `-----END CERTIFICATE-----`. The `.crt` files requested by `update-ca-certificates` (discussed below) are generally binary DER files, but can also be base64 encoded. Downloading certificates ======================== You can download certificates from remote servers using [[OpenSSL's simple client|Simple_servers]]: $ openssl s_client -showcerts -connect host:port The PEM certificates will be printed to your terminal. System wide certificates ======================== The situation is confusing because there is currently no standardized way to track trusted certificates. Here are some things to keep in mind: ca-certificates --------------- [[Gentoo]] uses [Debian][]'s [ca-certificates][] package to manage trusted CAs. The certificates are stored under `/etc/ssl/certs` in three forms: 1. As a `.pem` symlink to the external certificate (if it was already base64 encoded) or an encoded version (if the external certificate is binary). 2. As a symlink to 1 named with the certificate's hashed subject name, key identifier (if present), and serial number. 3. As an entry in `ca-certificates.crt`, which is a concatenated list of all the trusted certificates. You can update these system certificates using `update-ca-certificates`, from the the `ca-certificates` package: # update-ca-certificates On Fedora-based systems, `update-ca-certificates` also [updates the system NSS storage][fedora] at `/etc/pki/nssdb` (more on NSS in a second). `update-ca-certificates` looks in a number of places to find trusted CAs. To add a new CA, place the certificate in `/usr/local/share/ca-certificates/` as a single file ending in `.crt` and run `update-ca-certificates`. ### GnuTLS In [[GnuTLS]], you set the list of trusted CAs using [gnutls_certificate_set_x509_trust_file][]. By convention this function is pointed to the `/etc/ssl/certs/ca-certificates.crt` file mentioned above. ### OpenSSL OpenSSL loads trusted CAs with [SSL_CTX_load_verify_locations][], which loads certificates from a file (like `gnutls_certificate_set_x509_trust_file`) or from a directory (usually `/etc/ssl/certs/`). For efficiency, many applications prefer the directory approach, as certificates can then be loaded on an as-needed basis using their hashed subject name, key identifier (if present), and serial number. If you place a new CA this directory, you'll want to run `c_rehash` to generate the hashed symlinks: # c_rehash /etc/ssl/certs OpenSSL doesn't currently provide a man page for `c_rehash`, but there's one attached to [Debian bug 215618][215618]. `update-ca-certificates` (mentioned above) uses `c_rehash` internally to generate hashed symlinks for OpenSSL. NSS --- [NSS][] is the crypto library used by [Firefox][] and [Chromium][] that *doesn't* use the `/etc/ssl/certs` framework discussed above. It [looks in a number of places][nss-places] depending on the package type, but the system-wide `sql:/etc/pki/nssdb`. User applications will also look in `sql:~/.pki/nssdb`. You manage the databases with [certutil][]. You can install `certutil` on Gentoo by emerging `dev-libs/nss` with the `utils` `USE` flag enabled. Add your certificate with something like: $ certutil -A -n jdoe -t "C,," -d "sql:${HOME}/.pki/nssdb" -i /etc/ssl/certs/cacert.org.pem This adds a certicate (`-A`) to the `sql:${HOME}/.pki/nssdb` database (`-d`). The certificate is named `jdoe` (`-n`), and you can use this name to manage the certificate later (e.g. to delete it). `-t "C,,"` sets SSL trust to `C`, but does not grant email or object signing trust. `C` means you trust this certificate to issue SSL server certificates (but not client certificates, which would be `T`), and that you don't trust it for direct SSL authentication or email signing (which would be `u`). Unfortunately, many applications using NSS have a [compiled-in list][certdata.txt] of trusted CAs, so you don't have complete control from a sysadmin perspective unless you tweak that file at compile time. [gnutls-manual]: http://www.gnu.org/software/gnutls/manual/html_node/Invoking-gnutls_002dserv.html [certtool]: http://www.gnu.org/software/gnutls/manual/html_node/Invoking-certtool.html#Invoking-certtool [SAN]: http://tools.ietf.org/html/rfc4985 [OpenSSL]: http://www.openssl.org/docs/apps/openssl.html [genpkey]: http://www.openssl.org/docs/apps/genpkey.html [req]: http://www.openssl.org/docs/apps/req.html [x509v3_config]: http://www.openssl.org/docs/apps/x509v3_config.html#Subject_Alternative_Name_ [x509]: http://www.openssl.org/docs/apps/x509.html [verify]: http://www.openssl.org/docs/apps/verify.html [Debian]: http://debian.org/ [ca-certificates]: http://packages.debian.org/sid/ca-certificates [.pem]: http://en.wikipedia.org/wiki/X.509#Certificate_filename_extensions [base64]: http://en.wikipedia.org/wiki/Base64 [DER]: http://en.wikipedia.org/wiki/Distinguished_Encoding_Rules [fedora]: https://fedorahosted.org/update-ca-certificates/browser/update-ca-certificates.8 [gnutls_certificate_set_x509_trust_file]: http://www.gnu.org/software/gnutls/manual/gnutls.html#gnutls_certificate_set_x509_trust_file [SSL_CTX_load_verify_locations]: http://www.openssl.org/docs/ssl/SSL_CTX_load_verify_locations.html [215618]: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=215618 [NSS]: http://www.mozilla.org/projects/security/pki/nss/ [Firefox]: https://bugs.gentoo.org/325723 [Chromium]: http://code.google.com/p/chromium/wiki/LinuxCertManagement [nss-places]: https://wiki.mozilla.org/NSS_Shared_DB_And_LINUX [certutil]: http://www.mozilla.org/projects/security/pki/nss/tools/certutil.html [certdata.txt]: http://comments.gmane.org/gmane.comp.mozilla.crypto/16347 [[!tag tags/linux]] [[!tag tags/tools]] [[!tag tags/web]]