ueno / ruby-gpgme

a ruby interface to GnuPG Made Easy (GPGME).
GNU Lesser General Public License v2.1
231 stars 99 forks source link

= GPGME

This README is better viewed through the YARD formatted documentation: https://www.rubydoc.info/github/ueno/ruby-gpgme for latest github version, or https://www.rubydoc.info/gems/gpgme for latest gem release.

{Build Status}[https://github.com/ueno/ruby-gpgme/actions/workflows/test.yml] {Coverage Status}[https://coveralls.io/r/ueno/ruby-gpgme]

== Requirements

== Installation

$ gem install gpgme

== API

GPGME provides three levels of API. The highest level API is as simple as it gets, the mid level API provides more functionality but might be less user-friendly, and the lowest level API is close to the C interface of GPGME.

=== The highest level API

For example, to create a cleartext signature of the plaintext from stdin and write the result to stdout can be written as follows.

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

=== The mid level API

The same example can be rewritten in the mid level API as follows.

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

=== The lowest level API

The same example can be rewritten in the lowest level API as follows.

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)

As you see, it's much harder to write a program in this API than the highest level API. However, if you are already familiar with the C interface of GPGME and want to control detailed behavior of GPGME, it might be useful.

== Usage

All the high level methods attack the mid level GPGME::Ctx API. It is recommended to read through the GPGME::Ctx.new methods for common options.

Also, most of the input/output is done via GPGME::Data objects that create a common interface for reading/writing to normal strings, or other common objects like files. Read the GPGME::Data documentation to understand how it works. Every time the lib needs a GPGME::Data object, it will be automatically converted to it.

=== Crypto

The GPGME::Crypto class has the high level convenience methods to encrypt, decrypt, sign and verify signatures. Here are some examples, but it is recommended to read through the GPGME::Crypto class to see all the options.

=== Key

The GPGME::Key object represents a key, and has the high level related methods to work with them and find them, export, import, deletetion and creation.

=== Engine

Provides three convenience methods to obtain information about the gpg engine one is currently using. For example:

=== Round trip example using keychain keys

Rather than importing the keys it's possible to specify the recipient when performing crypto functions. Here's a roundtrip example, and note that as this is for a console, the conf.echo = false line is to stop IRB complaining when echoing binary data

Stop IRB echoing everything, which errors with binary data.

Not required for production code

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

recipients can be found using $ gpg --list-keys --homedir ./keychain_location

pub 2048R/A1B2C3D4 2014-01-17

Use that line to substitute your own. 2048R is the key length and type (RSA in this case)

If you want to substitute a non-default keychain into the engine do this:

home_dir = Rails.root.join('keychain_location').to_s

GPGME::Engine.set_info(GPGME::PROTOCOL_OpenPGP, '/usr/local/bin/gpg', home_dir)

Note GPG executable location will change across platforms

crypto = GPGME::Crypto.new options = {:recipients => 'A1B2C3D4'}

plaintext = GPGME::Data.new(File.open(Rails.root.join('Gemfile')))

data = crypto.encrypt plaintext, options

f = File.open(Rails.root.join('Gemfile.gpg'), 'wb') bytes_written = f.write(data) f.close

puts bytes_written

crypto = GPGME::Crypto.new options = {:recipients => 'A1B2C3D4', :passphrase_callback => PassphraseCallback.new('my_passphrase')}

cipthertext = GPGME::Data.new(File.open(Rails.root.join('Gemfile.gpg')))

data = crypto.decrypt cipthertext, options puts data

== Contributing

To run the local test suite you need bundler and gpg:

bundle rake compile # simple rake task to compile the extension rake # runs the test suite

== License

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