CakeFest 2024: The Official CakePHP Conference

stream_socket_enable_crypto

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

stream_socket_enable_crypto接続済みのソケットについて暗号化の on/off を切り替える

説明

stream_socket_enable_crypto(
    resource $stream,
    bool $enable,
    ?int $crypto_method = null,
    ?resource $session_stream = null
): int|bool

ストリームの暗号化を有効あるいは無効にします。

暗号化設定が確立されると、それ以降は enable パラメータに true あるいは false を指定することで暗号化の on/off を動的に切り替えられます。

パラメータ

stream

ストリームリソース。

enable

ストリームの暗号化を有効にするか無効にするか。

crypto_method

ストリームの暗号化の設定。以下の方法が使用できます。

  • STREAM_CRYPTO_METHOD_SSLv2_CLIENT
  • STREAM_CRYPTO_METHOD_SSLv3_CLIENT
  • STREAM_CRYPTO_METHOD_SSLv23_CLIENT
  • STREAM_CRYPTO_METHOD_ANY_CLIENT
  • STREAM_CRYPTO_METHOD_TLS_CLIENT
  • STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT
  • STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT
  • STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT
  • STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT (PHP 7.4.0 以降)
  • STREAM_CRYPTO_METHOD_SSLv2_SERVER
  • STREAM_CRYPTO_METHOD_SSLv3_SERVER
  • STREAM_CRYPTO_METHOD_SSLv23_SERVER
  • STREAM_CRYPTO_METHOD_ANY_SERVER
  • STREAM_CRYPTO_METHOD_TLS_SERVER
  • STREAM_CRYPTO_METHOD_TLSv1_0_SERVER
  • STREAM_CRYPTO_METHOD_TLSv1_1_SERVER
  • STREAM_CRYPTO_METHOD_TLSv1_2_SERVER
  • STREAM_CRYPTO_METHOD_TLSv1_3_SERVER (PHP 7.4.0 以降)

省略した場合は、ストリームの SSL コンテキストのオプション crypto_method を利用します。

session_stream

ストリームで session_stream からの設定を送信します。

戻り値

成功した場合に true、ネゴシエーションに失敗した場合に false、 十分なデータがないために再試行が必要な場合(非ブロックモード時のみ) に 0 を返します。

変更履歴

バージョン 説明
8.0.0 session_stream は、nullable になりました。

例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);
?>

上の例の出力は、 たとえば以下のようになります。


add a note

User Contributed Notes 8 notes

up
21
bobe at webnaute dot net
7 years ago
Constants added in 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

Now, be careful because since PHP 5.6.7, STREAM_CRYPTO_METHOD_TLS_CLIENT (same for _SERVER) no longer means any tls version but tls 1.0 only (for "backward compatibility"...).

Before 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 bug : https://bugs.php.net/bug.php?id=69195
Commit : https://github.com/php/php-src/commit/10bc5fd4c4c8e1dd57bd911b086e9872a56300a0

STREAM_CRYPTO_METHOD_SSLv23_CLIENT is not safe to use because before php 5.6.7, it means sslv2 or sslv3. So, you should do this :
<?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);
?>
up
3
Anonymous
2 years ago
If you need to change a stream from unencrypted to crypted after unencrypted traffic has been processed, you use the stream-socket-recvfrom function to read instead of fread when reading the unencrypted traffic. Using fread will cause some of the buffer of the initial CLIENT HELLO message to be read into it's buffers causing the SSL handshake to fail in some situations.
up
3
tigger (AT) tiggerswelt d0t net
16 years ago
As already mentioned above:

stream_socket_enable_crypto is likely to fail/return zero if the socket is in non-blocking mode.

You may either wait some seconds until all neccessary data has arrived or switch temporary to blocking mode:

<?PHP

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

?>

This works very fine for me ;-)
up
1
play dot it at play-it dot net
4 months ago
Information to the difference of `crypto_method`

There is `STREAM_CRYPTO_METHOD_*_CLIENT` and `STREAM_CRYPTO_METHOD_*_SERVER`

`STREAM_CRYPTO_METHOD_*_CLIENT` is used for clients, like:
```php
<?php
$client
= stream_socket_client("tcp://example.com:443", $errno, $errstr);
stream_socket_enable_crypto($client, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);

//...
?>
```

This code makes a TLS Handshake and the `stream_socket_enable_crypto` sends a `Client HELLO`

`STREAM_CRYPTO_METHOD_*_SERVER` is used for servers, like:
<?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);

//...
?>

This code makes a TLS Handshake and the `stream_socket_enable_crypto` sends a `Server HELLO` after the client send a `Client HELLO`.

so use `STREAM_CRYPTO_METHOD_*_CLIENT` for requesting data and `STREAM_CRYPTO_METHOD_*_SERVER` for serving data, after accepting a client.
up
1
Zero
5 months ago
Since PHP 7.2, TLS equates to TLS_ANY, so STREAM_CRYPTO_METHOD_TLS_CLIENT means any TLS versions.
up
0
cgy at anymacro dot com
5 years ago
$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
up
0
bobe at webnaute dot net
9 years ago
There is an error in the description of the third argument:
"If omitted, the crypto_type context option on the stream's SSL context will be used instead."

The name of the context option is "crypto_method", NOT "crypto_type" which is just the name of the argument.
up
-1
mark at kinoko dot fr
16 years ago
Just to avoid letting you search everywhere why your code doesn't work when using this function to enable crypto as a server, and when using TLS, you have to put the certificate in the "ssl" context, even if you start a TLS, SSLv3, etc.. server.

I had some troubles because of that...
To Top