Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to import key #26

Open
apanzerj opened this issue Jul 25, 2013 · 24 comments
Open

Unable to import key #26

apanzerj opened this issue Jul 25, 2013 · 24 comments

Comments

@apanzerj
Copy link

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?

@yoshie902a
Copy link

I have the same error when I try:

ctx = GPGME::Ctx.new

Was these a solution for this error?

@dansketcher
Copy link
Collaborator

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.

@yoshie902a
Copy link

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)

@dansketcher
Copy link
Collaborator

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

@jeffreytheobald
Copy link

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.

@andrehjr
Copy link

andrehjr commented Jan 6, 2015

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..

@recurrence
Copy link

+1 on having this issue with Cedar14

@andrehjr Were you able to solve it?

@andrehjr
Copy link

@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 :)

@recurrence
Copy link

I tried a custom built gpgme and it also failed.

I ended up using shell commands :)

@ueno
Copy link
Owner

ueno commented Feb 12, 2015

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

@ueno
Copy link
Owner

ueno commented Feb 13, 2015

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

@vovayartsev
Copy link

Just tried make check on Heroku.
Here's the output: https://gist.github.com/vovayartsev/a466aa82320b84f32b13

@slepkin
Copy link

slepkin commented Jun 2, 2015

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?

@slepkin
Copy link

slepkin commented Jun 2, 2015

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.

@ueno
Copy link
Owner

ueno commented Aug 27, 2015

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

@jorgevaldivia
Copy link

👍 @ueno, upgrading to 2.0.10 on Heroku fixed the issue for me.

@lhagemann
Copy link

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?

@ueno
Copy link
Owner

ueno commented Mar 7, 2017

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?

@adet4ever
Copy link

@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

dansketcher added a commit that referenced this issue Nov 29, 2018
@dansketcher
Copy link
Collaborator

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

@adet4ever
Copy link

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

@dansketcher
Copy link
Collaborator

Use GPGME 1.4, or a dummy pinentry program per #126 or see the note on the pinentry loopback in the same PR

@joshuamcginnis
Copy link

@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)

@dvkch
Copy link

dvkch commented Aug 25, 2020

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)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests