PGP for ssh, git commit signing and password management
PGP - Pretty Good Privacy
- created by Phil Zimmermann in 1991
- owned by Symantec
- OpenPGP is a standard defined in RFC 4880
- GPG/GnuPG (GNU Privacy Guard) implements OpenPGP
basic concepts
- encryption - convert plaintext to ciphertext using a key
- symmetric - use same key for encryption and decryption
- asymmetric - use 2 keys - public and private
- pgp encryption - nobody should read this except the recipient
- sender generates a random encryption key (session key)
- sender encrypts message contents with session key using a symmetric cipher
- sender encrypts session key using recipient’s public PGP key
- sender sends both encrypted message and encrypted session key to recipient
- recipient decrypts session key using their private PGP key
- recipient uses session key to decrypt message
- pgp signature - verify integrity - use keys the opposite way as above:
- signer generates checksum of message
- signer encrypts the checksum using own private PGP key
- signer sends encrypted checksum along with message
- verifier generates their own checksum of message
- verifier decrypts provided checksum using signer’s public PGP key
- if checksums match, integrity is verified
- combined usage - sign encrypted message with sender’s own PGP key
- key identities
- each PGP key must have one or more identities (name+email like
Alice <[email protected]>
) associated with it - if multiple identities are used, one of them would be marked as primary. e.g.
Alice <[email protected]> Alice <[email protected]>
- you can create new identities, revoke old ones and change which identity is primary
- each PGP key must have one or more identities (name+email like
- key validity
- full – pretty sure this key belongs to Alice
- marginal – somewhat sure this key belongs to Alice
- unknown – no assurance that this key belongs to Alice
- Web of Trust (WoT) vs Trust on First Usage (ToFU)
- WOT - sign each others keys to ascertain that he is who he claims to be
- TOFU - SSH-like, i.e. first time you connect to a system, record its key fingerprint (in
.ssh/known_hosts
). Check this from next time and fail if it doesn’t match
generate and protect master PGP key
- a PGP key can have 4 capabilities - these are just functional limitations
assigned at creation time:
- [S] - use for signing
- [E] - use for encryption
- [A] - use for authentication
- [C] - use for certifying other keys - master key
- add or revoke other keys (subkeys) with S/E/A capabilities
- add, change or revoke identities (uids) associated with the key
- add or change the expiration date on itself or any subkey
- sign other people’s keys for WoT purposes
- a single key can have multiple capabilities
- no technical difference between master key and subkeys
generate master key
$ gpg --quick-generate-key 'Alice Engineer <[email protected]>' rsa4096 cert
output will be something like:
pub rsa4096 2017-12-06 [C] [expires: 2019-12-06]
111122223333444455556666AAAABBBBCCCCDDDD
uid Alice Engineer <[email protected]>
the 2nd line above is the full fingerprint of your new key.
- key ids can be represented in 3 forms:
- fingerprint - full 40-character key identifier (
111122223333444455556666AAAABBBBCCCCDDDD
) - long - last 16 characters of fingerprint (
AAAABBBBCCCCDDDD
) - short - last 8 characters of fingerprint - avoid using this (
CCCCDDDD
)
- fingerprint - full 40-character key identifier (
- backup your master key on paper using
paperkey
:$ gpg --export-secret-key <FINGERPRINT> | paperkey -o /tmp/key-backup.txt
you can convert this text file to a PDF using
enscript --no-header -p - /tmp/key-backup.txt | ps2pdf - /tmp/key-backup.pdf
and then print it out on paper. Keep it safe! - add more identities using:
$ gpg --quick-add-uid <FINGERPRINT> 'Alice Engineer <[email protected]>' $ gpg --quick-set-primary-uid <FINGERPRINT> 'Alice Engineer <[email protected]>' # reset your primary uid
generate PGP subkeys
- generate 1 subkey each for encryption, signing and authentication
$ gpg --quick-add-key <FINGERPRINT> rsa2048 encr $ gpg --quick-add-key <FINGERPRINT> rsa2048 sign $ gpg --quick-add-key <FINGERPRINT> rsa2048 auth
move master key offline
- create an encrypted USB drive (you can use the same passphrase as your master
key passphrase) and backup your
~/.gnupg
to it - I used GNOME Disks (LUKS) for this, but you can also do it on the cmdline.
common gnupg operations
- mounting master key offline storage
$ export GNUPGHOME=/media/disk/name/gnupg-backup $ gpg --list-secret-keys
You want to make sure that you see sec and not sec# in the output (the # means the key is not available and you’re still using your regular home directory location).
- import any changes made using offline storage keys:
$ gpg --export | gpg --homedir ~/.gnupg --import $ unset GNUPGHOME
- import any changes made using offline storage keys:
- extend key expiration date
$ gpg --quick-set-expire <FINGERPRINT> 1y # extend by 1 year $ gpg --quick-set-expire <FINGERPRINT> 2020-07-01 # extend till
- export public key to stdout - share this with everyone and bug
them to send you encrypted emails or pictures or what have you.
$ gpg --export --armor <FINGERPRINT>
- upload your public key to keyservers - just be aware that your
key can’t be deleted once pushed
$ gpg --send-key <FINGERPRINT>
- import a public key
- from file (get mine here):
$ gpg --import <PUBLICKEYFILE>
- from keyserver:
$ gpg --search-keys <EMAIL> $ gpg --recv-keys <FINGERPRINT>
for example, Linus Torvalds’ key:
$ gpg --search-keys [email protected] gpg: data source: https://192.146.137.99:443 (1) Linus Torvalds <[email protected]> 2048 bit RSA key 6211AA3B00411886, created: 2014-07-21 (revoked) (2) Linus Torvalds <[email protected]> Linus Torvalds <[email protected]> 2048 bit RSA key 79BE3E4300411886, created: 2011-09-20
- from file (get mine here):
- refresh other people’s keys in your keyring:
$ gpg --refresh
- encrypt file with receiver’s public key:
$ gpg --recipient <EMAIL|FINGERPRINT> --encrypt <FILENAME>
- decrypt file with your private key:
$ gpg --output <OUTPUTFILE> --decrypt <ENCRYPTEDFILENAME>
- sign a file with your private key:
$ gpg --output <OUTPUTFILE> --sign <FILENAME> # binary $ gpg --output <OUTPUTFILE> --clearsign <FILENAME> # plaintext $ gpg --output <OUTPUTFILE> --detach-sig <FILENAME> # detached signature
- verify a signature:
$ gpg --verify doc.sig $ gpg --verify archlinux.iso.sig # verify detached signature for archlinux.iso
- encrypt and sign (in ASCII armor)
$ gpg --encrypt --sign --armor -r <RECIPIENT> <FILENAME> # will create <FILENAME>.asc
- decrypt encrypted and signed file
$ gpg <FILENAME>.asc
- sign someone’s key (WOT):
$ gpg --sign-key <RECP_EMAIL>
send them this signed key:
$ gpg --output ~/signed.key --export --armor <RECP_EMAIL>
they can now import this into their gpg database:
$ gpg --import ~/signed.key
- export your auth key in OpenSSH public key format
$ gpg --export-ssh-key <FINGERPRINT>
android
- use OpenKeyChain on android
- transfer your key as per the OpenKeyChain
FAQ
$ gpg --armor --gen-random 1 20 # generate random password to use for below $ gpg --armor --export-secret-keys <FINGERPRINT> | gpg --armor --symmetric --output mykey.sec.asc
- copy above to your phone using USB and chose
Import Key from File
. Enter the random password using which it was encrypted.
pgp with ssh
- make sure you have an auth subkey
- add following to your
~/.bashrc
export GPG_TTY=$(tty) # as per gpg-agent(1) unset SSH_AGENT_PID [[ "${gnupg_SSH_AUTH_SOCK_by:-0}" -ne $$ ]] && export SSH_AUTH_SOCK="$(gpgconf --list-dirs agent-ssh-socket)"
- add following to
~/.gnupg/gpg-agent.conf
enable-ssh-support
- if using GNOME, stop the keyring daemon from starting up
ssh-agent
$ cp /etc/xdg/autostart/gnome-keyring-ssh.desktop ~/.config/autostart/ && echo 'Hidden=true' >> ~/.config/autostart/gnome-keyring-ssh.desktop
- add your auth key’s keygrip to
~/.gnupg/sshcontrol
$ gpg --list-keys --with-keygrip <FINGERPRINT>|grep -A1 '\[A\]'|tail -n1|awk -F= '{print $2}'|tr -d ' '>>~/.gnupg/sshcontrol
- use
ssh-copy-id
as usual to copy this to any remote hosts
pgp with git
- use
git commit -S
to sign your commits - copy your public key to GitHub/GitLab
to get a little
Verified
icon next to your signed commits
password management with pass
- store your GPG encrypted passwords in a git repository!
- initialize with
$ pass init <gpd-id or email>
- also initialize git repo:
$ pass git init $ pass git remote add origin <REMOTEURL> $ pass git config --bool --add pass.signcommits true # sign commits $ pass git push -u --all
- add multiline passwords (
pass insert -m archlinux.org/wiki/username
) in the following form so passff/browserpass can work:<the_password> login: <the_login> url: <the_url> <other_inputfield_name> : <inputfield_value>
- push changes to git server:
$ pass git push
- generate n length password for xyz.com
$ pass generate xyz.com n # add -n before xyz.com so no symbols are added
- On Android, install Password Store
via F-Droid.
It depends on OpenKeyChain,
so make sure to install that as well
- follow this to transfer your keys to your phone
references
- https://github.com/lfit/itpol/blob/master/protecting-code-integrity.md
- https://0day.work/using-a-yubikey-for-gpg-and-ssh/
- https://www.digitalocean.com/community/tutorials/how-to-use-gpg-to-encrypt-and-sign-messages
- https://wiki.archlinux.org/index.php/GnuPG
- https://futureboy.us/pgp.html
- https://budts.be/weblog/2012/08/ssh-authentication-with-your-pgp-key/
- https://ryanlue.com/posts/2017-06-29-gpg-for-ssh-auth
- https://wiki.archlinux.org/index.php/Pass