#74424accepted
x/crypto/ssh: refactor signers API
ステータス変更: likely_accept accepted
要約
AIによる要約であり、誤りを含む場合があります。
概要
x/crypto/ssh パッケージが持つ複雑化したSigner関連API(Signer/AlgorithmSigner/MultiAlgorithmSignerの3種の乱立や、鍵の解析・シリアライズ関数群)を整理し、将来標準ライブラリへ移行する布石として新しいV2系APIを追加するproposalです。
ステータス変更
likely_accept → accepted
2026年8月のレビューで「likely accept」となった後、2026年9月23日のレビュー会議(@aclements, @cherrymui, @griesemer, @ianlancetaylor, @neild)で「コンセンサスに変化なし」として正式にacceptedとなりました。提案内容自体は最初のissue本文(2025年6月29日時点)から大きくは変わっておらず、コミュニティおよびレビューグループの合意が維持されたことが承認理由です。
技術的背景
現状の問題点
現在のx/crypto/sshには署名関連のインターフェースが乱立しています。
Signer、AlgorithmSigner、MultiAlgorithmSignerという3つの異なるインターフェースが存在し、RSA鍵が複数の署名アルゴリズム(ssh-rsa、rsa-sha2-256、rsa-sha2-512)をサポートするために後付けで拡張されてきた結果、APIが分かりにくくなっているNewSignerFromKey(interface{}引数でDSA鍵もサポート)とNewSignerFromSigner(crypto.Signer引数)が重複した役割を持つ- DSA鍵は OpenSSH 10.0 で廃止されたにもかかわらず、これらのAPIには互換性のためのコードが残っている
- 暗号化された秘密鍵の解析(
ParsePrivateKeyWithPassphraseなど)が、非推奨のx509.DecryptPEMBlock(RFC 1423の古い暗号方式)に依存している
提案された解決策
新たにSignerV2インターフェースと関連関数群を追加します。
SignerV2はPublicKey()、Sign(後方互換用)、SignContext(ctx, rand, data, algorithm)(コンテキストと使用アルゴリズムを指定可能)、Algorithms()(利用可能なアルゴリズム一覧)、Signer()(内部のcrypto.Signerを取得、対応しない場合はerrors.ErrUnsupported)を持つ単一インターフェースに統合NewSignerV2(signer crypto.Signer)でcrypto.Signerからラップ(RSAはデフォルトでSHA-1系ssh-rsaを除外)NewSignerV2WithAlgorithms(signer crypto.Signer, algorithms []string)で許可アルゴリズムを明示的に制限(議論を経て引数をSignerV2からcrypto.Signerに変更)NewCertificateSignerV2、ParsePrivateKeyV2(ParsePrivateKeyV2OptionsでSignatureAlgorithms指定可)、MarshalPrivateKeyV2を追加- DSAサポートと、レガシーなPEM暗号化(
x509.DecryptPEMBlock依存)は廃止 SignerV2は既存のSignerインターフェースと互換性があり、ServerConfig.AddHostKeyなど既存APIにもそのまま渡せる
これによって何ができるようになるか
ハードウェアセキュリティモジュール(HSM)やKMSバックエンドの鍵を扱う開発者、SSHエージェントの実装者などが、コンテキスト対応の署名やアルゴリズムの明示的な制御を行いやすくなります。
コード例
// Before: 複数のインターフェース・関数が混在し、アルゴリズム制御が煩雑
signer, err := ssh.NewSignerFromKey(key)
if multiAlgo, ok := signer.(ssh.MultiAlgorithmSigner); ok {
// ssh-rsa を除外したい場合、独自ラッパーを実装する必要がある
}
// After: SignerV2で一貫したAPI、アルゴリズムを明示的に制御
signer, err := ssh.NewSignerV2(cryptoSigner) // ssh-rsa はデフォルトで除外
restricted, err := ssh.NewSignerV2WithAlgorithms(cryptoSigner, []string{"rsa-sha2-256"})
sig, err := signer.SignContext(ctx, rand.Reader, data, "rsa-sha2-256")
議論のハイライト
- **「v2パッケージにすべきか」**という議論があったが、
x/crypto/sshほどの規模のパッケージで完全なv2を作るのは負担が大きく、かつv1/v2間の循環依存が避けられないため見送られ、既存パッケージへの「V2サフィックス付き追加API」という折衷案が採用された(レビューグループも命名には消極的ながら現実的な選択と判断) - レビューアシニア@rolandshoemakerがAPIを精査し「妥当」と判断したことが、likely acceptへの後押しとなった
- コミュニティから、
NewSignerV2WithAlgorithmsが当初SignerV2を引数に取る設計だった点が「非対称で分かりにくい」と指摘され、crypto.Signerを直接受け取る設計に修正された - レガシーなPEM暗号化鍵(DES-CBC/AES-CBC等)のサポート終了について懸念が示されたが、提案側はセキュリティ上の理由から意図的にサポート対象外とし、必要であれば別途検討する方針を維持
MarshalPrivateKeyV2がcrypto.PrivateKeyではなくSignerV2から鍵をシリアライズする点が分かりにくいとの指摘を受け、ドキュメント改善が求められた- SSHエージェント(
ServeAgent)へのコンテキスト伝播についても要望が出ており、提案者は別途フォローアップのproposalを提出する意向を示している