dougan4884
2017-02-08 05:32
浏览 498
已采纳

如何在Golang SSH中使用加密的私钥

I would appreciate pointers because I cannot work out how to decrypt an encrypted key in order to use it with golang ssh. I'm attempting to mash together two other sources of code (including this one) but unable to get this to work.

I think I'm getting to a DER but need to marshall this back to PEM in order to use it with crypto/ssh

-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,D7C72273BE168626E5B2D1BC72E56326
...
-----END RSA PRIVATE KEY-----

I read it:

key, err := ioutil.ReadFile(privateKey)
if err != nil {
    log.Fatalf("Unable to read private key: %v", err)
}

With an unencrypted (!) key, I can then:

signer, err := ssh.ParsePrivateKey(key)
if err != nil {
    log.Fatalf("Unable to parse private key: %v", err)
}

config := &ssh.ClientConfig{
    User: username,
    Auth: []ssh.AuthMethod{
        ssh.PublicKeys(signer),
    },
}

And this would work.

I reused some code that I think gets me the decrypted PEM as a DER:

func decrypt(key []byte, password []byte) []byte {
    block, rest := pem.Decode(key)
    if len(rest) > 0 {
        log.Fatalf("Extra data included in key")
    }
    der, err := x509.DecryptPEMBlock(block, password)
    if err != nil {
        log.Fatalf("Decrypt failed: %v", err)
    }
    return der
}

But, how do I get from the DER to a signer?

Or, what's the best way to solve this?

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

3条回答 默认 最新

  • douke6027 2017-02-08 15:33
    已采纳

    If you have the DER block with an RSA private key, you use x509.ParsePKCS1PrivateKey to parse the key, and ssh.NewSignerFromKey to get the ssh.Signer

    key, err := x509.ParsePKCS1PrivateKey(der)
    if err != nil {
        log.Fatal(err)
    }
    signer := ssh.NewSignerFromKey(key)
    
    点赞 打赏 评论
  • drap5081683 2017-05-29 18:37

    I'm just going to provide an alternative here, which allows to reuse the ssh.ParsePrivateKey(key). I've modified the decrypt function to decrypt and encode the private key, if it is encrypted, and return it, so that the returned key can be used directly in ssh.ParsePrivateKey(key). It utilizes pem.EncodeToMemory to get the key from decrypted PEM block.

    func decrypt(key []byte, password []byte) []byte {
        block, rest := pem.Decode(key)
        if len(rest) > 0 {
            log.Fatalf("Extra data included in key")
        }
    
        if x509.IsEncryptedPEMBlock(block) {
            der, err := x509.DecryptPEMBlock(block, password)
            if err != nil {
                log.Fatalf("Decrypt failed: %v", err)
            }
            return pem.EncodeToMemory(&pem.Block{Type: block.Type, Bytes: der})
        }
        return key
    }
    
    点赞 打赏 评论
  • duannei1477 2018-06-13 09:22
    import "golang.org/x/crypto/ssh"
    

    With unencrypted key:

    signer, err := ssh.ParsePrivateKey(key)
    

    With encrypted key:

    signer, err := ssh.ParsePrivateKeyWithPassphrase(key, []byte("password"))
    

    Then:

    config := &ssh.ClientConfig{
        User: username,
        Auth: []ssh.AuthMethod{
            ssh.PublicKeys(signer),
        },
    }
    
    点赞 打赏 评论

相关推荐 更多相似问题