If you decide to use the PGP family of software, there are two parts to the puzzle: You need PGP on your Web server (to encrypt) and PGP on the recipient's machine (to decrypt). The best place to start is www.pgp.com, where you can follow the links to either download for free or purchase the pieces of the PGP puzzle. If you're using PGP for noncommercial purposes, it's free. If you're using PGP commercially, you must pay for it.

Once you've followed the installation and key-creation procedures outlined in the PGP documentation and you have received (or created) a valid public key for the person who is to receive encrypted data, there's one more step that could get a little tricky. In this tutorial, PHP scripts will invoke the encryption process, and the public key has to be on the key ring of the user invoking the encryption. On the Web server, PHP usually runs as user "nobody" or "www" or as the user for your Web server. It could even be your own login name. Whichever user is assigned to PHP/the Web server, "nobody", "www," etc. must have a PGP key ring, and that key ring needs to hold the public key for any person to whom you wish to send encrypted mail by using PHP to invoke the encryption process.

Most ISPs have PGP installed on their Web servers, and you may very well have access to it for the encryption side of the equation. If you don't have direct control over the server, be sure to check with your system administrator about the availability of PGP and how to add keys to the public key rings of users. Otherwise, follow the steps below to add a key to the key ring on the system.

1. Export an ASCII version of a user's public key, following the steps in the PGP documentation.

2. Upload the public key text file to the PHP user's directory on the server (/home/www/, for example).

3. Log on to your Web server via telnet or SSH, or walk over to it and type at the keyboard if you are so lucky.

4. Become the PHP user. This step could involve the su command, such as: su www.

5. Add the key to the key ring: pgpk -a /path/to/keyfile.

6. Assign a trust level to the key: pgpk -e [keyname].

7. Select "always trust."

8. Test this process by creating an input file that contains something unimportant, such as the line "I want to test this encryption sequence."

9. Manually issue the command to encrypt the test file: pgpe -r [keyname] -o [output file] -a [input file].

10. When prompted to trust the key file, answer Y.

11. The output file will contain the encrypted version of the text in the input file.

If you're stuck on any of these steps or if you don't have access to the key ring of the PHP user, contact your system administrator. Otherwise, you can skip ahead to Invoking Public-Key Encryption.

If you decide to use the open-source GnuPG software, you have to do two things: You need to put GnuPG on your Web server (to encrypt) and place GnuPG on the recipient's machine (to decrypt). To get started, visit www.gnupg.org and download the proper version based on your operating system. Then follow the installation and key-creation procedures outlined in the GnuPG documentation.

Once you've followed the installation and key-creation procedures outlined in the GnuPG documentation and you have received (or created) a valid public key for the person who is to receive encrypted data, there's one more step that could get a little tricky. In this tutorial, PHP scripts will invoke the encryption process, and the public key has to be on the key ring of the user invoking the encryption. On the Web server, PHP usually runs as user "nobody" or "www" or as the user for your Web server. It could even be your own login name. Whichever user is assigned to PHP/the Web server, "nobody", "www," etc. must have a GnuPG key ring, and that key ring needs to contain the public key for any person to whom you wish to send encrypted mail by using PHP to invoke the encryption process.

Most ISPs have PGP rather GnuPG installed, so check with your system administrator regarding the availability or installation of the software on the server side. Otherwise, if you have the GnuPG software on your server, follow the steps below to add a key to the key ring on the system.

1. Export an ASCII version of a user's public key, following the steps in the GnuPG documentation.

2. Upload the public key text file to the PHP user's directory on the server (/home/www/, for example).

3. Log on to your Web server via telnet or SSH, or walk over to it and type at the keyboard if you are so lucky.

4. Become the PHP user. This step could involve the su command, such as: su www.

5. Add the key to the key ring: gpg --import /path/to/keyfile.

6. Edit the key to assign a trust level: gpg --edit-key [keyname]

7. At the gpg command prompt, type "trust".

8. Select "I trust fully."

If you're stuck on any of these steps or if you don't have access to the key ring of the PHP user, contact your system administrator. Otherwise, you can move on to Invoking Public-Key Encryption.


Before using PHP to invoke any sort of encryption, the data has to come from somewhere. In this example, we'll create an HTML form to accept data, and the PHP script will encrypt and email the results to a specified recipient. The recipient's public key must be on the PHP user's key ring, and must have been assigned a level of trust.

To begin, open your favorite text editor, create a file called secret_form.html, and start with your basic HTML tags. Then give the page a heading:

<h1>Form to Send Secret Stuff</h1>
To create the form code, assume that step 2 in the sequence will be a PHP script called do_sendsecret.php and that your form will use the POST method:

<FORM method="POST" action="do_sendsecret.php">
Next, create two text fields and a text area to capture the message variables:



Your Name:

<INPUT type="text" name="sender_name" size=25></p>


Your E-Mail Address:

<INPUT type="text" name="sender_email" size=25></p>



The Secret Message:

<TEXTAREA name="secret_msg" cols=35 rows=5></TEXTAREA></p>

Finally, add the Send Secret Message button:



<INPUT type="submit" value="Send Secret Message"></p>
And remember, don't forget those closing tags!

Your HTML source code should look something like this:

<HTML>
<HEAD>
<TITLE>Secret Form</TITLE>
</HEAD>
<BODY>
<h1>Form to Send Secret Stuff</h1>

<FORM method="POST" action="do_sendsecret.php">



Your Name:

<INPUT type="text" name="sender_name" size=25></p>



Your E-Mail Address:

<INPUT type="text" name="sender_email" size=25></p>



The Secret Message:

<TEXTAREA name="secret_msg" cols=35 rows=5></TEXTAREA></p>



<INPUT type="submit" value="Send Secret Message"></p>

</FORM>
</BODY>
</HTML>


Place this form on a secure (SSL) Web server. Secure Web servers encrypt the data flowing between the user's Web browser and your server. Using this form/script sequence on a non-SSL server will still work but will defeat the purpose of sending encrypted data. Unless your form is located on a secure server, the information is transmitted in cleartext, and encryption won't occur until the PHP script runs. For more information about SSL, start with the Cryptography FAQs: About SSL.

If the form is sitting on a secure server (or it's not, and you realize it's not completely secret), then you're ready to move on to the next step: creating the PHP script that invokes the encryption. Please note: This example uses PGP for the encryption, but the differences when using GNUPG are slight, and are noted at the end of this section.

Open your text editor and create a file called "do_sendsecret.php". The first thing to do is to place the plain-text contents of the form submission into a variable called $msg:

$msg = "Sender's Full Name:\t$sender_name\n";
$msg .= "Sender's E-Mail:\t$sender_email\n";
$msg .= "Secret Message?\t$secret_msg\n\n";
Next, set the PGPPATH environment variable, so that the form uses the proper key ring. This value of PGPPATH should be the directory containing the PHP user's key ring:

putenv("PGPPATH=/homedir/of/PHP/user/.pgp");
The next step creates a temporary file on your Web server and writes the contents of the form submission to this new file. I use a randomly-generated filename, to avoid problems with concurrent accesses to the script and thus the creation of filenames that would be over-written. Although on my production system it only takes something like 0.875633 seconds to run this script (Note: I have a relatively slow production machine: one PII-450mhz CPU and 128MB of RAM), avoiding any concurrencey issues is always A Good Thing.

To create this random filename, I usually tack a random token to the beginning of the filenames, created by:

$tmpToken = md5(uniqid(rand()));
The value of $tmpToken turns out to be something like "430eb4c228983845043530c192bd9a4f".

Create a couple of variables to hold the value of the path to the datafiles. The PHP user must have write permissions in this directory, so use the home directory of the PHP user to be safe:

$plainTxt = "/home/www/" . "$tmpToken" . "data";
$crypted = "/home/www/" . "$tmpToken" . "pgpdata";
Next, open a new file and write the cleartext of $msg to it, then close the file.

$fp = fopen($plainTxt, "w+");
fputs($fp, $msg);
fclose($fp);
So now you have a plaintext file ready for encryption. This example uses the system() function to invoke the PGP program on your Web server (if you are unsure of the location of the PGP program, contact your system administrator).

To encrypt the contents of a file, PGP needs a user ID (corresponding to a public key on the key ring), an input file, and a path and file name for the output file. This example encrypts the file using the public key for "Julie Meloni <julie@thickbook.com>", which is on a key ring on my server (and available for download at http://www.thickbook.com/comments/tb_pubkey.txt — if anyone wants to encrypt messages to me as a test, please feel free).

Substitute the ID of a key on your server, appropriately.

system("/usr/local/bin/pgpe -r 'Julie Meloni <julie@thickbook.com>' -o $crypted -a $plainTxt");
This command should output a file containing the encrypted version of the message sent via the "secret message" form.

The next step is to read the contents of the output file into a variable, which will be used later to populate the email message. Open the encrypted file for reading, and read the entire contents of the file to a variable called $mail_cont, then close the file:

$fd = fopen($crypted, "r");
$mail_cont = fread($fd, filesize($crypted));
fclose($fd);
Now, use the unlink() function to remove the datafiles:

unlink($plainTxt);
unlink($crypted);
Finally, create the remainder of the email and send it to the target recipient:

$recipient = "julie@thickbook.com";
$subject = "Secret Message";
$mailheaders = "From: My Web Site\n";
$mailheaders .= "Reply-To: $sender_email\n\n";

mail("$recipient", "$subject", $mail_cont, $mailheaders);

After your mail is sent, return some sort of confirmation to the user by adding an echo statement. You can even include the sender's name, since you have access to the variable $sender_name. Returning some sort of confirmation is always a good idea, so the sender doesn't keep pressing that "Send" button, wondering if something happened or not, thereby flooding your mailbox.

echo "
<H1 align=center>Thank You, $sender_name</h1>
<p align=center>Your secret message has been sent.</p>
";
The entire PHP script, to invoke PGP and send encrypted e-mail, will look something like this:

<?
//build the message string
$msg = "Sender's Full Name:\t$sender_name\n";
$msg .= "Sender's E-Mail:\t$sender_email\n";
$msg .= "Secret Message?\t$secret_msg\n\n";
//set the environment variable for PGPPATH
putenv("PGPPATH=/home/www/.pgp");

//generate token for unique filenames
$tmpToken = md5(uniqid(rand()));

//create vars to hold paths and filenames
$plainTxt = "/home/www/" . "$tmpToken" . "data";
$crypted = "/home/www/" . "$tmpToken" . "pgpdata";

//open file and dump in plaintext contents
$fp = fopen($plainTxt, "w+");
fputs($fp, $msg);
fclose($fp);

//invoke PGP to encrypt file contents
system("/usr/local/bin/pgpe -r 'Julie Meloni <julie@thickbook.com>' -o $crypted -a $plainTxt");

//open file and read encrypted contents into var
$fd = fopen($crypted, "r");
$mail_cont = fread($fd, filesize($crypted));
fclose($fd);

//delete files!
unlink($plainTxt);
unlink($crypted);

// Build mail message and send it to target recipient.
$recipient = "julie@thickbook.com";
$subject = "Secret Message";

$mailheaders = "From: My Web Site\n";
$mailheaders .= "Reply-To: $sender_email\n\n";

mail("$recipient", "$subject", $mail_cont, $mailheaders);

// Print confirmation to screen.
echo "
<H1 align=center>Thank You, $sender_name</h1>
<p align=center>Your secret message has been sent.</p>
";

?>
The target recipient should receive an email that looks something like this:

-----BEGIN PGP MESSAGE-----
Version: PGP for Personal Privacy 5.0
MessageID: ruVxzGiwNH9hJMbhAt5mEfUmWtozI3/4
qANQR1DBwk4DJoa8eforpr0QDAC2QHWlBYRTGKepMDcFXqyO1vrXlTh1p7yB0Wo4
lqYoZ9FippFCJddmLbZkvBRpEBceODLg+gEf5hrtXl3b5NO7Q6xUyMiPnF/71M9v
hdUvhJD/2gPnVZmq5qm0HhrjYLwQv9/2+z3sRN70NqohaWMjMR7kTcCAus/eZGS0
7ZWbyWc8x1c6qWU8EyDIw1nqfF62s4WTixx6BCve5m0A4xUXHncWZhDLvC/a47x5
C6oX5C7Dv+KpyROl++1aPOfFfZ+38fEZC5+E4IgPVYvxyLRVgDoeJbZ7QlDyxkVh
6Qe/bTI9CpP5kAb6uxCywgpaecj6P8ABg4ONR6xu0uYC1lG9UhNg5a/KzNyJNpTe
SYPx+1jS1q5285v3kF4ptDFQdLML/i4LTx9oE68WksAzVaqBE/zVRmGQaaczf+gx
fWjQZGbU4l11TImfpO16vZ21CkbobD6AZOaG0B3a1df4GqQwIK3Jf+hWWnXNQ514
DUWzW5puY6VHiEb60cztvds0/KsHNVZUAQ4VYm4R+Ahyb0M44MS4UpzILbH3HbV9
GpvfxeIZ/aUNOOSpJjhn8hzjEALZP1habVZKFJV6sVRtnCadoSV2gSQNQg0kfEY1
vxmbvxBAQRDga6CS8oHaFb45LJo2gVlLhiShDdp2eDR8X4KtUA6MdtO66w56qAy0
UWNKKwsqv0UP3jMHvQl1eb0rHWayxMmSfYw69zo56CjnUWNJN6Rh0y1g54Bl0afA
bt2D7FkQwGNPSm7e5HGcMVLocQ/XV5NTUOmX+s2DqvFT4h9/bAoBkxmR8hf2C7el
v8AJ4Ya/6D139cogzfDQtCy4Bo07vqz79lXfQYSGmk5f2c4LqvtKPhmDAWmSgUsW
-----END PGP MESSAGE-----
Recipients will then be able to decrypt the message using the PGP tools installed on their own machines.

Using GnuPG

If you don't want to use PGP encryption, or if you are in a country to which PGP cannot be exported, you can use the open source GnuPG software and substitute the following in the generic script above:

Substitute the environment variable:

putenv("GNUPGHOME=/home/www/.gnupg");
Substitute the system() call:

system("/path/to/gpg --encrypt -ao $crypted -r 'Julie Meloni <julie@thickbook.com>' $plainTxt");
The encrypted message will look quite similar, something like:

-----BEGIN PGP MESSAGE-----
Version: GnuPG v1.0.1a (MingW32)
Comment: For info see http://www.gnupg.org
hQIOA7hAqKZWjd30EAf8D4xjHG+QUt9RIbE1VEKCyl6iNmhoh7laR2HkFWitRWnZ
MPwyZ6AqJKXLqzorKcRaA8TEifRC/Ec7ZmPqShByH0KBrsUGc95dX6YVLikJ70fS
81bwwjvbd4273u9MWVK8NvaJuEFvdEob4vBzkkh8Dsbw4s03jKdpAaBTC9gPyycf
hBypw/blnkHJOeNE1n+caW1itY385PsR9HmmzlY8kCK4LC+dZEgxwdlCwqROLB4F
zm8RSKmC4gxL5Dd3UiuJFwjWjO+gH3dAuEXsbI5k70c29v/P8+vyoeV51jmJTDHo
loBGV42bJBnELBwTmaeDfC9RM32LrPOnd/R8XfQtX52rOnnTFw2uIuMZzXDmjmWV
c0UI3/Xul8k6nB+i6kIfHYtT+gJPTEEz53y/f1YZ7yN9l969np1z8Z6TqLwruI3F
Gx33u/gZhCy/iPTMVpDKfjNPTA9mGTabnl2YkifPjPcpCaUD86UBRh19VjXP4+5W
-----END PGP MESSAGE-----

Alrighty then. That's a real-world example of asymmetric encryption, in a nutshell.'


Source: http://hotwired.lycos.com/webmonkey/...tutorial1.html