dvf5907 has asked for the wisdom of the Perl Monks concerning the following question:

Has anyone tried using GPG.pm on a win32 machine? When I run a script that worked on my linux box, it hangs on my NT box.
After playing around with GPG.pm's 'debug' parameter, I can see that its freezing when the parameters are passed to gpg through IPC. (I believe)
My question is, has anyone else encountered this?
And if so, did you have any luck getting around it?
And if so, how?

Thank you for your time,
Daniel Fisher
dan@webslingerz.com

Replies are listed 'Best First'.
Re: GPG batch mode, GPG.pm, and win32
by ton (Friar) on Apr 13, 2001 at 02:44 UTC
    Heh

    I had this exact same problem a couple months ago. There are three modules on CPAN that deal with GPG: GPG.pm, GnuPG.pm, and Crypt::GPG.pm. I couldn't get any of them to work, so I wrote my own interface. Here it is:

    package GPGWrapper; use IPC::Open2; use IO::File; use POSIX qw(tmpnam); use strict; our @ISA = qw(Exporter); our @EXPORT = qw(GPG_Encrypt GPG_Decrypt GPG_Encrypt_Asym GPG_Decrypt_Asym); our $VERSION = 1.0; # The regular encrypt methods are not in current use because they requ +ire me to write # the data out to a file. This incurs a I/O penalty for no good reaso +n. # The asymmetric methods do this too, but I only call those each once, + # so I don't care about the penalty. # # Actually, there is a good reason: I am unable to pipe in the data st +ream to GPG (although # I _can_ pipe in other things, like the passphrase). Attempting to d +o so hangs the program # indefinately. Incidentally, none of GPG package on CPAN (GPG, GnuPG +, and Crypt::GPG) # solve this problem: GPG also hangs indefinately, GnuPG writes the da +ta to IPC (which Windows lacks), and # Crypt::GPG won't compile on Windows systems. sub GPG_Encrypt($$) { my $passphrase = shift; my $data = shift; my @result; $passphrase .= "\n" if $passphrase !~ /\n$/; my $hackname; my $fh; do { $hackname = tmpnam(); } until $fh = IO::File->new($hackname, O_RDWR | O_CREAT | O_EXCL); binmode($fh); print $fh $data; close $fh; if (eval { open2(*README, *WRITEME, "gpg --no-tty --passphrase-fd +0 --output - --symmetric $hackname"); }) { binmode(README); binmode(WRITEME); print WRITEME $passphrase; close WRITEME; @result = <README>; close README; } wait(); unlink $hackname; return join("", @result); } sub GPG_Decrypt($$) { my $passphrase = shift; my $data = shift; my @result; $passphrase .= "\n" if $passphrase !~ /\n$/; my $hackname; my $fh; do { $hackname = tmpnam(); } until $fh = IO::File->new($hackname, O_RDWR | O_CREAT | O_EXCL); binmode($fh); print $fh $data; close $fh; if (eval { open2(*README, *WRITEME, "gpg --no-tty --passphrase-fd +0 --output - --decrypt $hackname"); }) { binmode(README); binmode(WRITEME); print WRITEME $passphrase; close WRITEME; @result = <README>; close README; } wait(); unlink $hackname; return join("", @result); } # Asymmetric encryption. Used for the handshake. sub GPG_Encrypt_Asym($$) { my $user = shift; # We will encrypt using this user's public ke +y my $data = shift; my @result; my $hackname; my $fh; do { $hackname = tmpnam(); } until $fh = IO::File->new($hackname, O_RDWR | O_CREAT | O_EXCL); binmode($fh); print $fh $data; close $fh; open(README, "gpg --no-tty --quiet --output - --recipient \"$user\ +" --encrypt $hackname |") || die "Error on asymmetric encryption with user $user: $!\n"; binmode(README); @result = <README>; close README; unlink $hackname; return join("", @result); } sub GPG_Decrypt_Asym($) { my $data = shift; my @result; my $hackname; my $fh; do { $hackname = tmpnam(); } until $fh = IO::File->new($hackname, O_RDWR | O_CREAT | O_EXCL); binmode($fh); print $fh $data; close $fh; open(README, "gpg --no-tty --quiet --output - --decrypt $hackname +|") || die "Error on asymmetric decryption: $!\n"; binmode(README); @result = <README>; close README; unlink $hackname; return join("", @result); } 1;
    You should be able to extend this code to call any other GPG methods you desire. The asymmetric methods are in current use, so I'll vouch for their reliability. The symmetric methods worked ok the last time I checked...

    Hope this helps,

    -Ton
    -----
    Be bloody, bold, and resolute; laugh to scorn
    The power of man...

Re: GPG batch mode, GPG.pm, and win32
by dvf5907 (Novice) on Apr 13, 2001 at 03:49 UTC
    Ton,
    Thank you for your help.
    I'm trying the module that you've posted, but I'm having hard time figuring out which subroutine to use where...
    (How can GPG_Decrypt_Asym decrypt if you don't send it a passphrase?)
    Could you post some client code too?

    Thank you for your time,
    Dan
      Oddly enough, GPG asymmetric decryption doesn't need a username... it somehow knows which one to use. Here's some code ('Ton' is a public/private key that I had previously added to GPG's keyring. UPDATE: 'Ton' also does not have a passphrase.):
      use GPGWrapper; use strict; my $data = "Hello World!\n"; my $user = "Ton"; print $data; $data = GPG_Encrypt_Asym($user, $data); print $data; $data = GPG_Decrypt_Asym($data); print "\n$data\n"; $data = GPG_Encrypt('dumb password', $data); print $data; $data = GPG_Decrypt('dumb password', $data); print "\n$data\n";
      The code assumes that you have the GPG executable in the system path. If it isn't, you'll have to put the path in the open2 statements. Hope this helps...

      -Ton
      -----
      Be bloody, bold, and resolute; laugh to scorn
      The power of man...

        In asymmetric decryption, the key ID of the intended recipient's key is contained in the encrypted stream, so GnuPG automatically chooses that key for the decryption. dvf5907's question, though, is how do you pass the key passphrase to GnuPG since the only parameter to GPG_Decrypt_Asym is the encrypted datastream?

        From your code, I can only assume that your private key is not itself encrypted with a passphrase, otherwise, GnuPG would require that passphrase to decrypt the key to decrypt the data.

        --isotope
        http://www.skylab.org/~isotope/