How to use an encrypted private key with golang ssh

huangapple go评论81阅读模式
英文:

How to use an encrypted private key with golang ssh

问题

我会尽力帮助你解决问题。你想要解密一个加密的密钥以便在golang ssh中使用它,但是你无法弄清楚如何做到这一点。你正在尝试将两个代码源(包括这个)组合在一起,但无法使其工作。

我认为你已经得到了一个DER格式的密钥,但是需要将其转换回PEM格式以便与crypto/ssh一起使用。

你可以使用以下代码读取密钥:

key, err := ioutil.ReadFile(privateKey)
if err != nil {
    log.Fatalf("无法读取私钥:%v", err)
}

如果你有一个未加密的密钥,你可以使用以下代码:

signer, err := ssh.ParsePrivateKey(key)
if err != nil {
    log.Fatalf("无法解析私钥:%v", err)
}

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

这样就可以工作了。

你可以使用以下代码将DER格式的密钥解密为PEM格式:

func decrypt(key []byte, password []byte) []byte {
    block, rest := pem.Decode(key)
    if len(rest) > 0 {
        log.Fatalf("密钥中包含额外的数据")
    }
    der, err := x509.DecryptPEMBlock(block, password)
    if err != nil {
        log.Fatalf("解密失败:%v", err)
    }
    return der
}

但是,你如何从DER格式的密钥获取到一个signer呢?

或者,有没有更好的解决方法?

英文:

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?

答案1

得分: 19

import "golang.org/x/crypto/ssh"

使用未加密的密钥:

signer, err := ssh.ParsePrivateKey(key)

使用加密的密钥:

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

然后:

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

英文:
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),
    },
}

答案2

得分: 10

如果你有一个包含RSA私钥的DER块,你可以使用x509.ParsePKCS1PrivateKey来解析该密钥,并使用ssh.NewSignerFromKey来获取ssh.Signer

key, err := x509.ParsePKCS1PrivateKey(der)
if err != nil {
    log.Fatal(err)
}
signer := ssh.NewSignerFromKey(key)
英文:

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)

答案3

得分: 7

我只会翻译代码部分,以下是翻译好的内容:

我这里提供了一种替代方法,可以重用 ssh.ParsePrivateKey(key)。我修改了 decrypt 函数,用于解密和编码私钥(如果它被加密),并返回它,以便返回的 key 可以直接在 ssh.ParsePrivateKey(key) 中使用。它利用 pem.EncodeToMemory 从解密的 PEM 块中获取密钥。

func decrypt(key []byte, password []byte) []byte {
    block, rest := pem.Decode(key)
    if len(rest) > 0 {
        log.Fatalf("密钥中包含额外的数据")
    }
    
    if x509.IsEncryptedPEMBlock(block) {
        der, err := x509.DecryptPEMBlock(block, password)
        if err != nil {
            log.Fatalf("解密失败:%v", err)
        }
        return pem.EncodeToMemory(&pem.Block{Type: block.Type, Bytes: der})
    }
    return key
}
英文:

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
}

huangapple
  • 本文由 发表于 2017年2月8日 13:32:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/42105432.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定