[インデックス 10363] ファイルの概要
コミット
コミットハッシュ: 59a92cde3dce85cc091c1134fae1bc08f056c445
作成者: Dave Cheney dave@cheney.net
日付: Sun Nov 13 20:57:15 2011 -0500
コミットメッセージ: exp/ssh: use ClientConfig.rand() for publickey authentication
関連Issue: Closes TODO from 5373055
レビュー: R=agl
CC: golang-dev
Code Review URL: https://golang.org/cl/5375081
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/ce4eec2e0acf9ec36c34bd42e81bbb2e32f18b81
元コミット内容
このコミットは、Go言語のSSHクライアント実装において、公開鍵認証時に使用する乱数源をcrypto/rand
パッケージからClientConfig.rand()
メソッドを使用するように変更したものです。
変更されたファイル:
src/pkg/exp/ssh/client_auth.go
(14行削除、6行追加)
主な変更点:
crypto/rand
パッケージのインポートを削除- 全ての認証メソッドのシグネチャに
rand io.Reader
パラメータを追加 publickeyAuth
のSign
メソッド呼び出しでrand.Reader
をrand
パラメータに変更- TODOコメントを削除
変更の背景
このコミットは、SSH認証における乱数源の統一化を目的としています。従来、SSH公開鍵認証ではcrypto/rand.Reader
を直接使用していましたが、これにより以下の問題が発生していました:
- 設定の不整合:
ClientConfig
で乱数源を設定しても、公開鍵認証では異なる乱数源が使用される - テスト困難性: テスト時に決定論的な乱数源を使用することが困難
- カスタマイズ性の欠如: ハードウェア乱数生成器やカスタム乱数源を使用できない
前提知識の解説
SSH公開鍵認証の仕組み
SSH公開鍵認証は、暗号学的な鍵ペア(公開鍵と秘密鍵)を使用したチャレンジ・レスポンス認証方式です:
- 初期化: クライアントが公開鍵をサーバーに送信
- チャレンジ: サーバーがランダムデータを生成し、クライアントに送信
- 署名: クライアントが秘密鍵でチャレンジデータに署名
- 検証: サーバーが公開鍵を使用して署名を検証
乱数源の重要性
SSH認証では、以下の用途で乱数が使用されます:
- ナンス生成: 再送攻撃を防ぐためのランダム値
- 署名パディング: RSA-PSS等の署名方式で使用
- 鍵交換: Diffie-Hellman鍵交換でのランダム値
- セッション鍵: 暗号化で使用する対称鍵の生成
ClientConfigの役割
ClientConfig
は、SSH接続の設定を管理する構造体で、以下の情報を含みます:
type ClientConfig struct {
User string
Auth []AuthMethod
HostKeyCallback func(hostname string, remote net.Addr, key PublicKey) error
Rand io.Reader // 乱数源の設定
// その他の設定項目
}
Rand
フィールドがnil
の場合、crypto/rand.Reader
がデフォルトで使用されます。
技術的詳細
変更前の実装
// 直接crypto/rand.Readerを使用
sign, err := p.Sign(i, rand.Reader, buildDataSignedForAuth(session, userAuthRequestMsg{
User: user,
Service: serviceSSH,
Method: p.method(),
// ...
}))
変更後の実装
// ClientConfig.rand()を使用
sign, err := p.Sign(i, rand, buildDataSignedForAuth(session, userAuthRequestMsg{
User: user,
Service: serviceSSH,
Method: p.method(),
// ...
}))
インターフェース変更
全ての認証メソッドのauth
関数シグネチャが統一されました:
// 変更前
auth(session []byte, user string, t *transport) (bool, []string, error)
// 変更後
auth(session []byte, user string, t *transport, rand io.Reader) (bool, []string, error)
コアとなるコードの変更箇所
1. インポート文の削除
-import (
- "crypto/rand"
- "errors"
- "io"
-)
+import (
+ "errors"
+ "io"
+)
2. 認証メソッドの呼び出し
-ok, methods, err := auth.auth(session, c.config.User, c.transport)
+ok, methods, err := auth.auth(session, c.config.User, c.transport, c.config.rand())
3. 公開鍵認証での乱数使用
-// TODO(dfc) use random source from the ClientConfig
-sign, err := p.Sign(i, rand.Reader, buildDataSignedForAuth(session, userAuthRequestMsg{
+sign, err := p.Sign(i, rand, buildDataSignedForAuth(session, userAuthRequestMsg{
コアとなるコードの解説
ClientConfig.rand()メソッド
ClientConfig
のrand()
メソッドは、設定された乱数源を返すか、デフォルトのcrypto/rand.Reader
を返します:
func (c *ClientConfig) rand() io.Reader {
if c.Rand == nil {
return rand.Reader
}
return c.Rand
}
統一されたインターフェース
変更により、全ての認証メソッドが同じ乱数源を使用するようになりました:
- noneAuth: 認証処理なし(パラメータの統一のみ)
- passwordAuth: パスワード認証(パラメータの統一のみ)
- publickeyAuth: 公開鍵認証(実際に乱数を使用)
セキュリティ上の利点
- 一貫性: 全ての認証メソッドで同じ乱数源を使用
- 設定可能性: カスタム乱数源を
ClientConfig.Rand
で設定可能 - テスト容易性: テスト時に決定論的な乱数源を使用可能
関連リンク
- Go SSH Package Documentation
- RFC 4252 - The Secure Shell (SSH) Authentication Protocol
- Go Code Review 5375081
- SSH Public Key Authentication