Using Passphrase Callback in Ruby Gpgme

Using passphrase callback in ruby gpgme

Sample of callback you can find in the following working example. It signs a file in detached mode, i.e., the signature file is separated from the original file. It uses the default keyring at ~/.gnupg or something like that. To use a different directory for your keyring, set the environment variable ENV["GNUPGHOME"]="" before call GPGME::sign().

#!/usr/bin/ruby
require 'rubygems'
require 'gpgme'

puts "Signing #{ARGV[0]}"
input = File.open(ARGV[0],'r')

PASSWD = "abc"

def passfunc(hook, uid_hint, passphrase_info, prev_was_bad, fd)
puts("Passphrase for #{uid_hint}: ")
io = IO.for_fd(fd, 'w')
io.write(PASSWD+"\n")
io.flush
end

output = File.open(ARGV[0]+'.asc','w')

sign = GPGME::sign(input, {
:passphrase_callback => method(:passfunc),
:mode => GPGME::SIG_MODE_DETACH
})
output.write(sign)
output.close
input.close

how to bypass pinentry (passphrase screen) while decrypting a file using gpgme

I am unable to bypass the passphrase or pinentry screen, but I used gpg-agent options like default-cache-ttl to set the cache time. So that from the second attempt, the pinentry is going to retrieve the cached passphrase and will reset the timer on defaul-cache-ttl.

There is one more called max-cache-ttl option, even after the successfull retrieval of cached passphrase and reset of default-cache-ttl, this option doesn't change its timer and expires the cached passphrase after the set timeout.

For ex: If I set both of them for 10hrs (i.e., 36000sec), if I call the decrypt after 5hrs, default is going to reset its timer and now we have 10more hours. But the max is going to expire after the initial 10hours and thus removes the cached passphrase after 10hours.

One more problem I found is, session issue with gpg-agent. i.e., if I open a new session and try to decrypt, it doesn't happen and errors out that gpg-agent is not available for this session. I wrote some shell script and put it on bashrc so that it starts as soon as a new session is started

Why does GPGME / GnuPG use pinentry for password input?

GnuPG starting with 2.1 removed the most critical private key functionality into the gpg-agent, to reduce the attack surface on the most intimate secrets -- the private keys.

Such a callback would not only expose the passphrase to the application you're writing (which probably means an even larger attack surface than GnuPG would be), but also GnuPG gets aware of the passphrase.

If you really need to control entry of the passphrase from your application, you have several choices.

Implementing Pinentry

The information flow would then be: your application calls GnuPG through GPGME, GnuPG requests some private key operation from gpg-agent, which again asks your application for the passphrase. Be aware this will only work if you also started the gpg-agent with appropriate pinentry configuration (you might have to start another instance, separate from the one already running on your system).

gpg-preset-passphrase

The most important use case of passing the passphrase directly is in headless daemons, where no humans waits for entering the passphrase. GnuPG also brings a small utility gpg-preset-passphrase (on Debian and derivatives, it is installed as /usr/lib/gnupg2/gpg-preset-passphrase), which also can be used to precache the passphrase (so it is not queried for a configurable time).

Pinentry Loopback

With GnuPG 2.1, another option was added: in gpg-agent, you can allow pinentry loopback with the allow-loopback-pinentry option. An additional parameter pinentry-mode set to loopback in GnuPG/GPGME should allow you to handle passphrase interaction using passphrase_cb again.

But: consider this exposes the passphrase not both your application and GnuPG, and might prove to be a (possibly minor but existing and maybe unnecessary) security risk. Also, GnuPG 2.1 is not yet widely spread, which might be a problem if you do not control the environment.



Related Topics



Leave a reply



Submit