从 golang 生成一个 ed25519 密钥对
Generate an ed25519 key pair from golang
我想在 go 中使用 ed25519 生成与 openssh 兼容的 ssh 密钥以替换
rsa.GenerateKey 因为 github 不再支持它了。
应该相当于:
ssh-keygen -t ed25519 -C "your_email@example.com"
但是我找不到办法。
现在,我有这个代码:
func GenerateSSHKeys() (*ED25519Keys, error) {
publicKey, privateKey, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
return nil, err
}
publicED25519Key, err := ssh.NewPublicKey(publicKey)
if err != nil {
return nil, err
}
pubKeyBytes := ssh.MarshalAuthorizedKey(publicED25519Key)
bytes, err := x509.MarshalPKCS8PrivateKey(privateKey)
if err != nil {
return nil, err
}
privBlock := pem.Block{
Type: "PRIVATE KEY",
Headers: nil,
Bytes: bytes,
}
privatePEM := pem.EncodeToMemory(&privBlock)
return &ED25519Keys{
Public: pubKeyBytes,
Private: privatePEM,
}, nil
}
但私钥似乎更短,我无法解释我将它与 git 或 argocd 一起使用时的一些奇怪行为(有时有效,但大多数时候无效)。
-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VwBCIEINV+5Hyey1xTblwsVGfGmDCMdZgKQdhf1ublkGO2Qaf+
-----END PRIVATE KEY-----
我怎么能得到这样的结果:
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACAxIu+ndqJXpEJLk5c2qsjPvUybP8OANZlSqLaOau9ZCQAAAKCocC5dqHAu
[...]
AAAEChVq8FJPCYbKnNFFuISac83mzF+DDFCDrLd9Xva9fQ2zEi76d2olekQkuTlzaqyM+9
TJs/w4A1mVKoto5q71kJAAAAFnlvdXJfZW1haWxAZXhhbXBsZS5jb20BAgMEBQYH
-----END OPENSSH PRIVATE KEY-----
是的,我也 运行 喜欢这个。
x509
包不支持以 openssh
使用的格式封送 ed25519
键类型,所以正如您所发现的,此代码 - 适用于其他键类型- ed25519
键失败:
bytes, err := x509.MarshalPKCS8PrivateKey(privateKey) // produces invalid output for ed25519 keys
有一个 repo(github.com/mikesmitty/edkey) with a helper function edkey.MarshalED25519PrivateKey 来解决这个问题:
/* Writes ed25519 private keys into the new OpenSSH private key
format. I have no idea why this isn't implemented anywhere yet, you
can do seemingly everything except write it to disk in the OpenSSH
private key format. */
它似乎是仿照 openssh 源:sshkey.c
sshkey_private_to_blob2
因此,要么将该辅助函数复制到您的代码中(推荐,因为 repo 已有 5 年以上历史),要么将其作为导入引用:
import "github.com/mikesmitty/edkey"
pubKey, privKey, _ := ed25519.GenerateKey(rand.Reader)
publicKey, _ := ssh.NewPublicKey(pubKey)
pemKey := &pem.Block{
Type: "OPENSSH PRIVATE KEY",
Bytes: edkey.MarshalED25519PrivateKey(privKey), // <- marshals ed25519 correctly
}
privateKey := pem.EncodeToMemory(pemKey)
authorizedKey := ssh.MarshalAuthorizedKey(publicKey)
_ = ioutil.WriteFile("id_ed25519", privateKey, 0600)
_ = ioutil.WriteFile("id_ed25519.pub", authorizedKey, 0644)
我想在 go 中使用 ed25519 生成与 openssh 兼容的 ssh 密钥以替换 rsa.GenerateKey 因为 github 不再支持它了。
应该相当于:
ssh-keygen -t ed25519 -C "your_email@example.com"
但是我找不到办法。
现在,我有这个代码:
func GenerateSSHKeys() (*ED25519Keys, error) {
publicKey, privateKey, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
return nil, err
}
publicED25519Key, err := ssh.NewPublicKey(publicKey)
if err != nil {
return nil, err
}
pubKeyBytes := ssh.MarshalAuthorizedKey(publicED25519Key)
bytes, err := x509.MarshalPKCS8PrivateKey(privateKey)
if err != nil {
return nil, err
}
privBlock := pem.Block{
Type: "PRIVATE KEY",
Headers: nil,
Bytes: bytes,
}
privatePEM := pem.EncodeToMemory(&privBlock)
return &ED25519Keys{
Public: pubKeyBytes,
Private: privatePEM,
}, nil
}
但私钥似乎更短,我无法解释我将它与 git 或 argocd 一起使用时的一些奇怪行为(有时有效,但大多数时候无效)。
-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VwBCIEINV+5Hyey1xTblwsVGfGmDCMdZgKQdhf1ublkGO2Qaf+
-----END PRIVATE KEY-----
我怎么能得到这样的结果:
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACAxIu+ndqJXpEJLk5c2qsjPvUybP8OANZlSqLaOau9ZCQAAAKCocC5dqHAu
[...]
AAAEChVq8FJPCYbKnNFFuISac83mzF+DDFCDrLd9Xva9fQ2zEi76d2olekQkuTlzaqyM+9
TJs/w4A1mVKoto5q71kJAAAAFnlvdXJfZW1haWxAZXhhbXBsZS5jb20BAgMEBQYH
-----END OPENSSH PRIVATE KEY-----
是的,我也 运行 喜欢这个。
x509
包不支持以 openssh
使用的格式封送 ed25519
键类型,所以正如您所发现的,此代码 - 适用于其他键类型- ed25519
键失败:
bytes, err := x509.MarshalPKCS8PrivateKey(privateKey) // produces invalid output for ed25519 keys
有一个 repo(github.com/mikesmitty/edkey) with a helper function edkey.MarshalED25519PrivateKey 来解决这个问题:
/* Writes ed25519 private keys into the new OpenSSH private key format. I have no idea why this isn't implemented anywhere yet, you can do seemingly everything except write it to disk in the OpenSSH private key format. */
它似乎是仿照 openssh 源:sshkey.c
sshkey_private_to_blob2
因此,要么将该辅助函数复制到您的代码中(推荐,因为 repo 已有 5 年以上历史),要么将其作为导入引用:
import "github.com/mikesmitty/edkey"
pubKey, privKey, _ := ed25519.GenerateKey(rand.Reader)
publicKey, _ := ssh.NewPublicKey(pubKey)
pemKey := &pem.Block{
Type: "OPENSSH PRIVATE KEY",
Bytes: edkey.MarshalED25519PrivateKey(privKey), // <- marshals ed25519 correctly
}
privateKey := pem.EncodeToMemory(pemKey)
authorizedKey := ssh.MarshalAuthorizedKey(publicKey)
_ = ioutil.WriteFile("id_ed25519", privateKey, 0600)
_ = ioutil.WriteFile("id_ed25519.pub", authorizedKey, 0644)