|
openssl_pkcs7_sign
Sign an S/MIME message
(PHP 4 >= 4.0.6, PHP 5)
Example 1675. openssl_pkcs7_sign() example<?php Code Examples / Notes » openssl_pkcs7_signdmitri
Working example: <?php $data = <<< EOF Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit You have my authorization to spend 10,000 on dinner expenses. The CEO EOF; $fp = fopen("msg.txt", "w"); fwrite($fp, $data); fclose($fp); $headers = array("From" => "me@email.com"); openssl_pkcs7_sign("msg.txt", "signed.txt", "file://email.pem", array("file://email.pem", "123456"), $headers); $data = file_get_contents("signed.txt"); $parts = explode("\n\n", $data, 2); mail("you@email.com", "Signed message.", $parts[1], $parts[0]); echo "Email sent"; ?> maciej_niemir
This command doesn't work correctly on WIN32 with IIS. Mails arent interpreted correctly by IIS SMTP Server (and by Outlook too). The reason is that UNIX and WINDOWS interpret the enter to the next line ascii code in a different way. Below I present an improved code: <?php $data = <<<EOD Testing 123 This is a test Test EOD; //save the message to a file $fp = fopen("msg.txt","w"); fwrite($fp,$data); fclose($fp); //sign the message using the sender's keys openssl_pkcs7_sign("msg.txt", "signed.eml", "file://c:/max/cert.pem", array("file://c:/max/priv.pem","your_password"), array("To" => "recipient <recipients@mail.com>", "From" => "sender <sender@mail.com>", "Subject" => "Order Notification - Test"),PKCS7_DETACHED,"c:\max\extra_cert.pem"); $file_arry = file("signed.eml"); $file = join ("", $file_arry); $message = preg_replace("/\r\n|\r|\n/", "\r\n", $file); $fp = fopen("c:\Inetpub\mailroot\Pickup\signed.eml", "wb"); flock($fp, 2); fputs($fp, $message); flock($fp, 3); fclose($fp); ?> Besides, if you want to use the keys created with Windows, you should export them (from IE) to the form of PKCS#12 file (*.pfx). Install OpenSSLWin32 from http://www.shininglightpro.com/search.php?searchname=Win32+OpenSSL execute: openssl.exe enter the commands: pkcs12 -in <pfx-file> -nokeys -out <pem-certs-file> pkcs12 -in <pfx-file> -nocerts -nodes -out <pem-key-file> Next export from IE Root CA certificate as Base-64 *.cer and rename the file to *.pem And that's all! del
The "mycert.pem" parameters as shown in the example above are not correct. You either have to pass a string containing the PEM encoded certificate or key, or the location of a file in file://path/to/file.pem notation. See the comments on the OpenSSL functions page (the page above this one).
php
It's probably worth noting that I had a great deal of difficulty getting either Mozilla 1.4 or Outlook Express 6 to verify signatures generated by openssl_pkcs7_sign() until I added a newline (\n) to the beginning of the message I was signing. Not sure why that is, but as soon as I made that change all problems disappeared.
maarten
It is also possible to sign message including attachments. An easy way to do this: <? $boundary = md5(uniqid(time())); $boddy = "MIME-Version: 1.0\n"; $boddy .= "Content-Type: multipart/mixed; boundary=\"" . $boundary. "\"\n"; $boddy .= "Content-Transfer-Encoding: quoted-printable\n\n"; $boddy .= "This is a multi-part message in MIME format.\n\n"; $boddy .= "--$boundary\n"; $boddy .= "Content-Type: text/plain; charset=\"iso-8859-1\"\n"; $boddy .= "Content-Transfer-Encoding: quoted-printable\n\n"; $boddy .= $EmailText . "\n\n"; // Add the attachment to the message do { $boddy .= "--$boundary\n"; $boddy .= "Content-Type: application/pdf; name=\"FileName\"\n"; $boddy .= "Content-Transfer-Encoding: base64\n"; $boddy .= "Content-Disposition: attachment;\n\n"; $boddy .= chunk_split(base64_encode($file)) . "\n\n"; } while ( {files left to be attached} ); $boddy .= "--$boundary--\n"; // Save message to a file $msg = 'msg.txt'; $signed = 'signed.txt'; $fp = fopen($msg, "w"); fwrite($fp, $boddy); fclose($fp); // Sign it if (openssl_pkcs7_sign($msg, $signed, 'file://cert.pem', array('file://key.pem', 'test'), array("To" => "joes@example.com", // keyed syntax "From: HQ <ceo@example.com>", // indexed syntax "Subject" => "Eyes only"), PKCS7_DETACHED, 'intermediate_cert.pem' )) { exec(ini_get('sendmail_path') . ' < ' . $signed); } ?> The same can be established by using the PEAR package Mail_Mime in combination with openssl_pkcs7_sign. meint dot post
If you want to integrate PKCS7 signing/verifying with a browser and it's not a problem that it's only Internet Explorer (or Netscape + ActiveX plugin) you can look at Capicom. It's a free component and available at the MSDN website.
ungdi
I would like to make a modification from my previous note. Some clients prefer a certain order in which messages should be signed and encrypted (if both is desired). Newer email clients, such as Thunderbird and Outlook 2003 will accept the most secure method of "sign -> encrypt -> sign again". Why? The first signing authenticates the message saying that you did indeed write it. Then the email is encrypted so that only the recipient can open and read it. Then the second signing ensure confidentiality by identifying that the person encrypting is the one whom encrypted it, a message intended for the decrypting person. This is the most secure method. This ensures: Non-Repudiation of message (first sign), Confidentiality (encrypt), and Context Integrity [you were intended to be addressed] (second sign). If you only sign then encrypt, there is no way you can guarantee that (aside from the contents of the letter, headers are placed in plain text outside the message) that the message was intended for you by the original sender. For example: Bob signs a love letter and encrypts it to Amy saying only "I love you. -- Bob". Amy decrypts it, sees the message (and plays a joke) and forwards the message to John using John's public key, re-encrypting, but not tampering with the message contents keeping the signature valid. This allows Amy to make it look like Bob sent John a love letter and that Bob loves John, as you cannot verify whom sent it during encryption. That is not what you want! This is also analogous to someone taking a government document, put it in an envelope themselves and write the government address in the return address and send it to you. You know the letter is written by the government, but you don't know for sure whether the government sent it to you directly or was opened and relayed. While encrypting then signing has a problem, this is affectively signing on the envelope of a snail mail piece. I know you sent it, but is the message really from you? Or are you forwarding it? Sign - Encrypt - Sign Again method will make the first sign show that you know the writer of the message is the person, encrypt it to keep others from reading it, sign again to indicate the message was not relayed and that the sender intended to sent the mail to address you. Just make sure the headers of the mail is applied in the last step and not the second or third step. For more information about the security and integrity risks of this situation, please read this web page: http://world.std.com/~dtd/sign_encrypt/sign_encrypt7.html |
Change Languageopenssl_csr_export_to_file openssl_csr_export openssl_csr_get_public_key openssl_csr_get_subject openssl_csr_new openssl_csr_sign openssl_error_string openssl_free_key openssl_get_privatekey openssl_get_publickey openssl_open openssl_pkcs12_export_to_file openssl_pkcs12_export openssl_pkcs12_read openssl_pkcs7_decrypt openssl_pkcs7_encrypt openssl_pkcs7_sign openssl_pkcs7_verify openssl_pkey_export_to_file openssl_pkey_export openssl_pkey_free openssl_pkey_get_details openssl_pkey_get_private openssl_pkey_get_public openssl_pkey_new openssl_private_decrypt openssl_private_encrypt openssl_public_decrypt openssl_public_encrypt openssl_seal openssl_sign openssl_verify openssl_x509_check_private_key openssl_x509_checkpurpose openssl_x509_export_to_file openssl_x509_export openssl_x509_free openssl_x509_parse openssl_x509_read |