Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 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行追加)

主な変更点:

  1. crypto/randパッケージのインポートを削除
  2. 全ての認証メソッドのシグネチャにrand io.Readerパラメータを追加
  3. publickeyAuthSignメソッド呼び出しでrand.Readerrandパラメータに変更
  4. TODOコメントを削除

変更の背景

このコミットは、SSH認証における乱数源の統一化を目的としています。従来、SSH公開鍵認証ではcrypto/rand.Readerを直接使用していましたが、これにより以下の問題が発生していました:

  1. 設定の不整合: ClientConfigで乱数源を設定しても、公開鍵認証では異なる乱数源が使用される
  2. テスト困難性: テスト時に決定論的な乱数源を使用することが困難
  3. カスタマイズ性の欠如: ハードウェア乱数生成器やカスタム乱数源を使用できない

前提知識の解説

SSH公開鍵認証の仕組み

SSH公開鍵認証は、暗号学的な鍵ペア(公開鍵と秘密鍵)を使用したチャレンジ・レスポンス認証方式です:

  1. 初期化: クライアントが公開鍵をサーバーに送信
  2. チャレンジ: サーバーがランダムデータを生成し、クライアントに送信
  3. 署名: クライアントが秘密鍵でチャレンジデータに署名
  4. 検証: サーバーが公開鍵を使用して署名を検証

乱数源の重要性

SSH認証では、以下の用途で乱数が使用されます:

  1. ナンス生成: 再送攻撃を防ぐためのランダム値
  2. 署名パディング: RSA-PSS等の署名方式で使用
  3. 鍵交換: Diffie-Hellman鍵交換でのランダム値
  4. セッション鍵: 暗号化で使用する対称鍵の生成

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()メソッド

ClientConfigrand()メソッドは、設定された乱数源を返すか、デフォルトのcrypto/rand.Readerを返します:

func (c *ClientConfig) rand() io.Reader {
    if c.Rand == nil {
        return rand.Reader
    }
    return c.Rand
}

統一されたインターフェース

変更により、全ての認証メソッドが同じ乱数源を使用するようになりました:

  1. noneAuth: 認証処理なし(パラメータの統一のみ)
  2. passwordAuth: パスワード認証(パラメータの統一のみ)
  3. publickeyAuth: 公開鍵認証(実際に乱数を使用)

セキュリティ上の利点

  1. 一貫性: 全ての認証メソッドで同じ乱数源を使用
  2. 設定可能性: カスタム乱数源をClientConfig.Randで設定可能
  3. テスト容易性: テスト時に決定論的な乱数源を使用可能

関連リンク

参考にした情報源リンク