Skip to content

Instantly share code, notes, and snippets.

@jpwilliams
Last active July 6, 2022 14:35
Show Gist options
  • Save jpwilliams/ab8b1d07ffce518857b7acfccbdfe1a8 to your computer and use it in GitHub Desktop.
Save jpwilliams/ab8b1d07ffce518857b7acfccbdfe1a8 to your computer and use it in GitHub Desktop.
Securely transferring files with GPG keys

Secure data transfer using GPG keys

Sometimes you need a secure way to pass a file from one place to another, ensuring that only the intended recipient can read its contents. We can achieve this simply using GPG keys.

The flow is:

  1. Recipient generates a GPG key
  2. Recipient exports a public key
  3. Recipient sends public key to sender
  4. Sender receives public key from recipient
  5. Sender verifies validity of public key with recipient
  6. Sender encrypts the file using the recipient's public key
  7. Sender sends encrypted file to recipient
  8. Recipient receives encrypted file from sender
  9. Recipient decrypts encrypted file with their private key

Recipient

The recipient of the file must generate a GPG key and pass their public key to the sender so that they may encrypt it. Upon receipt, the recipient can then decrypt the file using their private key.

Generate a GPG key

gpg ---full-generate-key
  • Default suggested encryption is fine
  • Short duration is best
  • Note down the email address you use
  • Add a useful comment like "Key to transfer a file"

Export your public key

gpg --output ~/recipient.key --armor --export "recipient@jpwilliams.dev"

The file recipient.key should have been exported. If the file contains the following header, you've output the correct key.

-----BEGIN PGP PUBLIC KEY BLOCK-----

Send your public key to the sender

Pass your public key to the target sender. They'll use this to encrypt the file so that only you can decrypt it. Your public key is safe to be transferred over insecure space.

If asked for your key's fingerprint in order for the sender to verify the key they have is yours, run the below command:

gpg --list-keys

This will output something like this:

/home/jack/.gnupg/pubring.kbx
-----------------------------
pub   rsa2048 2022-01-13 [SC] [expires: 2022-01-14]
      BC024822B9F833023C3E985A4D2D04E58B6F5EBA
uid           [ultimate] Jack Williams (Key to transfer a file) <recipient@jpwilliams.dev>
sub   rsa2048 2022-01-13 [E] [expires: 2022-01-14]

The second pub line (starting BC02 in the example above) is your key's fingerprint. Send this to the sender so they can match it to the key they received.

Decrypting the file

Once the sender has sent you an encrypted file (probably a file with a .asc extension), you can use your private GPG key to decrypt it.

gpg --decrypt file.zip.asc > file.zip

Done! 🥳 You have securely received and decrypted a file.

Sender

The sender of the file must use the recipient's public GPG key to encrypt the file, ensuring that only the receipient (in possession of the private GPG key) can decrypt it.

Receive a public key

Ask your recipient for their public GPG key. You will use this to encrypt the file so that only the recipient can decrypt it.

Once you have this, you must import it.

gpg --import recipient.key

You should receive an output like this:

gpg: key 4D2D04E58B6F5EBA: public key "Jack Williams (Key to transfer a file) <recipient@jpwilliams.dev>" imported
gpg: Total number processed: 1
gpg:               imported: 1

Verify the recipient's key (optional)

If you want to be doubly sure that the GPG key you're importing actually belongs to the person you think it does, you can manually verify it. If you don't do this you'll still be able to securely encrypt/decrypt data, but GPG will warn you that you haven't explicitly trusted the key you're using.

In order to verify your key, run the command below:

gpg --fingerprint recipient@jpwilliams.dev

Once run, you should get an output that looks something like this:

pub   rsa2048 2022-01-13 [SC] [expires: 2022-01-14]
      BC02 4822 B9F8 3302 3C3E  985A 4D2D 04E5 8B6F 5EBA
uid           [ unknown] Jack Williams (Key to transfer a file) <recipient@jpwilliams.dev>
sub   rsa2048 2022-01-13 [E] [expires: 2022-01-14]

The second pub line (starting BC02 in the example above) is the key's fingerprint. Ask the recipient to send you their key's fingerprint. If the fingerprints match then you have the correct key.

Let's tell GPG that we now trust this key using the --sign-key flag:

gpg --sign-key recipient@jpwilliams.dev

Encrypt the file

Using the public key we received, let's encrypt the file so that only the recipient can decrypt it.

If you have an existing private GPG key, you can also include the --sign flag to sign the file with your details.

gpg --encrypt --armor -r recipient@jpwilliams.dev file.zip

The above would generate a file called file.zip.asc. Send this file to the recipient, and you're now done! 🥳

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment