A few weeks back, I wrote an article about why writing exploits for vulnerabilities you find in APIs is important. Several community members contacted me through emails, Slack, and Discord messages with varying questions about my comments on digitally signing reports and encrypting exploits to ensure they didn’t fall into the wrong hands.
It’s clear that some security researchers don’t know how to use public-key cryptography. I hope to change that with this article.
By the end, you will understand how to protect sensitive data and easily encrypt messages that can only be accepted by the intended recipient, preventing other parties from weaponizing your findings.
Let’s get to it!
What is GPG and why is it important for security researchers
GNU Privacy Guard, better known as GnuPG or just GPG, is an implementation of public key cryptography. This allows you to securely transmit information between parties that can be used to ensure the information is genuine and only accessible by authorized parties.
GPG relies on the OpenPGP standard (RFC-4880), an open-source implementation of Phil Zimmermann’s work with Pretty Good Privacy (PGP). GPG can provide digital encryption, signing, and key exchange and is interoperable with modern versions of PGP.
And here lies the first bit of confusion.
The inverted acronym of PGP vs. GPG leads some people to believe they are the same thing. But they are not. PGP has a long checkered history as it has changed hands with different commercial entities over the years. I think last I heard, it’s called Symantec Encryption Desktop, but it’s owned by Broadcom because they own the controlling stake in Symantec’s enterprise security business.
Whatever it’s called… just stick with using GPG. You will find installable packages for pretty much every platform you will use, is available for free, and integrates well with hardware smartcards and Yubikeys.
Why GPG is important
So GNU Privacy Guard provides a complete key management system for you that you will learn to love (or love to hate). It’s an essential but necessary evil.
As a security researcher, you will converse with many security triage teams throughout your career. You will use GPG to manage all the public keys for the security teams you regularly communicate with.
You will leverage those gpg keys to ensure that your conversations are protected and that all parties maintain situational awareness around any vulnerability disclosures and exploit code exchanges that occur.
The last thing you want is someone on the other side accidentally double-clicking an exploit and detonating it in an uncontrolled environment. Or forwarding an unencrypted message and leaking a disclosure to the wrong people within an organization.
Trust me, it happens.
Setting up GPG on your system
GPG is incredibly easy to install and set up on most systems. It’s a free download, so you can head to their website and follow the directions for your OS.
Note: Many Linux distributions already have GnuPG installed. To ensure you have the latest compatible version (GPG v2.x), check with
Below is a quick cheat sheet to install GPG to several operating systems using a command prompt or shell.
Ubuntu and Debian-based Linux distros
sudo apt-get install gnupg
sudo yum install gnupg2
You can install the GPG Suite for MacOS, but I prefer package management with Homebrew:
brew install gnupg
winget install -e --id GnuPG.Gpg4win
This will also work with Windows 10 if you have App Installer installed from the Microsoft Store. Read here for more details.
Generating your key pair for signing and encryption
Once the software is installed on your OS, you must create your own GPG keys. Before we do that though, we need to discuss what kind to generate.
Since around 2021, GPG now supports default keys for ECC (Elliptic Curve Cryptography). ECC is more efficient as you get an equivalent cryptographic strength with significantly smaller key sizes. However, it comes at a cost… there is far more support for RSA keys across different operating systems.
If you plan to use Yubikeys, I’d recommend using ECC. The size and speed will matter there. Otherwise, use RSA to have the most compatibility.
As such, for now, you do not want to follow the guidance online to use
gpg --gen-key🚫 as it may not generate the proper RSA keys you will probably want to use.
Instead, to generate your first set of keys, run the following command:
When prompted, answer the questions as follows:
- Select the kind of key of RSA and RSA.
- Set the key size to 4096.
- Set the key to expire in 2 years (2y).
- Accept the expiration prompt (y)
- Enter your name as you want the recipients to see it. Use your real name or maybe your handle.
- Enter your email address.
- Leave the comment blank.
- Hit O to accept the configuration.
- Enter a strong secret passphrase.
- If prompted, move your mouse around to generate extra entropy.
When the process completes, you should be able to run
gpg --list-keys to see your public key on your GPG keyring. If you want to see your secret key, type
Time to back them up.
How to securely back up your keys
GPG includes tooling to import and export keys across systems. I highly recommend you ASCII armor these so they can be easily moved around. Like any sensitive confidential text file, it’s up to you to properly handle and safeguard them.
Backing up your keys
When backing up your keys, it is good to name them appropriately so they are easy to identify. For this exercise, I will use simple naming for the examples. In a real-world export, I would recommend you be far more descriptive.
Note: When using the
-a argument with the following commands GPG will output the key(s) in a PEM format.
Export all public keys:
gpg --armor --export > public-keys.asc
Export a single public key:
gpg --armor --export key-id > my-public-key.gpg
You can retrieve the key id using the following command:
Export all private keys:
gpg --armor --export-secret-keys > private-keys.asc
Note: You will be prompted for your secret passphrase to do this.
Export trust store:
gpg --export-ownertust > ownertrust.asc
Restoring your keys
gpg --import public-keys.asc gpg --import private-keys.asc gpg --import-ownertrust ownertrust.asc
Getting a vendor’s public key
Now that you have created your own keys and backed them up properly, it’s time to find the public keys of those people you want to converse with securely.
There are many ways to find them. You can use public key servers like keys.openpgp.org or get the recipient’s public key directly from the other party by asking.
As you are doing security research, chances are the vendor will publish their public key somewhere findable, like on their website or within its Vulnerability Disclosure Policy (VDP). Have you ever heard about security.txt? It’s a proposed standard that allows websites to define security policies in a well-known and established manner through a text file. It’s now an RFC standard (RFC 9116).
You can usually find this file in an app directory at <domain>/.well-known/security.txt or at the root of the domain at <domain>/security.txt.
You can take that corresponding public key file and download it locally. Then you can import it using a command like
gpg --import publickey.txt . In this case, you will end up importing one for email@example.com and one for firstname.lastname@example.org.
Importing keys doesn’t immediately trust them. A key’s trust level is something that you alone assign to the key and is considered private information. In fact, it’s not even stored with the key in case you ever export it. This is what the ownertrust database is for.
If you want to trust a key, you can edit it and assign a trust level. Try this:
gpg --edit-key email@example.com # In the interactive GPG prompt gpg> trust Your decision? 4 gpg> save
OK, so now you have the recipient’s public key imported and trusted in your keyring. Let’s start using it!
Using GPG to sign and encrypt your vulnerability reports and PoC exploits
Now that we have all the necessary keys in place, we can start communicating with the security triage team. Many email clients have plugins and extensions that can be used to help with this, but I am going to show you how to do it manually.
The main reason is that if you use modern web clients like GMail, Outlook.com, or Office 365… these extensions don’t work. And many browser extensions that try to compensate for this are flaky at best.
I will show you several scenarios, from encrypting files, signing exploits, and verifying messages.
Encrypting and Signing a Vulnerability Report
Let’s say you want to submit your report to the Google security triage team. You’ve downloaded, imported, and trusted their public key and now want to send them your sensitive report that you’ve written in markdown.
You could do something like this to encrypt files:
gpg --sign --encrypt --armor -r firstname.lastname@example.org report.md
This would then produce report.md.asc, an ASCII armored PGP encrypted message file that you could attach to any email. The contents would look something like this:
-----BEGIN PGP MESSAGE----- hF4DET/HSwnaeLESAQdAKYsZIaPdzmfK8bIG13IULn05AA1JS6C09ejXsOJGAnwx . [LOTS OF CIPHER TEXT HERE] . =Mgny -----END PGP MESSAGE-----
Personally, I get lazy at the command line and would use the shortened version of that command which looks like this:
gpg -sea -r email@example.com report.md
You can use
gpg --help to see other options you might want to consider. As an example, if your original report name included sensitive metadata you would want to redact, you could rename the output using
gpg -sea -r firstname.lastname@example.org -o report.md.gpg cart-ssrf-report.md
How to decrypt messages from the security triage team
As you engage with the security triage team, they may have sensitive communications, information, or files that they will share with you. These will be encrypted with their private key and your public key to ensure only you can open them.
When they send you encrypted messages and/or files you can quickly decrypt them using the following gpg command:
gpg -d -o filename.msg filename.msg.asc
You will be prompted to enter passphrase before you can decrypt files.
If you don’t include the
-o option during decryption, it will dump the contents to stdout.
Signing an Exploit
So when sending exploits to the security triage team, you could (and should) consider following the previous guidance on signing, encrypting, and ASCII armoring the file(s). If you have multiple files, you might consider archiving/zipping up all the original files and then using GPG against that entire archive file instead.
But you might come across times when you are directly communicating with the triage team and/or developers who may be unable to decrypt something you send. I’ve had occasions where I was having real-time communications with developers where the comm channel was secure, but I wanted to make sure what they got from me wasn’t altered during transmission.
This is where GPG’s –clear-sign param comes into play. You can use the following command:
gpg --clear-sign exploit.py
This would generate a PGP signed message in which the exploit is still in plaintext but signed by me. It’s also defanged enough that someone can’t execute it without removing the PGP artifacts around the exploit.
It might look something like this:
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 #!/bin/env python3 # Some exploit code goes here -----BEGIN PGP SIGNATURE----- iHUEARYIAB0WIQTbUZcJCvqHzeEW7cCsmagrIhcuSwUCZCeU+wAKCRCsmagrIhcu SxlnAP9zo5WBqxhvZQquwqzVBEJNbPYK/drk9m86e+aGJaB7BQD/beqDdEc8b5or LBzrayKsLOPMjIrfLv41JBZYt6OyZAE= =ApQL -----END PGP SIGNATURE-----
On their end, they can verify that the exploit hasn’t been tampered with by importing your public key to their GPG keyring and then running the gpg command
gpg --verify exploit.py.asc.
If they want to view the file’s contents without the signature, they can use
gpg -d exploit.py.asc > exploit.py
Kinda simple, huh?
Every security researcher should get familiar with GNU Privacy Guard (GPG). Knowing how GPG works is invaluable for securely sending vulnerability findings, exploits, or other sensitive information over the internet to those you will be working with.
Hopefully, I’ve given you the foundation to encrypt files, verify signatures, and decrypt messages. Once you get comfortable with GPG encryption, you’ll find it’s a powerful tool in your arsenal.
Found this useful? Keep up with my work by subscribing to my free weekly newsletter, where I share exclusive tips, tricks, and killer command line cheats to hack your apps and infrastructure.