Giter VIP home page Giter VIP logo

how2gpg's Introduction

GNU Privacy Guard - Short Reference

Tip

For a more detailed treatise check Dr. Duh's YubiKey-Guide.

Backup Storage

Creation

For a local and secure backup a small encrypted file will suffice.
Additional perk: you can put multiple such files on a drive.

sudo dd if=/dev/urandom of=store.dat bs=1M count=25
sudo cryptsetup -c aes-xts-plain64 -s 512 -h sha512 -y luksFormat store.dat
sudo cryptsetup luksOpen store.dat backup
sudo mkfs.ext4 /dev/mapper/backup
sudo cryptsetup luksClose backup

Now just put this file on a safely-stored thumb drive.

Mounting

Tip

Do this in the secure live system (e.g. tails, see below).

Mount encrypted file as non-root user

udisksctl mount -b /dev/mmcblk0p1 backup
sudo cryptsetup luksOpen store.dat backup
udisksctl mount -b /dev/mapper/backup

# -> do your stuff

udisksctl unmount -b /dev/mapper/backup
sudo cryptsetup luksClose backup
udisksctl unmount -b /dev/mmcblk0p1

Versioning

It might make sense to version all backups.

git init

# don't use the `--global` option, we want to store it locally in `.git/config`
git configuser.email <email>
git config user.name <name>
git config commit.gpgsign true

git log --show-signature

Environment

Make your life easy and use Tails. Live systems like Arch Linux which directly start in a root shell won't work well with GPG (see here).

Important

For Tails, don't forget to enable the administrator password in additional settings during startup!

Create temporary working directory (run as user)

export GNUPGHOME=$(mktemp -d -t gnupg_$(date +%Y%m%d%H%M)_XXX)

Harden GPG config

wget -O $GNUPGHOME/gpg.conf https://raw.githubusercontent.com/drduh/config/master/gpg.conf

or copy existing one from backup drive to avoid early network connections.

Generating

Note

(Arguably) best practice:

  • primary keys should never expire
  • subkeys are valid for not longer than 1 year

Parent key (pure ed25519 / cv25519)

gpg --quick-generate-key 'Your Name <[email protected]>' ed25519 cert never

Subkeys

export KEYID='<fingerprint>'
gpg --quick-add-key $KEYID ed25519 sign 1y
gpg --quick-add-key $KEYID cv25519 encr 1y
gpg --quick-add-key $KEYID ed25519 auth 1y

Add additional UIDS

gpg --expert --edit-key $KEYID
gpg> adduid

Select UIDS and fully trust them (will not show correct "ultimate trust" until all changes have been saved)

gpg> uid 2
gpg> uid 3
gpg> trust
Your decision? 5

Make other UID primary

gpg> uid 3
gpg> primary

Save and quit

gpg> save
gpg> quit

Quality check (requires openpgp-tools package)

gpg --export $KEYID | hokey lint

Exporting

Create export folder

mkdir $GNUPGHOME/exports

Note

Exported files will always differ because of salting, see here.

All secret keys incl. subkeys

gpg --armor --export-secret-keys $KEYID > primary.asc

"Laptop keypair" - i.e. only subkeys but no primary

gpg --armor --export-secret-subkeys $KEYID > subs.asc

Tip

Use the backup option to export all necessary information to restore the secrets keys (including local signatures) but NOT the trust database entry, check docs.

gpg --armor --export-options export-backup --export-secret-keys $KEYID > full_backup.asc

# import would read
gpg --import-options restore[,keep-ownertrust] --import full_backup.asc

Paperkey and QR code (examples here)

sudo pacman -S paperkey qrencode
gpg --export-secret-key $KEYID | paperkey --output paperkey.asc
gpg --export-secret-key $KEYID | paperkey --output-type raw | qrencode --8bit --level H --output paperkey.qr.png

Print paperkey (make sure to set a default printer in CUPS)

lp -o media=a4 -o portrait -o fit-to-page -o sides=two-sided-long-edge paperkey.asc

Paperkey needs public keys for restoration, so export them in their armored and binary versions

gpg --armor --export $KEYID > pubkey.asc
gpg --export $KEYID > pubkey.gpg

Revocation certificate (with optionally specified reason) in case key gets compromised

Note

By default a generic one is already created in $GNUPGHOME/openpgp-revocs.d/$KEYID.rev.

gpg --gen-revoke $KEYID > revoke_compromised.asc

Export trust database

Important

Exported trust values are equal to trust level + 1:

Trust Level 1 (export: 2) = I don't know or won't say
Trust Level 2 (export: 3) = I do NOT trust
Trust Level 3 (export: 4) = I trust marginally
Trust Level 4 (export: 5) = I trust fully
Trust Level 5 (export: 6) = I trust ultimately

gpg --export-ownertrust > export/ownertrust.txt

Private keys are stored in $GNUPGHOME/private-keys-v1.d/, check with

gpg -K --with-keygrip

Push to proper keyserver

gpg --export $KEYID | curl -T - https://keys.openpgp.org
# on tails via Tor
gpg --export $KEYID | torify curl -T - https://keys.openpgp.org

Legacy keyservers

gpg --keyserver hkps://keyserver.ubuntu.com --send-keys $KEYID
gpg --keyserver https://pgp.mit.edu --send-keys $KEYID

Recovery

Process

  1. requires binary pubkey in addition (dearmor if required)
  2. needs export GPG_TTY=$(tty) for gpg --import on live system

From QR code

zbarimg -1 --raw -q -Sbinary paperkey.qr.png | paperkey --pubring pubkey.gpg | gpg --import

From paperkey text file

paperkey --pubring pubkey.gpg --secrets paperkey.asc | gpg --import

Optionally use some OCR software like OCRmyPDF / tesseract to convert printed sheets into paperkey.asc file.

Extending

Important

The expiration date is a public key attribute only (the private keys never expire).

Boot into secure environment and mount backup drive as explained in the respective sections above.

Create temporary GPG working directory

export GNUPGHOME=$(mktemp -d -t gnupg_$(date +%Y%m%d%H%M)_XXX)
cp <decrypted_backup_drive>/gpg.conf $GNUPGHOME

Import expired key

# pinentry setting might be necessary when in TTY
gpg [--pinentry-mode loopback] --import full_backup.asc

List expired subkeys

gpg --list-options show-unusable-subkeys -K

Extend expiration dates

gpg --edit-key $KEYID

Note

(Arguably) best practice:

  • primary keys should never expire
  • subkeys are valid for not longer than 1 year

Primary key

gpg> expire
gpg> never
gpg> save

Subkeys

# use key 0 to deselect all
gpg> key 1
gpg> key 2
gpg> key 3
gpg> expire
gpg> 1y
gpg> save

Public keys have changed, so export and upload them (secret keys are kept unaltered!)

# all relevant exports
gpg --armor --export-secret-keys --export-options export-backup $KEYID > full_backup.asc
gpg --armor --export $KEYID > pubkey.asc
gpg --export $KEYID > pubkey.gpg

Note

When not under version control, it might be a good idea to give the exports a different name like

gpg --armor --export $KEYID > $KEYID-$(date +%F).asc

On each host import updated public key

# from keyserver
gpg [--keyserver hkps://keys.openpgp.org] --recv $KEYID
# or alternatively
gpg [--keyserver hkps://keys.openpgp.org] --refresh-keys
# or from file
gpg --import pubkey.asc

YubiKey

Setup

Important

You can safely enable KDF if you're planning to use the key on Android with OpenKeyChain.
See open-keychain/open-keychain#2368.

Confirm yubikey is genuine: https://www.yubico.com/genuine/

Prepare yubikey

gpg --card-edit
gpg/card> admin
gpg/card> kdf-setup
gpg/card> passwd

Transfer keys

gpg --edit-key $KEYID
gpg> key 1
gpg> keytocard
Your selection? 1

gpg> key 1
gpg> key 2
gpg> keytocard
Your selection? 2

gpg> key 2
gpg> key 3
gpg> keytocard
Your selection? 3

gpg> save
gpg> quit

Verify all subkeys start with ssb>

gpg -K

Add pubkey URL to yubikey

gpg --edit-card
gpg/card> admin
gpg/card> url # https://keys.openpgp.org/vks/v1/by-fingerprint/<fingerprint>
gpg/card> quit

Remove and reinsert yubikey, then check its status

gpg --card-status

Enforce touch for GPG operations

sudo pacman -S yubikey-manager
ykman openpgp keys set-touch aut on
ykman openpgp keys set-touch sig on
ykman openpgp keys set-touch enc on

New Host

Basically follow the "Using keys" section in Dr. Duh's guide.

Assuming the pubkey URL field has been set in the yubikey.

Fetch public key and deploy subkey references pointing to yubikey

gpg --edit-card
gpg/card> fetch
gpg: requesting key from '<URL>'
gpg: /home/pi/.gnupg/trustdb.gpg: trustdb created
gpg: key FF3E7D88647EBCDB: public key "Dr Duh <[email protected]>" imported
gpg: Total number processed: 1
gpg: imported: 1
gpg/card> quit

Otherwise download the public keys from a keyserver or local computer, import with

gpg --search [email protected]
gpg --import $KEYID

and then only run

gpg --card-status

to create the references.


Set trust level

export KEYID='<fingerprint>'
gpg --edit-key $KEYID
gpg> trust (5)
gpg> quit

Yubikey and GPG keys should now show these symbols in front of the secret keys:

gpg -K
gpg --card-status
sec# ed25519/0xAABBCCDDEEFF0011
ssb> ed25519/0xAABBCCDDEEFF0022
ssb> ed25519/0xAABBCCDDEEFF0033
ssb> cv25519/0xAABBCCDDEEFF0044

Unblock PIN

After 3 failed attempts yubikey gets blocked. Unblock with

# https://github.com/drduh/YubiKey-Guide/issues/168#issuecomment-1379532749
gpg --edit-card
admin
passwd # select "2 - unblock PIN" and enter admin PIN
gpg --card-status # verify "PIN retry counter" says again "3 0 3"

Android

For use with the Android Password Store:

  1. Install OpenKeyChain
  2. Remove Google Authenticator, it will block APS's NFC connection
  3. Generate SSH key in APS and add it as "deploy key" to the shared repo
  4. Add recipient to gopass
  5. Clone repo on phone and unlock secrets like a boss

SSH Agent

Setup

GPG can also act as SSH agent. To enable, add in ~/.gnupg/gpg-agent.conf

enable-ssh-support

and reload the agent

gpg-connect-agent reloadagent /bye

In zsh you might want to use this oh-my-zsh plugin for convenience. It takes care of properly starting the agent and exporting SSH_AUTH_SOCK.

Import SSH PrivKey

Tip

To understand the difference between GPG and SSH fingerprints, consult this great blogpost.

Native SSH keys created with e.g.

ssh-keygen -a 100 -t ed25519 -f ~/.ssh/customer/sshkey -C "<email>::<customer>::$(date +'%Y-%m-%d')"

are added to the agent via

# sets the cache lifetime to 3600s, use -c for always confirm
ssh-add -c -t 3600 ~/.ssh/id_rsa

This converts the SSH key irreversibly into GPG format and stores it separately from the original private key as

cat ~/.gnupg/private-keys-v1.d/<KEYGRIP>.key

The keygrip is basically the same protocol-agnostic ID as calculated for GPG keys with

gpg -K --with-keygrip

All enabled SSH keys are listed with their keygrip and selected hashes here:

cat ~/.gnupg/sshcontrol
-----------------------
# Ed25519 key added on: 2023-02-18 20:43:21
# Fingerprints:  MD5:31:7f:60:ca:e2:25:69:d7:cb:7b:7d:a1:fd:33:28:cc
#                SHA256:USoxG0ZJuMMwicxRhjgPpqGPzk5cNKA/0R7o0SOddrc
4F8C61F5B655A3F682A2FBB2ECC5B888F933E421 0 confirm
# Ed25519 key added on: 2023-11-09 20:36:07
# Fingerprints:  MD5:f8:21:2e:ad:14:35:63:74:49:34:a8:fd:bc:55:8b:8b
#                SHA256:uKzAVdF4S3yb5RNe10JbUCmmPdJmp1vf3F1YvTnqbZQ
F97B2173319631EC38520EE3E82780E9A24960B4 3600

These hashes (as in SSH fingerprints) can be manually obtained from the original SSH key with

ssh-keygen -E sha256 -lf <ssh-pubkey>
ssh-keygen -E md5 -lf <ssh-pubkey>

Removing an SSH key involves

  1. delete GPG-converted private key ~/.gnupg/private-keys-v1.d/<KEYGRIP>.key
  2. remove corresponding entry in ~/.gnupg/sshcontrol

Export SSH PubKey

In order to use an authentication-enabled GPG (sub)key for SSH, run either of these commands

ssh-add -L
gpg --export-ssh-key <ID>

This will output a public key in SSH format that can be added to ~/.ssh/authorized_keys on remote hosts.

Misc

GoPass

Make sure to add encryption subkey instead of primary and set

export $GOPASS_GPG_OPTS="--no-throw-keyids"

in your shell.

Git Subkeys

When working with subkeys for git commit signatures, add them with trailing exclamation mark to ~/.gitconfig, otherwise GPG will use the latest one with signing capability or resolve to primary.

Caution

Depending on the shell (e.g. for zsh) you need to escape the exclamation mark or use single quotes so it is not interpreted. See https://unix.stackexchange.com/a/234300.

# for zsh
git config user.signingkey "1F8375B06B86E11DB5707569FB9D7A2564F37DB4\!"
git config user.signingkey '1F8375B06B86E11DB5707569FB9D7A2564F37DB4!'

how2gpg's People

Contributors

pandascience avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.