note 51005 modified in function.openssl-pkcs7-sign by vrana
| From: | vrana@php.net | Date: | Thu, 11 Feb 2010 13:31:27 +0000 |
| Subject: | note 51005 modified in function.openssl-pkcs7-sign by vrana | ||
| References: | 1 | Groups: | php.notes |
| Request: | Send a blank email to php-notes+get-165867@lists.php.net to get a copy of this message | ||
Amongst the many discussions about signing or encrypting email by itself, none really discuss the
pain of having an email BOTH signed AND encrypted.
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.
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.
<?php
// 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.
THIS IS WRONG!:
<?php
// [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!
<?php
// [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]);
?>
--was--
Amongst the many discussions about signing or encrypting email by itself, none really discuss the
pain of having an email BOTH signed AND encrypted.
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.
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.
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]);
?>
http://php.net/manual/en/function.openssl-pkcs7-sign.php