PHPでCURLとか使わずに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 ....