php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #52356 In memory support for openssl_pkcs7_*
Submitted: 2010-07-16 10:06 UTC Modified: 2010-07-16 11:00 UTC
Votes:2
Avg. Score:5.0 ± 0.0
Reproduced:2 of 2 (100.0%)
Same Version:1 (50.0%)
Same OS:1 (50.0%)
From: p dot vanbrouwershaven at networking4all dot com Assigned: pajoye
Status: Assigned Package: OpenSSL related
PHP Version: Irrelevant OS:
Private report: No CVE-ID:
Have you experienced this issue?
Rate the importance of this bug to you:

 [2010-07-16 10:06 UTC] p dot vanbrouwershaven at networking4all dot com
Description:
------------
The PHP functions openssl_pkcs7_(sign|encrypt|decrypt|verify) do require files to 
be executed. In many cases this will create the unintended requirement of 
temporary files. In compare with openssl_(sign|encrypt|decrypt|verify|...) which 
are doing almost the same thing this is a strange behavior.

When we look at the purpose of openssl_pkcs7_* (working with digital signatures in 
mail), you would not expect to work with files instead of strings for this few 
data.



Patches

openssl_pkcs7_mem_functions (last revision 2014-01-13 15:05 UTC) by php at kriegt dot es)
openssl_pkcs7_sign.patch (last revision 2010-07-16 08:10 UTC) by jille at quis dot cx)

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2010-07-16 10:13 UTC] jille at quis dot cx
Attached patch is a proof-of-concept patch. It changes openssl_pkcs7_sign() to use the input filename as a string instead of as a filename. Paul has tested this and it seems to work.
 [2010-07-16 10:14 UTC] pajoye@php.net
-Status: Open +Status: Feedback -Assigned To: +Assigned To: pajoye
 [2010-07-16 10:14 UTC] pajoye@php.net
Thanks, will take care of them asap. Do you have some tests as well, would help to reduce the time to commit :)
 [2010-07-16 10:30 UTC] p dot vanbrouwershaven at networking4all dot com
-Status: Feedback +Status: Assigned
 [2010-07-16 10:30 UTC] p dot vanbrouwershaven at networking4all dot com
First exmaple, signing mail with the current PHP version, content is located in 
file unsigned.txt, strangely this file needs to start with an empty line to get 
the signature recognized.

<?php
if (openssl_pkcs7_sign("unsigned.txt", "signed.txt", "file://public.cer",
    array("file://private.key", "password"),
    array("To" => "me@example.com", // keyed syntax
          "From: Me <me@example.com>", // indexed syntax
          "Subject" => "This is my subject"),
    PKCS7_DETACHED,
    "intermediate.cer"
    )) {
    // message signed - send it!
    exec(ini_get("sendmail_path") . " < signed.txt");
}
?>

A second example that runs with this patch, please not the linefeed "\n", 
without this linefeed the signature will not be recognized.

<?php
if (openssl_pkcs7_sign("\nunsigned.txt", "signed.txt", "file://public.cer",
    array("file://private.key", "password"),
    array("To" => "me@example.com", // keyed syntax
          "From: Me <me@example.com>", // indexed syntax
          "Subject" => "This is my subject"),
    PKCS7_DETACHED,
    "intermediate.cer"
    )) {
    // message signed - send it!
    exec(ini_get("sendmail_path") . " < signed.txt");
}
?>

Please not this proof of concept does only changes the infilename and not the 
other files like the outfilename, signcert, privkey & extracerts.
 [2010-07-16 10:45 UTC] pajoye@php.net
-Status: Assigned +Status: Feedback
 [2010-07-16 10:45 UTC] pajoye@php.net
Can you link to a zip containing what you use for this example please? May help to debug the issue you are describing while being at it.
 [2010-07-16 11:00 UTC] p dot vanbrouwershaven at networking4all dot com
-Status: Feedback +Status: Assigned
 [2010-07-16 11:00 UTC] p dot vanbrouwershaven at networking4all dot com
You can download the zipfile here:

https://docs.google.com/leaf?
id=0B3a2D2VoY8NgZGEzZGIxYzQtYWFiNS00NDNkLWI2ZGQtM2Y5YjQwNjM3Yjc2&hl=en&authkey=C
KeKg4cJ

Please request a free 30 day trail client certificate if you don't have one 
already for your own. (takes just a minute, the intermediate is already included 
in the zipfile)

http://www.globalsign.com/authentication-secure-email/digital-id/trial-
personalsign.html
 [2014-01-13 12:23 UTC] php at kriegt dot es
Hi,
what is the status of this feature request? I really would love to see this in some of the next versions as I already asked something about that on stackoverflow:
http://stackoverflow.com/questions/21053935/php-openssl-pkcs7-needs-files-security-issue


If you need a free S/Mime certificate for one year for testing purposes, request it on https://www.startssl.com/ for any Mailaddress you want AND OWN ofcourse (either gmail or hotmail, whatever).

There should be a way to pass the encrypted/unencrypted mail as a string variable, not as a filename. Since PKCS7_decrypt(3) says that the BIO filehandler could be even memory based. 
https://www.openssl.org/docs/crypto/PKCS7_encrypt.html

Please check this out again.
 [2014-01-13 15:10 UTC] php at kriegt dot es
Since I see no chance to change the current functions (openssl_pkcs7_encrypt/decrypt) to the schema I would need it, I just added two new functions named:
- openssl_pkcs7_mem_encrypt
- openssl_pkcs7_mem_decrypt

These functions use BIO_s_mem instead of BIO_s_file to create the necessary BIO data handled by the PKCS7 functions.
I tested this with the following skript and it worked as it should:

<?php
$message = "hey there, this is top secret message which gets encrypted by memory soon";
#$infile =  tempnam(sys_get_temp_dir(),'smime');
#$tmpfile = fopen( $infile, 'w+' );
#fwrite($tmpfile,$message,strlen($message));
#echo "Raw Message in $infile\n";

#$outfile = tempnam(sys_get_temp_dir(),'smime');

$certfile = "/path/to/just/the/certificate.pem";

$encrypted = "";
if( openssl_pkcs7_mem_encrypt( $message, $encrypted, file_get_contents($certfile), array() ) ) {
    var_dump( $encrypted );
}
$p12key = "/my/path/to/related/p12file.p12"
$password = "mysecretpasswordforkey";
openssl_pkcs12_read(file_get_contents($p12key), $certdata, $password);

$key = $certdata['pkey'];
$cert = $certdata['cert'];

if( strlen($key) != 0 ) {
#    echo "Key okay!\n";
}

if( trim($encrypted) != "" ) {
    if( openssl_pkcs7_mem_decrypt( $encrypted, $decrypted, $cert, array( $key, $password ) ) ) {
        var_dump( $decrypted );
    }
}


#################
First var_dump returns encrypted data
Second var_dump returns content of $message
 [2014-01-13 18:33 UTC] php at kriegt dot es
Added a pull request on github for this:
https://github.com/php/php-src/pull/560
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Tue Aug 29 15:01:52 2017 UTC