PHP 8.4.1 Released!

SSL 上下文选项

SSL 上下文选项SSL 上下文选项清单

说明

ssl://tls:// 传输协议上下文选项清单。

可选项

peer_name string

要连接的服务器名称。如果未设置,那么服务器名称将根据打开 SSL 流的主机名称猜测得出。

verify_peer bool

是否需要验证 SSL 证书。

默认值为 true

verify_peer_name bool

是否需要验证 peer name。

默认值为 true.

allow_self_signed bool

是否允许自签名证书。需要配合 verify_peer 参数使用(注:当 verify_peer 参数为 true 时才会根据 allow_self_signed 参数值来决定是否允许自签名证书)。

默认值为 false

cafile string

当设置 verify_peer 为 true 时, 用来验证远端证书所用到的 CA 证书。 本选项值为 CA 证书在本地文件系统的全路径及文件名。

capath string

如果未设置 cafile,或者 cafile 所指的文件不存在时, 会在 capath 所指定的目录搜索适用的证书。 该目录必须是已经经过哈希处理的证书目录。 (注:所谓 hashed certificate 目录是指使用类似 c_rehash 命令将目录中的 .pem 和 .crt 文件扫描并提取哈希码,然后根据此哈希码创建文件链接,以便于快速查找证书)

local_cert string

文件系统上的本地证书路径。 必须是 PEM 编码的文件,包含证书及私钥。 也可以包含证书颁发者证书链。 也可以通过 local_pk 指定包含私钥的独立文件。

local_pk string

如果使用独立的文件来存储证书(local_cert)和私钥, 那么使用此选项来指明私钥文件的路径。

passphrase string

local_cert 文件的密码。

verify_depth int

如果证书链条层次太深,超过了本选项的设定值,则终止验证。

默认情况下不限制证书链条层次深度。

ciphers string

设置可用的密码列表。 可用的值参见: » ciphers(1)

默认值为 DEFAULT.

capture_peer_cert bool

如果设置为 true 将会在上下文中创建 peer_certificate 选项, 该选项中包含远端证书。

capture_peer_cert_chain bool

如果设置为 true 将会在上下文中创建 peer_certificate_chain 选项, 该选项中包含远端证书链条。

SNI_enabled bool

设置为 true 将启用服务器名称指示(server name indication)。 启用 SNI 将允许同一 IP 地址使用多个证书。

disable_compression bool

如果设置,则禁用 TLS 压缩,有助于减轻恶意攻击。

peer_fingerprint string | array

当远程服务器证书的摘要和指定的散列值不相同的时候, 终止操作。

当使用 string 时, 会根据字符串的长度来检测所使用的散列算法:“md5”(32 字节)还是“sha1”(40 字节)。

当使用 array 时, 数组的键表示散列算法名称,其对应的值是预期的摘要值。

security_level int

设置安全级别。如果未指定,则使用库默认安全级别。 安全级别说明请参考 » SSL_CTX_get_security_level(3)

从 PHP 7.2.0 和 OpenSSL 1.1.0 开始可用。

更新日志

版本 说明
7.2.0 添加了 security_level。 需要 OpenSSL >= 1.1.0。

注释

注意: 因为 ssl://https://ftps:// 的底层传输协议, 所以,ssl:// 的上下文选项也同样适用于 https://ftps:// 上下文。

注意: PHP 必须联合 OpenSSL 0.9.8j 或以上版本编译才可以支持 SNI, 同时也支持使用 OPENSSL_TLSEXT_SERVER_NAME 来探测 SNI 服务器名称。

添加备注

用户贡献的备注 9 notes

up
7
tianyiw at vip dot qq dot com
1 year ago
Enable SNI (Server Name Indication):
PEM must be contains certificate and private key.
<?php
$context
= stream_context_create([
'ssl' => [
'SNI_enabled' => true,
'SNI_server_certs' => [
'host1.com' => '/path/host1.com.pem',
'host2.com' => '/path/host2.com.pem',
],
]
]);
?>
up
9
website at meezaan dot net
8 years ago
There is also a crypto_type context. In older versions this was crypto_method. This is referenced on http://php.net/manual/en/function.stream-socket-enable-crypto.php
up
3
gabri dot ns at gmail dot com
4 years ago
i usually download root CA certificate from https://curl.haxx.se/docs/caextract.html then put it as 'cafile' and it work almost all of the time.

the only problem i'v ever found is when the server does not properly sending intermediete CA certificate, then, you must add it manually to the file.
up
4
Charlie
7 years ago
I am unable to load a PEM that was generated with the stunnel tools. However, I am able to use PHP calls to generate a working PEM that is recognized both by stunnel and php, as outlined here:

http://www.devdungeon.com/content/how-use-ssl-sockets-php

This code fragment is now working for me, and with stunnel verify=4, both sides confirm the fingerprint. Oddly, if "tls://" is set below, then TLSv1 is forced, but using "ssl://" allows TLSv1.2:

$stream_context = stream_context_create([ 'ssl' => [
'local_cert' => '/path/to/key.pem',
'peer_fingerprint' => openssl_x509_fingerprint(file_get_contents('/path/to/key.crt')),
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true,
'verify_depth' => 0 ]]);

$fp = stream_socket_client('ssl://ssl.server.com:12345',
$errno, $errstr, 30, STREAM_CLIENT_CONNECT, $stream_context);
fwrite($fp, "foo bar\n");
while($line = fgets($fp, 8192)) echo $line;
up
4
Botjan kufca
14 years ago
CN_match works contrary to intuitive thinking. I came across this when I was developing SSL server implemented in PHP. I stated (in code):

- do not allow self signed certs (works)
- verify peer certs against CA cert (works)
- verify the client's CN against CN_match (does not work), like this:

stream_context_set_option($context, 'ssl', 'CN_match', '*.example.org');

I presumed this would match any client with CN below .example.org domain.
Unfortunately this is NOT the case. The option above does not do that.

What it really does is this:
- it takes client's CN and compares it to CN_match
- IF CLIENT's CN CONTAINS AN ASTERISK like *.example.org, then it is matched against CN_match in wildcard matching fashion

Examples to illustrate behaviour:
(CNM = server's CN_match)
(CCN = client's CN)

- CNM=host.example.org, CCN=host.example.org ---> OK
- CNM=host.example.org, CCN=*.example.org ---> OK
- CNM=.example.org, CCN=*.example.org ---> OK
- CNM=example.org, CCN=*.example.org ---> ERROR

- CNM=*.example.org, CCN=host.example.org ---> ERROR
- CNM=*.example.org, CCN=*.example.org ---> OK

According to PHP sources I believe that the same applies if you are trying to act as Client and the server contains a wildcard certificate. If you set CN_match to myserver.example.org and server presents itself with *.example.org, the connection is allowed.

Everything above applies to PHP version 5.2.12.
I will supply a patch to support CN_match starting with asterisk.
up
2
consatangmail dot com
2 years ago
recommended use "ssl://" transport.

in php 5.5 ~ 7.1
ssl:// transport = ssl_v2|ssl_v3|tls_v1.0|tls_v1.1|tls_v1.2
tls:// transport = tls_v1.0

after 7.2 ssl:// and tls:// transports is same
php 7.2 ~ 7.3 = tls_v1.0|tls_v1.1|tls_v1.2
php 7.4 ~ 8.1 = tls_v1.0|tls_v1.1|tls_v1.2|tls_v1.3
up
1
borbas dot geri at gmail dot com
10 years ago
I used this for Apple Push Notification Service.
Passed in a local certificate filename `cert.pem` trough local_cert option.
Worked fine, when invoked the script directly.

But when I included/required the script from a different location, it stopped working, without any explicit error message.

Resolved by passed in the full path for the file `<FullPathTo>cert.pem`.
up
-1
mechtecs at gmail dot com
6 years ago
If you want to validate the server against a local certificate, which you already saved, to further validate the target server, you have to use a fullchain.pem. Then the verify_peer option will work. So just get the server certificate, and search the root CA's pem's and copy everything into a single file. For example:

My certificate has the "GeoTrust TLS RSA CA G1" certificate in the chain, so you google that string. Go to the official digicert Geotrust page and download the "GeoTrustTLSRSACAG1.crt" certificate. Then you can use the following command to convert it into the pem format:
openssl x509 -inform DER -in GeoTrustTLSRSACAG1.crt -out GeoTrustTLSRSACAG1.crt.pem -outform PEM
up
-2
Charlie
7 years ago
It appears that "allow_self_signed" does not and cannot apply to the local_cert option.

The stunnel verify=4 option, which verifies but ignores a CA, has no analog in these settings, which is unfortunate.

Even more perplexingly, while the "openssl verify -CAfile" is successful, PHP appears unable to use the new ca/crt pair in any configuration.

I did actually link my PHP against a copy of LibreSSL 2.3.8, but PHP oddly is unable to use TLS1.1 or 1.2. It does, however, enable EC secp521r1 (of which my native OpenSSL 0.9.8e is incapable).
To Top