php中ssl开发的若干问题
最近利用php开发ssl的相关功能,由于第一次做相关的事情,遇到了很多问题,庆幸的是最终都顺利解决了。不过相关的资料很少,都是综合了国内外的相关信息才解决的。现在整理一下,方便后来者遇到问题时解决。
1. 首先扫下盲,什么是数字签名
其实整个过程就是:
数据->hash-》摘要-》私钥对摘要加密-》数字签名
| |
hash 公钥解密
| |
摘要-------------是否相等--------------摘要
2. Fatal error: Call to undefined function openssl_pkey_get_public() in 。。。这个问题主要是因为php.ini中,extension=php_openssl.dll的选项没有打开,把分号去掉,重启apache即可。
3. 用php的openssl_verify函数无法验证由其他函数库生成的签名
比如用c++的函数库生成了一个签名,将其发送给服务器端验签,用php的openssl_verify函数,总是无法通过,并且有以下错误提示:
error:0D07207B:asn1 encoding routines:ASN1_get_object:header too long
error:0D068066:asn1 encoding routines:ASN1_CHECK_TLEN:bad object header
error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested asn1 error
主要原因是openssl_verify函数是对上面讲的验签过程的高度封装,包括公钥解密,数据校验,比较摘要等过程。这个函数的特别之处是,它需要这个签名必须包含hash头,而有些函数生成的签名是不包含这个hash头的,所以总是有参数错误。
解决的办法就是自己实现这个verify函数。简单的过程如下:
$sha1 = sha1($data, true);
$sign = base64_decode($sign);
$deco = '';
$pubkid = openssl_pkey_get_public($cert);
openssl_public_decrypt($sign, $deco, $pubkid);
最后比较$sha1和$deco是否相等。
4.Warning: openssl_verify(): Don't know how to get public key from this private key in。。。
Warning: openssl_verify(): supplied key param cannot be coerced into a public key in。。。Warning: openssl_public_decrypt(): Don't know how to get public key from this private key in。。。
Warning: openssl_public_decrypt(): key parameter is not a valid public key in 。。。
明明各种配置都正确,为什么会有这样的警告?而且函数无法得到正确结果。
这个原因是apache和php的openssl版本不一致。apache和php的openssl功能都依赖于libeay32.dll和 ssleay32.dll这两个库,但是这两个文件并非被apache和php共用,而是各用各的。比如apache中这两个文件一般在bin目录,而 php中就在php目录中。仔细看他们的信息会发现,这些文件都有版本信息,关键就是这个版本不一致导致。有人说将php中的这两个文件直接复制到 apache的bin目录中可以解决问题,但是不推荐这样做,因为也许在其他地方会出现错误。如果是自己配置,就下载apache和php中这两个文件版 本一致的。如果不想自己配置,可以使用xampp1.7.1版本。下载地址。
5.最后说一下https的配置 (转自这里,并做了适当修改)
SSL: SSl是为Http传输提供安全的协议,通过证书认证来确保客户端和网站服务器之间的数据是安全。也就是说在SSL下http传输是安全的,我们成为 https.
配置过程如下:
步骤一:安装apache,使其支持SSL,并安装php
1.安装配有SSL模块的apache,比如apache_2.2.8-win32-x86-openssl-0.9.8g
2.配置apache以支持SSL:打开apache的配置文件conf/httpd.conf
1)LoadModule ssl_module modules/mod_ssl.so、Include conf/extra/httpd-ssl.conf
去掉两行前面的#
2)注意修改httpd-ssl.conf 文件里的两个字段:
SSLCertificateFile "C:/Apache2.2/conf/server.crt"
SSLCertificateKeyFile "C:/Apache2.2/conf/server.key"
3.安装php,整合apache和Php(略)
为下面你所生成的证书和密钥地址。
步骤二:为网站服务器生成证书及私钥文件
1. 生成服务器的私钥
进入命令行:
D:\local\apache2\bin\openssl genrsa -out server.key 1024
在当前目录下生成了一个server.key生成签署申请
2. 生成签署申请
D:\local\apache2\bin>openssl req -new –out server.csr -key server.key -config..\conf\openssl.cnf
此时生成签署文件server.csr.
步骤三:通过CA为网站服务器签署证书
1.生成CA私钥
D:\local\apache2\bin\openssl genrsa -out ca.key 1024
多出ca.key文件
2.利用CA的私钥产生CA的自签署证书
D:\local\apache2\bin\openssl req -new -x509 -days 365 -key ca.key -out ca.crt -config ..\conf\openssl.cnf
此时需要输入一些信息,注意Common Name为服务器域名,如果在本机,为本机IP。
3.CA为网站服务器签署证书
D:\local\apache2\bin\openssl ca -in server.csr -out server.crt -cert ca.crt -keyfile ca.key -config ..\conf\openssl.cnf
但,此时会报错,于是在在当前目录创建demoCA,里面创建以下文件,index.txt,serial,serial中内容为01,其他为空,以及文件夹 newcert.再执行一遍,即可生成server.crt文件
但,此时会报错,于是在在当前目录创建demoCA,里面创建以下文件,index.txt,serial,serial中内容为01,其他为空,以及文件夹 newcert.再执行一遍,即可生成server.crt文件
步骤四:然后将 server.crt,server.key复制到apache的conf文件夹下,重启apache
若是使用了xampp,其中自带了证书和私钥,不用自己配置,直接支持https。只需修改http-ssl.conf中的documentroot字段,想用https访问哪个目录就改为哪个。
若以http访问,则http.conf中documentroot指向哪里,就访问哪里;若以https访问,则http-ssl.conf中的documentroot指向哪里就访问哪里。