# OpenPGP Workshop

[important reference](img/iceberg.png)

---

## What is OpenPGP

* OpenPGP is an open standard for encrypting and decrypting data, as well as
creating and managing digital signatures.

* It is based on the PGP (Pretty Good Privacy) protocol, which was originally
developed by Phil Zimmermann in the 1990s.

* Uses asymmetric / public key cryptography

<!--
What are some useful ways we can use OpenPGP:
    * Email encryption and signing
    * Signing git commits
    * SSH
    * Password management
-->

---

## Implementations

* GPG
    * Gnu Privacy Guard
    * Best known and most widely used
    * Great starting point

* There are lots of other implementations of OpenPGP:
    * https://www.openpgp.org/software/developer/

---

## How Does It Work?

---

## Encrypt / Decrypt

![Encryption vs Decryption diagram](img/encrypt-decrypt.png)

---

## Sign / Verify

![Signing vs Verifying diagram](img/sign-verify.png)

---

## Diffie Helman Key Exchange

![Diffie Helman Key Exchange diagram](img/diffie-helman.png)

---

## OpenPGP Anatomy

* Many components but key ones are:
    * Public Key
    * Private Key

---

## Let's Try It!

* Most OS come with GPG pre-installed (not Windows!)

* `gpg --version`
* `man gpg`
* **THESE FOLLOWING KEYS WILL NOT BE SECURE, DO NOT USE THEM FOR ANYTHING OTHER THAN THIS EXERCISE!**
* Generate keypair: `gpg --expert --full-gen-key`
    * 1, 4096, Enter (3072), Enter (0), y, "Test Key", <your_email>, Enter (""), O, "password1"
    * Use a unique email otherwise you will have issues with the exercise that follows
    * During generation, **mash input devices for added entropy**

---

## Test Your GPG Key

* `gpg --list-keys`
* `echo "super secret text" > test.txt && cat test.txt`
* `gpg --encrypt --recipient <email/ID> test.txt`
	* `gpg -er <email/ID> <filename> && cat test.txt.gpg`: notice it's a binary
	    * You can use `--armor/-a` to encode it as ASCII so you can send the encrypted data as text
* `gpg --armor -er <email/ID> test.txt && cat test.txt.asc`
* `rm test.txt && ls`
* `gpg --decrypt test.txt.gpg > test.txt`
* `gpg --decrypt test.txt.asc > test.txt`

---

## Sharing Your Public Key 🔑

* `gpg --list-keys`
* `gpg --export --armor <email/ID> > <name>.asc`
* `gpg --import <name>.asc`

* Task: pair up and exchange your keys, encrypt data to each other, then decrypt the message so you can tell your partner the contents of the message
    * Tip: you may encrypt the data to multiple people

---

## Verifying Signatures 📝

* Go to: https://www.qubes-os.org/downloads/
* Download:
    * Qubes-R*.iso
    * Cryptographic hash values
    	* `gpg --verify --default-key <key> <filename>`
    * Detached PGP signature
    * Qubes release signing key

* They have a guide that's worth reading: https://www.qubes-os.org/security/verifying-signatures/
* Task: verify the signatures for the software are valid

---

## Solution

* `gpg --import qubes-release-*`: import qubes signing key
* `gpg --verify *.DIGESTS`: verify signature
* `sha256sum -c Qubes-<...>.iso.DIGESTS`: verify hashes match

---

## Secure Key Management 🔒

* You should assume your computer is compromised

* How do we protect the GPG private key?

    * Never expose them to an untrusted environment

---

## Basic: On-board generation:
* YubiKey offers generating keys inside of the YubiKey
* Cryptographic attestation keys were never exposed available: https://developers.yubico.com/PGP/Attestation.html
* CON: can't back up the keys
* PRO: simple setup

---
## Advanced - cold / virtualization

* Can use `gpg` / `sq` / `keyfork` to derive

* Key is to derive keys in a secure environment:
    * Airgapped system (preferred)
        * [AirgapOS](https://git.distrust.co/public/airgap): A full-source-bootstrapped, deterministic, minimal, immutable, and offline, workstation linux distribution designed for creating and managing secrets offline.
    * Virtual machine on a hypervisor via hardware virtualization (ok for some threat models)

* [Hashbang GPG Guide](https://book.hashbang.sh/docs/security/key-management/gnupg/): helpful guide for GPG - good resource for beginners who want to do the advanced setup

* [openpgp-card-tools](https://codeberg.org/openpgp-card/openpgp-card-tools): great for loading keys onto smart cards
    * Can use a variety of smart cards: NitroKey3, SoloKey, Yubikey
        * NitroKey and SoloKey are fully open which is great for verifiability - may requires flashing firmware

* [Quorum Key Management](https://docs.distrust.co/qkm/)

---

## Backup Trick 🧙

* Generate long lived keys

* Load them onto smart card

* Take plaintext key data and put it in a dir

* Encrypt the dir to your public key

* Delete keys so that only ones that remain are on smart cards (recommended to have at least 2 or 3, for redundancy)

* Smart cards have a "brick" after x attempts feature

---

## SSH Usage

* OpenPGP keys can be used for SSH as well 🪄:
    * `gpg --export-ssh-key <email/keyID>`

* Set up shell to use smart card for ssh:
    ```
    # always use smart card for ssh
    unset SSH_AGENT_PID
    if [ "${gnupg_SSH_AUTH_SOCK_by:-0}" -ne $$ ]; then
        export SSH_AUTH_SOCK="$(gpgconf --list-dirs agent-ssh-socket)"
    fi
    ```
---

## Git Usage

* You can sign commits using OpenPGP / GPG

    ```~/.bashrc
    GPG_TTY=$(tty)
    export GPG_TTY
    ```

    ```~/.gitconfig
    [user]
        email = <email>
        name = <name>
        signingKey = <key_id>
    [commit]
        gpgSign = true
    [merge]
        gpgSign = true
    [gpg]
        program = gpg
    ```

---

## Further Studies

* [keyoxide](https://keyoxide.org/): decentralized tool to create and verify decentralized online identities

* [pass](https://www.passwordstore.org/): Unix based `gpg` password manager

* [OpenPGP for application developers](https://openpgp.dev/book/): Deep dive on OpenPGP

* [Sequoia](https://sequoia-pgp.org/): alternate OpenPGP implementation in rust

* [openpgp-card](https://codeberg.org/openpgp-card)
    * [openpgp-card-tools](https://codeberg.org/openpgp-card/openpgp-card-tools)
    * [ssh-agent](https://codeberg.org/openpgp-card/ssh-agent)

---

# Cleanup

* `gpg --delete-secret-and-public-keys <key_id>`
