这是一个简单的PHP脚本,它打开一个SSL套接字准备发送HTTP请求:
$ contextOptions = array(); $ socketUrl ='ssl://google.com:443'; $ streamContext = stream_context_create($ contextOptions); $ socket = stream_socket_client($ socketUrl,$ errno,$ errstr,30,STREAM_CLIENT_CONNECT,$ streamContext); if(!$ socket || $ errno!== 0){ var_dump($ socket,$ errstr); 出口; } 后续代码var_dump($sockets); 退出('套接字创build');
这工作 – 我刚刚testing它 – 但没有对受信任的CA商店的validation。
我们可以修改该脚本以使用PHP的SSL上下文选项 :
$ contextOptions = array( 'ssl'=>数组( 'cafile'=>'C:\ xampp \ cacerts.pem', 'CN_match'=>'* .google.com',// CN_match只有在'verify_peer'设置为TRUE时才会被检查。 见https://bugs.php.net/bug.php?id=47030。 'verify_peer'=> TRUE, ) ); $ socketUrl ='ssl://google.com:443'; $ streamContext = stream_context_create($ contextOptions); $ socket = stream_socket_client($ socketUrl,$ errno,$ errstr,30,STREAM_CLIENT_CONNECT,$ streamContext); if(!$ socket || $ errno!== 0){ var_dump($ socket,$ errstr); 出口; } 后续代码var_dump($sockets); 退出('套接字创build');
只要'cafile'存在,并有正确的CA,那么这个例子也适用…
…但是我们怎么能不用硬编码一个CA文件名/文件path呢? 我们正在尝试创build一些独立于操作系统的validationSSL证书的操作,而不需要为运行此脚本的每台服务器单独进行configuration。
我知道Linux有一个CA的目录,我们可以把它作为'capath'。 那么Windows呢? 它在哪里存储可信任的CA? 我search,这些不幸似乎是在registry中,那么我们有没有办法可以从PHP访问它们? 那么其他操作系统呢?
失败的战斗…
如果没有在PHP 5.6之前手动设置"cafile"
和"CN_match"
上下文选项,没有办法在PHP中进行安全的加密传输。 不幸的是,即使您正确地设置了这些值,您的传输仍然很有可能失败,因为在验证主机名时,5.6版之前的版本不会咨询对等证书中日益流行的SAN(subjectAltName)扩展名。 因此,通过PHP的内置流包装进行“安全”加密在很大程度上是一种误导。 用老版本的PHP最安全的赌注就是curl扩展。
关于Windows证书…
Windows使用自己的证书存储并以OpenSSL的不同格式对其证书进行编码。 相比之下,openssl应用程序使用开放的.PEM格式。 PHP的5.6之前版本无法以任何方式与Windows证书商店进行交互。 由于这个原因,使用内置的流包装器功能以跨OS的方式进行可靠和安全的加密是不可能的。
新的openssl.cafile和openssl.capath php.ini指令允许您全局分配证书位置,而不必在每个流上下文中设置它们
所有加密的流默认都会验证对等证书和主机名,如果没有提供"CN_match"
上下文选项,则会自动从URI中分析主机名。
在验证主机名时,流加密操作现在检查对等证书SAN条目
如果在流上下文或 php.ini指令中没有指定CA文件/路径,PHP会自动退回到操作系统的证书存储区(在Windows中)!
举例来说,在PHP-5.6中,您只需要安全地连接到github.com即可:
<?php $socket = stream_socket_client("tls://github.com:443");
是。 真的是这样。 不用担心上下文设置和验证参数。 PHP在这方面的功能就像你的浏览器一样。
更多关于这个问题的阅读
这些PHP 5.6的变化只是SSL / TLS改进方面的冰山一角。 迄今为止,我们一直在努力使5.6最安全的PHP版本与加密通信有关。
如果您想了解更多关于这些新功能的信息,可以通过官方渠道获取丰富的信息
5.4 / 5.5中有关SAN匹配的说明
我们正在努力将至少SAN匹配到5.4和5.5分支,因为如果没有这个功能,以任何有意义的方式使用加密包装(作为客户端)是非常困难的。 虽然这个backporting工作很大程度上依赖于我作为一名志愿者的空闲时间,upvoting这个答案可能会更快地发生:)