我可以使用两个文件通过 SSH(使用 openssh 客户端)连接到我的服务器: ~/.ssh/id_ed25519{,-cert.pub}
debug1: Trying private key: /home/xavier/.ssh/id_ed25519
debug1: Authentications that can continue: publickey,keyboard-interactive
debug1: Offering ED25519-CERT public key: /home/xavier/.ssh/id_ed25519
debug1: Server accepts key: pkalg ssh-ed25519-cert-v01@openssh.com blen 441
debug1: sign_and_send_pubkey: no separate private key for certificate "/home/xavier/.ssh/id_ed25519"
debug1: Authentication succeeded (publickey).
Run Code Online (Sandbox Code Playgroud)
我想要一个做同样事情的 go 客户端,但我不知道如何将id_ed25519-cert.pub文件合并到https://godoc.org/golang.org/x/crypto/ssh#example-PublicKeys的示例中
key, err := ioutil.ReadFile("/home/xavier/.ssh/id_ed25519")
if err != nil {
log.Fatalf("unable to read private key: %v", err)
}
// Create the Signer for this private key.
signer, err := ssh.ParsePrivateKey(key)
if err != nil {
log.Fatalf("unable to parse private key: %v", err)
}
config := &ssh.ClientConfig{
User: "user",
Auth: []ssh.AuthMethod{
// Use the PublicKeys method for remote authentication.
ssh.PublicKeys(signer),
},
}
// Connect to the remote server and perform the SSH handshake.
client, err := ssh.Dial("tcp", "host.com:22", config)
if err != nil {
log.Fatalf("unable to connect: %v", err)
}
defer client.Close()
Run Code Online (Sandbox Code Playgroud)
部分问题是我不知道这个文件是什么(公钥?证书?),部分问题是即使我知道我不明白它在这个交换中播放的目的。
我已确认此文件是必需的:删除它会导致 ssh CLI 失败。
那是一个SSH证书文件,用于实现基于SSH证书的用户认证。这通过在公钥层次结构中检查来自受信任证书颁发机构的有效签名来验证用户登录时的真实性。与基于标准 SSH 密钥的身份验证(使用authorized_keys文件)相比,此方法具有多种优势,例如:
ssh-keygen)authorized_keys每个主机上的每个用户填充一个文件假设您正在使用内置golang.org/x/crypto/ssh库,您可以通过以下方式实现:
OpenSSH 公钥证书的指定格式类似于authorized_keys文件。在ParseAuthorizedKeys转到库的功能会分析这个文件,并返回相应的键作为实例ssh.PublicKey接口; 对于证书,这具体是结构的一个实例ssh.Certificate。
请参阅代码示例(注意:我HostKeyCallback向您添加了 a以ClientConfig使其与测试框连接 - 但是,它使用InsecureIgnoreHostKey检查器,我不建议在生产中使用!)。
package main
import (
"bytes"
"io/ioutil"
"log"
"golang.org/x/crypto/ssh"
)
func main() {
key, err := ioutil.ReadFile("/tmp/mycert")
if err != nil {
log.Fatalf("unable to read private key: %v", err)
}
// Create the Signer for this private key.
signer, err := ssh.ParsePrivateKey(key)
if err != nil {
log.Fatalf("unable to parse private key: %v", err)
}
// Load the certificate
cert, err := ioutil.ReadFile("/tmp/mycert-cert.pub")
if err != nil {
log.Fatalf("unable to read certificate file: %v", err)
}
pk, _, _, _, err := ssh.ParseAuthorizedKey(cert)
if err != nil {
log.Fatalf("unable to parse public key: %v", err)
}
certSigner, err := ssh.NewCertSigner(pk.(*ssh.Certificate), signer)
if err != nil {
log.Fatalf("failed to create cert signer: %v", err)
}
config := &ssh.ClientConfig{
User: "user",
Auth: []ssh.AuthMethod{
// Use the PublicKeys method for remote authentication.
ssh.PublicKeys(certSigner),
},
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}
// Connect to the remote server and perform the SSH handshake.
client, err := ssh.Dial("tcp", "host.com:22", config)
if err != nil {
log.Fatalf("unable to connect: %v", err)
}
defer client.Close()
}
Run Code Online (Sandbox Code Playgroud)
如果您想编写一个支持证书和非证书的更通用的连接客户端,您显然需要额外的逻辑来处理其他类型的公钥。正如所写,我希望pk.(*ssh.Certificate)非证书公钥文件的类型断言失败!(实际上,对于非证书连接,您可能根本不需要读取公钥。)
| 归档时间: |
|
| 查看次数: |
1024 次 |
| 最近记录: |