gnuPG and Php

Adi Linden adil@adis.on.ca
Tue Feb 25 23:27:02 2003


> I can use it from command line, but would like either a cgi or php way 
> to use gnuPG from a webpage.

I am still new to gnupg but perhaps I can help. I read some info on it, 
one suggested piping the data to encrypt into gpg via stdin using 
backticks:

    `echo $data | gpg ....`

Unfortunatly many nasty things happened when I did that, because i was 
sending a xml form to gpg. I suspect quoting got mixed up. Instead I used 
popen to write the data to gpg and output the data to a temporary file. I 
figured that even in scenary where the site is hosted on a shered server 
there is little risk in writing the ascii armored output of gpg to a file, 
since the webserver only has the public key but no private key.

Here's the php function I came up with. The global variables 
$email_recipients, $gpg_path and $gpg_home need to be set prior to calling 
this. $email_recipients is an array of recipient email addresses, 
$gpg_path is the path and name of gpg (i.e. /usr/bin/gpg) and $gpg_home is 
the directory containing the key ring.

/*
 * enc_gpg -- encode data using gpg
 *            To make this work I open a pipe to gpg and write the output
 *            to a file. This should be safe since the private key to
 *            decrypt the file is nowhere on the server.
 *
 * &$data    - data is modified only on success
 * returns   - true on success
 */
function enc_gpg(&$data)
{
    global $email_recipients;
    global $gpg_path, $gpg_home;
    
    /* Create a temporary file name for gpg */
    $tmpfile = '/tmp/phpbasket_' . md5(uniqid(time()));
        
    /* Build the command line for gpg */
    $cmd  = $gpg_path . ' --always-trust --batch --no-tty -e -a ';
    $cmd .= ' --no-secmem-warning --homedir ' . $gpg_home;
    $cmd .= ' -o ' . $tmpfile;
    foreach ($email_recipients as $r) {
        $cmd .= ' -r ' . $r;
    }   
        
    /* Pipe data to gpg */
    $fp = (popen($cmd, 'w'));
    if (!$fp) {
        unlink($tmpfile);
        return false;
    }
    fwrite($fp, $data);
    pclose($fp);
   
    /* Read data from temporary file */
    $fp = (fopen($tmpfile, 'r'));
    if (!$fp) {
        unlink($tmpfile);
        return false;
    }
    $res = fread($fp, filesize($tmpfile));
    fclose($fp);
    unlink($tmpfile);
    
    /* Verify we have valid encrypted data */
    if(ereg("-----BEGIN PGP MESSAGE-----.*-----END PGP MESSAGE-----", $res)) {
        $data = $res;
        return true;
    }       
    return false;
}           
 
Hope this is of use...

Adi