0

我目前正在使用 PHP 实现 S/Mime 解密。到目前为止我得到了什么:

    $keys = array("public"=>$atm."/public-keys/".$usr.".smime",
        "private"=>$atm."/private-keys/".$usr.".smime");
    if(!file_exists($keys["public"])) die("Public Key not found");
    if(!file_exists($keys["private"])) die("Private Key not found");
    $public = file_get_contents($keys["public"]);
    $private = file_get_contents($keys["private"]);

    switch($_GET["debug"])
    {
        case "encrypt":
        {
            $outfile = realpath("demo-msg/out.txt");
            $outfile_signed = realpath("demo-msg/out.signed.txt");
            $infile = realpath("demo-msg/in.txt");

            file_put_contents($infile,$msg);
            $adddata = array("To" => "XXX", "From: Demo Name <XXX>", "Subject" => "Demo Subject");
            if (openssl_pkcs7_encrypt($infile, $outfile, $public, $adddata))
            {
                //$info = file_get_contents($outfile);
                echo "winenc & transfer<br>\n";
                file_put_contents($infile, file_get_contents($outfile));
                //if(openssl_pkcs7_sign($outfile,$outfile_signed,$public,$private,$adddata, PKCS7_BINARY)) echo "winsign";
                //else echo "failsign";
            } 
            else echo "Failed Encryption";
            exit;
        }
        default:
        {
            $outfile2 = realpath("demo-msg/out2.txt");
            $outfile = realpath("demo-msg/out.txt");
            $infile = realpath("demo-msg/smime.p7m");
            //$infile = realpath("demo-msg/in.txt");

            if(openssl_pkcs7_verify($infile)) echo "verified<br>\n"; //tried: openssl_pkcs7_verify($infile,$PKCS7_DETACHED, tmpfile(), array(), array(), $outfile)
            else die("invalid sig");

            if(openssl_pkcs7_decrypt($infile, $outfile2, $public, $private)) //tried: openssl_pkcs7_decrypt($outfile, $outfile2, $public, $private)
            {
                echo "dec win:".file_get_contents($outfile2);
            }
            else echo "Oh oh! Decryption failed!";
            exit;
        }
    }

这个片段已经可以做什么:

  • 加密消息
  • 解密加密消息(自己创建)
  • 解密未签名的加密邮件 (Office 2010)

现在,我也想解密已签名的消息(因为它通常是一步)。问题:

  • 如果我第一次尝试解密,它将返回具有不同标头的加密消息。多次解密导致相同的结果。
  • 我的想法是使用 $content - 验证命令的参数(openssl_pkcs7_verify)。您可以在代码注释中看到我的尝试。

不过,我不知道第二次尝试有什么问题。任何帮助,将不胜感激!

4

1 回答 1

1

对自己说。

我在脚本中犯的错误:

  • 验证返回 -1(错误),但我将其处理为 true(成功)。验证从未奏效。
  • 验证是完全错误的。DETACHED 是一个常数,而不是一个变量。“extracert”参数需要一个有效文件作为包含有效签名的字符串。不过,我的想法是正确的(使用“内容”参数进行设计)。
  • 签名和解密顺序

我误解的是处理签名(并进行验证)的方式。我假设消息被加密,然后签名。可以这样,但是很多工具,包括Office2010,都是先给消息签名,然后再加密。这样您就无法在解密之前检查签名,而必须在解密进行设计。

您可以在下面看到我的调试代码。当你偶然发现这个线程时,这将帮助你解决解密问题。

            $test = openssl_pkcs7_verify($infile, PKCS7_DETACHED ); //just to see that it doesn't work
            echo "signature is ".$test."\n<br>".openssl_error_string(); 

            $dec = openssl_pkcs7_decrypt($infile, $outfile, $public, $private);
            echo "<br><br>\n\ndec is ".$dec."\n<br>".openssl_error_string()."\n<br>".file_get_contents($outfile); 

            $test = openssl_pkcs7_verify($outfile, PKCS7_DETACHED, $tmp, array(), $tmp, $outfile2 );
            echo "<br><br>\n\nsignature2 is ".$test."\n<br>".openssl_error_string()."\n<br>".file_get_contents($outfile2); 
于 2014-09-04T19:17:27.780 回答