April 18th, 2022
First, some clarification/background: PGP. PGP stands for Pretty Good Privacy, which was developed in 1991 by Phil Zimmermann. It provides encryption, decryption, and authentication of data. OpenPGP is the open standard, and GPG is GNU Project’s free/libre implementation.
GPG uses assymetric cryptography (private/public key pairings). Private keys and public keys are mathematically linked, and while it is very easy to produce a public key from a private key, it is impossible to generate the private key from the public key. This is important, because (as the name implies), private keys need to remain private, while public keys can be stored publicly, for others to see.
A private key is essentially a large random number, that (for GPG), allows you to decrypt as well as sign communications. A public key is what is needed to receive encrypted messages.
To clarify, let’s say there is Alice, Bob, and Charlie. Each have a website accessible to the public, where they post their public key. Each hold their private key, privately. Alice wants to send Bob a message.
Alice encrypts the message, by sending it to Bob’s public key. Bob sees a bunch of nonsense data, and can decrypt it by using his private key, which is paired to his public key. This results in the message “Hi, this is Alice. Here is this secret _____”. However, how does Bob know this is not Charlie pretending to be Alice?
The way to solve this would be to have Alice sign the message:
Alice encrypts the message again to Bob, and then signs the encrypted message. Bob sees the encrypted nonsense, and decrypts it with his private key, that is paired to the public key which Alice’s message is encrypted to. This results in the message, “Hi, this is Alice. Here is this secret _____”, which also now has a cryptographic signature attached to it.
To create a signature, Alice hashed* her message and then encrypted the hash with her own private key. This allows Bob to validate the integrity and authenticity of the message by using Alice’s public key to decrypt the hash. If the decrypted hash matches the hash of the message that Bob computes himself, then the message is valid. If it does not, the message has either been A) tampered with in some way, indicating a failure of integrity, or B) the signature was created with a private key that doesn’t correspond to the public key presented by the sender, indicating a failure of authentication. In our scenario, this would mean it was sent by a fourth party, Dan, who was pretending to be Alice.
*You’re probably asking, What is a hash? A hash is the output of a cryptographic hash function, which is another one-way mathematical function. You can input a message of any size, and the output (the hash) is a fixed size of seemingly random data with certain properties:
Deterministic — the same message always results in the same (seemingly random) hash
You cannot generate the message from the hash
Two separate messages cannot generate the same hash
Any small change to a message generates a large change in the hash
Here are some examples to demonstrate, using SHA-256 (the Secure Hashing Algorithm with 256 bit output).
Here I am hashing 'RobertSpigler':
user@work:~$ echo -n RobertSpigler | sha256sum
58bb03d3839d3b30c0af8ae02828cab2d20728b456ef8cce5410153089b3bb18
(Lowercase ‘s’) results in a completely different hash:
user@work:~$ echo -n Robertspigler | sha256sum
f7e663c5a51abe2ce9f9228563d7138602c36c2cae6f4d987af846d72c2e2407
Hashing my article on Hardware Wallets (over 20 pages), results in the same length output. (Due to formatting this may look like one character more/less, but it is not :) 256 bits can be represented as 64-character hexadecimal strings, you can count them to check).
user@work:~$ sha256sum ‘/home/user/Documents/Medium Post/HWW/Final.odt’
5f732121c4b4bb125a9e60b0545b0e22c8806d20238c22457c9e4465221ced0d
This is the ‘magic’ behind assymetric cryptography — knowing the public key, anyone can encrypt messages to another party over the internet (and verify the sender) without having to reveal the private key or transfer a shared secret over insecure channels.
Traditionally, with only one key pair (the private/public key), your private key is sitting on your computer exposed. The same computer that your browser, email, etc runs on. It must, right? Because how else would you be able to use that private key to decrypt messages sent to you, or sign messages sent to your friends? However, this opens up your private key to all sorts of serious attacks.
Subkeys allow for improved key management policies. With subkeys, you can generate additional key pairs that are tied to a master key. These additional keys can be stored independent of the master key pair, have restricted policies (encryption or signing only), and be revoked independent of the master key in case of private subkey compromise.
This allows you to securely store your master private key offline, upload your public keys online, and use your subkeys to decrypt and sign communications on an insecure device (your daily laptop). If these subkeys get compromised, you can use your master private key to revoke them individually (before anyone impersonates you), and generate new subkeys.
To understand Split GPG, you need to first understand Qubes. Qubes is an operating system that is built around the concept of security through isolation.
How compartmentalization works in Qubes is through the Xen hypervisor. Unlike more traditional virtual machines which build their VM’s on top of the host operating system (such as Docker), Xen is a bare-metal hypervisor which enables users to build their VM’s with separate OS’s running in isolation.
Malware exists, and bugs happen, so users should set up security domains isolated within the one physical computer, with the expectation that a vulnerability will occur. Some beginning users think that you set domains based on applications (for example, you have a domain for ‘Firefox’, a domain for ‘Email’, a domain for ‘Word’, etc). This is not true, and wouldn’t make sense, since you use Firefox for different purposes, across domains. Domains are set with predefined purposes and levels of trust.
For example, you can separate your computer into Public Work, Private Work, Personal, etc domains. I also have domains for School, Banking, and Bitcoin. This means that when your computer inevitably becomes infected, the vulnerability won’t spread throughout your entire computer. The parts of the internet that are inherently insecure (untrusted browsing) don’t mix with the parts of your computer that need perfect security (storing passwords, private keys (GPG, that’s what we’re talking about, right?), etc). Qubes also isolates your network cards and USB controllers, allows for the creation of Disposable Virtual Machines, integrates with Whonix, allows for separate network profiles for each VM, etc. Getting into every detail of what makes Qubes a great OS should be an entirely separate article.
Qubes has an integrated file and clipboard copy/paste operation that allows you to securely share files and text between different VM’s.
This is secure because Qubes’ implementation of this doesn’t allow any other VM (called a qube) other than your selected one to steal any of the contents.
However, that doesn’t mean the data itself being transferred is necessarily safe. (Even if it is just some text for your GPG application to decrypt). Therefore, there is one rule that must always be followed:
Never move data from a less trusted qube to a more trusted qube; only from a more trusted qube to a less trusted qube!
The default install comes with some qubes already setup. One of these is Vault, which is the most trusted qube, and has networking turned off. It can be treated as an airgapped computer. Our GPG master private key will be created and stored here.
We will create another high-security qube (although inferior to Vault) to store our subkeys. On the laptop, you will go browsing for software and receive email on a much lower level domain (by definition of the activities of browsing the internet and receiving email). So if you are trying to confirm the validity of a piece of software, or decrypt a message received by email, how do you do this? You cannot copy the signature or encrypted message from this low level domain to the subkey domain! That would be against the above rule, and break the security separation.
This is the purpose behind Split-GPG:
Split-GPG is a protocol that allows you to use GPG in the untrusted domain, while delegating the actual crypto operations to the more trusted domains. Then, if (when) your untrusted daily browsing/email domain becomes compromised, your private keys will not be compromised as well.
With the use of subkeys with Split-GPG, your master private key remains the most airgapped (in Vault), never even touched by the Split-GPG protocol, which uses the subkeys for the crypto operations.
Now that we understand what we are doing and why, here is how we do it:
Qubes has very well written official documentation. Follow their guide on how to install Qubes OS, which includes important details on hardware trust, verification of the iSO, system requirements, etc.
Then, follow the documentation to update dom0 and your template VMs:
I may at one point write a more extensive tutorial for Qubes OS as a whole for beginners (rather than just geared towards GPG), but that is out of scope for this guide, which is already fairly beginner-friendly. However, if you are lost, viewing the 'Getting Started' guide is a good place to start.
Finally, to install and setup Split GPG, view this documentation:
If you have any difficulty generating subkeys, or exporting specific types of keys, Google is your friend
Once setup, you will drive yourself crazy trying to fix the errors it feeds you as you try to encrypt/decrypt/sign/verify. So I have written a cheat sheet (of some very unconventional) commands that consistently work with this setup.
To Sign:
(inline, like forum post)
export QUBES_GPG_DOMAIN=work-gpg
cat InFile | qubes-gpg-client --clearsign > OutFile
Detached (ex. for a file)
export QUBES_GPG_DOMAIN=work-gpg
cat InFile | qubes-gpg-client --detach-sign -a > OutFile.sig
To Verify:
export QUBES_GPG_DOMAIN=work-gpg
qubes-gpg-client -d InFile > OutFile
If detached signature (ex. for application)
export QUBES_GPG_DOMAIN=work-gpg
qubes-gpg-client --verify detached_signature.asc signed_file
To Decrypt:
export QUBES_GPG_DOMAIN=work-gpg
qubes-gpg-client -d InFile > OutFile
To Encrypt:
export QUBES_GPG_DOMAIN=work-gpg
qubes-gpg-client --encrypt --armor -r UserID --trusted-key LongKeyID InFile
Fingerprint: C2C6 0E27 9E86 F10D 5697 7825 35CE 0FE6 C214 1823
Long KeyID: 35CE 0FE6 C214 1823
Short KeyID: C214 1823
To Setup AppVM:
gpg -K
export QUBES_GPG_DOMAIN=work-gpg
gpg -K
qubes-gpg-client -K
To import key (do in DispVM; or if failing, set up VM then Delete)
export QUBES_GPG_DOMAIN=work-gpg
qubes-gpg-import-key (drag and drop downloaded.asc)
Copyright © 2022 Robert Spigler - All Rights Reserved.
I do not host this website. Default cookies for the purpose of analytics and performance tracking are loaded. I do not have control over how these cookies are stored. If this is a concern of yours, I suggest installing something like 'Privacy Badger' in addition to selecting "Decline". View 'Privacy Policy' for details.