http://www.perlmonks.org?node_id=241103

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

Dear Monks!

I ask your help in a little mystery on which I've been beating my head. Solving it will make reasonable public key encryption on old perls a reality, I think. The purpose is to encrypt some user data which can be decrypted on a client PC with WinPT (Gnu's PGP-compatible GPG program with Windows Privacy Tray freeware).

First, the problem in short: This script works just fine from the command line, spitting out a PGP-style ascii-armored block of encrypted data. But when run in a browser, it dies on the line where it prints to the tied handle (see below).

The longer story: I need to encrypt some data using public key encryption on a server which has perl 5.00503 / FreeBSD 4.3. All the nice looking modules including the so-called pure perl ones in reality require a web of dependencies that seem to roll right up to perl 5.8.

Since this server also has limited resources, there is not enough memory to build perl 5.8, which I tried. I also built bits and pieces of it and other modules to get around various nitpicking errors like using strict, symbols not being defined in old Fcntl, constant not defined in XLoader.pm, and trouble with Math::Pari and File:: modules. One nasty problem came up in that I wanted to use an IO handle to work with another GPG module and discovered that in this version of perl there are some problems with seek on these handles which make them less than full-fledged. Anyway, that sheaf of strategies and all the Crypt:: modules (well I didn't try all of them of course..) were not the Way To Do It.

I found GnuPG, which seems nice. It has a tie interface which lets you print to a tied filehandle which encrypts your data into a buffer, then you can read the encrypted data back out. This is exactly what I want.

Run on the command line it works as mentioned above. But run as a CGI it dies at the print CIPHER $plaintext line, printing to the browser a wierd error.. "error on write: Broken pipe". I have a theory that STDOUT gets trashed by this tying,.. anyway as brain cells have undergone sludge conversion I request the help of more experienced or masochistic monks!

#!/usr/local/bin/perl -w print "Content-type: text/html\n\n"; use lib qw(/home/www/davxw000/data/sitelib); use CGI::Carp qw(fatalsToBrowser warningsToBrowser); use GnuPG::Tie::Encrypt; $s = "This is a test.\nAnd another test."; $m = 'test@test.com'; # registered in gpg key ring $e = &encrypted($s,$m); print "Encrypted: <PRE>\n" . $e; sub encrypted { my ($plaintext,$recip) = @_; my $encrypted = ""; tie(*CIPHER,'GnuPG::Tie::Encrypt',armor=>1,recipient=>$recip); # tie interface. open buffer print CIPHER $plaintext; # and encrypt into buffer. $encrypted .= $_ while (<CIPHER>); # now read from buffer close CIPHER; # the encrypted data untie *CIPHER; # and close buffer return $encrypted; }
Thank you very much for your help. If you have any idea of what the problem is, or if anyone has been able to build pgp or gpg perl modules on an old perl I'd like to know. My last chance beyond this would be to attempt to open a pipe right to the binary and see if I can deal with that. I'd rather not be sending the data to another server to be encrypted even over SSL. FYI code also in mattr's scratchpad.

Regards,

Matt