Gpg functionality in server?

I’d like to encrypt/decrypt and manage gpg keys but am not sure how best to do this. I see a gem gpgme[1] that looks promising. Is this something that could be added? What is the process for determining if a gem can safely be added (selinux, fips. etc)?

[1] https://rubygems.org/gems/gpgme/versions/2.0.12

I’m not sure how to use gpgme, has anyone else used it?

To get encrypted file: curl --output rhel7-etcd.sig
https://access.redhat.com/webassets/docker/content/sigstore/rhel7/etcd@sha256=35fdf949dd7698ab5def00c504293be5fb5a5af29066a6e1684cf81a80bd6ce2/signature-1
To get public key: wget https://www.redhat.com/security/fd431d51.txt

I’m not sure how to decrypt rhel7-etcd.sig

It’s two actions, one is download the public key, and the second is to import it.
But first to list and see that it is not listed in the keyring.

So for importing (did not test it myself):

require 'openuri'
require 'gpgme'

open('https://www.redhat.com/security/fd431d51.txt') do |f|
  GPGME::Key.import(f)
end

To Encrypt:

require 'gpgme'

crypto = GPGME::Crypto.new
crypto.encrypt "Hello world!", :recipients => "someone@example.com"

To Decrypt:

require 'gpgme'
crypto.decrypt File.open("text.gpg")

To Verify encryption:

require 'gpgme'
sign = crypto.sign "Some text"
data = crypto.verify(sign) { |signature| signature.valid? }

@ik5 - Did you try to decrypt the file rhel7-etcd.sig? Maybe I am misunderstanding how gpgme is supposed to work. That file decrypts fine with gpg -d locally but in ruby I get error of “No data”. Any guidance very much appreciated!

I could make gpg system calls instead of using the gem but I don’t think the entire application should rely on the system gpg. Or maybe that’s alright? Users will be managing multiple keys in different organizations so I’d prefer it be something like the gem functionality.

Yes, I have imported the key and verified it, and it told me:

The code itself uses libgpg and wrapping up some gpg commands to do it, so it’s more or less the same :slight_smile:

What am I doing wrong here?

#!/usr/bin/env ruby

require 'open-uri'
require 'gpgme'

open('https://www.redhat.com/security/fd431d51.txt') do |f|
  GPGME::Key.import(f)
end

crypto = GPGME::Crypto.new
open('https://access.redhat.com/webassets/docker/content/sigstore/rhel7/etcd@sha256=35fdf949dd7698ab5def00c504293be5fb5a5af29066a6e1684cf81a80bd6ce2/signature-1') do |f|
  crypto.decrypt(f)
end

If I read that right you’re loading a public key and then trying to decrypt with it, but decryption requires the private key. Public keys can be used for encrypt (to send data to the private-key-holder) and verify (to prove the private-key-holder wrote that text). Do you not need crypto.verify(f)?

1 Like

To continue what Greg has said, also it should be

GPGME::Key.import(f.read)

Or

GPGME::Key.import(open('https://www.redhat.com/security/fd431d51.txt').read)

After testing, open returns a StringIO, and it seems like the import method does not know how to read it, so the read part returns the content as a string instead.

Sorry for misleading in my first comment, wrote it from my memory and not from testing it first.

Alright, this was confusion on my part. The file is compressed. The file itself is uncompressed during the call to verify.

    uncompressed = crypto.verify(f.read) do |signature|
      signature.valid?
    end

Thanks for the help!

2 Likes