PGP (Pretty Good Privacy) keys are not used by many, I think it is because they are difficult to grasp. During the years I have struggled too trying to understand them and these are the notes I took during this time. Hope they will give you an easier time than mine with this awesome keys!
Glossary
- SCEA
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Constant Character
───────────────────────────────
PUBKEY_USAGE_SIG S
PUBKEY_USAGE_CERT C
PUBKEY_USAGE_ENC E
PUBKEY_USAGE_AUTH A
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-
other symbols:
#
secret key not present>
stub present (probably on smart card)
-
extensions
gpg/pgp
might be used for binary filesasc
is generally used for armored files
-
info on the stored keys
gpg-connect-agent 'keyinfo --list' /bye
- meaning of the above informations
gpg-connect-agent 'help keyinfo' /bye
- meaning of the above informations
Create a key
We can either input every value interactively or prepare a text file and load that. We are gonna explore both the methods.
semi-automatic key creation
note: “Key-Lenght:
” has to be copied from the reference web page, else might not work, I think because of UTF-8.
- Edit this script to suit your needs and save it somewhere safe for execution (if writing the password on it)
%echo Generating a basic OpenPGP key
Key-Type: RSA
Key-Length: 4096
# specify usage if want to limit to Cert only
Key-Usage: cert
Subkey-Type: RSA
Subkey-Length: 4096
# specify usage if want limit the usage only to encryption
Subkey-Usage: encrypt
Name-Real: name
Name-Comment: comment
Name-Email: [email protected]
Expire-Date: 0
# If passphrase is commented out, it will prompt for password
#Passphrase: abc
# Do a commit here, so that we can later print "done" :-)
%commit
-
kill the agent if running
gpgconf --kill gpg-agent
-
generate the key by using the script
gpg --batch --full-generate-key <script>
-
Create other subkeys as needed on
--edit-keys
as detailed in the manual section of this guide. -
handy continued-generation from the GNUPGHOME (let’s say we don’t like the numbers)
rm -r ./* && gpgconf --kill gpg-agent && gpg -K && gpg --batch --full-generate-key ../script
or from a level above the .gnupg
directory
rm -r .gnupg && gpgconf --kill gpg-agent && mkdir .gnupg && chmod 700 .gnupg && gpg -K && gpg --batch --full-generate-key ../script
Interactive key creation (manual method)
-
create a directory in a safe place, ideally you would do it in a live and offline system, but also a tmpfs (ramdisk) could do it, just be sure not to save on an unencrypted directory and/or a compromised computer.
-
kill the agent if running, just in case as it might interfere
gpgcong --kill gpg-agent
-
set the GNUPGHOME in there with
export GNUPGHOME=/secure/path/.gnupg
-
generate the key
gpg --full-generate-key
-
enter edit mode to continue
gpg --edit-key <key>
- downgrade the SC (Sign + Certify) key into C only
change-usage
- add more than one uuid if needed (emails)
adduid
- create Sign and Encryption subkeys (RSA to have 4096)
addkey
- set the trust for your keys to Ultimate, after verifying that you is actually… you.
select the UID (an asterisk will appear)
uid <n>
and set the trust leveltrust
- downgrade the SC (Sign + Certify) key into C only
-
Authentication and other types of keys can also be created, but we need to be in expert mode
gpg --expert --edit-key <key>
- create a key
addkey
- set the capabilities
RSA (set your own capabilities)
- create a key
-
export the keys
- secret key
gpg --export-secret-keys <key> > <destination>.pgp
- secret subkey
gpg --export-secret-subkeys <subkey> > <destination>.pgp
- secret subkey striped (exclamation point after the key, it reduces the size of it and /stripes/ it from the private master key)
gpg --export-secret-subkeys <subkey>! > <destination>.pgp
- revocation certificate (automatic if no expiration, is a
.rev
file)gpg --armor --gen-revoke <key> > <destination>.rev
- export the public key in armored version
gpg --export --armor --output <name>.pub
- export the trust store (cleartext)
gpg --export-ownertrust > <destination>.asc
- export for print using the Dark Otter approach
sourced from https://unix.stackexchange.com/questions/481939/how-to-export-a-gpg-private-key-and-public-key-to-a-filegpg --output public.pgp --export SOMEKEYID && \ gpg --output - --export-secret-key SOMEKEYID |\ cat public.pgp - |\ gpg --armor --output keys.asc --symmetric --cipher-algo AES256
- secret key
-
ssh key handling to use the Auth subkey as ssh key. (more to explore on https://medium.com/@chrispisano/ssh-authentication-with-gpg-411676781647 )
- conversion from gpg format to ssh’s pub
gpg --export-ssh-key <subkey>! > .ssh/<ssh_key_name>.pub
- conversion from gpg format to ssh’s pub
-
Publish the keys
- verify the UID (emails) at https://keys.openpgp.org
- upload the keys to default keyserver (if any is set)
gpg --send-key <key>
- upload the keys in bunch to a list of keyservers using bash
for line in $(cat <list-file>); do gpg --keyserver $line --send-key <key>; done
my personal list:
http://pool.sks-keyservers.net https://pgp.mit.edu https://pgp.key-server.io https://pgp.surfnet.nl https://keyserver.ubuntu.com https://keys.openpgp.org
-
import the needed striped secret sub-keys into your devices and store the others in a safe, possibily offline and encrypted place. I would also suggest to store them in more than a place, just in case of a disaster. Without the Certification key, we cannot modify them and without the revocation key, revocate compromized ones.
Troubleshooting
- subkey does not delete
it is not possible to delete a key directly with gpg, we need to make use of the gpg-agent this way:# Obtain the keygrip of the subkey you want to delete. $ gpg --with-keygrip --list-secret-keys "$YOUR_FINGERRINT" # Ask gpg-agent to delete the key for you. # There should be a graphical confirmation prompt. $ gpg-connect-agent "delete_key $KEYGRIP" /bye
from: https://security.stackexchange.com/questions/207138/how-do-i-delete-secret-subkeys-correctly
- Key reports back:
gpg: agent_genkey failed: No such file or directory
in such case, just kill the agent and continuegpgconf --kill gpg-agent
example procedure to modify the keys
- mount/copy the safe backup with the secret keys somewhere safe, as in point 1 of the manual creation
- kill the gpg-agent if running
gpgconf --kill gpg-agent
- set the GNUPGHOME variable
export GNUPGHOME=/path/to/mount/.gnupg
list the secret keysgpg -K
- enter key editing (
--expert
for more options)gpg --edit-key
- export modified keys (see manual section)
- populate keyservers with modifications (see manual creation for details)
- populate applications that also make use of the pubkey, like Github and Gitlab.
- populate keybase with modifications by opening the app and using
keybase pgp update
seach keys and store keyserver for fast interrogation
example:
gpg --keyserver keyserver.ubuntu.com --search-keys <key>
to abbreviate the input, we can
create the file ~/.gnupg/dirmngr.conf
and add the keyserver used for checking
keyserver https://keyserver.ubuntu.com
might be necessary to run dirmngr
at least once and reload the agent if already running with gpgconf --reload dirmgr
then keys can now be searched with gpg --search-key <key>
and --search-keys <key>
Signatures on keys
Having our keys signed is very important on the Web Of Trust, people that know us and have good faith in our handling of the private keys, should assign us a reasonably high trust level, sign our pubkey and send it to us, so we can publish the upgraded key.
To sign a key, we need to have the Certification master key loaded, for this… I’d suggest the same procedure as in the manual creation for the creation of a safe environment.
Be aware that is good practive to not publish signed pubkeys but to let the owner publish them.
-
import the key by asking for the updated pubkey
- be sure to use a secure channel or to encrypt it with the Encryption key of our friend, this can be done by them with
gpg --encrypt </path/to/key.pub> --recipient <[email protected]> </path/to/key.pub.pgp>
or in one command (untested)gpg -a --export <key> | gpg -se -r <key> > >~/path/to/key>.asc.pgp
optimally, the email itself should be used during this process, so we can be totally sure they have access to it (and hopefully, they are not also the impostors) - decrypt the received pubkey
gpg --decrypt </path/to/key.asc.pgp>
- import the key `gpg –import friend.pub~
- be sure to use a secure channel or to encrypt it with the Encryption key of our friend, this can be done by them with
-
import by downloading the key from the keyservers
gpg --recv-keys <key>
or if using a non-default keyservergpg --keyserver <address.of.keyserver.ext> --recv-keys <key>
-
enter edit mode for the key
gpg --edit-key
- select the uid if we want to sign a single email or skip to select all
uid <n>
- sign only using
sign
- or sign better using trust levels
-
set the trust on the keyring (not sure, might not be necessary)
trust
-
sign with trust (there are other types on the documentation
tsign
-
we are prompted twice for the various levels of trust we have in this key, the first one defines how much we are sure about the identity of the key’s owner (2, we are sure about identity, 1 not totally sure), the second defines how much we are willing to go deep with the sign, any value above 1 means that we also trust keys that this person might sign. A key that has 3 marginal (1) signs is considered trusted during verifications if we also have the other 2 keys in our keyring. I highly suggest the D’Artagnan story to fully understand the various trust levels.
ideally, we should fully verify the identity (2) and assign a marginal level on trust (1) on the keys this person might sign, unless that person is another key of ours, in which case.. We might trust ourself, or not if it is a key dedicated to untrusty things, you know how you are gonna use it.
-
- signatures are revokable, unless
nrsign
ornrtsign
is used (non-revokable), which should really only be used with our personal keys or some legaly keys we want to sign because we are departing to afterlife. it can be done withrevsign
not sure about the implications, tho… but you know that you can, let’s say that person becomes untrusty or they have their keys compromised and are not able to revoke them for whatever reason.
- select the uid if we want to sign a single email or skip to select all
-
see if our signature has been successfully applied
gpg --list-signatures <key>
-
export the pubkey and send it to our friend in the same way, by encrypting it and sending it via a certified/secure channel.
troubleshooting
- during sign, this error pops up
gpg: no default secret key: No public key
it might be because we have a smartcard (Yubikey) inserted, which has keys associated with different key. Just remove it and try again.
Yubikey
initial setup
- install all the needed packages for reading the key (refer to your distro documentation for this, generally suffice to search and install all packages that have
yubi
orfido2
in the name, but we might also want to install only those relative to the smartcard operations) - change the PIN and Admin PIN
default pin is 123456, new PIN must be 6 digits
gpg --card-edit
passwd
default admin pin is 12345678, new PIN must be 8 charactersadmin
passwd
- assign informations on the card (admin mode)
name
lang
(i.e. en)login
(i.e. frayoshi)sex
(i.e. M)url
(where to retrieve the pub key - i.e. https://furayoshi.com/frayoshi-pgp.pub) - show added informations
gpg --card-status
add keys
note: keys are MOVED/linked, export the secret subkeys before hand as backup if you want to reuse it!
note2: exported subkey AFTER the move to the smartcard is DIFFERENT from the one before.
note3: public key file is hash identical with or without the key on the smartcard.
- enter edit mode
gpg --edit-key <key>
- select the subkey to MOVE/link
key <subkey ID>
- move to the yubi
keytocard
and then select the one we want to move if multiple options are given. - save and quit
save
- export the secret subkey with the stub indicating it is on a smartcard (
>
) and then import this on the main computer’s keyring. - import the key and then refresh the main computer’s keyring and tell it to look for the stubs on the card by using
gpg --card-status
- seem like the importing phase is not necessary, as
--card-status
does create the keygrips.
- seem like the importing phase is not necessary, as
backup or restore keys
note: there’s a bkuptocard
command I have not explored.
links to the keys are stored as keygrip files, which by default are located under
$HOME/.gnupg/private-keys-v1.d/
to restore the state from “link to smartcard” (>
) to “missing secret-key” (#)
we delete the keygrip relative to the key.
- find the keygrip
gpg --with-keygrip -k <key>
- locate and remove from the directory
- import the secret subkey (not on the smartcard)
gpg --import </path/to/secret-subkey.gpg>
- repeat the procedure to move the secretkeys to the smartcard.
usage
the gpg stub to the keys will always point to the one we moved it lastly. To force the repointing to the one which is connected now, we can make use of
gpg-connect-agent "scd serialno" "learn --force" /bye
NOTE: This will override secret keys we might have locally, which will need repointing and have no gone deeper into the argument.
It is recommended to create an alias for this command.
check integrations for existing app, included gnome-keyring https://wiki.archlinux.org/title/GNOME/Keyring#Integration_with_applications
Notes
sent to my acquaintance, The Doctor
-
various concepts: https://security.stackexchange.com/questions/104059/help-me-understand-the-relationship-between-gpg-public-keys-sub-keys-and-expira
-
subkeys: https://wiki.debian.org/Subkeys
-
Various types of keys: https://unix.stackexchange.com/questions/31996/how-are-the-gpg-usage-flags-defined-in-the-key-details-listing
-
revokation of keys: http://blog.chapagain.com.np/gpg-revoking-your-public-key-and-notifiying-key-server/
-
explanation of why we should not create multiple encryption keys (which I have done and later revokated, autch): https://security.stackexchange.com/questions/186649/gpg-masterkey-and-subkey-for-encryption-and-signature-and-default-keys
-
github, commits signing: https://help.github.com/en/articles/signing-commits
more notes
anatomy of a GPG key
https://davesteele.github.io/gpg/2014/09/20/anatomy-of-a-gpg-key/
keys creation
- https://www.redhat.com/sysadmin/creating-gpg-keypairs
- https://help.ubuntu.com/community/GnuPrivacyGuardHowto
Sign of keys
- Description: https://security.stackexchange.com/questions/14479/what-does-key-signing-mean
- procedure: https://gist.github.com/F21/b0e8c62c49dfab267ff1d0c6af39ab84
- signature types https://gnupg.org/documentation/manuals/gnupg-2.0/OpenPGP-Key-Management.html#:~:text=nrsign,the%20%22trust%22%20command ).
Note that “l” (for local / non-exportable), “nr” (for non-revocable, and “t” (for trust) may be freely mixed and prefixed to “sign” to create a signature of any type desired.
revoke signs:
https://www.ias.edu/security/how-revoke-gnupgpgp-signature-key
Good argument on RSA vs DSA
https://security.stackexchange.com/questions/5096/rsa-vs-dsa-for-ssh-authentication-keys
Export subkey striped and create a dedicated password for it
https://superuser.com/questions/879977/how-to-have-a-different-pass-phrase-for-a-gpg-subkey
semi-complete guide
https://s0cm0nkey.gitbook.io/s0cm0nkeys-security-reference-guide/grey-privacy-tor-opsec/pgp-guide
Generate key from script
https://www.gnupg.org/documentation/manuals/gnupg/Unattended-GPG-key-generation.html
Trust levels
- easy https://security.stackexchange.com/questions/69062/what-is-the-difference-between-full-and-ultimate-trust
- deeper https://gpgtools.tenderapp.com/kb/faq/what-is-ownertrust-trust-levels-explained#:~:text=Ultimate%3A%20is%20only%20used%20for,ownertrust%20of%20the%20signed%20key.
- for signs (tsign) https://security.stackexchange.com/questions/235345/validity-owner-trust-trust-signatures-certification-level
- more trust with diagrams and the story of King Arthur and D’Artagnan https://www.linux.com/news/pgp-web-trust-delegated-trust-and-keyservers/
D’Artagnan was the captain of the King’s musketeers, reporting directly to his commander, M. De Tréville, who in turn reported directly to King Louis XIII. In the book, the queen-escort Anne d’Autriche and her lover the Duke of Buckingham run the risk of getting exposed due to Cardinal Richelieu’s plotting. In desperation, Anne turns to her trusted courtisane, Constance Bonacieux, asking her to find someone she trusts for a quick trip to England. Cardinal Richelieu finds that out and tasks his henchman, Comte de Rochefort, to make sure the queen’s desperate plot fails.
[…]
level 1: “you can trust this key I’ve signed as much as mine, but that’s as far as I’m willing to vouch“ level 2: “you can trust this key I’ve signed as much as mine, plus any other key this person trust-signs, if you are so inclined”
In cryptographic parlance, trust-signing a key with “level 1” designates that person as a “Trusted Introducer.” Trust-signing a key with “level 2” designates that person as a “Meta-introducer”.
SSH
GPG card (yubikey)
- guides:
- main https://developer.okta.com/blog/2021/07/07/developers-guide-to-gpg
- another guide, different info https://blog.josefsson.org/2014/06/23/offline-gnupg-master-key-and-subkeys-on-yubikey-neo-smartcard/
- A LOT lot of informations, specifically for SSH + the force reload of the stub https://github.com/drduh/YubiKey-Guide
- another one, technical with scripts and conversations https://gist.github.com/ageis/14adc308087859e199912b4c79c4aa4a
- remove the keygrip to the smart-card reader https://gnupg-users.gnupg.narkive.com/gSBmiYJu/deleting-a-smart-card-secret-key-stub-from-the-secret-keyring