自从老罗赞助了openssl以及心脏出血事件的新闻,得以了解了openssl。那么什么是openssl呢?下面摘自官网:
The OpenSSL Project is a collaborative effort to develop a robust, commercial-grade, full-featured, and Open Source toolkit implementing the Secure Sockets Layer (SSL v2/v3) and Transport Layer Security (TLS) protocols as well as a full-strength general purpose cryptography library. The project is managed by a worldwide community of volunteers that use the Internet to communicate, plan, and develop the OpenSSL toolkit and its related documentation.
简单地说,就是用来保证通信安全的。那么我们常用的php怎么使用呢?在网上找了一下,方法是在php.ini文件中添加extension=php_openssl.dll这个模块,然后将php_openssl.dll, ssleay32.dll, libeay32.dll 3个文件拷贝到 WINDOWS\system32\ 文件夹下。其实就是将这些dll放入环境变量path中去。
但是我一般都是使用集成的服务器套件的,比如phpnow,但是缺点是其没有默认打开这个模块,导致我按照这个步骤做依然不行;然后我在使用xampp的时候,就发现其是默认打开了Openssl的,所以相对是比较方便的。
然后当环境搭建好了,我们肯定就会迫不及待地去测试了。这里我给出网上找的两个例子:
1.使用了openssl_encrypt()这个函数,然后会在目录中产生一个加密后的文件,要解密这个文件,这个例子中使用的是命令行的方法。
<?php function strtohex($x)
{
$s='';
foreach (str_split($x) as $c) $s.=sprintf("%02X",ord($c));
return($s);
} $source = 'It works !'; $iv = "1234567812345678";
$pass = '1234567812345678';
$method = 'aes-128-cbc'; echo "<br>iv in hex to use: ".strtohex ($iv);
echo "<br>key in hex to use: ".strtohex ($pass);
echo "<br>"; file_put_contents ('./file.encrypted',openssl_encrypt ($source, $method, $pass, true, $iv)); $exec = "openssl enc -".$method." -d -in file.encrypted -nosalt -nopad -K ".strtohex($pass)." -iv ".strtohex($iv); echo 'executing: '.$exec."<br><br>";
echo exec ($exec);
echo "<br>"; ?>
2.第二个例子使用openssl_pkey_new()这个函数产生了一个密钥对,然后利用公钥加密和私钥解密举例。
<?php if (isset($_SERVER['HTTPS']) )
{
echo "SECURE: This page is being accessed through a secure connection.<br><br>";
}
else
{
echo "UNSECURE: This page is being access through an unsecure connection.<br><br>";
} // Create the keypair
$res=openssl_pkey_new(); // Get private key
openssl_pkey_export($res, $privatekey); // Get public key
$publickey=openssl_pkey_get_details($res);
$publickey=$publickey["key"]; echo "Private Key:<BR>$privatekey<br><br>Public Key:<BR>$publickey<BR><BR>"; $cleartext = '1234 5678 9012 3456'; echo "Clear text:<br>$cleartext<BR><BR>"; openssl_public_encrypt($cleartext, $crypttext, $publickey); echo "Crypt text:<br>$crypttext<BR><BR>"; openssl_private_decrypt($crypttext, $decrypted, $privatekey); echo "Decrypted text:<BR>$decrypted<br><br>";
?>
但是这个例子我在机子上确没有正确地运行。首先是使用https协议访问就会出问题,第二个是openssl_pkey_new()这个函数没有办法产生密钥对。
使用openssl_error_string()查看出错的问题,error:02001003:system library:fopen:No such process,然后我将xampp/php这个路径加入到path环境变量中去。然后再查看,问题是:error:2006D080:BIO routines:BIO_new_file:no such file。
好像是openssl不能找到openssl.cnf这个文件。然后查看文档:
PHP will search for the openssl.cnf using the following logic:
- the OPENSSL_CONF environmental variable, if set, will be used as the path (including filename) of the configuration file.
- the SSLEAY_CONF environmental variable, if set, will be used as the path (including filename) of the configuration file.
- The file openssl.cnf will be assumed to be found in the default certificate area, as configured at the time that the openssl DLL was compiled. This is usually means that the default filename is c:\usr\local\ssl\openssl.cnf.
很清楚地说明了php寻找openssl.cnf有三种方式。
添加环境变量,右击我的电脑属性里就可以,然后我试了,没有成功:(看到计算机里众多的dll和openssl.cnf,我就想放弃了。如果有人成功了请告诉我。
然后看到官方文档最后一句话:Note that it is possible to override the default path from the script using the configargs
of the functions that require a configuration file.
于是我在范例前面添加一个config变量,以后用的所有openssl函数里都添加$config来设置,这样居然成功了!!!!
<?php
//cnf存放路径
$opensslConfigPath = "D:/xampp/apache/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);
if (empty($res)) {return false;}
openssl_pkey_export($res, $privKey, NULL, $config);
$pubKey = openssl_pkey_get_details($res);
if ($pubKey === FALSE){return false;}
$pubKey = $pubKey["key"];
$data = '1234 5678 9012';
echo '原文:'.$data;
// 加密
if ($res === FALSE){return false;}
openssl_public_encrypt($data, $encrypted, $pubKey);
// 解密
$res = openssl_private_decrypt($encrypted, $decrypted, $privKey);
if ($res === FALSE){return false;}
else echo '<br>解密后:'.$decrypted;
大家可以复制过去看看运行结果。
至此终于顺利试用了openssl:)