Amongst the many discussions about signing or encrypting email by itself, none really discuss the pain of having an email BOTH signed AND encrypted.
*** What do you do first? Sign then Encrypt? Or Encrypt then Sign?
According to RFC 2311, you can encrypt then sign or sign then encrypt. However, it depends on the client in which you are programming for. In my experience, in Outlook 2000, it prefers it Encrypt then Sign. While in Outlook 2003, it is Sign then Encrypt. Generally, you want Sign then Encrypt, as it seems most logical from a snail-mail piece point of view. You first sign a letter than put it in an envelope. Certain clients complain if you do it in an order it does not like, so you may want to experiement with it.
*** Example of doing both signing AND encrypting.
When you perform the first function, do NOT put in any headers in the headers array parameters, you want to put it in the SECOND function you want to perform. If you put the headers in the first function, the second function will hide it from the mail servers. You do not want that. Here I will sign then encrypt.
<?
// Setup mail headers.
$headers = array("To" => "someone@nowhere.net",
"From" => "noone@somewhere.net",
"Subject" => "A signed and encrypted message.");
// Sign the message first
openssl_pkcs7_sign("msg.txt","signed.txt",
"signing_cert.pem",array("private_key.pem",
"password"),array());
// Get the public key certificate.
$pubkey = file_get_contents("cert.pem");
//encrypt the message, now put in the headers.
openssl_pkcs7_encrypt("signed.txt", "enc.txt",
$pubkey,$headers,0,1);
$data = file_get_contents("enc.txt");
// separate header and body, to use with mail function
// unfortunate but required, else we have two sets of headers
// and the email client doesn't decode the attachment
$parts = explode("\n\n", $data, 2);
// send mail (headers in the Headers parameter will override those
// generated for the To & Subject parameters)
mail($mail, $subject, $parts[1], $parts[0]);
?>
Note that if you use a function that picks up the data from the disk to be used in another function in your program, remember that you may have used the explode("\n\n",$data,2) function which may have removed the spacing between the header and the message content.
When you take the signed message and feed it in to the encryption part, you have to remember that the line spacing must also be fed AS PART OF THE MESSAGE BODY! If you plan to sign then encrypt, do not feed the header output from the signing into the encrypting as part of the headers array parameter! The output of the signing should stay as part of the message body being encrypted. (And the same is true if you are doing the reverse of encrypting then signing.) An example of both the signing and encryption function made in to a routine for reusability, and then called to sign and encrypt a message.
*** Example of signing and encrypting executed from a routine function for code reusability through a program.
THIS IS WRONG!:
<?
// [0] of Array contains headers of message. [1] of Array contains signed body of message.
$signedOutputArray = signMessage($inputMessage,$headers);
// [0] of Array contains headers of message and the signing.
// [1] of Array contains encrypted body of message without the signing header.
$signedAndEncryptedArray = encryptMessage($signedOutputArray[1],
$signedOutputArray[0]);
mail($emailAddr,$subject,$signedAndEncryptedArray[1],
$signedAndEncryptedArray[0]);
?>
THIS IS CORRECT!
<?
// [0] of Array contains headers of signing.
// [1] of Array contains signed body of message.
$signedOutputArray = signMessage($inputMessage,array());
// [0] of Array contains headers of message.
// [1] of Array contains encrypted contents of both the signed message and its headers of the signing.
$signedAndEncryptedArray =
encryptMessage($signedOutputArray[0] . "\n\n" . $signedOutputArray[1],$headers);
mail($emailAddr,$subject,$signedAndEncryptedArray[1],
$signedAndEncryptedArray[0]);
?>