PHP和SSL CA验证 - 与操作系统无关(PHP and SSL CA Verification

2019-09-01 11:10发布

这里是打开一个SSL套接字准备发送HTTP请求一个简单的PHP脚本:

$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);
    exit;
}

var_dump($socket);
exit('Socket created.');

这工作 - 我只是测试它 - 但有对信任的CA存储任何验证。

我们可以修改脚本,以使用PHP的SSL上下文选项 :

$contextOptions = array(
    'ssl' => array(
        'cafile' => 'C:\xampp\cacerts.pem',
        'CN_match' => '*.google.com',  // CN_match will only be checked if 'verify_peer' is set to TRUE.  See 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);
    exit;
}

var_dump($socket);
exit('Socket created.');

只要“凭证档案错误”存在并具有正确的CA那么这个例子也适用...

......但我们怎样才能做到这一点没有硬编码CA文件名/文件路径? 我们正在努力创造的东西,OS-独立验证SSL证书,而无需为运行该脚本的每个服务器单独配置。

我知道,Linux有,我们可以把作为“capath” CA的目录。 什么有关Windows? 它在哪里存储其信任的CA? 我搜索,这些不幸的是似乎是在注册表中,所以是有没有办法,我们可以从PHP访问它们? 那么其他的操作系统?

Answer 1:

一场败仗...

没有办法进行PHP中的安全的加密传输,而无需手动设置"cafile""CN_match"之前PHP 5.6上下文选项。 不幸的是,即使正确设置这些值的转让仍然很可能失败,因为验证主机名时前5.6版本不征询日益流行的SAN(SubjectAltName)扩展目前在同行证书。 其结果是,通过PHP内置的流包装“安全”加密主要是用词不当。 你最安全的赌注(直译)与旧版本的PHP是卷曲的延伸。

关于窗口证书...

Windows使用其自己的证书存储,并从不同的OpenSSL编码格式的证书。 相比之下,OpenSSL的应用程序使用开放.PEM格式。 预5.6版本的PHP不能以任何方式证书存储Windows接口。 出于这个原因,它是不可能有一个跨操作系统的方式可靠和安全的加密使用内置的流包装的功能。

PHP 5.6是向前迈进一大步

  • openssl.cafileopenssl.capath php.ini配置让您全局分配证书的位置,而不必设置他们在每流上下文

  • 所有加密的数据流默认验证同行证书和主机名,如果没有主机名自动从URL解析"CN_match"上下文选项提供。

  • 流加密操作现在检查对证书SAN项验证主机名时

  • 如果串流上下文没有指定CA文件/路径 php.ini配置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版本迄今为止关于加密的通信。

如果您想了解更多关于这些新功能也通过官方渠道提供了丰富的信息

  • [RFC改进的TLS默认值
  • [RFC] TLS对等认证
  • 5.6 NEWS文件
  • 5.6升级的文件

在SAN匹配的说明5.4 / 5.5

我们正在努力,因为它是很难用任何有意义的方式加密封装(客户端)没有这个功能至少反向移植的SAN匹配到5.4和5.5分支机构。 虽然这向后移植工作,在很大程度上取决于我的可用时间作为一名志愿者,upvoting这个答案一定会帮助它快发生:)



文章来源: PHP and SSL CA Verification - OS Independent