ruby-gpgme
ruby-gpgme copied to clipboard
Unable to import key
I'm unable to import a key file. I'm using ruby 1.9.3-p448
running:
require "gpgme"
begin
key = GPGME::Key.import(File.open("private.key"), {:password => "redacted"})
rescue GPGME::Error => g
puts g.inspect
puts g.message
puts g.code
puts g.source
end
Output
#<GPGME::Error: GPGME::Error>
Inappropriate ioctl for device
32870
7
I have gpg, MacGPGTools and gpg-agent installed on my system. Am I missing something?
I have the same error when I try:
ctx = GPGME::Ctx.new
Was these a solution for this error?
Because ruby-gpgme is a wrapper for the C code, the errors are sometimes obtuse and not immediately helpful.
How was the key exported, as in, was it a GPGME export? Or is it from somewhere else? For example, OpenSSL keys can't be imported because the key formats are different.
Update: I reinstalled pgpme with brew and after that the "Inappropriate ioctl for device" device error was gone. However, I ran into getting a empty string with, so I added decrypted.seek(0) per the other fix request. Is this still the most appropriate way to decrypt the file?
require 'rubygems' require 'gpgme'
encrypted_data = GPGME::Data.new(File.open("list.csv.pgp")) key = GPGME::Data.new(File.open("key.gpg"))
ctx = GPGME::Ctx.new :password=> thepassword' ctx.import_keys key
decrypted = ctx.decrypt encrypted_data decrypted.seek(0)
File.write('list.csv', decrypted.read)
Yeah, using the GPGME::Ctx classes is fine, and if that works for you, then no problem.
I tend to use keys in the keychain, so rather than importing the keys I specify the recipient when performing crypto functions. Here's a roundtrip example, and note that I wrote this for a console, the conf.echo = false line is to stop IRB complaining when echoing binary data, and is not required for production code
conf.echo = false # Stop IRB echoing everything, which errors with binary data
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
Hello there,
Ran into this problem today. It looks like it's something to do with the bundling/installing process of the gpgme gem and how it connects to the system gpg install. If you have gpg/gpgme installed natively on your system, everything works, but if not, you'll hit this error.
If you're seeing this error:
- uninstall the gem or remove it from your bundle,
- install gpg/gpgme natively (i.e., brew install gpg)
- rebundle/install the gpgme gem
At least, that's what worked for me.
I know the issue is not related to heroku stack.. but just wondering if someone can help me.
The very same problem happens on new Heroku Cedar14 stack... whenever I try to do something like: GPGME::Key.import(File.open("private.key"))
I get the "Inappropriate ioctl for device" error.
Same does not happen on Heroku Cedar.
Also had the same problem locally, but reinstalling gpg and the gem solved the issue.
Not sure what to do from here..
+1 on having this issue with Cedar14
@andrehjr Were you able to solve it?
@recurrence not yet.. we also tried different implementations, but new priorities came up..
One idea that one of the members of my team brought up was to use: https://github.com/ddollar/heroku-buildpack-apt and install gpgme from there instead...
If you try that and if it works, please let me know :)
I tried a custom built gpgme and it also failed.
I ended up using shell commands :)
I don't know much about Heroku, but if it is sort of chroot, perhaps it might be failing in GPGME's use of ttyname_r: http://article.gmane.org/gmane.comp.encryption.gpg.devel/10777 https://lists.archlinux.org/pipermail/arch-projects/2011-October/001953.html
maybe the first step would be to isolate the problem between the gem and GPGME C library. since the library has a test case of --import, you can run it with:
$ gem install -i tmpdir gpgme -- --disable-clean
$ cd tmpdir/gems/gpgme-2.0.8/ext/gpgme/tmp/.../ports/gpgme/1.5.3/gpgme-1.5.3
$ make check
Just tried make check on Heroku.
Here's the output: https://gist.github.com/vovayartsev/a466aa82320b84f32b13
I'm having this problem as well. I can confirm that it breaks in Cedar-14, but works perfectly fine in Cedar-10.
My current guess is that the version of GPGME installed by ruby-gpgme needs to be changed here. Perhaps the versions of libassuan or libgpg-error need to be changed, too; I don't actually know what they do. :)
Does this sound like an avenue worth exploring?
A correction: Circle CI has GPGME installed on their VMs, so I'm no longer confident that Ubuntu 12.04 is compatible with this gem (without reinstalling gpgme). I edited the above to reflect this.
2.0.10 gem might fix the issue, as it contains gpgme 1.6.0, which has a fix to the ttyname_r error handling: http://git.gnupg.org/cgi-bin/gitweb.cgi?p=gpgme.git;a=commit;h=028a0ef3336c5180797fb247448683195376c007
:+1: @ueno, upgrading to 2.0.10 on Heroku fixed the issue for me.
Since this issue is still open ....
Is it intended that GPGME::Key.import() can be used to import public keys from a public key server? If so, are there undocumented configurations necessary?
I barely remember, but ruby-gpgme doesn't seem to export the gpgme_op_import_keys C function which imports keys from a keyserver. Could you open a separate issue if you need that feature?
@dansketcher Your comment was really helpful for my implementation and cleaner. I wished the GPGME github page provided clear example like that.
thanks and Great work
I'd completely forgotten I'd written this :) Now integrated into the Readme! https://github.com/ueno/ruby-gpgme#round-trip-example-using-keychain-keys
Trying to do some decryption today however, I keep getting the password GUI prompt to enter the passphrase. Is there any way to bypass the password prompt
Use GPGME 1.4, or a dummy pinentry program per https://github.com/ueno/ruby-gpgme/pull/126 or see the note on the pinentry loopback in the same PR
@adet4ever Setting the pinentry_mode to the following resolved the password prompt from showing up anytime I wanted to perform a crypt operation.
crypto = GPGME::Crypto.new(pinentry_mode: GPGME::PINENTRY_MODE_LOOPBACK)
Leaving a comment here for future readers around the Inappropriate ioctl for device issue. For me it was source 5, code 32870, following closely the example. Using the above line in combination with the example PassphraseCallback made the issue go away. For clarity :
crypto = GPGME::Crypto.new(pinentry_mode: GPGME::PINENTRY_MODE_LOOPBACK)