PDA

View Full Version : PHP to send PGP mail (port of Rich's pgpformail.pl)


kitchin
05-07-2005, 04:18 AM
I figured out how to PGP-encrypt text using a PHP script, and here it is in case it might help someone else.

No, I did not port all of Rich's famous
pgpformail.pl script (http://www.rsmarketing.com/pgp/) to PHP. I just figured out the PGP "plumbing" part. In other words, this is how to call the external program "/usr/bin/pgpe" from PHP.

So this works at Futurequest:


<?php
// A snippet, not a whole function.

/////////////////////////
// Some PHP code to port a section of Rich's pgpformail.pl (v4.0)
// See: http://www.rsmarketing.com/pgp/
// Start at the line....
/////////////////////////

# The PGP encryption command
// $pgpcmd = "$pgpprog -af --batchmode=1 -r \"$Config{'pgpuserid'}\" -u \"$Config{'pgpuserid'}\" ";
// port to something like:
$pgpcmd = "$pgpprog -af --batchmode=1 -r \"$Config[pgpuserid]\" -u \"$Config[pgpuserid]\" ";

if ($pubring) {
$pgpcmd.= "--pubring=$pubring ";
}


// you probably already defined these:
// $pgpprog = '/usr/bin/pgpe';
// $pgptext: should be a clear-text string

$pgpout= '';
$pgperr= '';

// php "plumbing," see http://php.net/proc_open

// magic array, see the manual:
$descriptorspec = array(
0 => array("pipe", "r"), // stdin is a pipe that the child will read from
1 => array("pipe", "w"), // stdout is a pipe that the child will write to
2 => array("pipe", "w") // stderr ?? instead of a file
);

// the essential step, call the program:
$process = proc_open($pgpcmd, $descriptorspec, $pipes);
if (! is_resource($process)) {
return false; // or however you want to handle errors
}

fwrite($pipes[0], $pgptext);
fclose($pipes[0]);

while($s= fgets($pipes[1], 1024)) {
$pgpout.= $s;
}
fclose($pipes[1]);

if ($pgpdebug) {
while($s= fgets($pipes[2], 1024)) {
$pgperr.= $s;
}
}
fclose($pipes[2]);

/////////////////////////
// End of port. You now have the ecrypted text in $pgpout,
// and possibly error text in $pgperr. Use mail() to mail them.
/////////////////////////

?>


I guessed on the stderr stuff, but it works. Also, you can shorten $pgpcmd, but I guess there's no reason to. :) By the way, there is always some error text, but usually it is not important.

I don't know how much FQ's Secure_Mode (different than standard PHP "safe mode") has to do with this working. I tried some code posted at php.net using the command "popen()" instead of "proc_open()" and it did not make good PGP text.

dank
05-09-2005, 03:13 AM
Interesting ... I'll have to take a closer look at it when I'm a bit less sleepy. I tried this a couple years back and thought it was deemed not possible at the time, but maybe that was before Secure_Mode came to be?

Dan

kitchin
05-09-2005, 12:56 PM
Yes, I'd guess Safe Mode would be a problem. Glad to have Secure_Mode!

Here's an update.

I ran into a small problem with line endings. The end user is on Windows, so I used to convert LF to to CRLF line endings before encrypting. That worked in Perl (with "open3"), bit in PHP (with "proc_open") it produced text I could not decrypt.

Solution:
change -af to -aft

That puts it in "textmode" and everything works. (I do not change any line endings before encrypting.)