本文へスキップ
ecdsa.com
golang.org/x/crypto/ssh (Go)Go

エラーメッセージ

ssh: this private key is passphrase protected

別の表記

  • ssh: no key found

「ssh: no key found」(別名として掲載)は、同じパーサーが報告する別の状態で、バイト列に PEM の鍵ブロックが含まれていないことを示します。たとえば、公開鍵、PuTTY の `.ppk` ファイル、空のファイルです。

golang.org/x/crypto/ssh (Go) — *ssh.PassphraseMissingError from ssh.ParsePrivateKey

このエラーの意味

`ssh.ParsePrivateKey` は暗号化された秘密鍵を認識しましたが、復号に使うパスフレーズがないため処理を中止しました。返される `*ssh.PassphraseMissingError` には公開鍵まで含まれていますが、署名には復号済みの秘密鍵が必要です。`ssh.ParsePrivateKeyWithPassphrase` を呼び出すか、署名を SSH エージェントに任せてください。関連するエラーの「ssh: no key found」は、入力に認識できる鍵がまったく含まれていないことを意味します。

発生する理由

修正方法

  1. 1.

    エラーを検出してパスフレーズを渡す

    `errors.As` でパスフレーズがないことを判別できます。パスフレーズはシークレットストアから読み込んでください。ソースコードに含めてはいけません。

    go
    signer, err := ssh.ParsePrivateKey(keyBytes)
    var missing *ssh.PassphraseMissingError
    if errors.As(err, &missing) {
    	passphrase := []byte(os.Getenv("SSH_KEY_PASSPHRASE"))
    	signer, err = ssh.ParsePrivateKeyWithPassphrase(keyBytes, passphrase)
    }
    if err != nil {
    	return err
    }
  2. 2.

    SSH エージェント経由で署名する

    `golang.org/x/crypto/ssh/agent` を使えば、秘密鍵がプロセスに読み込まれることはなく、パスフレーズもエージェントが処理します。

    go
    import "golang.org/x/crypto/ssh/agent"
    
    conn, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK"))
    if err != nil {
    	return err
    }
    agentClient := agent.NewClient(conn)
    auth := ssh.PublicKeysCallback(agentClient.Signers) // the agent holds the decrypted key

関連するエラー

署名エラーデータベースをすべて見る