From: Jo-Philipp Wich Date: Thu, 14 Apr 2016 13:58:04 +0000 (+0200) Subject: Add some documentation about signing and key generation X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=f2fb509cdeb01cf079a1a775ade66e0a7a9db97f;p=web.git Add some documentation about signing and key generation Signed-off-by: Jo-Philipp Wich --- diff --git a/pages/keygen.txt b/pages/keygen.txt new file mode 100644 index 0000000..c54e6a8 --- /dev/null +++ b/pages/keygen.txt @@ -0,0 +1,341 @@ +Key Generation +============== + +include::menu.inc[] + +== Generate GPG signing key pair + +The guide will explain how to generate a new key pair, how to create a +signing sub key and how to strip the secret master key to avoid leaking +your primary secret key identity in case your signing key (or the entire ++~/.gnupg/+) ever gets lost. + + +=== 1) Generate new, fresh key pair on a secure machine + +---- +$ mkdir /tmp/signing +$ chmod 0700 /tmp/signing +$ gpg --homedir /tmp/signing --gen-key +gpg (GnuPG) 1.4.18; Copyright (C) 2014 Free Software Foundation, Inc. +This is free software: you are free to change and redistribute it. +There is NO WARRANTY, to the extent permitted by law. + +gpg: keyring `/tmp/signing/secring.gpg' created +gpg: keyring `/tmp/signing/pubring.gpg' created +---- + +TIP: Pick 4 to generate an RSA-only key and choose a key size of 4096 bits. + For this how-to I choose to set no expiry at all. + +---- +Please select what kind of key you want: + (1) RSA and RSA (default) + (2) DSA and Elgamal + (3) DSA (sign only) + (4) RSA (sign only) +Your selection? 4 +RSA keys may be between 1024 and 4096 bits long. +What keysize do you want? (2048) 4096 +Requested keysize is 4096 bits +Please specify how long the key should be valid. + 0 = key does not expire + = key expires in n days + w = key expires in n weeks + m = key expires in n months + y = key expires in n years +Key is valid for? (0) +Key does not expire at all +Is this correct? (y/N) y +---- + +TIP: GPG will ask about your user identity now, provide your real name and + the mail address you intend to use for your project communication. + I also suggest to provide a meaningful comment, eg. "LEDE Signing Key" + + +---- +You need a user ID to identify your key; the software constructs the user ID +from the Real Name, Comment and Email Address in this form: + "Heinrich Heine (Der Dichter) " + +Real name: Jo-Philipp Wich +Email address: jo@mein.io +Comment: LEDE Signing Key +You selected this USER-ID: + "Jo-Philipp Wich (LEDE Signing Key) " + +Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O +You need a Passphrase to protect your secret key. +---- + +TIP: At this point enter a good pass phrase twice to protect your secret + key, the command will take a while to gather entropy and complete key + until it'll eventually print the key summary: + +---- +gpg: /tmp/signing/trustdb.gpg: trustdb created +gpg: key 612A0E98 marked as ultimately trusted +public and secret key created and signed. + +gpg: checking the trustdb +gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model +gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u +pub 4096R/612A0E98 2016-04-05 + Key fingerprint = 69B2 6A27 62D0 65E6 6F59 6755 C76F DE50 612A 0E98 +uid Jo-Philipp Wich (LEDE Signing Key) + +Note that this key cannot be used for encryption. You may want to use +the command "--edit-key" to generate a subkey for this purpose. +---- + +=== 2) Generate a sub key + +---- +$ gpg --homedir /tmp/signing --edit-key jo@mein.io +gpg (GnuPG) 1.4.18; Copyright (C) 2014 Free Software Foundation, Inc. +This is free software: you are free to change and redistribute it. +There is NO WARRANTY, to the extent permitted by law. + +Secret key is available. + +pub 4096R/612A0E98 created: 2016-04-05 expires: never usage: SC + trust: ultimate validity: ultimate +[ultimate] (1). Jo-Philipp Wich (LEDE Signing Key) +---- + +TIP: In the now appearing interactive gpg prompt enter "addkey" to create + a new signing subkey. GnuPG will ask your to unlock the master key using + the passphrase you've given in the previous step. + +---- +gpg> addkey +Key is protected. + +You need a passphrase to unlock the secret key for +user: "Jo-Philipp Wich (LEDE Signing Key) " +4096-bit RSA key, ID 612A0E98, created 2016-04-05 + +Please select what kind of key you want: + (3) DSA (sign only) + (4) RSA (sign only) + (5) Elgamal (encrypt only) + (6) RSA (encrypt only) +---- + +TIP: We'll use a signing-only 4096bit RSA key with an validity of two years + +---- +Your selection? 4 +RSA keys may be between 1024 and 4096 bits long. +What keysize do you want? (2048) 4096 +Requested keysize is 4096 bits +Please specify how long the key should be valid. + 0 = key does not expire + = key expires in n days + w = key expires in n weeks + m = key expires in n months + y = key expires in n years +Key is valid for? (0) 730 +Key expires at Thu Apr 5 18:19:42 2018 CEST +Is this correct? (y/N) y +Really create? (y/N) y +---- + +TIP: At this point, GnuPG will start gathering entropy again, running an + "find /" in the background is a good way to speed it up. When done it + will print the sub key summary and return to the prompt. Note the ID + "1584F206" of the subkey, we'll need that in step 4. + +---- +pub 4096R/612A0E98 created: 2016-04-05 expires: never usage: SC + trust: ultimate validity: ultimate +sub 4096R/1584F206 created: 2016-04-05 expires: 2018-04-05 usage: S +[ultimate] (1). Jo-Philipp Wich (LEDE Signing Key) +---- + +TIP: Enter "save" to commit the new key pair and its sub key to disk, the + GnuPG will automatically exit to the shell. + +---- +gpg> save +---- + +=== 3) Put the key into a vault + +At this point it is a good idea to make a *reliable and secure* backup +of the +/tmp/signing/+ directory, I suggest burning it onto a CDROM or +copying it onto a thumb drive which you can safely lock away or hide in +your apartment :) + +=== 4) Export the private sub key only + +We'll now export just the secret sub key since that is all we'll ever +need to sign files. Use the sub key ID from step 2 followed by an +exclamation mark to select the sub key to export: + +---- +$ gpg --homedir /tmp/signing --export-secret-subkeys 1584F206! \ + > /tmp/secret-signing-key.pgp +$ file /tmp/secret-signing-key.pgp +secret-signing-key.pgp: PGP\011Secret Key - 1024b created on Tue Apr 5 +16:08:15 2016 - RSA (Encrypt or Sign) +---- + +=== 5) Import the secret signing sub key into your actual key store + +You can now import the secret signing sub key on any machine you'll use +for signing files in the future. To import the sub key file, pass it to ++gpg --import+ and leave out the alternative homedir argument: + +---- +$ gpg --import /tmp/secret-signing-key.pgp +gpg: key 612A0E98: secret key imported +gpg: key 612A0E98: public key "Jo-Philipp Wich (LEDE Signing Key) +" imported +gpg: Total number processed: 1 +gpg: imported: 1 (RSA: 1) +gpg: secret keys read: 1 +gpg: secret keys imported: 1 +---- + +TIP: You can now issue a "gpg -K" to list all secret keys in your key store, + you should see the key you've imported with a leading "sec#". The hash + mark here indicates that the secret master key is missing, which is what + we want. + +---- +$ gpg -K +/home/jow/.gnupg/secring.gpg + --------------------------- +[...] +sec# 4096R/612A0E98 2016-04-05 +uid Jo-Philipp Wich (LEDE Signing Key) +ssb 4096R/1584F206 2016-04-05 +---- + +TIP: It is time to upload your public key part to a key server now so that + others can easily fetch it by its fingerprint or your chosen mail + address later on. For uploading use the primary key ID printed after + the "sec#" word in the previous command. + +---- +$ gpg --keyserver hkp://pool.sks-keyservers.net --send-keys 612A0E98 +gpg: sending key 612A0E98 to hkp server pool.sks-keyservers.net +---- + +=== 6) Delete original + +Make sure once again that your backup of the +/tmp/signing+ directory is +complete and readable, then remove the secret sub key file and the +entire temporary signing directory: + +---- +$ rm -r /tmp/signing/ +$ rm /tmp/secret-signing-key.pgp +---- + +TIP: You're now done setting up a suitable signing key pair. + +=== 7) Finish + +To export your public key in ASCII format use the following command, +again with the primary ID you've already used for uploading the pubkey. + +Make sure to provide a meaningful comment so that people looking at the +key file know who it belongs to without having to inspect it using GPG +utilities: + +---- +$ gpg --armor --export --no-version \ + --comment="Public key of Jo-Philipp Wich" 612A0E98 +---- + +In order to sign a file with your signing sub key, use the command below: + +---- +$ gpg --no-version -a -b -u 612A0E98 \ + --comment="My signature for something" -o output.sig input.file +---- + +TIP: Use your key ID as filename when adding your public signing key to the + repository: + +---- +$ cd keyring/gpg/ +$ gpg --armor --export --no-version \ + --comment="Public key of Me Myself" 612A0E98 > 612A0E98.asc +$ git add 612A0E98.asc +$ git commit -sm "Add my public key" +$ git push origin master +---- + +== Generate _usign_ key pair + +In order to generate an _usign_ key pair for use in LEDE release and package +repositories, follow the steps below. + +=== 1) Obtain _usign_ + +Clone the _usign_ repository and compile it. Note that the compilation requires +an installed +cmake+ to succeed. + +---- +$ git clone https://git.openwrt.org/project/usign.git +$ cd usign/ +$ cmake . +$ make +---- + +TIP: Run +./usign+ to check that the binary works. + +---- +$ ./usign +Usage: ./usign +Commands: + -V: verify (needs at least -m and -p|-P) + -S: sign (needs at least -m and -s) + -F: print key fingerprint of public/secret key or signature + -G: generate a new keypair +Options: + -c : add comment to keys + -m : message file + -p : public key file (verify/fingerprint only) + -P : public key directory (verify only) + -q: quiet (do not print verification result, use return code only) + -s : secret key file (sign/fingerprint only) + -x : signature file (defaults to .sig) +---- + +=== 2) Generate key pair + +Instruct the +usign+ executable to generate a new key pair and provide a +suitable comment to be able to identify the key file later on. + +---- +./usign -G -c "LEDE usign key of Jo-Philipp Wich" \ + -s secret.key -p public.key +---- + +TIP: Store the +secret.key+ file in a *secure and reliable* location, you'll + need it to sign package repositories in the future. + +=== 3) Add public key to the repository + +Obtain the fingerprint of your public key with the +usign -F+ command and use +it as filename for storing the pubkey in the +keyring.git+ repository: + +---- +$ ./usign -F -p public.key +72a57f2191b211e0 +---- + +TIP: Add the key to Git, using the fingerprint as filename: + +---- +$ cd keyring/usign/ +$ cp /some/where/public.key 72a57f2191b211e0 +$ git add 72a57f2191b211e0 +$ git commit -sm "Add my public usign key" +$ git push origin master +---- diff --git a/pages/signing.txt b/pages/signing.txt new file mode 100644 index 0000000..006e931 --- /dev/null +++ b/pages/signing.txt @@ -0,0 +1,128 @@ +Release Signing +=============== + +include::menu.inc[] + +== Signing Approach + +LEDE uses both https://www.gnupg.org/[GnuPG] and _usign_, a derivate of the +OpenBSD http://www.openbsd.org/papers/bsdcan-signify.html[_signify_] utilitiy. + +The _OPKG_ package manager uses _usign_ Ed25519 signatures to verify repository +metadata when installing packages while release image files are usually signed +by one or more developers with detached GPG signatures to allow users to verify +the integrity of installation files. + +Our _usign_ signature files carry the extension +.sig+ while the detached +GPG signatures end with +.gpg+. + +Note that not every file is signed individually but that we're signing the ++md5sums+ and +sha256sums+ or - for repositories - the +Packages+ files to +establish a chain of trust: The SHA256 checksum will verify the integrity of the +actual file while the signature will verify the integrity of the file containing +the checksums. + +=== Verify download integrity + +In order to verify the integrity of a firmware download you need to do the +following steps: + +. Download the +sha256sum+ and +sha256sum.gpg+ files +. Check the signature with +gpg --with-fingerprint --verify sha256sum.gpg + sha256sum+, ensure that the GnuPG command reports a good signature and that + the fingerprint matches the ones listed on our fingerprints (TODO:link) page. +. Download the firmware image and calculate its hash using one of the + +sha256sum+ or +openssl sha256+ commands. +. Verify that the calculated checksum matches the one listed in the +sha256sums+ + file. + +You can use the example script below to verify the integrity of image downloads, +call it as +./script.sh https://downloads.lede-project.org/path/to/image.bin+ + +---- +#!/bin/bash + +[ -n "$1" ] || { + echo "Usage: $0 " >&2 + exit 1 +} + +finish() { + echo "Cleaning up." + rm -r "/tmp/verify.$$" + exit $1 +} + +trap "finish 7" INT TERM + +destdir="$(pwd)" +image_url="$1" +image_file="${image_url##*/}" +sha256_url="${image_url%/*}/sha256sums" +gpgsig_url="${image_url%/*}/sha256sums.gpg" + +mkdir -p "/tmp/verify.$$" +cd "/tmp/verify.$$" + +echo "1) Downloading image file" +echo "=========================" +wget -O "$image_file" "$image_url" || { + echo "Failed to download image file!" >&2 + finish 1 +} + +echo "2) Downloading checksum file" +echo "============================" +wget -O "sha256sums" "$sha256_url" || { + echo "Failed to download checksum file!" >&2 + finish 2 +} + +echo "3) Downloading the GPG signature" +echo "================================" +wget -O "sha256sums.gpg" "$gpgsig_url" || { + echo "Failed to download GPG signature!" >&2 + finish 3 +} + +echo "4) Verifying GPG signature" +echo "==========================" +gpg --with-fingerprint --verify "sha256sums.gpg" "sha256sums" || { + echo "Failed to verify checksum file with GPG signature!" >&2 + finish 4 +} + +echo "" +echo "5) Verifying SHA256 checksum" +echo "============================" +remote_csum="$(grep -F "SHA256($image_file)=" "sha256sums")" +local_csum="$(openssl sha256 "$image_file")" +[ "$remote_csum" = "$local_csum" ] || { + echo "Checksums do not match!" >&2 + echo "REMOTE: $remote_csum" >&2 + echo "LOCAL: $local_csum" >&2 + finish 5 +} + +cp "$image_file" "$destdir/$image_file" || { + echo "Failed to write '$destdir/$image_file'" >&2 + finish 6 +} + +echo "" +echo "Verficiation done!" +echo "==================" +echo "Firmware image placed in '$dest_dir/$image_file'." + +finish 0 +---- + + +=== Developer information + +Developers participating in the LEDE project need to provide both _GnuPG_ and +_usign_ public keys which are stored in the central +https://git.lede-project.org/?p=keyring.git[keyring.git] repository. + +Refer to the link:/keygen.html[key generation howto] page for instruction on how to +generate suitable signing keys.