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 require me to write # the data out to a file. This incurs a I/O penalty for no good reason. # 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 stream to GPG (although # I _can_ pipe in other things, like the passphrase). Attempting to do 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 data 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 = ; 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 = ; 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 key 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 = ; 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 = ; close README; unlink $hackname; return join("", @result); } 1;