You want to send encrypted email messages. For example, you take orders on your web site and need to send an email to your factory with order details for processing. By encrypting the email message, you prevent sensitive data such as credit card numbers from passing over the network in the clear.
Encrypt the body of the email message with GNU Privacy Guard (GPG) before sending it:
<?php $message_body = escapeshellarg($message_body); $gpg_path = '/usr/local/bin/gpg'; $sender = 'email@example.com'; $recipient = 'firstname.lastname@example.org'; $home_dir = '/home/web'; $user_env = 'web'; $cmd = "echo $message_body | HOME=$home_dir USER=$user_env $gpg_path " . '--quiet --no-secmem-warning --encrypt --sign --armor ' . "--recipient $recipient --local-user $sender"; $message_body = `$cmd`; mail($recipient, 'Web Site Order', $message_body); ?>
The email message can be decrypted by GPG, Pretty Good Privacy (PGP), or an email client plug-in that supports either program.
PGP is a popular public key encryption program; GPG is an open source program based on PGP. Because PGP is encumbered by a variety of patent and control issues, it's often easier to use GPG.
The code in the Solution invokes /usr/local/bin/gpg to encrypt the message in $message_body. It uses the private key belonging to $sender and the public key belonging to $recipient. This means that only $recipient can decrypt the email message and when he does, he knows the message came from $sender.
Setting the HOME and USER environment variables tells GPG where to look for its keyring: $HOME/.gnupg/secring.gpg. The --quiet and --no-secmem-warning options suppress warnings GPG would otherwise generate. The --encrypt and --sign options tell GPG to both encrypt and sign the message. Encrypting the message obscures it to anyone other than the recipient. Signing it adds information so that the recipient knows who generated the message and when it was generated. The --armor option produces plain-text output instead of binary, so the encrypted message is suitable for emailing.
Normally, private keys are protected with a passphrase. If a private key protected by a passphrase is copied by an attacker, the attacker can't encrypt messages with the private key unless she also knows the passphrase. GPG prompts for the passphrase when encrypting a message. In this recipe, however, we don't want the private key of $sender to have a passphrase. If it did, the web site couldn't send new order email messages without a human typing in the passphrase each time. Storing the passphrase in a file and providing it to GPG each time you encrypt offers no additional security over not having a passphrase in the first place.
The downside of using a key without a passphrase for encryption is that an attacker who obtains the secret key can send fake order emails to your order processor. This is a manageable risk. Since orders can be submitted via a web site in the first place, there is already a place where false information can be injected into the order process. Any procedures for catching bad orders can also be triggered by these potential fake emails. Also, once the key theft is discovered, and the problem that enabled the theft is fixed, switching to a new private key easily disables the attacker.
18.14.4. See Also
The GNU Privacy Guard home page at http://gnupg.org/ and the MIT PGP distribution site at http://web.mit.edu/network/pgp.html.