PHPでSSL通信を自力でやってみる 1.ClientHelloとServerHelloを解析

PHPCURLとか使わずにSSL通信したい。
自力と言っても、流石にOpenSSL関数は使うけど。
で、今回はClientHelloとServerHelloについてやってみた。
とりあえず、シリーズ物にする予定。
 

作ったもの

$ tree .
.
|-- SSL
|   |-- Certificate.php
|   |-- CipherSuite.php
|   |-- CompressionMethod.php
|   |-- ContentType.php
|   |-- Handshake
|   |   |-- Certificate.php
|   |   |-- ClientHello.php
|   |   |-- ServerHello.php
|   |   `-- ServerHelloDone.php
|   |-- Handshake.php
|   |-- HandshakeType.php
|   |-- Plaintext.php
|   |-- ProtocolVersion.php
|   |-- Random.php
|   |-- SessionID.php
|   |-- Utils.php
|   |-- iFragment.php
|   `-- iHandshake.php
|-- SSL.php
|-- test.php
`-- test2.php

2 directories, 20 files

 

ClientHelloとServerHelloを解析

データは、あらかじめダンプしといたものを使用。
 

ソース
<?php
require_once(dirname(__FILE__).'/SSL.php');

$clienthello = file_get_contents('../dump/clienthello');
$serverhello = file_get_contents('../dump/serverhello');

try {
	echo "### ClientHello ###\n";
	print_r(SSL_Plaintext::parse($clienthello));
	echo "### ServerHello ###\n";
	print_r(SSL_Plaintext::parse($serverhello));
} catch (Exception $e) {
	echo $e."\n";
}

 

結果
$ php test.php
### ClientHello ###
Array
(
    [0] => SSL_Plaintext Object
        (
            [_type:private] => SSL_ContentType Object
                (
                    [_code:private] => 22
                )

            [_version:private] => SSL_ProtocolVersion Object
                (
                    [_major:private] => 3
                    [_minor:private] => 0
                )

            [_fragment:private] => SSL_Handshake Object
                (
                    [_type:private] => SSL_HandshakeType Object
                        (
                            [_code:private] => 1
                        )

                    [_body:private] => SSL_Handshake_ClientHello Object
                        (
                            [_version:private] => SSL_ProtocolVersion Object
                                (
                                    [_major:private] => 3
                                    [_minor:private] => 0
                                )

                            [_random:private] => SSL_Random Object
                                (
                                    [_time:private] => 1267588080
                                    [_bytes:private] => 68617ba4f5c9ccdba09b824932eea538a6a64723aef925a81de255ca
                                )

                            [_session:private] => SSL_SessionID Object
                                (
                                    [_session:private] =>
                                )

                            [_cipher:private] => Array
                                (
                                    [0] => SSL_CipherSuite Object
                                        (
                                            [_cipher:private] => 4
                                        )

                                    [1] => SSL_CipherSuite Object
                                        (
                                            [_cipher:private] => 5
                                        )

                                    [2] => SSL_CipherSuite Object
                                        (
                                            [_cipher:private] => 10
                                        )

                                    [3] => SSL_CipherSuite Object
                                        (
                                            [_cipher:private] => 9
                                        )

                                    [4] => SSL_CipherSuite Object
                                        (
                                            [_cipher:private] => 100
                                        )

                                    [5] => SSL_CipherSuite Object
                                        (
                                            [_cipher:private] => 98
                                        )

                                    [6] => SSL_CipherSuite Object
                                        (
                                            [_cipher:private] => 3
                                        )

                                    [7] => SSL_CipherSuite Object
                                        (
                                            [_cipher:private] => 6
                                        )

                                    [8] => SSL_CipherSuite Object
                                        (
                                            [_cipher:private] => 19
                                        )

                                    [9] => SSL_CipherSuite Object
                                        (
                                            [_cipher:private] => 18
                                        )

                                    [10] => SSL_CipherSuite Object
                                        (
                                            [_cipher:private] => 99
                                        )

                                )

                            [_compression:private] => Array
                                (
                                    [0] => SSL_CompressionMethod Object
                                        (
                                            [_compression:private] => 0
                                        )

                                )

                        )

                )

        )

)
### ServerHello ###
Array
(
    [0] => SSL_Plaintext Object
        (
            [_type:private] => SSL_ContentType Object
                (
                    [_code:private] => 22
                )

            [_version:private] => SSL_ProtocolVersion Object
                (
                    [_major:private] => 3
                    [_minor:private] => 0
                )

            [_fragment:private] => SSL_Handshake Object
                (
                    [_type:private] => SSL_HandshakeType Object
                        (
                            [_code:private] => 2
                        )

                    [_body:private] => SSL_Handshake_ServerHello Object
                        (
                            [_version:private] => SSL_ProtocolVersion Object
                                (
                                    [_major:private] => 3
                                    [_minor:private] => 0
                                )

                            [_random:private] => SSL_Random Object
                                (
                                    [_time:private] => 1267588207
                                    [_bytes:private] => 8d5615085f5831231e160d22b127dec1236a3099298e31d1f8f967d6
                                )

                            [_session:private] => SSL_SessionID Object
                                (
                                    [_session:private] => 8c0af55d7367783a83f5ccf53bba389864e526c4bbf08672fe8d48096d94c0ae
                                )

                            [_cipher:private] => SSL_CipherSuite Object
                                (
                                    [_cipher:private] => 4
                                )

                            [_compression:private] => SSL_CompressionMethod Object
                                (
                                    [_compression:private] => 0
                                )

                        )

                )

        )

    [1] => SSL_Plaintext Object
        (
            [_type:private] => SSL_ContentType Object
                (
                    [_code:private] => 22
                )

            [_version:private] => SSL_ProtocolVersion Object
                (
                    [_major:private] => 3
                    [_minor:private] => 0
                )

            [_fragment:private] => SSL_Handshake Object
                (
                    [_type:private] => SSL_HandshakeType Object
                        (
                            [_code:private] => 11
                        )

                    [_body:private] => SSL_Handshake_Certificate Object
                        (
                            [_certificate:private] => Array
                                (
                                    [0] => SSL_Certificate Object
                                        (
                                            [_x509:private] => Resource id #25
                                        )

                                )

                        )

                )

        )

    [2] => SSL_Plaintext Object
        (
            [_type:private] => SSL_ContentType Object
                (
                    [_code:private] => 22
                )

            [_version:private] => SSL_ProtocolVersion Object
                (
                    [_major:private] => 3
                    [_minor:private] => 0
                )

            [_fragment:private] => SSL_Handshake Object
                (
                    [_type:private] => SSL_HandshakeType Object
                        (
                            [_code:private] => 14
                        )

                    [_body:private] => SSL_Handshake_ServerHelloDone Object
                        (
                        )

                )

        )

)

 

ClientHelloを生成

めちゃくちゃ長くなった。
全部コンストラクタで値を渡しててやたらと汚い。
ぱっと見て、入れ子関係がとっても解りづらい。
セッターメソッド作って後から入れていった方がまだマシかも…?
これでちゃんとServerHelloが返ってくるかは未検証。
 

ソース
<?php
require_once('SSL.php');

$content_type = new SSL_ContentType(SSL_ContentType_Handshake);
$version = new SSL_ProtocolVersion(0x03, 0x00);

$handshake_type = new SSL_HandshakeType(SSL_HandshakeType_ClientHello);

$random = new SSL_Random(time(), '01020304050607080910111213141516171819202122232425262728');
$session = new SSL_SessionID('');
$cipher = array();
$cipher[] = new SSL_CipherSuite(0x0004);
$cipher[] = new SSL_CipherSuite(0x0005);
$compression = array();
$compression[] = new SSL_CompressionMethod(0x00);
$handshake_body = new SSL_Handshake_ClientHello($version, $random, $session, $cipher, $compression);
$fragment = new SSL_Handshake($handshake_type, $handshake_body);

$clienthello = new SSL_Plaintext($content_type, $version, $fragment);

echo $clienthello->build();

 

結果
$ php test2.php | xxd
0000000: 1603 0000 2f01 0000 2b30 004b 9014 7a01  ..../...+0.K..z.
0000010: 0203 0405 0607 0809 1011 1213 1415 1617  ................
0000020: 1819 2021 2223 2425 2627 2800 0004 0004  .. !"#$%&'(.....
0000030: 0005 0100                                ....