Не могу расшифровать подписанное сообщение S/Mime

Сейчас я понимаю, как расшифровывать S/Mime с помощью PHP. Что я получил так далеко:

    $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). Вы можете увидеть мою попытку в коде-комментариях.

Тем не менее, у меня нет никаких подсказок, что может быть не так со второй попыткой. Любая помощь будет оценена!

1 ответ

Решение

Говоря самому себе.

Ошибки, которые я сделал в скрипте:

  • Подтверждение возвращает -1 (ошибка), но я обрабатываю его как true (успех). Проверка никогда не работала.
  • Подтверждение совершенно неверно. DETACHED - это константа, а не переменная. Параметр "extracert" ожидает допустимый файл в виде строки, содержащей действительную подпись. Хотя идея, которая у меня была, была правильной (снятие подписи с использованием параметра "content").
  • Порядок подписания и расшифровки

То, что я неправильно понял, было способом, подписи обрабатываются (и проверки сделаны). Я предположил, что сообщение зашифровано, а затем подписано. Это может быть так, но многие инструменты, в том числе 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); 
Другие вопросы по тегам