ueno/ruby-gpgme

GPGME::Ctx.decrypt returns empty GPGME::Data

Opened this issue · 4 comments

I've been pulling my hair out over this. I'm having an empty GPGME::Data object returned every time that I attempt to decrypt a valid GPG message, without an error.

GPGME::Ctx.new(:passphrase_callback => method(:passphrase_callback), :progress_callback => method(:progress_callback)) do |c|
    p last_response.body.force_encoding('utf-8')
    data = GPGME::Data.new '-----BEGIN PGP MESSAGE-----\n...'
    data.seek 0
    p data.read
    data.seek 0
    msg = c.decrypt data
    msg.seek 0
    p msg.read
    msg.seek 0
end

All those .seek 0 and .read lines are to debug, and here's the output from running this code:

"-----BEGIN PGP MESSAGE-----\n..."                           
""17: 1287/0                                                                                                                                                                                                                                                                

.to_s also returns an empty string. 17: 1287/0 is (I think?) a result of the :progress_callback method, which is the same as is used in your example:

def progress_callback(hook, what, type, current, total)
    $stderr.write("#{what}: #{current}/#{total}\r")
    $stderr.flush
end

GPGMe version is GnuPG 1.4.11 on a linux-based machine (string is encrypted using ruby-gpgme on the same machine).

ueno commented

could you provide a self-contained test case? I can't reproduce it with the code below, where the cipher is created with:

$ echo a > a
$ gpg --symmetric --armor --output - a

passphrase is "test".

require 'gpgme'

def passphrase_callback(hook, uid_hint, passphrase_info, prev_was_bad, fd)
  $stderr.write("Passphrase for #{uid_hint}: ")
  $stderr.flush
  begin
    system('stty -echo')
    io = IO.for_fd(fd, 'w')
    io.puts(gets)
    io.flush
  ensure
    (0 ... $_.length).each do |i| $_[i] = ?0 end if $_
    system('stty echo')
  end
  $stderr.puts
end

def progress_callback(hook, what, type, current, total)
    $stderr.write("#{what}: #{current}/#{total}\r")
    $stderr.flush
end

GPGME::Ctx.new(:passphrase_callback => method(:passphrase_callback), :progress_callback => method(:progress_callback)) do |c|
    data = GPGME::Data.new <<EOF
-----BEGIN PGP MESSAGE-----
Version: GnuPG v1

jA0EAwMCGOL8CjJfFkVgyRmhoGzOBEBQR5/mj4iH9KSYsJo/tmbtt1rz
=1exF
-----END PGP MESSAGE-----
EOF
    data.seek 0
    p data.read
    data.seek 0
    msg = c.decrypt data
    msg.seek 0
    p msg.read
    msg.seek 0
end

this produces:

$ ruby test.rb 2>/dev/null
"-----BEGIN PGP MESSAGE-----\nVersion: GnuPG v1\n\njA0EAwMCGOL8CjJfFkVgyRmhoGzOBEBQR5/mj4iH9KSYsJo/tmbtt1rz\n=1exF\n-----END PGP MESSAGE-----\n"
"a\n"
  • The test case you have given works.
  • The test case in this gist works, with this output (same passphrase_callback / progress_callback)
"a"                                                                                                                                                                                                                                                                         
"\x8C\r\x04\x03\x03\x02\f.\xE1A\x18\xDC\x99\a`\xC9\e\xCE\xB3\x85\x7F\r\xD4\xFE\xA8-CG?e{J0K\xF6\xAE\xB2\xF1\xCB$\xE6\x88\x9B\x1E"                                                                                                                                           
"a"
  • As soon as we enter the realm of Asymmetric encryption, the example no longer works, as encrypt and decrypt no longer give an output.
"a"

Will inspect further, as encrypt is working elsewhere...?

I've confirmed how I've fixed this but I'm baffled as to how this would act as the fix and it appears to be unintended behavior.

What seems to have done the trick was enabling :armor => true on the creation of the GPGME::Ctx object. I'm unsure that is supposed to make a difference - if that option is still disabled, it should still be able to decrypt ASCII-Armored objects, correct?

I'm going to leave this issue open as this appears to be a bug with the library. It is also possible it's a bug with an older version of GPG (I am stuck on 1.4.11) or it's possible it's entirely user error and that's noted somewhere I didn't read.

ueno commented

I suspect this is #12 or related to it. that is, the data is truncated at encryption phase.