🚩
Practical CTF
BlogContact
  • 🚩Home - Practical CTF
  • 🌐Web
    • Enumeration
      • Finding Hosts & Domains
      • Masscan
      • Nmap
      • OSINT
    • Client-Side
      • Cross-Site Scripting (XSS)
        • HTML Injection
        • Content-Security-Policy (CSP)
      • CSS Injection
      • Cross-Site Request Forgery (CSRF)
      • XS-Leaks
      • Window Popup Tricks
      • Header / CRLF Injection
      • WebSockets
      • Caching
    • Server-Side
      • SQL Injection
      • NoSQL Injection
      • GraphQL
      • XML External Entities (XXE)
      • HTTP Request Smuggling
      • Local File Disclosure
      • Arbitrary File Write
      • Reverse Proxies
    • Frameworks
      • Flask
      • Ruby on Rails
      • NodeJS
      • Bun
      • WordPress
      • Angular
    • Chrome Remote DevTools
    • ImageMagick
  • 🔣Cryptography
    • Encodings
    • Ciphers
    • Custom Ciphers
      • Z3 Solver
    • XOR
    • Asymmetric Encryption
      • RSA
      • Diffie-Hellman
      • PGP / GPG
    • AES
    • Hashing
      • Cracking Hashes
      • Cracking Signatures
    • Pseudo-Random Number Generators (PRNG)
    • Timing Attacks
    • Blockchain
      • Smart Contracts
      • Bitcoin addresses
  • 🔎Forensics
    • Wireshark
    • File Formats
    • Archives
    • Memory Dumps (Volatility)
    • VBA Macros
    • Grep
    • Git
    • File Recovery
  • ⚙️Reverse Engineering
    • Ghidra
    • Angr Solver
    • Reversing C# - .NET / Unity
    • PowerShell
  • 📟Binary Exploitation
    • ir0nstone's Binary Exploitation Notes
    • Reverse Engineering for Pwn
    • PwnTools
    • ret2win
    • ret2libc
    • Shellcode
    • Stack Canaries
    • Return-Oriented Programming (ROP)
      • SigReturn-Oriented Programming (SROP)
      • ret2dlresolve
    • Sandboxes (chroot, seccomp & namespaces)
    • Race Conditions
  • 📲Mobile
    • Setup
    • Reversing APKs
    • Patching APKs
    • HTTP(S) Proxy for Android
    • Android Backup
    • Compiling C for Android
    • iOS
  • 🌎Languages
    • PHP
    • Python
    • JavaScript
      • Prototype Pollution
      • postMessage Exploitation
    • Java
    • C#
    • Assembly
    • Markdown
    • LaTeX
    • JSON
    • YAML
    • CodeQL
    • NASL (Nessus Plugins)
    • Regular Expressions (RegEx)
  • 🤖Networking
    • Modbus - TCP/502
    • Redis/Valkey - TCP/6379
  • 🐧Linux
    • Shells
    • Bash
    • Linux Privilege Escalation
      • Enumeration
      • Networking
      • Command Triggers
      • Command Exploitation
      • Outdated Versions
      • Network File Sharing (NFS)
      • Docker
      • Filesystem Permissions
    • Analyzing Processes
  • 🪟Windows
    • The Hacker Recipes - AD
    • Scanning/Spraying
    • Exploitation
    • Local Enumeration
    • Local Privilege Escalation
    • Windows Authentication
      • Kerberos
      • NTLM
    • Lateral Movement
    • Active Directory Privilege Escalation
    • Persistence
    • Antivirus Evasion
    • Metasploit
    • Alternate Data Streams (ADS)
  • ☁️Cloud
    • Kubernetes
    • Microsoft Azure
  • ❔Other
    • Business Logic Errors
    • Password Managers
    • ANSI Escape Codes
    • WSL Tips
Powered by GitBook
On this page
  • GNU Privacy Guard (GPG)
  • Signing and Verifying
  • Encrypting and Decrypting
  • Python
  1. Cryptography
  2. Asymmetric Encryption

PGP / GPG

The "Pretty Good Privacy" asymmetric encryption scheme used in email and sending encrypted or signed messages

PreviousDiffie-HellmanNextAES

Last updated 1 year ago

GNU Privacy Guard (GPG)

In Linux, a common command-line utility to perform PGP actions is the gpg program. See a small reference here:

Signing and Verifying

Putting a signature under a message can prove that a certain private key owner has written the message. Anyone can verify it with your public key, but only you can create it with your private key. This is often found in the following format:

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

Hello, world!
-----BEGIN PGP SIGNATURE-----

iQGzBAEBCgAdFiEEQctSPuIHmG7eGC/HYLG3XetyYecFAmSRkqsACgkQYLG3Xety
Yec2fwwAuwOmfZJlttuFxOlLP6RPD1yMD8XDDfRUxg96NvDvzYNnntZhU6Jeevvf
0rdogx5NsRZMPFYb9ysXlO/RDk9ZS4w8vNvZtiqDBQjjOKLblsU/sjgC7SQKLPnD
TZiQYbqBDH3DQIGgkbmU3fiOrps8Atu0dJR7o0y6Kf9/HqTBN2nCvA0jnhhXTA00
R5f6h+KXtBcMw29aHeLSO3c27+8LelTLKSyXEuUNev8ssbt5T7JdorckJzq3cwUG
zkXAtEMOzvOYd9SeftXeThTmMoiT1I8ZaBgJ60MnxVaaJUZAahQSx0wHtIV7NZCz
auNfR14XvAyUSyPbKLDI98+qygn/ljgI0yU5nRj5fvRptuJBDUWywKJF+Zj7iGRL
opPyb6BS5kSOba1PgubgICoKGMyWWWVi33OZjoFqNVq4W4i/tNL3+oQbVBpfqXYo
fRAx5C9tAv6moRRnyyE2gZolCs7grdZVqpbTMOQzMJMjwjOfG+Rmsfc81zi1v3Z3
HzEdXwrj
=RtST
-----END PGP SIGNATURE-----

It is very recognizable and easy to understand. The first part is the readable plaintext message, and the second part is the signature of that text above, signed (encrypted) with the sender's private key. If anyone wants to verify the validity, they would need to take your public key, and decrypt the signature to be left with an exact match of the text above.

In practice, you can sign a message like this:

message.txt
Hello, world!
$ gpg --clearsign message.txt
$ cat message.txt.asc
-----BEGIN PGP SIGNED MESSAGE-----
...

If you don't have a keypair yet, you can generate one with:

$ gpg --gen-key

or import an existing one with:

$ gpg --import [keyfile]

To then verify it, make sure to first have the public key from the sender imported:

$ gpg --import sender.pub

Afterward, you can verify any messages they send came from that key:

$ gpg --verify msg.txt.asc
gpg: Signature made Tue Jun 20 13:51:07 2023 CEST
gpg:                using RSA key 41CB523EE207986EDE182FC760B1B75DEB7261E7
gpg: Good signature from "Jorian" [ultimate]

Encrypting and Decrypting

If a message is intended for only a specific person to be able to read it, you can encrypt it with their public key so only they can decrypt it with their private key. An encrypted PGP message looks like this:

-----BEGIN PGP MESSAGE-----

hQGMA+DFCnh6q6yZAQwAvLRxIVGgqmpLM8OyE7YbW67djAKcq8RtTEGfRzj7dRf/
FRIljcJiqQXYrRlzgQR9qd7lpnfFb5goPVYzaCHA8HRtQo7XfZnRZ7lt821SPxmS
H4hrgf33euSt3fACvGhIIR5kmUz2ExL7n3/tMTwld0y5dgwtaGsl3ikD+TWZKM3f
pVKH+SAj37VermnBv2m4eAVMFWuykYPp82HIruNVRXlbCbFuC6QRzRHzvyhIwf+t
gFyJhiwwq74twHBnpKDgMN+z2uEyMGI9b2FYnfMs6MGFlOWgqALXryUtuVM2XnqM
1KBLReW5AihlvJn984t2joYu5ASeuTaN/Bf5gmVtcoHOVVQCiu1xS36bJmvdz+Q/
Q/EJSsfVn19e6o2FvXWaGA7w7g9uNoZj0oBM1LzQO9gtYsgQel7TfEbrMmT8lWZ4
RUi1jHvpph6+tUGrK7e/nK9z1F1lYuqEn4sZcfv6Y6hFFibI0vunfU3eKulJKVkE
QqCQug2XnKAX4t91uy1f0lABFkBI6X+j7182AjdleTAXWI/XNQgSNk+SN35mX6KO
F61+m5OjcsPer6cq7mylnWND3Ix+PRIynFbVNsHpRN+JOI79mC7sirVOZAKxXU9n
Xg==
=/OLC
-----END PGP MESSAGE-----

It is generated by encrypting the message with the recipient's public key, which means you first need to have imported their key like shown before. Then use the following options:

  • -e: to select encryption

  • -r [name or ID]: to select the recipient public key

  • -a: Add "armor" to the resulting file, meaning it is simply an ASCII format in Base64 and BEGIN/END instead of the regular .gpg binary format

For example:

$ gpg -a -e -r Jorian message.txt  # Using saved name
$ gpg -a -e -r 41CB523EE207986EDE182FC760B1B75DEB7261E7 message.txt  # Using ID

$ cat message.txt.ascl
-----BEGIN PGP MESSAGE-----

hQGMA+DFCnh6q6yZAQv/RNVXrpb4awnHSOQUkr0dn32NvgmwwXXXCKChAr17SpAt
Tu7ppTjSBIfSYDSGvLNHYDQdKBaqHxR+YGfiUKKgJahqTX8n17HgG4FLESWyWJJq
adQpE3sr9d+PpexZ/L1i+dtTk5XYkxXtbXXg4MvgLj/YWKNhPoTEEzlSxYIW1sjB
/7yyZuLcG0Y6DEt6/apnpF2HWh+ygFM/Xhx4RplM0HwpE3fdYZQxNVYcoMgEsm51
PQfaHml5lDAviJNdv7tMpS90wE6jWJMPj1GojOx0oQK4nM+k62Bppj/OVSo5RMkl
N6i1SYngyKcTVN8EF7g60lp3Z6tKd/a781ecsdXAJyNXP0/ccfgkzaMEHuOkfY66
9cig0RbglG11uXBygeU+V5mriKV2lw+I8rW5uIE9ZZgfW8e5fuOkBDfZ44uEYKrO
ZPBCWFXSwKrbKSUw+KOJiiJjk+7An3/0a/rrM2RcQzx9yfIWHeVl5Psi697LO3ps
PsQmjsIDJg/77UzFWUT50lQBydrV62gwxaC2j2i6X2ctffGMUReovang9IDfmQP+
2kDnsSiT9HQtLRMex0I9S+ZIK4CehgjdCWqCW+74HO1Tz/RRhdjoONSBkU8506kK
3d/nhX0=
=LSK8
-----END PGP MESSAGE-----

When the recipient wants to read this message, they have to decrypt it with their private key. Simply using the -d option will automatically find the correct key used and owned by you:

$ gpg -d msg.txt.asc
gpg: encrypted with 3072-bit RSA key, ID E0C50A787AABAC99, created 2023-06-18
      "Jorian"
Hello, world!

You can also encrypt and sign at the same time, using both options ( -s and -e) together

Python

Using the PGPy module you can easily automate any PGP tasks like generating keys, signing/verifying messages and encrypting/decrypting messages.

This can also be useful to generate low-level keys where you can easily control exactly what data is in the name, comment or email. If an application parses these fields in some what it may be worth trying to inject unexpected data in here like any other field on a website.

Here is a simple example of generating a key and signing a message:

import pgpy

from pgpy.constants import PubKeyAlgorithm, KeyFlags, HashAlgorithm, SymmetricKeyAlgorithm, CompressionAlgorithm

key = pgpy.PGPKey.new(PubKeyAlgorithm.RSAEncryptOrSign, 4096)
uid = pgpy.PGPUID.new("Jorian", comment="This is a comment", email="contact@jorianwoltjer.com")

key.add_uid(uid, usage={KeyFlags.Sign, KeyFlags.EncryptCommunications, KeyFlags.EncryptStorage},
            hashes=[HashAlgorithm.SHA256, HashAlgorithm.SHA384, HashAlgorithm.SHA512, HashAlgorithm.SHA224],
            ciphers=[SymmetricKeyAlgorithm.AES256, SymmetricKeyAlgorithm.AES192, SymmetricKeyAlgorithm.AES128],
            compression=[CompressionAlgorithm.ZLIB, CompressionAlgorithm.BZ2, CompressionAlgorithm.ZIP, CompressionAlgorithm.Uncompressed])

print(str(key.pubkey))  # -----BEGIN PGP PUBLIC KEY BLOCK----- ...

text = "Hello, world!"
signed_text = key.sign(text)

print(str(signed_text))  # -----BEGIN PGP SIGNATURE----- ...
🔣
Useful GPG commands
A short list of useful GPG commands to encrypt, decrypt, sign or manage keys
Logo
Examples — PGPy 0.6.0 documentation
Official documentation of PGPy with examples for common tasks
Logo