在許多關於郵件簽章或加密的討論中,沒有人真正討論過同時進行郵件簽章和加密的痛苦。
根據 RFC 2311,您可以先加密後簽章,或者先簽章後加密。然而,這取決於您編程的用戶端。根據我的經驗,Outlook 2000 偏好先加密後簽章。而在 Outlook 2003 中,則是先簽章後加密。一般來說,您會希望先簽章後加密,因為從傳統郵件的角度來看,這似乎是最合乎邏輯的。您會先簽署一封信,然後再將其放入信封中。如果您以某些用戶端不喜歡的順序執行,它們可能會出現問題,因此您可能需要進行一些實驗。
當您執行第一個函式時,請勿在 headers 陣列參數中放入任何標頭,您需要將其放入要執行的第二個函式中。如果您將標頭放在第一個函式中,第二個函式會將其從郵件伺服器中隱藏。您不希望這樣。這裡我會先簽名,然後加密。
<?php
$headers = array("To" => "someone@nowhere.net",
"From" => "noone@somewhere.net",
"Subject" => "已簽名和加密的訊息。");
openssl_pkcs7_sign("msg.txt","signed.txt",
"signing_cert.pem",array("private_key.pem",
"password"),array());
$pubkey = file_get_contents("cert.pem");
openssl_pkcs7_encrypt("signed.txt", "enc.txt",
$pubkey,$headers,0,1);
$data = file_get_contents("enc.txt");
$parts = explode("\n\n", $data, 2);
mail($mail, $subject, $parts[1], $parts[0]);
?>
請注意,如果您使用一個函式從磁碟中提取資料以在程式中的另一個函式中使用,請記住,您可能使用了 explode("\n\n",$data,2) 函式,該函式可能已移除標頭和訊息內容之間的間距。
當您取得已簽名的訊息並將其饋送到加密部分時,您必須記住,行距也必須作為訊息主體的一部分饋送!如果您打算先簽名然後加密,請勿將簽名輸出的標頭作為 headers 陣列參數的一部分饋送到加密中!簽名輸出應保留為要加密的訊息主體的一部分。(如果您先加密然後簽名,也是如此。)以下是一個將簽名和加密函式都製成例程以便重複使用的範例,然後呼叫該例程來簽名和加密訊息。
這是錯誤的!
<?php
$signedOutputArray = signMessage($inputMessage,$headers);
$signedAndEncryptedArray = encryptMessage($signedOutputArray[1],
$signedOutputArray[0]);
mail($emailAddr,$subject,$signedAndEncryptedArray[1],
$signedAndEncryptedArray[0]);
?>
這是正確的!
<?php
$signedOutputArray = signMessage($inputMessage,array());
$signedAndEncryptedArray =
encryptMessage($signedOutputArray[0] . "\n\n" . $signedOutputArray[1],$headers);
mail($emailAddr,$subject,$signedAndEncryptedArray[1],
$signedAndEncryptedArray[0]);
?>