From 24b361f76f1fdc488ab0784ef50d1346e9a3c018 Mon Sep 17 00:00:00 2001 From: tototo31 Date: Wed, 24 Jun 2026 22:01:44 +0000 Subject: [PATCH] Add You Wouldn't Download A (Private) Key --- ...Wouldn%27t-Download-A-%28Private%29-Key.md | 510 ++++++++++++++++++ 1 file changed, 510 insertions(+) create mode 100644 You-Wouldn%27t-Download-A-%28Private%29-Key.md diff --git a/You-Wouldn%27t-Download-A-%28Private%29-Key.md b/You-Wouldn%27t-Download-A-%28Private%29-Key.md new file mode 100644 index 0000000..706a27e --- /dev/null +++ b/You-Wouldn%27t-Download-A-%28Private%29-Key.md @@ -0,0 +1,510 @@ +Written by: Tototo31 + +You're just putting the final touches on your announcement to the world. Sipping your warm tea and winding down for the evening while you catch up on the latest happening on your favorite forums. + +The feds are at the door. Next thing you know, what you used to call your door is now simply splinters on the floor. You just finished signing your message to the world so that everyone knows it came from you. You upload your announcement to your blog, pull your PGP card, and dip. Computer's burned. Location's burned. Keys Secure. Man, what poor timing for unwanted visitors. + +Extreme scenario? Maybe. But whether you're protecting a pseudonymous identity, signing software releases, or simply reducing your attack surface, isolating cryptographic keys in hardware dramatically changes the risk a compromised workstation can pose to you. + +--- +# Background +A PGP card is a physical hardware device used to store the private keys of a PGP key pair. This enables you to gate your encryption, authentication, and signing operations behind physical access to a token as opposed to logical file-based access. + +Traditional software-based PGP keys are typically stored somewhere on disk. Malware, unauthorized file system access, or accidental backup exposure can result in complete private key compromise. + +PGP cards mitigate these risks by keeping private keys inside tamper resistant hardware. The host computer never directly accesses the private key material; instead cryptographic operations are performed on the card itself and only the resulting signatures or decrypted plain-text are returned. + +These physical tokens run applets that mediate access to private key operations. As a result, interacting with them requires several software layers and can take a little more effort to configure than traditional file-based keys. This is the case regardless of interface. Some smart cards have USB, some NFC, some use contact pads on the physical card they are all abstracted to GnuPG through pcscd and appear effectively the same. + +PGP cards have slots for 3 private keys. One for signing, one for encrypting, and one for authentication. Sometimes Yubikeys can have an extra 4th slot. + +The standard hardware for OpenPGP consists of: + - A pgp compatible smart card. This is where private keys will be physically stored. Yubikeys are a great off the shelf solution. + - PC/SC compatible card reader. This is important because PC/SC is the common api to talk to our smart cards. This abstraction means GnuPG does not need to know whether you're using a USB Yubikey, NFC implant, or contact smart card; they all appear through the same interface. + - A PC. + +The main software components of this setup are pcscd and GnuPG. +- pcscd is the interface that GnuPG uses to interface with smart cards. PGP cards(including yubikeys) are a type of smart card so we have to set up the PC/SC interface regardless of reader or smart card interface. +- GnuPG(GNU privacy guard) is the GNU implementation of open PGP. Its the primary OpenPGP implementation used on the Linux platform and facilitates access. + +The general physical access stack is: +`Smart Card -> PC/SC card reader -> PC with PCSC drivers + +When you send a card command from GnuPG the data goes: +`gnupg console -> gnupg sub-components -> pcscd -> PC/SC card reader connected to PC -> Smart card` + +Now with a little background you should be ready to start installing software. This tutorial has been tested on Debian 13, PopOS 24, and RaspberryPiOS Trixie + +--- +# Setup + Install: pcscd +pcscd is the typical way for Linux utilities to interact with smart cards. GPG packages its own smart card interface but for simplicity sake in future smart card endeavors I'm setting it up like this. + +Install the daemon + tools: +```bash +sudo apt install pcsc-tools pcscd +``` + +Ensure the daemon has started: +```bash +sudo systemctl enable --now pcscd +``` + +Validate everything is setup and installed properly: +```bash +pcsc_scan +``` + +If you see errors check out the troubleshooting section below, otherwise you are now ready to proceed to setting up GnuPG! +## Troubleshooting pcsc_scan Errors +If you get an error such as the following you may need to add a new polkit rule: +```bash +$ pcsc_scan +PC/SC device scanner +V 1.7.3 (c) 2001-2024, Ludovic Rousseau +SCardEstablishContext: Access denied. +``` + +Create this file: `/usr/share/polkit-1/rules.d/03-polkit-pcscd.rules` with the following contents (be sure to edit the username): +``` +polkit.addRule(function(action, subject) { + if (action.id == "org.debian.pcsc-lite.access_pcsc" && + subject.user == "YOUR_USERNAME") { + return polkit.Result.YES; + } +}); + +polkit.addRule(function(action, subject) { + if (action.id == "org.debian.pcsc-lite.access_card" && + subject.user == "YOUR_USERNAME") { + return polkit.Result.YES; } +}); +``` +If you wanted to allow a group access you could replace `subject.user == "YOUR_USERNAME"` with `subject.isInGroup("SMARTCARD_USERS_GROUP")` depending on your end goal for this setup. + +This rule instructs polkit to evaluate both the requested action and the user making the request. If the attempted action matches one of the specified PC/SC actions and the request originates from the configured user, polkit returns `YES`, and authorizes access without additional authentication. + +`org.debian.pcsc-lite.access_pcsc` governs access to the PC/SC daemon itself, while `org.debian.pcsc-lite.access_card` controls access to connected smart cards. GnuPG, `pcsc_scan`, and other smart card utilities require authorization for these actions in order to interact with readers and cards through `pcscd`. + +Validate functionality now: +``` +pcsc_scan +``` + +The error should no longer pop up, and you should see your card reader recognized. If you connect/disconnect a card you should also see that pop up in this utility. +You are now ready to proceed to setting up gnupg. + +--- +# Setup + Install: GnuPG +GnuPG relies on scdaemon for smart card access alongside pcscd in our use case. This is why we'll need to de-conflict drivers in the next step. +```bash +sudo apt install gnupg scdaemon +``` + +Both `pcscd` and GnuPG's `scdaemon` are capable of talking directly to smart cards. If both attempt to control the reader simultaneously, GnuPG may fail to detect the card even though `pcsc_scan` succeeds. + +To avoid this conflict, instruct `scdaemon` to defer hardware access to `pcscd`: +```bash +echo "disable-ccid" >> ~/.gnupg/scdaemon.conf +``` + +restart affected sub-components: +```bash +gpgconf --kill scdaemon +gpgconf --kill gpg-agent +``` + +Plug in your card and verify it is recognized: +```bash +gpg --card-status +``` + +--- +# PGP Card OPSec +Before we begin setting up the card itself it's important to understand the consequences that improperly securing or failing to build redundancy into your key infrastructure can pose.The next sections step through some important considerations to make before committing fully to this solution. +## Master Keys +OpenPGP supports a hierarchy of keys. The Master Key acts as the root +of trust and is primarily used to certify subkeys and identities. + +The Master Key should *ideally* never touch an internet-connected system after initial generation. + +It is best practice to keep the Master Key offline. It should be stored on encrypted +removable media or in cold storage. Only dedicated subkeys should be loaded onto +the hardware token: + +- `[S]` Signing subkey +- `[E]` Encryption subkey +- `[A]` Authentication subkey + +This limits the impact of hardware loss. If a token is lost, +the offline Master Key can revoke compromised subkeys and issue +replacements **without** rebuilding your entire identity infrastructure. + +## Backups +Hardware tokens fail, are lost, or become damaged. Before relying on a +PGP card operationally, establish a recovery plan. + +Recommended practices include: + +- Store an offline copy of the Master Key on encrypted removable media. +- Create and securely archive a revocation certificate. +- Maintain at least one spare hardware token populated with identical +subkeys. +- Store backups in geographically separate locations. + +A hardware token should never be your only copy of critical +cryptographic material. + +--- +# PGP Card Setup +Now its finally time to set up the PGP card, and load up certs. If all you have is a blank Java card or flex secure implant, or want to make your own check out the section at the end on setting them up! + +Before we begin lets validate our card is still seen by running: +```bash +gpg --card-status +``` + + +If you see your card and everything looks as expected lets go on to actually edit the card: +```bash +gpg --edit-card +``` +For simplicity, **this guide demonstrates generating keys directly on the card**. This is suitable for many personal use cases. However, users seeking the strongest operational security should generate their Master Key offline, create dedicated subkeys, and transfer only those subkeys to the hardware token. + +In the GPG Card prompt run the commands: +`list` <- Will list the current keys on the card +`admin` <- Will enable admin commands on the card +`generate` <- Will generate new keys and put them on the card + +If you are asked for your pin the default user pin is `123456` and the default admin pin is `12345678`. I would highly recommend changing these once the rest of your configuration has completed. + +Follow the prompts. Optionally set additional card details for login, cardholder name, and public key URL if you have it hosted somewhere. + +`login` -> configure the username associated with these keys +`name` -> configure the name of the card holder +`url` -> configure the URL where the public key can be downloaded + +If you get any weird errors double check your environment is configured according to this guide. Alternatively it is never a bad idea to disconnect/reconnect your PGP card. Also be aware you'll also run into issues if there isn't enough free space on your smart card for your keys. + +Now that you have your keys its time to learn how to use them. + +--- +# PGP Card Usage +Now that we have a configured PGP card lets do some tests with it. Here are some things we can do with our newly configured key. + +## How to export your public key +Public keys being public is half the equation for asymmetric encryption so getting them in an easily shareable format is extremely helpful. + +If you want to share your public key with someone you'd export your public key like this: +```bash +gpg --armor --export > pubkey.asc +``` + +If you want to import another users public key so you can verify or encrypt for them import their key by running: +```bash +gpg --import pubkey.asc +``` + +## How to Encrypt and Decrypt a File +Now comes the actual encrypting. This is the good part. + +To encrypt a file: +```bash +gpg --output .gpg --encrypt --recipient "" +``` +>The recipient field should be your own key if you're encrypting something only for yourself, or it should be the key of your recipient + +Now to decrypt the encrypted file we just created. Assuming we used own own key as the recipient we should be able to decrypt the file. +```bash +gpg --output secret-file.txt --decrypt secret-file.txt.gpg +``` + +## Clear Sign data + +Signing data allows us to prove both the authenticity and integrity of a message. If the message is modified after signing, signature verification will fail. + +One of the simplest signing methods is *clear signing*. A clear-signed message remains completely human-readable while embedding a cryptographic signature alongside the contents. + +This works really well for: + +- Emails +- Forum posts +- Security advisories +- Public announcements +- Text documents intended to be read directly + +To clear-sign a message directly from standard input: + +```bash +echo "Super important message here" | gpg --clear-sign > output.txt +``` + +This also works for an existing text file: +```bash +gpg --clear-sign [file] +``` + +The resulting file will contain both the original message and an ASCII armored signature block similar to the following: +``` +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +Super important message here + +-----BEGIN PGP SIGNATURE----- +... +-----END PGP SIGNATURE----- +``` + +This will allow us to sign our super important message to prove it came from whoever holds access to the private key while keeping the contents of the message completely readable by any party interested. +## Sign Data +Sometimes we want to preserve the original file exactly as it exists while still providing proof of authenticity. Detached signatures solve this problem by generating a separate signature file rather than modifying the original data. This approach is commonly used for: +- Software releases +- ISO images +- Package repositories +- Source code archives +- Backups + +To create a detached signature for a file: +```bash +gpg --detach-sign [file] +``` + +This produces a new file named: +``` +[file].sig +``` + +The original file remains unchanged. + +For example: +```bash +gpg --detach-sign example.iso +``` + +Produces: +``` +example.iso +example.iso.sig +``` + +Now you'll distribute these two files along side each other. + +## Verify Signed Data +Verifying signatures is just as important as creating them.Whether downloading software, validating a public statement, or confirming the authenticity of a document, signature verification allows us to confirm both who produced the file and whether it has been altered.To verify a clear-signed document: +```bash +gpg --verify signed-document.txt +``` +`` +To verify a detached signature: +```bash +gpg --verify example.iso.sig example.iso +``` + +A successful verification will produce output similar to: +``` +gpg: Signature made Thu 18 Jun 2026 using RSA key ... +gpg: Good signature from "Alice Example " +``` + +If the file has been modified in any way after signing, verification will fail and GnuPG will warn the user. + +Remember that a "Good signature" only confirms that the file was signed by the holder of the corresponding private key. You must still verify that you trust the public key used. for verification. +## Sign git Commits +Who doesn't want to be signing their git commits to affirm their authenticity? With all the supply chain attacks we see having a layer of assurance the commits your committing actually come from who they say they are. + +First you'll need to identify the key you want to use as the signing key in git. Do this by running: +```bash +gpg --list-public-keys +``` + +Next you'll export the public-key block for your git provider profile. Copy and paste the output of this command into your designated user profile in your git provider of choice. +``` +gpg --armor --export +``` + +Now well go back to setting up git. Set the signing key to the fingerprint used in the last command: +```bash +git config --global user.signingkey ! +``` + +If you want to make sure every commit you produce moving forward is signed set the following git config option: +```bash +git config --global commit.gpgsign true +``` + +Now finally to manually sign a commit: +```bash + git commit -a -S -m 'This is signed see the -S?' +``` + +--- +# Bonus: Making your own NFC Enabled PGP Cards +This is where my exploration into PGP cards initially began so I thought it would be a shame not to include it. If you don't have a compatible security key, or simply want to learn how these keys work at a lower level here's a basic tutorial for installing the SmartPGP Java card applet onto a java card to enable PGP card functions. +## Needed tools: +- A javacard + - J3R180 is a good one + - Flex Secure is also a great one if you want something implantable +- Acr1552 smart card reader - acr122u should also work + - Should expose a PCSC compatible interface like CCID + - You can also use a contact based reader if your card supports it. +- A working PGP setup as configured in the previous sections +## Blacklist NFC drivers if needed +Due to contactless readers occasionally also exposing a different interface to interact with the reader that is incompatible with smart card usage its recommended that you blacklist the systems default NFC Drivers + +To do so in your current runtime run the following commands: +```bash +sudo modprobe -r pn533_usb +sudo modprobe -r pn533 +sudo modprobe -r nfc +``` + +To make the change permanent introduce a modprobe config to blacklist the related kernel modules: +```bash +sudo touch /etc/modprobe.d/blacklist-nfc.conf +echo "blacklist nfc" | sudo tee -a /etc/modprobe.d/blacklist-libnfc.conf > /dev/null +echo "blacklist pn533" | sudo tee -a /etc/modprobe.d/blacklist-libnfc.conf > /dev/null +echo "blacklist pn533_usb" | sudo tee -a /etc/modprobe.d/blacklist-libnfc.conf > /dev/null +``` +## Download global platform pro +The tool global platform pro is the main interface for the java card. This allows us to manage applications on the smart card. We'll step through installing the open PGP applet which allows your java card to interact with the openpgp card standard. + +Global platform pro is java based so you'll need to install a compatible JRE: +```bash +sudo apt install default-jre +``` + +Next go ahead and download Global Platform Pro from their website: +https://javacard.pro/globalplatform/ + +Now run the application to test if you get valid output: +```bash +java -jar gp.jar -l +``` + +With a card connected this is what a successful read looks like: +``` +# Warning: no keys given, defaulting to 404142434445464748494A4B4C4D4E4F +ISD: A000000151000000 (OP_READY) + Parent: A000000151000000 + From: A0000001515350 + Privs: SecurityDomain, CardLock, CardTerminate, CardReset, CVMManagement, TrustedPath, AuthorizedManagement, TokenVerification, GlobalDelete, GlobalLock, GlobalRegistry, FinalApplication, ReceiptGeneration + +APP: F276A288BCFBA69D34F31001 (SELECTABLE) + Parent: A000000151000000 + From: F276A288BCFBA69D34F310 + +APP: D276000124010304AFAF000000000000 (SELECTABLE) + Parent: A000000151000000 + From: D27600012401 + +PKG: A0000001515350 (LOADED) + Parent: A000000151000000 + Version: 255.255 + Applet: A000000151535041 + +PKG: A00000016443446F634C697465 (LOADED) + Parent: A000000151000000 + Version: 1.0 + Applet: A00000016443446F634C69746501 + +PKG: A0000000620204 (LOADED) + Parent: A000000151000000 + Version: 1.0 + +PKG: A0000000620202 (LOADED) + Parent: A000000151000000 + Version: 1.3 + +PKG: F276A288BCFBA69D34F310 (LOADED) + Parent: A000000151000000 + Version: 1.0 + Applet: F276A288BCFBA69D34F31001 + +PKG: D27600012401 (LOADED) + Parent: A000000151000000 + Version: 1.0 + Applet: D276000124010304AFAF000000000000 +``` + +If you receive any errors despite having a valid smart card daemon setup try disconnecting and reconnecting the card. If you're experiencing key issues authenticating to your card then you may have different keys than default in which case you will need to supply them. + +## Install the applet: +Now that global platform pro is setup we can use it to install the application onto our java card. + +Go ahead and grab the latest release of the smart PGP applet from Github: +https://github.com/github-af/SmartPGP + +Once you have extracted the .zip archive and decided which .cap file you want to install its time to construct the command to install the applet: +```bash +java -jar gp.jar --install ~/Downloads/SmartPGP-v1.23.0-javacard-3.0.4/SmartPGP-v1.23.0-javacard-3.0.4/SmartPGPApplet-rsa_up_to_2048.cap +``` +>Your command will look very similar to mine but be sure to change the file path to point to your .cap file + +Once the command finishes you should be able to use it with all the commands listed in this articles previous sections. + +--- +# Troubleshooting: + +## `pcsc_scan` reports "Access denied" + +Review the PolicyKit rules described earlier in this guide. + +## Card appears in `pcsc_scan` but not `gpg --card-status` + +Ensure: + +```bash +echo "disable-ccid" >> ~/.gnupg/scdaemon.conf +``` + +Restart: +```bash +gpgconf --kill scdaemon +gpgconf --kill gpg-agent +``` + +## Card suddenly stops responding + +Disconnect and reconnect the token, then restart: + +```bash +gpgconf --kill scdaemon +sudo systemctl restart pcscd +``` + +## Smart card out of storage space + +Some cards cannot store RSA 4096-bit keys. Consider ECC keys or verify the storage limitations of your hardware. + +## Reader busy errors + +Only one application can communicate with the reader at a time. Close Kleopatra, `pcsc_scan`, or other smart-card utilities before attempting operations. + +--- +# Sources + +https://gist.github.com/ageis/5b095b50b9ae6b0aa9bf + +https://kevinsguides.com/guides/security/software/pgp-encryption/ + +https://blog.apdu.fr/posts/2023/11/pcsc-lite-and-polkit/ + +https://support.yubico.com/s/article/Troubleshooting-issues-with-GPG + +https://www.gnupg.org/howtos/card-howto/en/smartcard-howto.html + +https://wiki.debian.org/Smartcards/YubiKey4 + +https://keys.openpgp.org/ + +https://wiki.archlinux.org/title/OpenPGP_card + +https://docs.github.com/en/authentication/managing-commit-signature-verification/generating-a-new-gpg-key + +https://github.com/microsoft/vscode/wiki/Commit-Signing + +https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work + +https://github.com/martinpaljak/GlobalPlatformPro/wiki/Application-management + +https://github.com/github-af/SmartPGP