0.13
No release in over 3 years
There's a lot of open issues
Ruby-GPGME is a Ruby language binding of GPGME (GnuPG Made Easy). GnuPG Made Easy (GPGME) is a library designed to make access to GnuPG easier for applications. It provides a High-Level Crypto API for encryption, decryption, signing, signature verification and key management.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Development

~> 3.5.1
~> 2.1.0
~> 0.9.12
~> 0.9.11

Runtime

 Project Readme

GPGME Ruby Bindings

Build Status Coverage Status

Documentation:

Badges:

  • Build: Build Status
  • Coverage: Coverage Status (If badges do not render, check the respective service for status.)

Requirements

  • Ruby 2.5 or later (Ruby 2.0–2.4 are no longer supported)
  • GPGME 2.0.0 or later (older versions are deprecated)
  • gpg-agent (optional, but recommended)

Tested with:

  • Ruby 2.5, 2.6, 2.7, 3.0, 3.1, 3.2
  • GPGME 2.0.0, 1.21.0

Installation

$ gem install gpgme

API Overview

GPGME provides three levels of API:

  • High-level API: Easiest to use for common operations.
  • Mid-level API: More control, less user-friendly.
  • Low-level API: Closest to the C interface, for advanced use.

Recent Features

  • Support for GPGME 2.0.0 and later
  • Deletion of secret keys without confirmation
  • Improved thread safety and encryption flags
  • ignore_mdc_error flag setter/getter
  • Minimal key exports (GPGME::Key.valid?)
  • Support for Ruby 3.2 and later
  • More efficient key sign lookups
  • Updated dependency versions (libgpg-error, libassuan)

See NEWS for full changelog.

High-level API Example

crypto = GPGME::Crypto.new
crypto.clearsign $stdin, output: $stdout

Mid-level API Example

plain = GPGME::Data.new($stdin)
sig   = GPGME::Data.new($stdout)
GPGME::Ctx.new do |ctx|
  ctx.sign(plain, sig, GPGME::SIG_MODE_CLEAR)
end

Low-level API Example

ret = []
GPGME::gpgme_new(ret)
ctx = ret.shift
GPGME::gpgme_data_new_from_fd(ret, 0)
plain = ret.shift
GPGME::gpgme_data_new_from_fd(ret, 1)
sig = ret.shift
GPGME::gpgme_op_sign(ctx, plain, sig, GPGME::SIG_MODE_CLEAR)

The high-level API is recommended for most users. The low-level API is only needed for advanced use cases or when porting C code.

Usage

Most high-level methods use the mid-level GPGME::Ctx API. Input/output is handled via GPGME::Data objects, which can wrap strings, files, or other IO objects. See the documentation for GPGME::Ctx and GPGME::Data for details.

Crypto Operations

The GPGME::Crypto class provides methods for encryption, decryption, signing, and verification. Examples:

  • Encrypt for a recipient:
    crypto = GPGME::Crypto.new
    crypto.encrypt "Hello world!", recipients: "someone@example.com"
  • Symmetric encryption:
    crypto = GPGME::Crypto.new(password: "gpgme")
    crypto.encrypt "Hello world!", symmetric: true
  • Decrypt (with signature verification):
    crypto.decrypt File.open("text.gpg")
  • Sign data:
    crypto.sign "I hereby proclaim Github the beneficiary of all my money when I die"
  • Verify signature:
    sign = crypto.sign "Some text"
    data = crypto.verify(sign) { |signature| signature.valid? }

Key Management

The GPGME::Key object represents a key and provides methods to find, export, import, delete, and create keys.

  • List keys:
    GPGME::Key.find(:secret, "someone@example.com")
    # => Array of secret keys matching the email
  • Export a key:
    GPGME::Key.export("someone@example.com")
    # => GPGME::Data object with the exported key
    key = GPGME::Key.find(:secret, "someone@example.com").first
    key.export
    # => GPGME::Data object
  • Import a key:
    GPGME::Key.import(File.open("my.key"))
  • Validate a key:
    GPGME::Key.valid?(public_key)
    # => true/false
  • Key generation: (See API docs; new flags available in GPGME 2.0.0+)

Engine Information

GPGME provides methods to obtain information about the GPG engine in use:

  • Get engine info:
    GPGME::Engine.info.first
    # => #<GPGME::EngineInfo ...>
  • Change home directory:
    GPGME::Engine.home_dir = '/tmp'

Round Trip Example Using Keychain Keys

Rather than importing keys, you can specify the recipient directly. Example (for IRB/console):

# Stop IRB echoing everything, which errors with binary data (not needed in production)
conf.echo = false

class PassphraseCallback
  def initialize(passphrase)
    @passphrase = passphrase
  end

  def call(*args)
    fd = args.last
    io = IO.for_fd(fd, 'w')
    io.puts(@passphrase)
    io.flush
  end
end

# Find recipients using: $ gpg --list-keys --homedir ./keychain_location
# pub   2048R/A1B2C3D4 2014-01-17
# Use the key ID (e.g., 'A1B2C3D4')

# To use a non-default keychain:
# home_dir = Rails.root.join('keychain_location').to_s
# GPGME::Engine.set_info(GPGME::PROTOCOL_OpenPGP, '/usr/local/bin/gpg', home_dir)

crypto = GPGME::Crypto.new
options = { recipients: 'A1B2C3D4' }
plaintext = GPGME::Data.new(File.open(Rails.root.join('Gemfile')))
data = crypto.encrypt plaintext, options

File.open(Rails.root.join('Gemfile.gpg'), 'wb') { |f| f.write(data) }

# Decrypt
crypto = GPGME::Crypto.new
options = { recipients: 'A1B2C3D4', passphrase_callback: PassphraseCallback.new('my_passphrase') }
ciphertext = GPGME::Data.new(File.open(Rails.root.join('Gemfile.gpg')))
data = crypto.decrypt ciphertext, options
puts data

Contributing

To run the local test suite you need Bundler and GPG:

bundle
rake compile   # Compile the extension
rake           # Run the test suite

License

This library is licensed under LGPLv2.1+. See the file COPYING.LESSER and each source file for copyright and warranty information.