dotfiles/notes/linux/gnupg.md
2023-12-23 20:13:52 -07:00

6.3 KiB

GnuPG

Key files are a secure method for certifying credentials digitally. Everything is stored in ~/.gnupg and controlled through gpg. It's quite complicated... See tldr gpg for encryption, devhints for a cheat sheet, the Archwiki for a technical explanation and the Debian wiki for a newbie-friendly one

Terminology:

  • Public key - The one to share
  • Private key - The one to not share
  • Primary key - ??
  • Subkey - ??
  • Keygrip - The name of the key file
  • Key ID - The last few (8-16) characters of a fingerprint
  • Fingerprint - A unique identifier for a key
  • Keyring - Your entire collection of public or private keys
  • User ID - Email, part of name, Key ID, or Fingerprint of a key

Consider this example output:

 $ gpg --list-secret-keys --with-subkey-fingerprint --with-keygrip --keyid-format=long

# ///--- Short for "secret key". It's "pub" for public keys
# vvv           vvvvvvvvvvvvvvvv Key ID
> sec   ed25519/ABCDEFG123456789 4040-04-04 [SC] [expires: 4040-04-04]
>       DDEEDF222222222222222222ABCDEFG123456789
#                               ^^^^^^^^^^^^^^^^ Key ID also here
#       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Fingerprint
>       Keygrip = DDEBBA3482394AEE23432DEE32432BB2432432EE
# Key is ~/.gnupg/private-keys-v1.d/DDEBBA3482394AEE23432DEE32432BB2432432EE.key
> uid                 [ultimate] Emiliko Mirror <emiliko@mami2.moe>
# ///--- Short for "secret subkey". It's "sub" for public subkeys
# vvv           vvvvvvvvvvvvvvvv Key ID
> ssb   cv25519/987654321ABCDEED 4040-04-04 [E] [expires: 4040-04-04]
>       32423BDDAAAAAAAAAAAAAAAA987654321ABCDEED
#                               ^^^^^^^^^^^^^^^^ Key ID also here
#       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Fingerprint from --with-subkey-fingerprint
>       Keygrip = 2493ADDEDDDFEFEFE23432432FDEEFDD24324232
# Key is ~/.gnupg/private-keys-v1.d/2493ADDEDDDFEFEFE23432432FDEEFDD24324232.key

Providing the --fingerprint flag will alter the output slightly, tho it's the same fingerprint, for example:

> sec   ed25519/ABCDEFG123456789 4040-04-04 [SC] [expires: 4040-04-04]
>       Key fingerprint = DDEE DF22 2222 2222 2222  2222 ABCD EFG1 2345 6789
#                                     Key ID is now here ^^^^^^^^^^^^^^^^^^^
>       Keygrip = DDEBBA3482394AEE23432DEE32432BB2432432EE
> uid                 [ultimate] Emiliko Mirror <emiliko@mami2.moe>
> ssb   cv25519/987654321ABCDEED 4040-04-04 [E] [expires: 4040-04-04]
>       Key fingerprint = 3242 3BDD AAAA AAAA AAAA  AAAA 9876 5432 1ABC DEED
#                                     Key ID is now here ^^^^^^^^^^^^^^^^^^^
>       Keygrip = 2493ADDEDDDFEFEFE23432432FDEEFDD24324232

Creating a new key

This closely follows the Archwiki, with an elliptic cipher

gpg --full-gen-key --expert
 > (9) ECC and ECC
 > (1) Curve 25519
 > 1y  # Optional, 1 year is recommended
 > Your Name          # This will be visible in the public key
 > emiliko@mami2.moe  # This is also visible in the public key
 > No comment
 > Put a password on the primary key

Signing and verification

Git commits, binaries and really any file can be signed by a private key to prove authenticity of the file. For github, you'll need to paste your public key to your profile settings

gpg --list-secret-keys --keyid-format=long
gpg --armor --export <user-id> | wl-copy

Git commits aren't signed by default. Either explicitly sign at commit time, with git commit -S, or add the following to your ~/.gitconfig. If the signing key you specify is a subkey, add an ! mark at the end

[user]
name = Emiliko Mirror
email = emiliko@mami2.moe
signingkey = ABCDEF1234567890
[commit]
gpgsign = true

Encryption

Gpg can encrypt pretty much anything. Consider bundling into a tarball beforehand if it's more than one file

The -a/--armor flag will make sure the encrypted file is made up entirely of ascii characters, which is easier to copy/paste than binary nonsense

Encryption can be symmetric or asymmetric. Symmetric encryption uses 1 key and a password to encrypt. To decrypt, use the same key and re-enter the same password

Symmetric encryption

Symmetric encryption uses 1 key and 1 password to encrypt. To decrypt, you'll need the same key and the same password

Asymmetric encryption

Asymmetric encryption is meant for sending to a specific receiver. It uses 1 public key to encrypt. To decrypt, you'll need the private key pair to that public key. pass uses this one

gpg -e -o encrypted_file -r emiliko@mami2.moe secret_file
# Then emiliko can decrypt it with her private key
gpg -d -o secret_file encrypted_file

Moving keys

You'll want to export your keys to other devices. Ideally, you'd only export subkeys and not the primary key. The primary key should be stored offline and used to generate revocation certificates for compromised subkeys

gpg -o pub_key.pgp -a --export emiliko@mami2.moe
gpg -o sec_key.pgp -a --export-secret-key emiliko@mami2.moe

scp pub_key.gpg emiliko@192.168.0.1:/tmp/safe_directory
scp sec_key.gpg emiliko@192.168.0.1:/tmp/safe_directory

gpg --import pub_key.gpg
gpg --import sec_key.gpg

A safer method skips the creation of any intermediary files by sending it through ssh right away

gpg --export-secret-key <user-id> | ssh emiliko@192.168.0.1 'gpg --import'
# Or if you're on the receiving system
ssh emiliko@192.168.0.1 'gpg --export-secret-key emiliko@mami2.moe' | gpg --import

In either case, or actually whenever importing your keys, you'll need to edit the trust level after importing it

gpg --list-keys  # Get the Key ID here
gpg --edit-key <user-id>
> trust
> 5 # If it's your own key
> y
> quit

For use with pass, you can check if your encryption key is working by trying to add a new password, like pass insert -e something and see if it succeeds

Backing up keys

Keys should be backed up on offline, physically inaccessible, media. Usb sticks you leave at home or a piece of paper are both good choices. For the paper version see paperkey

gpg -o /run/media/my_usb/keys.gpg --export-options backup --export-secret-keys emiliko@mami2.moe

Now later, or on another device, you can restore these keys

gpg --import-options restore --import keys.gpg

Then edit the trust level, as with the other transfer methods