Skip to content

Instantly share code, notes, and snippets.

@kernelsmith
Last active February 23, 2024 17:03
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kernelsmith/fb8356287960750f43a4abe6517f27a7 to your computer and use it in GitHub Desktop.
Save kernelsmith/fb8356287960750f43a4abe6517f27a7 to your computer and use it in GitHub Desktop.
Basic GPGME ruby gem usage

Basic GPGME Ruby Gem Usage

I just found this API ridiculously confusing to use, and maybe I just suck, but I don't want to figure it out again, so I'm writing it down here

Establish a gpg home dir if desired

Optional, but if you have an established gpg home dir that you want to use or you don't want it chosen for you

GPGME::Engine.home_dir = "/some/dir" # e.g. env['GNUPG_HOME']

Note If you already have keys imported in that home dir, you can skip this part:

Import a key

Only need to do once for each key, but repeated imports are ok too.

A very basic explanation of keys in case you're not familiar:

  • Private keys
    • You need to import at least 1 private key to decrypt anything asymmetrically encrypted
    • You also need the private key in order to cryptographically "sign" something
    • When you use a private key for one of these operations you'll usually need to provide a password or a password callback function (hook, agent etc) in order to get access to the private key
  • Public keys
    • You'll need 1 public key for each person or account for which you want to encrypt
    • You'll also need these keys to verify they have cryptographically "signed" something
    • If you aren't using some sort of chain of trust (web of trust) and/or the keys aren't signed by anyone you already trust, you'll need to specify always_trust :true
### The keys are "saved" in your GPGME::Engine.home_dir which is why they don't really persist in ruby land
File.open("keyfile", 'rb') do |key_file|
  GPGME::Key.import(
    key_file,
    {armor: true, keylist_mode: GPGME::KEYLIST_MODE_LOCAL}
  )
end

Create a basic crypto object

It will inherit the keys assuming you don't change home_dir again) Note You can specify options now and/or when you call additional methods or both

list of crypto options

additional ctx options available

crypto = GPGME::Crypto.new({always_trust: true})

Note Most of the GPGME methods return a GPGME::Data object which can be read just like a typical IO object, but remember to seek(0) to return to the beginning if nec.

Encrypt

cipher_text = crypto.encrypt(
  "test text",
  {recipients: 'email@address.com'}
  # or recipients: ['email1@address.com', 'email2@address.com']
)
# recipients: could have been specified w/the crypto object or when calling encrypt
# same goes for always_trust:

Decrypt

clear_text = crypto.decrypt(
  cipher_text,
  {keylist_mode: GPGME::KEYLIST_MODE_LOCAL, password: 'blah'}
)

Note If you previously called cipher_text.read etc you'll need to first call cipher_text.seek 0

Read the output

clear_text.read
clear_text.see(0) # optional
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment