Tiny OpenPGP v0.2b
Introduction
Tiny OpenPGP is actually not compatible with the commercial software or its open source equivalent at all, but uses the fundamentals of asymmetric encryption to create encrypted+signed messages using AES and RSA. The title was chosen in-house and stuck. All of the things those packages do to enable multiple message types and encryption methods have been stripped out and is really only similar in concept.
This program uses mcrypt for Rijndael 256 (AES 256 bit) in order to do the symmetric portion of things and Crypt_RSA for the RSA portion. Crypt_RSA is a neat package that can use gmp, big_int, or bcmath to perform RSA functions, available from http://pear.php.net/package/Crypt_RSA. Note that I had to correct the require_once('') paths, which were wrong, and I went ahead and flattened their multiple directory structure- but the code is otherwise unmodified.
How it works
The basic concept of asymmetric encryption is that you generate a random number to use as a symmetric key to encrypt the body. You then encrypt the random symmetric key using each desired recipient's public key and place it in a header at the top of the message. Next, encode the message using the random symmetric key (binary safe). Finally, sign the message using your private key.
The receiving code validates the signature of the entire message with the sender's public key then tries to fetch the session key back out of the header by attempting to use its private key on each of the encrypted session keys (one for each recipient) until the random key is found. Once found, the message body is decrypted.
Ordinarily, the private keys are encrypted symmetrically for storage and can only be retrieved by the person with the password used. I suggest this practice as well, just use aesEncrypt and aesDecrypt. The functions expect the unencrypted keys.
Bugs
I'm sure there are many, but the code works fine with a properly formatted message =)
I'll have to work on 'idiot proofing' later.
How To
- Generate a Crypt_RSA public/private key pair of the desired length. (>=512bytes recommended, 1024 or better is preferred but slow with bcmath)
$key_pair = new Crypt_RSA_KeyPair($key_length);
$public_key = $key_pair->getPublicKey();
$private_key = $key_pair->getPrivateKey();
- (optionally) Encrypt the private key with aesEncrypt, using compression at your option (make sure to use the same setting for decryption)
$encryptedKey = aesEncryptV2($private_key, $password, $compress);
$password should probably be generated with binarySHA256($stringpassword)
- Save your key pair somewhere safe- you'll need it as long as you want to be able to decrypt messages encrypted using this pair
- When you're ready to send a message:
a) create an array of the public keys of the people you want to send the message to
$pubKeys[0] = ...;
$pubKeys[1] = ...;
b) if you encrypted your private key, decrypt it first
$private_key = aesDecryptV2($encryptedKey, $password, $compressed);
c) Now create your message. It will automatically be signed with your key.
$encryptedMessage = create_message($messageBody, $pubKeys, $private_key);
- To receive a message:
a) If you encrypted your private key, decrypt it first
$private_key = aesDecryptV2($encryptedKey, $password, $compressed);
b) simply decrypt it with:
$result = decrypt_message($encryptedMessage, $public_key, $private_key);
c) check for ($result === false) - note the triple equals, otherwise $result contains your message