From f1e75783c4d893bade132866b06395b00ff74912 Mon Sep 17 00:00:00 2001 From: Roman Zeyde Date: Sat, 7 May 2016 09:41:58 +0300 Subject: [PATCH 01/11] gpg: use environment variable for user_id --- trezor_agent/gpg/README.md | 26 ++++++++-------- trezor_agent/gpg/git_wrapper.py | 35 ---------------------- trezor_agent/gpg/signer.py | 28 ++++++++++++----- trezor_agent/gpg/trezor-git-gpg-wrapper.sh | 2 +- 4 files changed, 35 insertions(+), 56 deletions(-) delete mode 100755 trezor_agent/gpg/git_wrapper.py diff --git a/trezor_agent/gpg/README.md b/trezor_agent/gpg/README.md index 8add8d4..44fc300 100644 --- a/trezor_agent/gpg/README.md +++ b/trezor_agent/gpg/README.md @@ -1,22 +1,24 @@ -# Generate new stand-alone GPG identity - +# Generate new GPG signing key: ``` $ USER_ID="Satoshi Nakamoto " -$ trezor-gpg create "${USER_ID}" > identity.pub # create new TREZOR-based GPG identity -$ gpg2 --import identity.pub # import into local GPG public keyring -$ gpg2 --edit "${USER_ID}" trust # OPTIONAL: mark the key as trusted ``` -# Generate new subkey for existing GPG identity +## Create new GPG identity: ``` -$ USER_ID="Satoshi Nakamoto " -$ gpg2 --list-keys "${USER_ID}" # make sure this identity already exists -$ trezor-gpg create --subkey "${USER_ID}" > identity.pub # create new TREZOR-based GPG public key -$ gpg2 --import identity.pub # append it to existing identity +$ trezor-gpg create > identity.pub # create new TREZOR-based GPG identity +$ gpg2 --import identity.pub # import into local GPG public keyring +$ gpg2 --edit "${USER_ID}" trust # OPTIONAL: mark the key as trusted +``` + +# Create new subkey for an existing GPG identity: +``` +$ gpg2 --list-keys "${USER_ID}" # make sure this identity already exists +$ trezor-gpg create --subkey > identity.pub # create new TREZOR-based GPG public key +$ gpg2 --import identity.pub # append it to existing identity ``` # Generate signatures using the TREZOR device ``` -$ trezor-gpg sign EXAMPLE > EXAMPLE.sig # confirm signature using the device -$ gpg2 --verify EXAMPLE.sig # verify using standard GPG binary +$ trezor-gpg sign EXAMPLE # confirm signature using the device +$ gpg2 --verify EXAMPLE.asc # verify using standard GPG binary ``` diff --git a/trezor_agent/gpg/git_wrapper.py b/trezor_agent/gpg/git_wrapper.py deleted file mode 100755 index 09e1a09..0000000 --- a/trezor_agent/gpg/git_wrapper.py +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env python -"""A simple wrapper for Git commit/tag GPG signing.""" -import logging -import subprocess as sp -import sys - -from . import decode, encode - -log = logging.getLogger(__name__) - - -def main(): - """Main function.""" - logging.basicConfig(level=logging.INFO, - format='%(asctime)s %(levelname)-10s %(message)s') - - log.debug('sys.argv: %s', sys.argv) - args = sys.argv[1:] - if '--verify' in args: - return sp.call(['gpg2'] + args) - else: - command = args[0] - user_id = ' '.join(args[1:]) - assert command == '-bsau' # --detach-sign --sign --armor --local-user - pubkey = decode.load_from_gpg(user_id, use_custom=True) - s = encode.Signer.from_public_key(user_id=user_id, pubkey=pubkey) - - data = sys.stdin.read() - sig = s.sign(data) - sig = encode.armor(sig, 'SIGNATURE') - sys.stdout.write(sig) - s.close() - -if __name__ == '__main__': - main() diff --git a/trezor_agent/gpg/signer.py b/trezor_agent/gpg/signer.py index b8c6014..237d592 100755 --- a/trezor_agent/gpg/signer.py +++ b/trezor_agent/gpg/signer.py @@ -5,6 +5,7 @@ import logging import subprocess as sp import sys import time +import os from . import decode, encode @@ -13,17 +14,18 @@ log = logging.getLogger(__name__) def run_create(args): """Generate a new pubkey for a new/existing GPG identity.""" - s = encode.Signer(user_id=args.user_id, created=args.time, + user_id = os.environ['TREZOR_GPG_USER_ID'] + s = encode.Signer(user_id=user_id, created=args.time, curve_name=args.ecdsa_curve) if args.subkey: subkey = s.subkey() - primary = sp.check_output(['gpg2', '--export', args.user_id]) + primary = sp.check_output(['gpg2', '--export', user_id]) result = primary + subkey else: result = s.export() s.close() - return encode.armor(result, 'PUBLIC KEY BLOCK') + sys.stdout.write(encode.armor(result, 'PUBLIC KEY BLOCK')) def run_sign(args): @@ -39,7 +41,19 @@ def run_sign(args): sig = encode.armor(sig, 'SIGNATURE') decode.verify(pubkey=pubkey, signature=sig, original_data=data) - return sig + + filename = '-' # write to stdout + if args.output: + filename = args.output + elif args.filename: + filename = args.filename + '.asc' + + if filename == '-': + output = sys.stdout + else: + output = open(filename, 'wb') + + output.write(sig) def main(): @@ -49,8 +63,6 @@ def main(): subparsers = p.add_subparsers() create = subparsers.add_parser('create') - create.add_argument('user_id', help='e.g. ' - '"Satoshi Nakamoto "') create.add_argument('-s', '--subkey', action='store_true', default=False) create.add_argument('-e', '--ecdsa-curve', default='nist256p1') create.add_argument('-t', '--time', type=int, default=int(time.time())) @@ -58,13 +70,13 @@ def main(): sign = subparsers.add_parser('sign') sign.add_argument('filename', nargs='?') + sign.add_argument('-o', '--output', default=None) sign.set_defaults(run=run_sign) args = p.parse_args() logging.basicConfig(level=logging.DEBUG if args.verbose else logging.INFO, format='%(asctime)s %(levelname)-10s %(message)s') - result = args.run(args) - sys.stdout.write(result) + args.run(args) if __name__ == '__main__': diff --git a/trezor_agent/gpg/trezor-git-gpg-wrapper.sh b/trezor_agent/gpg/trezor-git-gpg-wrapper.sh index 04a8807..c65bbe9 100755 --- a/trezor_agent/gpg/trezor-git-gpg-wrapper.sh +++ b/trezor_agent/gpg/trezor-git-gpg-wrapper.sh @@ -3,5 +3,5 @@ if [[ "$*" == *"--verify"* ]] then gpg2 $* # verify using GPG2 (for ECDSA and EdDSA keys) else - python -m trezor_agent.gpg.git_wrapper $* # sign using TREZOR + trezor-gpg sign -o- # sign using TREZOR and write the signature to stdout fi From 513c19bf1f60fe719ba38968c7c91a4858033738 Mon Sep 17 00:00:00 2001 From: Roman Zeyde Date: Sat, 7 May 2016 09:48:07 +0300 Subject: [PATCH 02/11] gpg: remove unused files --- trezor_agent/gpg/debug_subkeys.py | 43 ------------------------------- trezor_agent/gpg/demo.sh | 19 -------------- trezor_agent/gpg/test.sh | 16 ------------ 3 files changed, 78 deletions(-) delete mode 100644 trezor_agent/gpg/debug_subkeys.py delete mode 100755 trezor_agent/gpg/demo.sh delete mode 100644 trezor_agent/gpg/test.sh diff --git a/trezor_agent/gpg/debug_subkeys.py b/trezor_agent/gpg/debug_subkeys.py deleted file mode 100644 index a9aff80..0000000 --- a/trezor_agent/gpg/debug_subkeys.py +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env python -"""Check GPG v2 signature for a given public key.""" -import argparse -import logging - -from . import decode -from .. import util - -log = logging.getLogger(__name__) - - -def main(): - """Main function.""" - p = argparse.ArgumentParser() - p.add_argument('pubkey') - p.add_argument('-v', '--verbose', action='store_true', default=False) - args = p.parse_args() - logging.basicConfig(level=logging.DEBUG if args.verbose else logging.INFO, - format='%(asctime)s %(levelname)-10s %(message)s') - stream = open(args.pubkey, 'rb') - parser = decode.parse_packets(util.Reader(stream)) - pubkey, userid, sig1, subkey, sig2 = parser - - digest = decode.digest_packets([pubkey, userid, sig1]) - assert sig1['hash_prefix'] == digest[:2] - decode.verify_digest( - pubkey=pubkey, digest=digest, - signature=sig1['sig'], label='GPG public key (self sig)') - - digest = decode.digest_packets([pubkey, subkey, sig2]) - assert sig2['hash_prefix'] == digest[:2] - decode.verify_digest( - pubkey=pubkey, digest=digest, - signature=sig2['sig'], label='GPG subkey (1st sig)') - - sig3, = sig2['embedded'] - digest = decode.digest_packets([pubkey, subkey, sig3]) - decode.verify_digest( - pubkey=subkey, digest=digest, - signature=sig3['sig'], label='GPG subkey (2nd sig)') - -if __name__ == '__main__': - main() diff --git a/trezor_agent/gpg/demo.sh b/trezor_agent/gpg/demo.sh deleted file mode 100755 index cf44a61..0000000 --- a/trezor_agent/gpg/demo.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash -set -x -CREATED=1460731897 # needed for consistent public key creation -NAME="trezor_demo" # will be used as GPG user id and public key name - -echo "Hello GPG World!" > EXAMPLE -# Create, sign and export the public key -trezor-gpg $NAME --time $CREATED -o $NAME.pub - -# Install GPG v2.1 (modern) and import the public key -gpg2 --import $NAME.pub -gpg2 --list-keys $NAME -# gpg2 --edit-key $NAME trust # optional: mark it as trusted - -# Perform actual GPG signature using TREZOR device -trezor-gpg $NAME EXAMPLE - -# Verify signature using GPG2 binary -gpg2 --verify EXAMPLE.sig diff --git a/trezor_agent/gpg/test.sh b/trezor_agent/gpg/test.sh deleted file mode 100644 index d80c208..0000000 --- a/trezor_agent/gpg/test.sh +++ /dev/null @@ -1,16 +0,0 @@ -# NEVER RUN ON YOUR OWN REAL GPG KEYS!!!!! THEY WILL BE DELETED!!!!! -set -x -e -u -CURVE=ed25519 -#CURVE=nist256p1 -(cd ~/.gnupg && rm -rf openpgp-revocs.d/ private-keys-v1.d/ pubring.kbx* trustdb.gpg /tmp/log *.gpg; killall gpg-agent || true) -gpg2 --full-gen-key --expert -gpg2 --export > romanz.pub -NOW=`date +%s` -USERID="Roman Zeyde " -trezor-gpg -t $NOW -e $CURVE --subkey "$USERID" -o subkey.pub -gpg2 -K -gpg2 -v --import <(cat romanz.pub subkey.pub) -gpg2 -K - -trezor-gpg -t $NOW -e $CURVE "$USERID" EXAMPLE -gpg2 --verify EXAMPLE.sig From 7e3c3b4f77c5cd3833b7e2195972d005ca1a96ae Mon Sep 17 00:00:00 2001 From: Roman Zeyde Date: Sat, 7 May 2016 12:49:01 +0300 Subject: [PATCH 03/11] gpg: fixup README --- trezor_agent/gpg/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/trezor_agent/gpg/README.md b/trezor_agent/gpg/README.md index 44fc300..2a38b71 100644 --- a/trezor_agent/gpg/README.md +++ b/trezor_agent/gpg/README.md @@ -1,23 +1,23 @@ # Generate new GPG signing key: ``` -$ USER_ID="Satoshi Nakamoto " +$ export TREZOR_GPG_USER_ID="Satoshi Nakamoto " ``` ## Create new GPG identity: ``` $ trezor-gpg create > identity.pub # create new TREZOR-based GPG identity $ gpg2 --import identity.pub # import into local GPG public keyring -$ gpg2 --edit "${USER_ID}" trust # OPTIONAL: mark the key as trusted +$ gpg2 --edit "${TREZOR_GPG_USER_ID}" trust # OPTIONAL: mark the key as trusted ``` -# Create new subkey for an existing GPG identity: +## Create new subkey for an existing GPG identity: ``` -$ gpg2 --list-keys "${USER_ID}" # make sure this identity already exists +$ gpg2 --list-keys "${TREZOR_GPG_USER_ID}" # make sure this identity already exists $ trezor-gpg create --subkey > identity.pub # create new TREZOR-based GPG public key $ gpg2 --import identity.pub # append it to existing identity ``` -# Generate signatures using the TREZOR device +# Generate GPG signatures using a TREZOR device: ``` $ trezor-gpg sign EXAMPLE # confirm signature using the device $ gpg2 --verify EXAMPLE.asc # verify using standard GPG binary From 78526d13798814916cd34ae5f893767625843bb8 Mon Sep 17 00:00:00 2001 From: Roman Zeyde Date: Sat, 7 May 2016 13:02:10 +0300 Subject: [PATCH 04/11] gpg: install gpg-git wrapper script --- setup.py | 1 + trezor_agent/gpg/README.md | 19 +++++++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/setup.py b/setup.py index 6b63997..97fc549 100644 --- a/setup.py +++ b/setup.py @@ -9,6 +9,7 @@ setup( author_email='roman.zeyde@gmail.com', url='http://github.com/romanz/trezor-agent', packages=['trezor_agent'], + scripts=['trezor_agent/gpg/trezor-git-gpg-wrapper.sh'], install_requires=['ecdsa>=0.13', 'ed25519>=1.4', 'Cython>=0.23.4', 'trezor>=0.6.6', 'keepkey>=0.7.0', 'semver>=2.2'], platforms=['POSIX'], classifiers=[ diff --git a/trezor_agent/gpg/README.md b/trezor_agent/gpg/README.md index 2a38b71..5928699 100644 --- a/trezor_agent/gpg/README.md +++ b/trezor_agent/gpg/README.md @@ -1,24 +1,35 @@ -# Generate new GPG signing key: +# Using TREZOR as hardware GPG agent + +## Generate new GPG signing key: ``` $ export TREZOR_GPG_USER_ID="Satoshi Nakamoto " ``` -## Create new GPG identity: +### Create new GPG identity: ``` $ trezor-gpg create > identity.pub # create new TREZOR-based GPG identity $ gpg2 --import identity.pub # import into local GPG public keyring $ gpg2 --edit "${TREZOR_GPG_USER_ID}" trust # OPTIONAL: mark the key as trusted ``` -## Create new subkey for an existing GPG identity: +### Create new subkey for an existing GPG identity: ``` $ gpg2 --list-keys "${TREZOR_GPG_USER_ID}" # make sure this identity already exists $ trezor-gpg create --subkey > identity.pub # create new TREZOR-based GPG public key $ gpg2 --import identity.pub # append it to existing identity ``` -# Generate GPG signatures using a TREZOR device: +## Generate GPG signatures using a TREZOR device: ``` $ trezor-gpg sign EXAMPLE # confirm signature using the device $ gpg2 --verify EXAMPLE.asc # verify using standard GPG binary ``` + +## Git commit/tag signature: +``` +$ git config --local gpg.program "trezor-git-gpg-wrapper.sh" +$ git commit --gpg-sign # create GPG-signed commit +$ git log --show-signature # verify commits' signatures +$ git tag --sign "TAG" # create GPG-signed tag +$ git verify-tag "TAG" # verify tag signature +``` \ No newline at end of file From 1f126f3002e1d66befa55c559f0017190a208b38 Mon Sep 17 00:00:00 2001 From: Roman Zeyde Date: Sat, 7 May 2016 13:05:25 +0300 Subject: [PATCH 05/11] gpg: better logging --- trezor_agent/gpg/encode.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trezor_agent/gpg/encode.py b/trezor_agent/gpg/encode.py index c672aa8..e3dc32b 100644 --- a/trezor_agent/gpg/encode.py +++ b/trezor_agent/gpg/encode.py @@ -251,7 +251,7 @@ def _make_signature(signer_func, data_to_sign, public_algo, log.debug('hashing %d bytes', len(data_to_hash)) digest = hashlib.sha256(data_to_hash).digest() - log.info('SHA256 digest to sign: %s', util.hexlify(digest)) + log.info('signing digest: %s', util.hexlify(digest)) sig = signer_func(digest=digest) return bytes(header + hashed + unhashed + From 939fdbe8295d4dd9b8431048666b87d0575d9da3 Mon Sep 17 00:00:00 2001 From: Roman Zeyde Date: Sat, 7 May 2016 13:15:29 +0300 Subject: [PATCH 06/11] gpg: add output examples --- trezor_agent/gpg/README.md | 43 +++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/trezor_agent/gpg/README.md b/trezor_agent/gpg/README.md index 5928699..a0d6098 100644 --- a/trezor_agent/gpg/README.md +++ b/trezor_agent/gpg/README.md @@ -2,27 +2,68 @@ ## Generate new GPG signing key: ``` -$ export TREZOR_GPG_USER_ID="Satoshi Nakamoto " +$ export TREZOR_GPG_USER_ID="John Doe " ``` ### Create new GPG identity: ``` $ trezor-gpg create > identity.pub # create new TREZOR-based GPG identity +2016-05-07 13:05:30,380 INFO nist256p1 GPG public key <976C7E8C5BF0EB2A> created at 2016-05-07 13:05:30 for "John Doe " +2016-05-07 13:05:30,380 INFO signing public key "John Doe " +2016-05-07 13:05:30,381 INFO signing digest: 32D9A9C5E6B39819A84B1B735FD7BB224E599D06AFCB1CD012992E5F2A7BEF2D + $ gpg2 --import identity.pub # import into local GPG public keyring +gpg: key 5BF0EB2A: public key "John Doe " imported +gpg: Total number processed: 1 +gpg: imported: 1 + +$ gpg2 -k # verify that the new identity is created correctly +pub nistp256/2576C1EF 2016-05-07 [SC] +uid [ unknown] John Doe + $ gpg2 --edit "${TREZOR_GPG_USER_ID}" trust # OPTIONAL: mark the key as trusted ``` ### Create new subkey for an existing GPG identity: ``` $ gpg2 --list-keys "${TREZOR_GPG_USER_ID}" # make sure this identity already exists +pub rsa2048/39ADCBA2 2016-05-07 [SC] +uid [ultimate] John Doe +sub rsa2048/0F1AA6CA 2016-05-07 [E] + $ trezor-gpg create --subkey > identity.pub # create new TREZOR-based GPG public key +2016-05-07 13:09:53,097 INFO nist256p1 GPG public key <302CE72CAF4A5DD7> created at 2016-05-07 13:09:52 for "John Doe " +2016-05-07 13:09:53,102 INFO adding subkey to primary GPG key "John Doe " (FC527CB939ADCBA2) +2016-05-07 13:09:53,102 INFO confirm signing subkey with hardware device +2016-05-07 13:09:53,103 INFO signing digest: C8686DF576AB3AC13F0CD65F1D3F9575709A56598849CE43882C2609F861FE29 +2016-05-07 13:09:56,305 INFO confirm signing subkey with gpg-agent +2016-05-07 13:09:56,323 INFO signing digest: CB02710AB6554D0D2734D2BEDAC0D914D2402644EE2C8E5F68422F6B71A22248 + $ gpg2 --import identity.pub # append it to existing identity +gpg: key 39ADCBA2: "John Doe " 1 new signature +gpg: key 39ADCBA2: "John Doe " 1 new subkey +gpg: Total number processed: 1 +gpg: new subkeys: 1 +gpg: new signatures: 1 + +$ gpg2 --list-keys "${TREZOR_GPG_USER_ID}" # verify that the new subkey is added to existing keyring +pub rsa2048/39ADCBA2 2016-05-07 [SC] +uid [ultimate] John Doe +sub rsa2048/0F1AA6CA 2016-05-07 [E] +sub nistp256/AF4A5DD7 2016-05-07 [S] ``` ## Generate GPG signatures using a TREZOR device: ``` $ trezor-gpg sign EXAMPLE # confirm signature using the device +2016-05-07 13:06:35,464 INFO nist256p1 GPG public key <976C7E8C5BF0EB2A> created at 2016-05-07 13:05:30 for "John Doe " +2016-05-07 13:06:35,464 INFO signing 7 byte message at 2016-05-07 13:06:35 +2016-05-07 13:06:35,464 INFO signing digest: A0D6CD4FA3AC68FED14EA8B4A712F4EA06426655911067C85FCB087F19043114 + $ gpg2 --verify EXAMPLE.asc # verify using standard GPG binary +gpg: assuming signed data in 'EXAMPLE' +gpg: Signature made Sat 07 May 2016 01:06:35 PM IDT using ECDSA key ID 5BF0EB2A +gpg: Good signature from "John Doe " [ultimate] ``` ## Git commit/tag signature: From 25a427081c902ba939a37645009b88218211110f Mon Sep 17 00:00:00 2001 From: Roman Zeyde Date: Sat, 7 May 2016 13:24:25 +0300 Subject: [PATCH 07/11] gpg: add more output examples --- trezor_agent/gpg/README.md | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/trezor_agent/gpg/README.md b/trezor_agent/gpg/README.md index a0d6098..e633701 100644 --- a/trezor_agent/gpg/README.md +++ b/trezor_agent/gpg/README.md @@ -70,7 +70,28 @@ gpg: Good signature from "John Doe " [ultimate] ``` $ git config --local gpg.program "trezor-git-gpg-wrapper.sh" $ git commit --gpg-sign # create GPG-signed commit -$ git log --show-signature # verify commits' signatures +2016-05-07 13:17:33,986 INFO nist256p1 GPG public key <4286F5982576C1EF> created at 2016-05-07 13:13:47 for "John Doe " +2016-05-07 13:17:33,986 INFO signing 240 byte message at 2016-05-07 13:17:33 +2016-05-07 13:17:33,987 INFO signing digest: A442D5C91058C53DC2A4E8CC9624FF6786AE2364D2FD326D72CA1271CBD36FA3 +[master dd11ad4] A commit to be signed + Date: Fri Apr 22 12:00:38 2016 +0300 + 1 file changed, 1 insertion(+), 1 deletion(-) + +$ git log --show-signature -1 # verify commits' signatures +commit dd11ad4e9ed43ed5c4ee114f50e3b943d4a48232 +gpg: Signature made Sat 07 May 2016 01:17:33 PM IDT using ECDSA key ID 2576C1EF +gpg: Good signature from "John Doe " [ultimate] +Author: Roman Zeyde +Date: Fri Apr 22 12:00:38 2016 +0300 + + A commit to be signed + $ git tag --sign "TAG" # create GPG-signed tag +2016-05-07 13:23:20,256 INFO nist256p1 GPG public key <4286F5982576C1EF> created at 2016-05-07 13:13:47 for "John Doe " +2016-05-07 13:23:20,256 INFO signing 149 byte message at 2016-05-07 13:23:20 +2016-05-07 13:23:20,256 INFO signing digest: 55A930F2646132BCFC05C550ED3394C6ED3EAF2F82F5400B079D1E8F3B78C8AC + $ git verify-tag "TAG" # verify tag signature +gpg: Signature made Sat 07 May 2016 01:23:20 PM IDT using ECDSA key ID 2576C1EF +gpg: Good signature from "John Doe " [ultimate] ``` \ No newline at end of file From 4270d8464ff3563245f947666cef6f595718161d Mon Sep 17 00:00:00 2001 From: Roman Zeyde Date: Sat, 7 May 2016 15:51:01 +0300 Subject: [PATCH 08/11] gpg: add screencasts --- trezor_agent/gpg/README.md | 108 +++++++++++-------------------------- 1 file changed, 31 insertions(+), 77 deletions(-) diff --git a/trezor_agent/gpg/README.md b/trezor_agent/gpg/README.md index e633701..d94deca 100644 --- a/trezor_agent/gpg/README.md +++ b/trezor_agent/gpg/README.md @@ -1,97 +1,51 @@ # Using TREZOR as hardware GPG agent ## Generate new GPG signing key: +First, verify that you have GPG 2.1+ [installed](https://gist.github.com/vt0r/a2f8c0bcb1400131ff51): ``` -$ export TREZOR_GPG_USER_ID="John Doe " +$ gpg2 --version | head -n1 +gpg (GnuPG) 2.1.11 ``` -### Create new GPG identity: +Define your GPG user ID as an environment variable: +``` +$ export TREZOR_GPG_USER_ID="John Doe " ``` -$ trezor-gpg create > identity.pub # create new TREZOR-based GPG identity -2016-05-07 13:05:30,380 INFO nist256p1 GPG public key <976C7E8C5BF0EB2A> created at 2016-05-07 13:05:30 for "John Doe " -2016-05-07 13:05:30,380 INFO signing public key "John Doe " -2016-05-07 13:05:30,381 INFO signing digest: 32D9A9C5E6B39819A84B1B735FD7BB224E599D06AFCB1CD012992E5F2A7BEF2D - -$ gpg2 --import identity.pub # import into local GPG public keyring -gpg: key 5BF0EB2A: public key "John Doe " imported -gpg: Total number processed: 1 -gpg: imported: 1 -$ gpg2 -k # verify that the new identity is created correctly -pub nistp256/2576C1EF 2016-05-07 [SC] -uid [ unknown] John Doe +There are two ways to generate TREZOR-based GPG public keys, as described below. -$ gpg2 --edit "${TREZOR_GPG_USER_ID}" trust # OPTIONAL: mark the key as trusted +### (1) create new GPG identity: ``` - -### Create new subkey for an existing GPG identity: +$ trezor-gpg create > identity.pub # create new TREZOR-based GPG identity +$ gpg2 --import identity.pub # import into local GPG public keyring +$ gpg2 --list-keys # verify that the new identity is created correctly +$ gpg2 --edit "${TREZOR_GPG_USER_ID}" trust # OPTIONAL: mark the key as trusted ``` -$ gpg2 --list-keys "${TREZOR_GPG_USER_ID}" # make sure this identity already exists -pub rsa2048/39ADCBA2 2016-05-07 [SC] -uid [ultimate] John Doe -sub rsa2048/0F1AA6CA 2016-05-07 [E] - -$ trezor-gpg create --subkey > identity.pub # create new TREZOR-based GPG public key -2016-05-07 13:09:53,097 INFO nist256p1 GPG public key <302CE72CAF4A5DD7> created at 2016-05-07 13:09:52 for "John Doe " -2016-05-07 13:09:53,102 INFO adding subkey to primary GPG key "John Doe " (FC527CB939ADCBA2) -2016-05-07 13:09:53,102 INFO confirm signing subkey with hardware device -2016-05-07 13:09:53,103 INFO signing digest: C8686DF576AB3AC13F0CD65F1D3F9575709A56598849CE43882C2609F861FE29 -2016-05-07 13:09:56,305 INFO confirm signing subkey with gpg-agent -2016-05-07 13:09:56,323 INFO signing digest: CB02710AB6554D0D2734D2BEDAC0D914D2402644EE2C8E5F68422F6B71A22248 - -$ gpg2 --import identity.pub # append it to existing identity -gpg: key 39ADCBA2: "John Doe " 1 new signature -gpg: key 39ADCBA2: "John Doe " 1 new subkey -gpg: Total number processed: 1 -gpg: new subkeys: 1 -gpg: new signatures: 1 +[![asciicast](https://asciinema.org/a/44880.png)](https://asciinema.org/a/44880) -$ gpg2 --list-keys "${TREZOR_GPG_USER_ID}" # verify that the new subkey is added to existing keyring -pub rsa2048/39ADCBA2 2016-05-07 [SC] -uid [ultimate] John Doe -sub rsa2048/0F1AA6CA 2016-05-07 [E] -sub nistp256/AF4A5DD7 2016-05-07 [S] +### (2) create new subkey for an existing GPG identity: ``` +$ gpg2 --list-keys "${TREZOR_GPG_USER_ID}" # make sure this identity already exists +$ trezor-gpg create --subkey > identity.pub # create new TREZOR-based GPG subkey +$ gpg2 --import identity.pub # append it to an existing identity +$ gpg2 --list-keys "${TREZOR_GPG_USER_ID}" # verify that the new subkey is added to keyring +``` +[![subkey](https://asciinema.org/a/8t78s6pqo5yocisaiolqnjp63.png)](https://asciinema.org/a/8t78s6pqo5yocisaiolqnjp63) ## Generate GPG signatures using a TREZOR device: ``` -$ trezor-gpg sign EXAMPLE # confirm signature using the device -2016-05-07 13:06:35,464 INFO nist256p1 GPG public key <976C7E8C5BF0EB2A> created at 2016-05-07 13:05:30 for "John Doe " -2016-05-07 13:06:35,464 INFO signing 7 byte message at 2016-05-07 13:06:35 -2016-05-07 13:06:35,464 INFO signing digest: A0D6CD4FA3AC68FED14EA8B4A712F4EA06426655911067C85FCB087F19043114 - -$ gpg2 --verify EXAMPLE.asc # verify using standard GPG binary -gpg: assuming signed data in 'EXAMPLE' -gpg: Signature made Sat 07 May 2016 01:06:35 PM IDT using ECDSA key ID 5BF0EB2A -gpg: Good signature from "John Doe " [ultimate] +$ trezor-gpg sign EXAMPLE # confirm signature using the device +$ gpg2 --verify EXAMPLE.asc # verify using standard GPG binary ``` +[![sign](https://asciinema.org/a/f1unkptesb7anq09i8wugoko6.png)](https://asciinema.org/a/f1unkptesb7anq09i8wugoko6) -## Git commit/tag signature: +## Git commit & tag signatures: +Git can use GPG to sign and verify commits and tags (see [here](https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work)): ``` $ git config --local gpg.program "trezor-git-gpg-wrapper.sh" -$ git commit --gpg-sign # create GPG-signed commit -2016-05-07 13:17:33,986 INFO nist256p1 GPG public key <4286F5982576C1EF> created at 2016-05-07 13:13:47 for "John Doe " -2016-05-07 13:17:33,986 INFO signing 240 byte message at 2016-05-07 13:17:33 -2016-05-07 13:17:33,987 INFO signing digest: A442D5C91058C53DC2A4E8CC9624FF6786AE2364D2FD326D72CA1271CBD36FA3 -[master dd11ad4] A commit to be signed - Date: Fri Apr 22 12:00:38 2016 +0300 - 1 file changed, 1 insertion(+), 1 deletion(-) - -$ git log --show-signature -1 # verify commits' signatures -commit dd11ad4e9ed43ed5c4ee114f50e3b943d4a48232 -gpg: Signature made Sat 07 May 2016 01:17:33 PM IDT using ECDSA key ID 2576C1EF -gpg: Good signature from "John Doe " [ultimate] -Author: Roman Zeyde -Date: Fri Apr 22 12:00:38 2016 +0300 - - A commit to be signed - -$ git tag --sign "TAG" # create GPG-signed tag -2016-05-07 13:23:20,256 INFO nist256p1 GPG public key <4286F5982576C1EF> created at 2016-05-07 13:13:47 for "John Doe " -2016-05-07 13:23:20,256 INFO signing 149 byte message at 2016-05-07 13:23:20 -2016-05-07 13:23:20,256 INFO signing digest: 55A930F2646132BCFC05C550ED3394C6ED3EAF2F82F5400B079D1E8F3B78C8AC - -$ git verify-tag "TAG" # verify tag signature -gpg: Signature made Sat 07 May 2016 01:23:20 PM IDT using ECDSA key ID 2576C1EF -gpg: Good signature from "John Doe " [ultimate] -``` \ No newline at end of file +$ git commit --gpg-sign # create GPG-signed commit +$ git log --show-signature -1 # verify commit signature +$ git tag --sign "TAG" # create GPG-signed tag +$ git verify-tag "TAG" # verify tag signature +``` +[![asciicast](https://asciinema.org/a/44879.png)](https://asciinema.org/a/44879) From 04a878374fd4bb94d78b5fb232350f35ea6bfa84 Mon Sep 17 00:00:00 2001 From: Roman Zeyde Date: Sat, 7 May 2016 20:38:19 +0300 Subject: [PATCH 09/11] setup: add gpg subpackage --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 97fc549..a026bc1 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ setup( author='Roman Zeyde', author_email='roman.zeyde@gmail.com', url='http://github.com/romanz/trezor-agent', - packages=['trezor_agent'], + packages=['trezor_agent', 'trezor_agent.gpg'], scripts=['trezor_agent/gpg/trezor-git-gpg-wrapper.sh'], install_requires=['ecdsa>=0.13', 'ed25519>=1.4', 'Cython>=0.23.4', 'trezor>=0.6.6', 'keepkey>=0.7.0', 'semver>=2.2'], platforms=['POSIX'], From 9888ef971aa50e4f71729a23162197ca1c9b6172 Mon Sep 17 00:00:00 2001 From: Roman Zeyde Date: Sat, 7 May 2016 20:41:34 +0300 Subject: [PATCH 10/11] gpg: add installation command to README --- trezor_agent/gpg/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/trezor_agent/gpg/README.md b/trezor_agent/gpg/README.md index d94deca..500b7e6 100644 --- a/trezor_agent/gpg/README.md +++ b/trezor_agent/gpg/README.md @@ -7,6 +7,11 @@ $ gpg2 --version | head -n1 gpg (GnuPG) 2.1.11 ``` +Install the latest development version of `trezor-agent`: +``` +$ pip install git+https://github.com/romanz/trezor-agent.git@master +``` + Define your GPG user ID as an environment variable: ``` $ export TREZOR_GPG_USER_ID="John Doe " From 695079e4b9cf8ddee0e0c6c8038ec065d8643091 Mon Sep 17 00:00:00 2001 From: Roman Zeyde Date: Sat, 7 May 2016 20:49:51 +0300 Subject: [PATCH 11/11] agent: raise explicit error when signature fails --- trezor_agent/gpg/agent.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/trezor_agent/gpg/agent.py b/trezor_agent/gpg/agent.py index e058ac7..a624643 100644 --- a/trezor_agent/gpg/agent.py +++ b/trezor_agent/gpg/agent.py @@ -123,10 +123,11 @@ def sign(sock, keygrip, digest): line = _unescape(line) log.debug('line: %r', line) prefix, sig = line.split(' ', 1) - assert prefix == 'D' + if prefix != 'D': + raise ValueError(line) sig, leftover = _parse(sig) - assert not leftover + assert not leftover, leftover return _parse_sig(sig)