stream_socket_enable_crypto

(PHP 5 >= 5.1.0, PHP 7, PHP 8)

stream_socket_enable_crypto在已连接的套接字上启用/禁用加密

描述

stream_socket_enable_crypto(
    资源 $stream,
    布尔值 $enable,
    ?整数 $crypto_method = null,
    ?资源 $session_stream = null
): 整数|布尔值

在流上启用或禁用加密。

一旦建立了加密设置,就可以通过在 enable 参数中传递 truefalse 来动态地启用和禁用加密。

返回值

如果成功,则返回 true,如果协商失败,则返回 false,如果数据不足,则返回 0,你应该再次尝试(仅适用于非阻塞套接字)。

变更日志

版本 描述
8.0.0 session_stream 现在可为空。

示例

示例 #1 stream_socket_enable_crypto() 示例

<?php
$fp
= stream_socket_client("tcp://myproto.example.com:31337", $errno, $errstr, 30);
if (!
$fp) {
die(
"无法连接: $errstr ($errno)");
}

/* 为登录阶段启用加密 */
stream_socket_enable_crypto($fp, true, STREAM_CRYPTO_METHOD_SSLv23_CLIENT);
fwrite($fp, "USER god\r\n");
fwrite($fp, "PASS secret\r\n");

/* 为其余部分禁用加密 */
stream_socket_enable_crypto($fp, false);

while (
$motd = fgets($fp)) {
echo
$motd;
}

fclose($fp);
?>

上面的示例将输出类似于


添加注释

用户贡献注释 8 个注释

bobe at webnaute dot net
8 年前
PHP 5.6 中添加了常量

STREAM_CRYPTO_METHOD_ANY_CLIENT
STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT
STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT
STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT
STREAM_CRYPTO_METHOD_ANY_SERVER
STREAM_CRYPTO_METHOD_TLSv1_0_SERVER
STREAM_CRYPTO_METHOD_TLSv1_1_SERVER
STREAM_CRYPTO_METHOD_TLSv1_2_SERVER

现在,请注意,从 PHP 5.6.7 开始,STREAM_CRYPTO_METHOD_TLS_CLIENT(_SERVER 相同)不再表示任何 tls 版本,而只表示 tls 1.0(为了“向后兼容性”...)。

PHP 5.6.7 之前
STREAM_CRYPTO_METHOD_SSLv23_CLIENT = STREAM_CRYPTO_METHOD_SSLv2_CLIENT|STREAM_CRYPTO_METHOD_SSLv3_CLIENT
STREAM_CRYPTO_METHOD_TLS_CLIENT = STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT|STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT|STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT

PHP >= 5.6.7
STREAM_CRYPTO_METHOD_SSLv23_CLIENT = STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT|STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT|STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT
STREAM_CRYPTO_METHOD_TLS_CLIENT = STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT

PHP 错误:https://bugs.php.net/bug.php?id=69195
提交:https://github.com/php/php-src/commit/10bc5fd4c4c8e1dd57bd911b086e9872a56300a0

STREAM_CRYPTO_METHOD_SSLv23_CLIENT 不安全使用,因为在 php 5.6.7 之前,它表示 sslv2 或 sslv3。所以,你应该这样做
<?php
$crypto_method
= STREAM_CRYPTO_METHOD_TLS_CLIENT;

if (
defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT')) {
$crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
$crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
}

stream_socket_enable_crypto($socket, true, $crypto_method);
?>
匿名
2 年前
如果你需要在处理完未加密的流量后将流从未加密更改为加密,则在读取未加密的流量时,使用 stream-socket-recvfrom 函数读取,而不是使用 fread。使用 fread 会导致一些初始 CLIENT HELLO 消息的缓冲区被读入其缓冲区,从而导致 SSL 握手在某些情况下失败。
tigger (AT) tiggerswelt d0t net
17 年前
如上所述

如果套接字处于非阻塞模式,则 stream_socket_enable_crypto 可能失败/返回零。

你可以等待几秒钟,直到所有必要的数据到达,或者暂时切换到阻塞模式

<?PHP

stream_set_blocking
($fd, true);
stream_socket_enable_crypto ($fd, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
stream_set_blocking ($fd, false);

?>

这对我很有效 ;-)
play dot it at play-it dot net
9 个月前
关于 `crypto_method` 的区别的信息

有 `STREAM_CRYPTO_METHOD_*_CLIENT` 和 `STREAM_CRYPTO_METHOD_*_SERVER`

`STREAM_CRYPTO_METHOD_*_CLIENT` 用于客户端,例如
```php
<?php
$client
= stream_socket_client("tcp://example.com:443", $errno, $errstr);
stream_socket_enable_crypto($client, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);

//...
?>
```

这段代码执行 TLS 握手,`stream_socket_enable_crypto` 函数发送 `Client HELLO` 消息。

`STREAM_CRYPTO_METHOD_*_SERVER` 用于服务器端,例如:
<?php
$server
= stream_socket_server("tcp://example.com:443", $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN);
stream_context_set_option($server, ["ssl" => [
"local_cert" => __DIR__."/https.crt",
"local_pk" => __DIR__."/https.key",
]]);

//...

$client = stream_socket_accept($server);
stream_socket_enable_crypto($client, true, STREAM_CRYPTO_METHOD_TLS_SERVER);

//...
?>

这段代码执行 TLS 握手,在客户端发送 `Client HELLO` 后,`stream_socket_enable_crypto` 函数发送 `Server HELLO` 消息。

因此,使用 `STREAM_CRYPTO_METHOD_*_CLIENT` 用于请求数据,使用 `STREAM_CRYPTO_METHOD_*_SERVER` 用于接收客户端连接后提供数据。
Zero
10 个月前
从 PHP 7.2 开始,TLS 等同于 TLS_ANY,所以 `STREAM_CRYPTO_METHOD_TLS_CLIENT` 表示任何 TLS 版本。
bobe at webnaute dot net
9 年前
第三个参数的描述有误。
"如果省略,将使用流的 SSL 上下文中 `crypto_type` 上下文选项的值。"

上下文选项的名称是 `crypto_method`,而不是 `crypto_type`,`crypto_type` 仅仅是参数的名称。
mark at kinoko dot fr
16 年前
为了避免你在使用此函数启用服务器端加密时代码无法正常工作而四处查找原因,请注意,即使你启动的是 TLS、SSLv3 等服务器,也需要将证书放在 `ssl` 上下文中。

我因为这个问题遇到了不少麻烦...
cgy at anymacro dot com
6 年前
$context = stream_context_create();
stream_context_set_option($context, 'ssl', 'allow_self_signed', false);
stream_context_set_option($context, 'ssl', 'verify_peer', false);
stream_context_set_option($context, 'ssl', 'verify_peer_name', false);
$fp = stream_socket_client("unix:///tmp/ssl.sock", $errno, $errstr, 30,STREAM_CLIENT_ASYNC_CONNECT | STREAM_CLIENT_CONNECT,$context);

stream_socket_enable_crypto($fp, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);

错误提示:
PHP Warning: stream_socket_enable_crypto(): this stream does not support SSL/crypto
To Top