如何在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?

ssh

3个回答



如果您具有带有RSA私钥的DER块,则可以使用 x509.ParsePKCS1PrivateKey </ code>来解析密钥 和 ssh.NewSignerFromKey </ code>来获取 ssh.Signer </ code> </ p>

  key,err:= x509.ParsePKCS1PrivateKey(der)

if err!= nil {
log.Fatal(err)
}
signer:= ssh.NewSignerFromKey(key)
</ code> </ pre>
</ div>

展开原文

原文

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)

dongsaolian8786
dongsaolian8786 真棒。 非常感谢你!
3 年多之前 回复

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
}
dongmaijie5200
dongmaijie5200 谢谢! 对答案进行了更改。
大约 3 年之前 回复
dora12345678
dora12345678 我将硬编码的{Type:“ RSA PRIVATE KEY”,...}更改为{Type:block.Type,...},因为如果输入块的类型不正确,此代码段将意外更改PEM块的类型 “ RSA私钥”。
大约 3 年之前 回复
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),
    },
}
drze7794
drze7794 -感谢您指出错别字,已修正。
大约 2 年之前 回复
ds0678
ds0678 也许ParsePrivateKeyWithPassphrase()是该程序包的新增功能。 如果您使用正确的软件包名称“ ssh”而不是“ ssh2”,则此方法有效。
大约 2 年之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问