最近做毕业设计,关于电子商务安全方面的,于是研究了下SSL加密的实现,发现网上的资料都是千篇一律,只涉及到了协议层的认真签名,对于业务层的完全不涉及;我也问过一些网友,发现很多人只认识到了协议层的认证,认为这样就完成了认证,到现在为止我认为这是不对的。
先说一下协议层的认证,这一层的认证主要是由浏览器和服务器之间通过几握手完成信息的传递的,具体的可以参考一下这篇文章SSL握手过程。这里就不做讲解了。
再谈谈OpenSSL这个工具。OpenSSL用一般在Apache里面自带的有,用来生成数字证书、签名。怎么生成数字证书这儿也不说了,网上资料很多,这里给个现成的命令就行了,不做具体解释。
CA证书 openssl genrsa -out ca.key 1024 openssl req -new -key ca.key -out ca.csr -config ./openssl.cnf openssl x509 -req -days 3650 -signkey ca.key -in ca.csr -out ca.crt 服务端证书 # openssl genrsa -out server.key 1024 # openssl req -new -key server.key -out server.csr -config ./openssl.cnf # openssl x509 -req -days 365 -CA ca.crt -CAkey ca.key -in server.csr -out server.crt -CAcreateserial 签客户端证书: openssl genrsa -out client.key 1024 openssl req -new -key client.key -out client.csr -config ./openssl.cnf openssl x509 -req -days 365 -CA ca.crt -CAkey ca.key -in client.csr -out client.crt -CAcreateserial openssl pkcs12 -export -clcerts -in client.crt -inkey client.key -out client.pfx
下面是我这次讲的重点。
首先把apache的mod_ssl模块开启,然后httpd.conf最后的Include conf/extra/httpd-ssl.conf前面的#去掉
再去conf目录下的extra目录下的httpd-ssl.conf打开设置相关配置
SSLCertificateFile "D:/Program Files/Apache Software Foundation/Apache2.2/conf/server.crt" SSLCertificateFile "D:/Program Files/Apache Software Foundation/Apache2.2/conf/server.key" SSLCACertificateFile "D:/Program Files/Apache Software Foundation/Apache2.2/conf/ca.crt" SSLVerifyClient require SSLVerifyDepth 4
其中SSLVerifyClient require SSLVerifyDepth 4 是做双向认证用的,向客户端索要证书。server.crt server.key ca.crt根据上面定义的目录放好就行。
到此为止基本上就完成了数字证书方面的配置工作,当然浏览器还要将client.pfx 导入,以及添加ca.crt的信任,不然假如客户端没有证书,服务器会终止会话。
假如有了证书,访问时,浏览器会弹出让用户选择证书,如图:
选择一个证书,然后服务器必须检验客户证书和签名随机数的合法性。具体的合法性验证过程包括:客户的证书使用日期是否有效,为客户提供证书的 CA 是否可靠,发行 CA 的公钥能否正确解开客户证书的发行 CA 的数字签名,检查客户的证书是否在证书废止列表(CRL)中。检验如果没有通过,通讯立刻中断;如果验证通过,服务器将用自己的私钥解开加密的"预主密码",然后执行一系列步骤来产生主通讯密码(客户端也将通过同样的方法产生相同的主通讯密码)[此处参考网上下载的腾讯文章,编写人tipyluo]。
然后浏览器就可以和服务器进行安全通信了,并且在协议层上认证了双方。
此时会在服务器上生成一系列有关SSL的相关环境变量,如图
然后我们在PHP脚本里面就可以写相关的业务层上的逻辑判断了,例如使用$_SERVER['SSL_CLIENT_S_DN_CN']来判断对方发送过来的用户名是否与证书上的一致。好了就这么简单。
最后在讲讲如何利用PHP的openssl函数来生成客户端的证书文件。具体如下‘
$dn = array( "countryName" => "CN", "stateOrProvinceName" => "SX", "localityName" => "TY", "organizationName" => "The ltd", "organizationalUnitName" => "PHP U", "commonName" => "PHP", "emailAddress" => "php@php.com" ); $configargs = array('config'=> 'G:/WWW/htdocs/https/openssl.cnf'); $privkey = openssl_pkey_new($configargs);//根据配置生产私钥 $csr = openssl_csr_new($dn, $privkey);//根据$dn和私钥产生有公钥的请求证书 $cacert = 'file://G:/WWW/htdocs/https/ca.crt'; $caprivkey = array('file://G:/WWW/htdocs/https/ca.key','123456789'); $scrt = openssl_csr_sign($csr, $cacert, $caprivkey, 365);//用CA和CA的KEY来给请求证书进行签名 openssl_pkcs12_export_to_file($scrt, 'G:/WWW/htdocs/https/client_2.pfx', $privkey,'123456'); //最后产生私钥和公钥证书在一起的格式文件 ,用于浏览器导入(服务器端的server.crt就没有必要用这步)
其实这样在输出错误 openssl_error_string()时还是会有错误信息,但是不影响使用。
具体每一个PHP的OPENSSL函数可以参考官方文档http://cn.php.net/openssl_csr_new,虽然是英文的但是不难,只有你明白数字证书的制作原理,不懂的先去熟悉前面讲的命令行下的openssl生成过程。
讲完了,有问题多用英文谷歌,这方面的资料英文的多些。