linux已通过源码安装openssl(假设安装目录为:/usr/local/openssl),目前php安装时所指定的openssl未能支持国密算法,若希望php也能实现国密算法,则编译安装php时,需指定gmssl(而非openssl)。
# unzip GmSSL-master.zip
# ./config --prefix=/usr/local/gmssl --openssldir=/usr/local/gmssl/ssl
# make
# make test
# make install
若在安装过程中出现:pod2man: command not found 错误信息,请使用whereis pod2man命令查看是否安装了pod2man,否则执行yum-yinstall perl-podlators进行安装(建议重装,即先执行yum remove perl-podlators)。
gmssl
命令行工具检查是否成功# /usr/local/gmssl/bin/gmssl version
GmSSL 2.0 - OpenSSL 1.1.0d
执行gmssl命令后,出现:/usr/local/gmssl/bin/gmssl: relocation error: /usr/local/gmssl/bin/gmssl: symbol PBEPARAM_it, version OPENSSL_1_1_0d not defined in file libcrypto.so.1.1 with link time reference 错误!
暂时解决方法如下:
(1)查看gmssl依赖库路径:ldd /usr/local/gmssl/bin/gmssl
libssl.so.1.1 => /usr/local/openssl/lib/libssl.so.1.1 (0x00007fc91a5d0000)
libcrypto.so.1.1 => /usr/local/openssl/lib/libcrypto.so.1.1 (0x00007fc91a0ed000)(2)把make后的两个依赖库拷贝到相应路径(覆盖原依赖文件,即安装openssl时所生成的libssl.so.1.1 及libcrypto.so.1.1 文件,注意:这种方法会影响到用openssl的应用,以下操作请三思而后行!)
cd /usr/local/src/GmSSL-master
cp libcrypto.so.1.1 /usr/local/openssl/lib/
cp libssl.so.1.1 /usr/local/openssl/lib/
GmSSL的PHP扩展代码位于源代码中的的php/ext/openssl
目录,PHP扩展需要和PHP源代码目录树一起编译,过程如下:
1、下载并编译安装GmSSL(上一步已完成);
2、下载最新的PHP源代码并解压;
3、用GmSSL的php/ext/openssl
目录替代PHP源代码中的ext/openssl
目录;
4、编译和安装PHP(centos7 php7.3安装);
!!!请注意!!!
PHP的默认配置不编译OpenSSL扩展,需要显式指--with-openssl才会编译OpenSSL扩展,而且,我们此处需要显示指定gmssl,因此,在安装php过程中,执行configure操作时,需这样指定:./configure --with-openssl=/usr/local/gmssl --with-libdir=lib。
在执行./configure命令时,若提示:"configure: error: Cannot find OpenSSL's libraries",请执行:"ln -s /usr/local/openssl/lib/libssl.so /usr/lib",即使用openssl的libssl而非gmssl的libssl(为的是安装gmssl时,将对openssl的影响程度降到最低)。
在编译php过程中(执行make 或 make ZEND_EXTRA_LIBS='-liconv'命令),若出现:"make: *** [ext/openssl/xp_ssl.lo] Error 1"错误信息,可尝试安装php7.1(亲测php7.1.11安装成功)而非php7.3。
php安装成功后,可以通过ldd检查可执行程序是否链接了预期的库:ldd /usr/local/php73/bin/php。
5、修改PHP配置文件php.ini
启用openssl扩展,即取消php.ini
中extension=openssl
前面的注释。
可以通过PHP的
phpinfo()
函数确认openssl扩展已经启用,通过ldd
命令检查PHP的二进制程序调用了GmSSL的动态库而不是系统默认的OpenSSL动态库。
OPENSSL_KEYTYPE_EC, "curve_name" => "sm2p256v1"));
openssl_pkey_export($prikey, $prikeypem);
echo $prikeypem;
$pubkeypem = openssl_pkey_get_details($prikey)["key"];
echo $pubkeypem;
$pubkey = openssl_pkey_get_public($pubkeypem);
$point = openssl_pkey_get_details($pubkey)["ec"];
printf("SM2 Public Key: (%s, %s)\n", bin2hex($point["x"]), bin2hex($point["y"]));
$ec = openssl_pkey_get_details($prikey)["ec"];
printf("SM2 Private Key: %s\n", bin2hex($ec["d"]));
openssl_sign($msg, $signature, $prikey, "sm3");
$ok = openssl_verify($msg, $signature, $pubkey, OPENSSL_ALGO_SM3);
printf("sm2sign(\"%s\") = %s\n", $msg, bin2hex($signature));
printf("sm2verify(\"%s\", %s) = %s\n", $msg, bin2hex($signature), $ok ? "OK" : "Failure");
openssl_seal($plaintext, $sealed, $ekeys, array($pubkey), "sms4", $iv);
openssl_open($sealed, $opened, $ekeys[0], $prikey, "sms4", $iv);
printf("sm2seal(\"%s\") = %s\n", $plaintext, bin2hex($sealed));
printf("sm2open(%s) = \"%s\"\n", bin2hex($sealed), $opened);
?>
如上述代码正常执行,则说明php已支持gmssl。
参考文献:The GmSSL Project