最終更新: haruyama_seigo 2011年07月14日(木) 17:30:39履歴
https://github.com/haruyama/ssh_client_sample/blob...
private def negotiateAlgorithm(transportManager: TransportManager) = { //以後はSSHのパケットでやりとりされる //クライアントから KEXINIT メッセージを送る //この実装はアルゴリズムをそれぞれ1つのみサポートし, //アルゴリズムに依存した実装を行なう val clientKexinit = TransportMessageBuilder.buildKexinit( List("diffie-hellman-group1-sha1"), List("ssh-rsa"), List("aes128-ctr"), List("aes128-ctr"), List("hmac-sha1"), List("hmac-sha1"), List("none"), List("none"), List(), List(), false) transportManager.sendMessage(clientKexinit) //サーバから KEXINIT メッセージを受け取る val serverKexinit = transportManager.recvMessage().asInstanceOf[Kexinit] //アルゴリズムのネゴシエーションが本来は必要 //この実装では, クライアント側が1つずつ指定したアルゴリズムが //受け入れられたと仮定して先に進む //クライアントとサーバのKEXINITメッセージが鍵の生成に必要なので //以下を返す (clientKexinit, serverKexinit) }
以後はSSHのパケットでやりとりされます.
以後の通信で用いるアルゴリズムを交渉するために, クライアントとサーバはサポートしているアルゴリズムを KEXINIT メッセージで交換します.
KEXINIT メッセージは以下の形式です. name-list で各アルゴリズムを優先度の降順に列挙します.
byte SSH_MSG_KEXINIT byte[16] cookie (random bytes) name-list kex_algorithms name-list server_host_key_algorithms name-list encryption_algorithms_client_to_server name-list encryption_algorithms_server_to_client name-list mac_algorithms_client_to_server name-list mac_algorithms_server_to_client name-list compression_algorithms_client_to_server name-list compression_algorithms_server_to_client name-list languages_client_to_server name-list languages_server_to_client boolean first_kex_packet_follows uint32 0 (reserved for future extension)
サンプルプログラムで println(serverKexinit) とすると, サーバから送られる KEXINIT メッセージがダンプできます. 私の環境での出力を整形したものを示します.
Kexinit( /* SSH_MSG_KEXINIT */ SSHByte(20), /* cookie */ (略), /* kex_algorithms */ SSHNameList(WrappedArray(ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521, diffie-hellman-group-exchange-sha256, diffie-hellman-group-exchange-sha1, diffie-hellman-group14-sha1, diffie-hellman-group1-sha1)), /* server_host_key_algorithms */ SSHNameList(WrappedArray(ssh-rsa, ssh-dss)), /* encryption_algorithms_client_to_server */ SSHNameList(WrappedArray(aes128-ctr, aes192-ctr, aes256-ctr, arcfour256, arcfour128, aes128-cbc, 3des-cbc, blowfish-cbc, cast128-cbc, aes192-cbc, aes256-cbc, arcfour, rijndael-cbc@lysator.liu.se)), /* encryption_algorithms_server_to_client */ SSHNameList(WrappedArray(aes128-ctr, aes192-ctr, aes256-ctr, arcfour256, arcfour128, aes128-cbc, 3des-cbc, blowfish-cbc, cast128-cbc, aes192-cbc, aes256-cbc, arcfour, rijndael-cbc@lysator.liu.se)), /* mac_algorithms_client_to_server */ SSHNameList(WrappedArray(hmac-md5, hmac-sha1, umac-64@openssh.com, hmac-ripemd160, hmac-ripemd160@openssh.com, hmac-sha1-96, hmac-md5-96)), /* mac_algorithms_server_to_client */ SSHNameList(WrappedArray(hmac-md5, hmac-sha1, umac-64@openssh.com, hmac-ripemd160, hmac-ripemd160@openssh.com, hmac-sha1-96, hmac-md5-96)), /* compression_algorithms_client_to_server */ SSHNameList(WrappedArray(none, zlib@openssh.com)), /* compression_algorithms_server_to_client */ SSHNameList(WrappedArray(none, zlib@openssh.com)), /* languages_client_to_server */ SSHNameList(WrappedArray()), /* languages_server_to_client */ SSHNameList(WrappedArray()), /* first_kex_packet_follows */ SSHBoolean(false), /* 0 (reserved for future extension) */SSHUInt32(0) )
このあとで行なう鍵交換のアルゴリズムを列挙します. 楕円曲線 Diffie-Hellman 鍵交換やDiffie-Hellman 鍵交換を用いるアルゴリズムを利用します.
サンプルプログラムでは, 「diffie-hellman-group1-sha1」 を指定しています.
サーバのホスト鍵アルゴリズムを列挙します. 楕円曲線 DSA, RSA, DSA(DSS) を利用します.
サンプルプログラムでは, 「ssh-rsa」 を指定しています.
暗号アルゴリズムを列挙します. 通信の方向によって別のアルゴリズムを利用することができます. 同じアルゴリズムを利用する場合でも方向によって鍵とIVは異なります. AESや arcfour などを利用します.
サンプルプログラムでは, 「aes128-ctr」 を指定しています.
MACアルゴリズムを列挙します. 通信の方向によって別のアルゴリズムを利用することができます. 同じアルゴリズムを利用する場合でも方向によって鍵は異なります. HMAC, UMACが利用できます.
サンプルプログラムでは, 「hmac-sha1」 を指定しています.
圧縮アルゴリズムを列挙します. 通信の方向によって別のアルゴリズムを利用することができます.
サンプルプログラムでは, 「none」(圧縮なし) を指定しています.
クライアントとサーバは交換した KEXINIT に基づき各アルゴリズムを決定します. 決定のための方法は, RFC4253に記述されています.
サンプルプログラムでは1つのアルゴリズムのみを指定しているので, そのアルゴリズムが利用できると仮定して先に進んでいます.
- カテゴリ:
- インターネット
- インターネットセキュリティ
最新コメント