Delicious Bookmark this on Delicious Share on Facebook SlashdotSlashdot It! Digg! Digg



PHP : Function Reference : OpenSSL Functions : openssl_pkcs7_sign

openssl_pkcs7_sign

Sign an S/MIME message (PHP 4 >= 4.0.6, PHP 5)
bool openssl_pkcs7_sign ( string infilename, string outfilename, mixed signcert, mixed privkey, array headers [, int flags [, string extracerts]] )

Example 1675. openssl_pkcs7_sign() example

<?php
// the message you want to sign so that recipient can be sure it was you that
// sent it
$data = <<<EOD

You have my authorization to spend $10,000 on dinner expenses.

The CEO
EOD;
// save message to file
$fp = fopen("msg.txt", "w");
fwrite($fp, $data);
fclose($fp);
// encrypt it
if (openssl_pkcs7_sign("msg.txt", "signed.txt", "mycert.pem",
   array(
"file://mycert.pem", "mypassphrase"),
   array(
"To" => "joes@example.com", // keyed syntax
         
"From: HQ <ceo@example.com>", // indexed syntax
         
"Subject" => "Eyes only")
   )) {
   
// message signed - send it!
   
exec(ini_get("sendmail_path") . " < signed.txt");
}
?>

Code Examples / Notes » openssl_pkcs7_sign

dmitri

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 aren’t 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 Language


Follow Navioo On Twitter
openssl_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
eXTReMe Tracker