简体   繁体   English

如何在 Go 中为 SSH 生成 ECDSA 密钥对?

[英]How to Generate ECDSA Key Pair for SSH in Go?

I'm trying to generate ECDSA Key Pair for SSH with Go, but I find that the private key format is different from ssh-keygen and can't be accepted by GitHub.我正在尝试使用 Go 为 SSH 生成 ECDSA 密钥对,但我发现私钥格式与ssh-keygen不同,不能被 ZD3B7C913CD04EBFEC0E9EC32CB6FD5 接受

Here's the 256-bit key pair generated via ssh-keygen -t ecdsa -b 256 :这是通过ssh-keygen -t ecdsa -b 256生成的 256 位密钥对:

ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOJWUhO+waiB+aKvXO0xC5XTL6P/X/TIzQ4hgdXkDfmAfntOj/HXRIu4GulCvJgUoyTiF5Qt9j9gK6Z17szUv3s= root@9e5eef4b58c5

-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS
1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQTiVlITvsGogfmir1ztMQuV0y+j/1/0
yM0OIYHV5A35gH57To/x10SLuBrpQryYFKMk4heULfY/YCumde7M1L97AAAAsDs42wc7ON
sHAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOJWUhO+waiB+aKv
XO0xC5XTL6P/X/TIzQ4hgdXkDfmAfntOj/HXRIu4GulCvJgUoyTiF5Qt9j9gK6Z17szUv3
sAAAAgOpAIXW6rZQqgYZboSJXojH2diS26wfm6P3hn8cQVZrwAAAARcm9vdEA5ZTVlZWY0
YjU4YzUBAgMEBQYH
-----END OPENSSH PRIVATE KEY-----

Here's the generator code in Go:这是 Go 中的生成器代码:

// GenerateECDSAKeys generates ECDSA public and private key pair with given size for SSH.
func GenerateECDSAKeys(bitSize int) (pubKey string, privKey string, err error) {
    // generate private key
    var privateKey *ecdsa.PrivateKey
    if privateKey, err = ecdsa.GenerateKey(curveFromLength(bitSize), rand.Reader); err != nil {
        return
    }

    // encode public key
    var (
        bytes     []byte
        publicKey ssh.PublicKey
    )
    if publicKey, err = ssh.NewPublicKey(privateKey.Public()); err != nil {
        return
    }
    pubBytes := ssh.MarshalAuthorizedKey(publicKey)

    // encode private key
    if bytes, err = x509.MarshalECPrivateKey(privateKey); err != nil {
        return
    }
    privBytes := pem.EncodeToMemory(&pem.Block{
        Type:  "ECDSA PRIVATE KEY",
        Bytes: bytes,
    })

    return string(pubBytes), string(privBytes), nil
}

func curveFromLength(l int) elliptic.Curve {
    switch l {
    case 224:
        return elliptic.P224()
    case 256:
        return elliptic.P256()
    case 348:
        return elliptic.P384()
    case 521:
        return elliptic.P521()
    }
    return elliptic.P384()
}

And generated result:并生成结果:

ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNYTtNRlEKh/harLSfIsSziDkEQ8E7OJ7azhTBJi1Qx+fDa6dGg9f/vudGEizJ5d9TINVLTP+Jemwg6FBhajiVA=

-----BEGIN ECDSA PRIVATE KEY-----
MHcCAQEEIEGZZ/4aD6tf0sc1ovyctlGWRSFp7RGw5ovRONZKLg4eoAoGCCqGSM49
AwEHoUQDQgAE1hO01GUQqH+FqstJ8ixLOIOQRDwTs4ntrOFMEmLVDH58Nrp0aD1/
++50YSLMnl31Mg1UtM/4l6bCDoUGFqOJUA==
-----END ECDSA PRIVATE KEY-----

So why SSH private key was so different after the generation, and how to make it works?那么为什么 SSH 私钥在生成之后会有这么大的不同,如何让它发挥作用呢?

OpenSSH uses different formats for private EC keys, the SEC1 (as generated by your Go code), the PKCS#8 or the newer OpenSSH format (as generated with the ssh-keygen command). OpenSSH 对私有 EC 密钥使用不同的格式、SEC1(由您的 Go 代码生成)、PKCS#8 或更新的 OpenSSH 格式(由ssh-keygen命令生成)。 This is described here , which also contains a more detailed explanation of the OpenSSH format.在此处进行了描述,其中还包含对 OpenSSH 格式的更详细说明。 The SEC1 format is explained eg in this post . SEC1 格式在这篇文章中进行了解释。

The current Go code generates a SEC1 key with wrong header and footer.当前的 Go 代码生成带有错误header 和页脚的 SEC1 密钥。 This turned out to be the cause of the problem, To fix the bug, ECDSA must be replaced by EC in header and footer:原来这是问题的原因,要修复这个错误, ECDSA必须在 header 和页脚中替换为EC

-----BEGIN EC PRIVATE KEY-----
...
-----END EC PRIVATE KEY-----

ie in the Go code in the EncodeToMemory() call Type: "ECDSA PRIVATE KEY" must be replaced by Type: "EC PRIVATE KEY" .即在 Go 代码中EncodeToMemory()调用Type: "ECDSA PRIVATE KEY"必须替换为Type: "EC PRIVATE KEY"

Note that a conversion between the formats is also possible eg with ssh-keygen .请注意,格式之间的转换也是可能的,例如使用ssh-keygen For instance例如

ssh-keygen -p -N "" -f data.key

converts the SEC1 key contained in data.key to the OpenSSH format, see here .data.key中包含的 SEC1 密钥转换为 OpenSSH 格式,请参见此处

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM