PHP, PGP, GPG and you…

โ€”

by

in

Ah, encryption. I recently had to use GPG/PGP to encrypt some data to store in a database with PHP. On the way to doing that I wound up doing a small proof of concept page. The code is shown below.

In essence, the steps are:

  1. Pull the clear text from the form at $_POST[‘plain’]
  2. Encrypt the data into $encrypted_message
  3. Put the encrypted data back into $_POST[‘crypted’]

I am storing the data back into the POST array so I can process it later with some code that is expecting to deal with data already in the form. That simply simulates that the encrypted data was POST’ed.

The form below also displayed the encrypted output. Be aware that there may be some errors in the HTML as I had to edit it down from the live client code for posting here and I haven’t tested it too heavily. Also note that it will display an encrypted text even on first run, it is simply encrypting nothing but by the nature of PGP/GPG it looks like something ๐Ÿ™‚

This code was adapted from several examples around the net, in particular the PHP manual pages for proc_open.

<?php
    $gpg = ‘/usr/bin/gpg’;
    $switches = ‘ –always-trust -a –batch –no-tty’;
    $recipient = ‘some@pgp_user.com‘;
    $command = “$gpg $switches -e -r $recipient”;

    // take in the plain text data
    $message = $_POST[‘plain’];

    $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(“file”, “/tmp/error-output.txt”, “a”) // stderr is a file to write to
    );

    putenv(“GNUPGHOME=/var/www/.gnupg”);
    $process = proc_open($command, $descriptorspec, $pipes);
    if (is_resource($process)) {
        // $pipes now looks like this:
        // 0 => writeable handle connected to child stdin
        // 1 => readable handle connected to child stdout
        // Any error output will be appended to /tmp/error-output.txt

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

        while (!feof($pipes[1])) {
            $encrypted_message .= fgets($pipes[1], 1024);
        }
        fclose($pipes[1]);

        // It is important that you close any pipes before calling
        // proc_close in order to avoid a deadlock
        $return_value = proc_close($process);
    }

    $_POST[‘crypted’] = $encrypted_message;
?>

<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01 Transitional//EN”  “http://www.w3.org/TR/html4/loose.dtd”>
<html>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=iso-8859-1″>
<title>GPG Proof of concept page.</title>
</head>

<body>
    <form name=”form1″ method=”POST” action=”gpg.php”>
    <p>Plaintext Data:</p>
    <p>
    <textarea name=”plain” cols=”80″ rows=”15″ id=”plain”><?php echo $_POST[‘plain’]; ?></textarea>
    </p>
    <p>
    <input type=”submit” name=”Submit” value=”Encrypt”>
    </p>
    <p>Encrypted Data (will always appear, even if blank input): </p>
    <p>
    <textarea name=”crypted_display” cols=”80″ rows=”15″ id=”crypted_display”><?php echo $_POST[‘crypted’]; ?></textarea>
    </p>
    <input name=”crypted” type=”hidden” id=”crypted”>
    </form>
</body>
</html>