php OpenSSL 不适用于 Windows,错误 0x02001003 0x2006D080 0x0E064002

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15558321/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 09:29:01  来源:igfitidea点击:

OpenSSL not working on Windows, errors 0x02001003 0x2006D080 0x0E064002

phpapacheapache2openssleasyphp

提问by Brock Hensley

Problem:OpenSSL is not working in my Windows environment. OpenSSL repeatedly reports errors 0x02001003, 0x2006D080 and 0x0E064002.

问题:OpenSSL 在我的 Windows 环境中不起作用。OpenSSL 反复报告错误 0x02001003、0x2006D080 和 0x0E064002。

Environment:

环境:

Windows NT x 6.1 build 7601 (Windows 7 Business Edition Service Pack 1) i586
Apache/2.4.4 (Win32)
PHP/5.4.13 x86
PHP Directory: E:\wamp\php\
Virtual Host Directory: E:\Projects\public_html

What I've Attempted:

我尝试过的:

  • Installation Instructionshttp://www.php.net/manual/en/openssl.installation.php
  • PHP.iniextension=php_openssl.dll
  • Openssl.cnfE:\wamp\php\extras\openssl.cnf
  • %PATH%E:\wamp\php
  • Rebooted
  • phpinfo:
    ----OpenSSL support enabled
    ----OpenSSL Library Version OpenSSL 1.0.1e 11 Feb 2013
    ----OpenSSL Header Version OpenSSL 0.9.8y 5 Feb 2013
  • With and without specifying configin configargs
  • With and without specifying <Directory E:\wamp\php\extras>in apache config
  • Copied openssl.cnfto virtualhost public_html, pointed to that and still get same errors
  • Nothing logged in error_log
  • Researched:I've spent the last 2 days researching this, surprised there isn't more info on it so I'm posting here. Seems to be problem with OpenSSL config or apache/php not reading config properly.
  • 安装说明http://www.php.net/manual/en/openssl.installation.php
  • 配置文件extension=php_openssl.dll
  • OpenSSL.cnfE:\wamp\php\extras\openssl.cnf
  • %小路%E:\wamp\php
  • 重新启动
  • phpinfo:
    ----OpenSSL 支持启用
    ----OpenSSL 库版本 OpenSSL 1.0.1e 2013 年 2 月 11 日
    ----OpenSSL 标头版本 OpenSSL 0.9.8y 2013 年 2 月 5 日
  • 带和不带指定配置configargs
  • <Directory E:\wamp\php\extras>在 apache 配置中指定和不指定
  • 复制openssl.cnf到虚拟主机 public_html,指向那个,仍然得到同样的错误
  • error_log 中没有记录任何内容
  • 研究:我在过去的 2 天里一直在研究这个,很惊讶没有更多的信息,所以我在这里发帖。似乎是 OpenSSL 配置或 apache/php 没有正确读取配置的问题。

Code:

代码:

$privateKey = openssl_pkey_new();
while($message = openssl_error_string()){
    echo $message.'<br />'.PHP_EOL;
}

Results:

结果:

error:02001003:system library:fopen:No such process
error:2006D080:BIO routines:BIO_new_file:no such file
error:0E064002:configuration file routines:CONF_load:system lib
error:02001003:system library:fopen:No such process
error:2006D080:BIO routines:BIO_new_file:no such file
error:0E064002:configuration file routines:CONF_load:system lib

OpenSSL Manually:

手动 OpenSSL:

E:\wamp\apache\bin>openssl.exe pkey
WARNING: can't open config file: c:/openssl-1.0.1e/ssl/openssl.cnf

E:\wamp\apache\bin>set OPENSSL_CONF="E:\wamp\php\extras\openssl.cnf"

E:\wamp\apache\bin>openssl.exe pkey
3484:error:0200107B:system library:fopen:Unknown error:.\crypto\bio\bss_file.c:169:fopen('"E:\wamp\php\extras\openssl.cnf"','rb')
3484:error:2006D002:BIO routines:BIO_new_file:system lib:.\crypto\bio\bss_file.c:174:
3484:error:0E078002:configuration file routines:DEF_LOAD:system lib:.\crypto\conf\conf_def.c:199:

EDIT:

编辑:

  1. Thanks to @Gordon I can now see open_ssl errors using openssl_error_string
  2. Completely uninstall EasyPHP. Manually installed stable versions of PHP/Apache. Same results! Definitely something I'm doing wrong with implementing openssl on windows.
  3. OpenSSL Manually section... additional error info
  1. 感谢@Gordon,我现在可以使用以下命令查看 open_ssl 错误 openssl_error_string
  2. 完全卸载 EasyPHP。手动安装稳定版本的 PHP/Apache。结果一样!在 Windows 上实现 openssl 肯定是我做错了。
  3. OpenSSL 手动部分...附加错误信息

FINAL THOUGHTS:
I set up a linux box and I'm getting the same errors. After some playing around I see that even though it's throwing errors at the openssl_pkey_new it does eventually create my test p12 file. Long story short, the errors are misleading and it has to deal more with howyou are using openssl functions not so much server-side configuration.

最后的想法:
我设置了一个 linux 机器,但遇到了同样的错误。经过一番尝试后,我发现即使它在 openssl_pkey_new 处抛出错误,它最终还是会创建我的测试 p12 文件。长话短说,这些错误具有误导性,它必须更多地处理您如何使用 openssl 功能而不是服务器端配置。

Final code:

最终代码:

// Create the keypair
$res=openssl_pkey_new();

// Get private key
openssl_pkey_export($res, $privkey);

// Get public key
$pubkey=openssl_pkey_get_details($res);
$pubkey=$pubkey["key"];

// Actual file
$Private_Key = null;
$Unsigned_Cert = openssl_csr_new($Info,$Private_Key,$Configs);
$Signed_Cert = openssl_csr_sign($Unsigned_Cert,null,$Private_Key,365,$Configs);
openssl_pkcs12_export_to_file($Signed_Cert,"test.p12",$Private_Key,"123456");

Close away.

关闭。

A year later...

一年后...

So I found myself doing this again a year later, and regardless of whatever PATH variables I set on the computer or during the script execution, it kept erroring about file not found. I was able to resolve it by passing in the configparameter in the config_argsarray in openssl_pkey_new. Here is a function that tests the ability to successfully use OpenSSL:

所以一年后我发现自己又这样做了,无论我在计算机上或在脚本执行期间设置了任何 PATH 变量,它都不断出现关于找不到文件的错误。我能够通过传入数组中的config参数来解决它。这是一个测试成功使用 OpenSSL 的能力的函数:config_argsopenssl_pkey_new

    /**
     * Tests the ability to 1) create pub/priv key pair 2) extract pub/priv keys 3) encrypt plaintext using keys 4) decrypt using keys
     * 
     * @return boolean|string False if fails, string if success
     */
    function testOpenSSL($opensslConfigPath = NULL)
    {
        if ($opensslConfigPath == NULL)
        {
            $opensslConfigPath = "E:/Services/Apache/httpd-2.4.9-win32-VC11/conf/openssl.cnf";
        }
        $config = array(
            "config" => $opensslConfigPath,
            "digest_alg" => "sha512",
            "private_key_bits" => 4096,
            "private_key_type" => OPENSSL_KEYTYPE_RSA,
        );

        $res = openssl_pkey_new($config); // <-- CONFIG ARRAY
        if (empty($res)) {return false;}

        // Extract the private key from $res to $privKey
        openssl_pkey_export($res, $privKey, NULL, $config); // <-- CONFIG ARRAY

        // Extract the public key from $res to $pubKey
        $pubKey = openssl_pkey_get_details($res);
        if ($pubKey === FALSE){return false;}

        $pubKey = $pubKey["key"];

        $data = 'plaintext data goes here';

        // Encrypt the data to $encrypted using the public key
        $res = openssl_public_encrypt($data, $encrypted, $pubKey);
        if ($res === FALSE){return false;}

        // Decrypt the data using the private key and store the results in $decrypted
        $res = openssl_private_decrypt($encrypted, $decrypted, $privKey);
        if ($res === FALSE){return false;}

        return $decrypted;
    }

    // Example usage:
    $res = testOpenSSL();
    if ($res === FALSE)
    {
        echo "<span style='background-color: red;'>Fail</span>";
    } else {
        echo "<span style='background-color: green;'>Pass: ".$res."</span>";
    }

采纳答案by Brock Hensley

The code below works as expected. BUT if you run openssl_error_string()after the openssl methods it shows error:0E06D06C:configuration file routines:NCONF_get_string:no valuewhich is some notice I have not been able to find documentation on.

下面的代码按预期工作。但是,如果您openssl_error_string()在 openssl 方法之后运行,它会显示出error:0E06D06C:configuration file routines:NCONF_get_string:no value我无法找到相关文档的一些注意事项。

Further note that according to http://www.php.net/manual/en/function.openssl-error-string.phpyou could be seeing mis-leading errors as error messages are queued:

进一步请注意,根据http://www.php.net/manual/en/function.openssl-error-string.php您可能会看到误导性错误,因为错误消息已排队:

Be careful when using this function to check errors, as it seems to read from a buffer of > errors, which could include errors from another script or process that was using openssl > functions. (I was surprised to find it returing error messages before I had called any > openssl_* functions)

使用此函数检查错误时要小心,因为它似乎是从 > 错误的缓冲区中读取的,其中可能包括来自使用 openssl > 函数的另一个脚本或进程的错误。(我很惊讶地发现它在我调用任何 > openssl_* 函数之前就返回了错误消息)

<?php
/* Create the private and public key */
$res = openssl_pkey_new();
openssl_error_string(); // May throw error even though its working fine!

/* Extract the private key from $res to $privKey */
openssl_pkey_export($res, $privKey);
openssl_error_string(); // May throw error even though its working fine!

/* Extract the public key from $res to $pubKey */
$pubKey = openssl_pkey_get_details($res);
$pubKey = $pubKey["key"];

$data = 'i.amniels.com is a great website!';

/* Encrypt the data using the public key
 * The encrypted data is stored in $encrypted */
openssl_public_encrypt($data, $encrypted, $pubKey);

/* Decrypt the data using the private key and store the
 * result in $decrypted. */
openssl_private_decrypt($encrypted, $decrypted, $privKey);

echo $decrypted;
?>

回答by borrel

a few things here :

这里有几件事:

%PATH%should also contain windows and system32 so your %PATH% should look like c:\windows;c:\windows\system32;E:\wamp\phpand in e:\wamp\phpshould be the openssl dll file

%PATH%还应该包含 windows 和 system32,因此您的 %PATH% 应该看起来像c:\windows;c:\windows\system32;E:\wamp\php并且e:\wamp\php应该是 openssl dll 文件

also try the openssl version matching the header version 0.9.8y 5 Feb 2013download here for 32bitand here for 64bit

还可以尝试使用与标头版本匹配的 openssl 版本在此处0.9.8y 5 Feb 2013下载32 位此处下载64 位

this code seems to work for me:

这段代码似乎对我有用:

// Create the keypair
$res=openssl_pkey_new();

// Get private key
openssl_pkey_export($res, $privkey);

// Get public key
$pubkey=openssl_pkey_get_details($res);
$pubkey=$pubkey["key"];
$Info = array(
    "countryName" => "UK",
    "stateOrProvinceName" => "Somerset",
    "localityName" => "Glastonbury",
    "organizationName" => "The Brain Room Limited",
    "organizationalUnitName" => "PHP Documentation Team",
    "commonName" => "Wez Furlong",
    "emailAddress" => "[email protected]"
);

// Actual file
$Private_Key = null;
$Unsigned_Cert = openssl_csr_new($Info,$Private_Key);
$Signed_Cert = openssl_csr_sign($Unsigned_Cert,null,$Private_Key,365);
openssl_pkcs12_export_to_file($Signed_Cert,"test.p12",$Private_Key,"123456");

回答by Larzan

I had a similar problem, for me it helped to set the environment variable 'OPENSSL_CONF' manuallyat the beginning of my script.

我有一个类似的问题,对我来说,它有助于在我的脚本开头手动设置环境变量“OPENSSL_CONF” 。

Somehow the environment variable wasn't set correctly, or didn't get through to my php (Setup: AMPPS, Win7 64Bit).

不知何故,环境变量设置不正确,或者没有进入我的 php(设置:AMPPS,Win7 64Bit)。

The example location used below is the path that you'd have to use with a standard AMPPS installation, so if you are using AMPPS, just copy&paste :

下面使用的示例位置是您必须与标准 AMPPS 安装一起使用的路径,因此如果您使用的是 AMPPS,只需复制和粘贴:

putenv("OPENSSL_CONF=C:\Program Files (x86)\Ampps\php\extras\openssl.cnf");

回答by Stritof

If you're using Apache 2.4 + mod_fcgid, you can specify OpenSSL conf file by adding FcgidInitialEnvin httpd.conf file:

如果您使用的是 Apache 2.4 + mod_fcgid,您可以通过添加FcgidInitialEnvhttpd.conf 文件来指定 OpenSSL conf文件:

# OPENSSL CONF
FcgidInitialEnv OPENSSL_CONF "D:/apps/php70/extras/ssl/openssl.cnf"

I'm not using preconfigured package such as WAMP, I've got Apache from Apache Loungeand PHP from windows.php.netand configured by myself.

我没有使用预配置的包,例如 WAMP,我从Apache Lounge获得了 Apache,从windows.php.net获得了PHP,并由我自己配置​​。

回答by StanE

Clean solution:

清洁解决方案:

  1. Download archive (doesn't matter which) for PHP Windows binaries from here: http://windows.php.net/download
  2. Inside you find file /extras/ssl/openssl.cnf
  3. Extract openssl.cnf somewhere (e. g. "C:/WEB/PHP/extras/ssl/openssl.cnf")
  4. Add global system variable OPENSSL_CONFwith your used path (e. g. "C:\WEB\PHP\extras\openssl.cnf" (without the double quotes)).
  1. 从这里下载 PHP Windows 二进制文件的存档(无关紧要):http: //windows.php.net/download
  2. 在里面你找到文件 /extras/ssl/openssl.cnf
  3. 将 openssl.cnf 提取到某处(例如“C:/WEB/PHP/extras/ssl/openssl.cnf”)
  4. OPENSSL_CONF使用您使用的路径添加全局系统变量(例如“C:\WEB\PHP\extras\openssl.cnf”(不带双引号))。

enter image description here

在此处输入图片说明

You must add the path to the OPENSSL_CONFsystem variable. Adding it to the Pathsystem variable is not sufficient! Under Windows 7 you find the settings dialog under: "Control Panel > System and Security > System > Advanced system settings (left menu) > Advanced (Tab) > Environment Variables...". Add the Variable OPENSSL_CONFthere.

您必须将路径添加到OPENSSL_CONF系统变量。将它添加到Path系统变量是不够的!在 Windows 7 下,您可以在以下位置找到设置对话框:“控制面板 > 系统和安全 > 系统 > 高级系统设置(左侧菜单)> 高级(选项卡)> 环境变量...”。在OPENSSL_CONF那里添加变量。

It is not required to prepare the openssl.cnf file before usage - it will work out of the box. But you can, if you want to fine tune settings.

在使用之前不需要准备 openssl.cnf 文件 - 它可以直接使用。但是,如果您想微调设置,则可以。

回答by Dwij

Have you installed OpenSSL via this method ? Installing OpenSSL on Windows

您是否通过这种方法安装了 OpenSSL?在 Windows 上安装 OpenSSL

  1. Go to http://gnuwin32.sourceforge.net/packages/openssl.htm, and download the "Setup" version of "Binaries", openssl-0.9.7c-bin.exe.

  2. Double click on openssl-0.9.7c-bin.exe to install OpenSSL to \local\gnuwin32 directory.

  3. Go back to the same page, download the "Setup" version of "Documentation", and install it to the same directory.

  4. Open command line window, and try the following command: Code:

  1. 转到http://gnuwin32.sourceforge.net/packages/openssl.htm,下载“二进制文件”的“安装”版本 openssl-0.9.7c-bin.exe。

  2. 双击 openssl-0.9.7c-bin.exe 将 OpenSSL 安装到 \local\gnuwin32 目录。

  3. 返回同一页面,下载“Documentation”的“Setup”版本,安装到同一目录下。

  4. 打开命令行窗口,并尝试以下命令:代码:

    \local\gnuwin32\bin\openssl -help
    openssl:Error: '-help' is an invalid command.

    Standard commands
    asn1parse      ca             ciphers        crl            crl2pkcs7
    dgst           dh             dhparam        dsa            dsaparam
    enc            engine         errstr         gendh          gendsa
    genrsa         nseq           ocsp           passwd         pkcs12
    pkcs7          pkcs8          rand           req            rsa
    rsautl         s_client       s_server       s_time         sess_id
    smime          speed          spkac          verify         version
    x509
    ......

If you see the list of commands printed by OpenSSL, you know that your installation is done correctly.

如果您看到 OpenSSL 打印的命令列表,您就知道您的安装已正确完成。

回答by Ed Vo

<?php 

         // also see  stackoverflow.com/questions/59195251/php-get-private-key-from-a-single-line-private-key 
         // micmap.org/php-by-example/de/function/openssl_get_publickey
         // best  stackoverflow.com/questions/15558321/openssl-not-working-on-windows-errors-0x02001003-0x2006d080-0x0e064002
         // sandrocirulli.net/how-to-encrypt-and-decrypt-emails-and-files/



         echo '<pre>';


        function testOpenSSL($openssl_args)
        {

                $res = openssl_pkey_new($openssl_args); // <-- CONFIG ARRAY
                openssl_error_string(); // May throw error even though its working fine!
                if (empty($res)) {return false;}
                $openssl_args['keysnew']=$res;
                        //var_dump($res);echo '<br><br>';


                // Extract the private key from $res to $privKey
                openssl_pkey_export($res, $privKey, NULL, $openssl_args); // <-- CONFIG ARRAY
                openssl_error_string(); // May throw error even though its working fine!

                // Extract the public key from $res to $pubKey
                $pubKey = openssl_pkey_get_details($res);
                openssl_error_string(); // May throw error even though its working fine!
                if ($pubKey === FALSE){return false;}
                $pubKey = $pubKey["key"];   

                // Encrypt the data to $encrypted using the public key
                $data = $openssl_args['data'];          
                $res = openssl_public_encrypt($data, $encrypted, $pubKey);
                if ($res === FALSE){return false;}
                        #var_dump($res);exit; //bool
                // Decrypt the data using the private key and store the results in $decrypted
                $res = openssl_private_decrypt($encrypted, $decrypted, $privKey);
                if ($res === FALSE){return false;}

                //return $decrypted;
                $openssl_args['pub_key']=$pubKey;
                $openssl_args['priv_key']=$privKey;
                $openssl_args['encr']=$encrypted;
                $openssl_args['decr']=$decrypted; 

                return $openssl_args;

        }




        // try sam openssl.cnf   , most error on windows xampp
        $try= 5;     
        $openssl_cnf_path = array(
            0=>'C:\xampp\apache\conf\openssl.cnf',   //11259 bytes
            1=>'C:\xampp\apache\bin\openssl.cnf',   //11259 bytes

            2=>'C:\xampp\php\windowsXamppPhp\extras\ssl\openssl.cnf',  //10909
            3=>'C:\xampp\php\extras\ssl\openssl.cnf',   //10909 byes
            4=>'C:\xampp\php\extras\openssl\openssl.cnf',   //9374 bytes

            5=>'C:\Program Files\Git\usr\ssl\openssl.cnf',  //10909 bytes
            6=>'C:\Program Files\Git\mingw64\ssl\openssl.cnf',  //10909 bytes
            );

        $data = ' todo in spin activate theme elementor-child plugin qw_casino ... permalinks postname media Lib. add new upload paysave pic make empty page   with template-casino in -child make page4todo in spin activate theme elementor-child plugin qw_casin245'; /**  ... permalinks postname media Lib. add new upload paysave pic make empty page   with template-casino in -child make page6todo in spin activate theme elementor-child plugin qw_casino  .. permalinks postname media Lib.add new upload paysave pic  make empty501'; 
        /** mist max str len 501  in RFC3447 can operate on messages of length up to k - 11 octets (k is the octet length of the RSA modulus) so if you are using 2048-bit RSA key then maximum length of the plain data to be encrypted is 245 bytes.  /***/

        echo 'str len : ', strlen($data);

        $openssl_args = array(
            "config" => $openssl_cnf_path[$try],
            "digest_alg" => "sha512",
            //"private_key_bits" => 4096,
            "private_key_bits" => 2048,
            "private_key_type" => OPENSSL_KEYTYPE_RSA,
            "try_path_ar" => $openssl_cnf_path,
            "data" => $data,
            );



        // Example
        $res = testOpenSSL($openssl_args);
        if ($res === FALSE)
        {
            echo "<h4 style='background-color: red;'>Fail</h4>";
        } else {
            echo '<h3 style=\'background-color: green; color:white;\'>with $try= '.$try.' decrypted ok: '.$res['decr'].'</h3>';
        }

                //////////////////////////////////////////
                //
                echo '<br>vardump res <br>';  var_dump($res);   
                echo '<br>======================<br>';      

        $privKey=$res['priv_key'];
        $pubKey =$res['pub_key'];
        file_put_contents('pri_key.txt',$privKey);
        file_put_contents('priv_key.txt',$privKey);
        file_put_contents('pub_key.txt',$pubKey);


        echo '<br><br><pre>';


        /* Encrypt the data using the public key
         * The encrypted data is stored in $encrypted */
        openssl_public_encrypt($data, $encrypted, $pubKey);
                echo '<br>public encrypt: '; var_dump( base64_encode($encrypted));


        /* Decrypt the data using the private key and store the
         * result in $decrypted. */
        openssl_private_decrypt($encrypted, $decrypted, $privKey);
                echo ' private decrypt: ', $decrypted;      



        // inverse testOpenSSL
        openssl_private_encrypt($data, $encrypted, $privKey);
                echo '<br><br> invers<br>pri encrypt: '; var_dump( base64_encode($encrypted));

        openssl_public_decrypt($encrypted, $decrypted, $pubKey);
                echo ' pub decrypt: ', $decrypted , '<br>'; 

回答by Stefan Michev

In my case copying the files to c:\windows\system32 helped me out

在我的情况下,将文件复制到 c:\windows\system32 帮助了我

libeay32.dll, ssleay32.dll

libeay32.dll、ssleay32.dll

One can find them in OpenSSL_INSTALL_PATH\bin.

可以在 OpenSSL_INSTALL_PATH\bin 中找到它们。

回答by Michael Sole

Might I suggest using Virtual Box, create a VM and install the LAMP stack. This will give you a "more real" environment. As well as troubleshooting OpenSSL is easier on Linux.

我是否建议使用Virtual Box,创建一个 VM 并安装 LAMP 堆栈。这会给你一个“更真实”的环境。在 Linux 上对 OpenSSL 进行故障排除也更容易。

With that said, I believe your problem is you can't find the plugin file itself. Make sure it lives in the right path and exists on your machine and the process Apache runs under has permissions to read it.

话虽如此,我相信您的问题是您找不到插件文件本身。确保它位于正确的路径中并存在于您的机器上,并且 Apache 运行的进程有权读取它。