Impossible tri-bar

Digital Phenomena - Your first stop for internet consultancy 
Data Encryption Tutorial — Lesson 1

Page 5 — 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:

<p>Your Name:<br>
<INPUT type="text" name="sender_name" size=25></p>

<p>Your E-Mail Address:<br>
<INPUT type="text" name="sender_email" size=25></p>

<p>The Secret Message:<br>
<TEXTAREA name="secret_msg" cols=35 rows=5></TEXTAREA></p>

Finally, add the Send Secret Message button:

<p><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">

<p>Your Name:<br>
<INPUT type="text" name="sender_name" size=25></p>

<p>Your E-Mail Address:<br>
<INPUT type="text" name="sender_email" size=25></p>

<p>The Secret Message:<br>
<TEXTAREA name="secret_msg" cols=35 rows=5></TEXTAREA></p>

<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. In the next lesson, we'll move into hashing and real-world examples of one-way encryption techniques.




|Home|About Us|Services|Search|
|Software|Products|Support|Links|Latest|
W3C validatedW3C validated CSSCompatible with all browsers