Created
April 6, 2022 17:13
-
-
Save jeffreytolar/9fd9ed8c01802fb7d36d98ed268f3a18 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module test | |
go 1.17 | |
require ( | |
github.com/cbeuw/connutil v0.0.0-20200411215123-966bfaa51ee3 // indirect | |
golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29 // indirect | |
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
github.com/cbeuw/connutil v0.0.0-20200411215123-966bfaa51ee3 h1:LRxW8pdmWmyhoNh+TxUjxsAinGtCsVGjsl3xg6zoRSs= | |
github.com/cbeuw/connutil v0.0.0-20200411215123-966bfaa51ee3/go.mod h1:6jR2SzckGv8hIIS9zWJ160mzGVVOYp4AXZMDtacL6LE= | |
golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29 h1:tkVvjkPTB7pnW3jnid7kNyAMPVWllTNOf/qKDze4p9o= | |
golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bytes" | |
"crypto/ecdsa" | |
"crypto/elliptic" | |
"crypto/rand" | |
"log" | |
"net" | |
"time" | |
"github.com/cbeuw/connutil" | |
"golang.org/x/crypto/ssh" | |
"golang.org/x/crypto/ssh/agent" | |
) | |
func check(err error) { | |
if err != nil { | |
panic(err) | |
} | |
} | |
func newSigner() (*ecdsa.PrivateKey, ssh.Signer) { | |
key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) | |
check(err) | |
signer, err := ssh.NewSignerFromKey(key) | |
check(err) | |
return key, signer | |
} | |
func makeCert() *ssh.Certificate { | |
cert := &ssh.Certificate{ | |
Key: userSigner.PublicKey(), | |
Serial: 1, | |
CertType: ssh.UserCert, | |
KeyId: "testkey", | |
ValidPrincipals: []string{"test"}, | |
ValidAfter: uint64(time.Now().Add(-time.Hour).Unix()), | |
ValidBefore: uint64(time.Now().Add(time.Hour).Unix()), | |
} | |
err := cert.SignCert(rand.Reader, userCASigner) | |
check(err) | |
return cert | |
} | |
var ( | |
userCAKey, userCASigner = newSigner() | |
hostKey, hostSigner = newSigner() | |
userKey, userSigner = newSigner() | |
userCert = makeCert() | |
) | |
func server(nConn net.Conn) { | |
config := &ssh.ServerConfig{ | |
PublicKeyCallback: (&ssh.CertChecker{ | |
IsUserAuthority: func(auth ssh.PublicKey) bool { | |
return bytes.Equal(auth.Marshal(), userCASigner.PublicKey().Marshal()) | |
}, | |
}).Authenticate, | |
} | |
config.AddHostKey(hostSigner) | |
_, _, _, err := ssh.NewServerConn(nConn, config) | |
check(err) | |
log.Print("[server] Completed handshake") | |
} | |
func client(nConn net.Conn, signers []ssh.Signer) { | |
config := &ssh.ClientConfig{ | |
User: "test", | |
HostKeyCallback: ssh.FixedHostKey(hostSigner.PublicKey()), | |
Auth: []ssh.AuthMethod{ssh.PublicKeys(signers...)}, | |
} | |
_, _, _, err := ssh.NewClientConn(nConn, "pipe", config) | |
check(err) | |
log.Print("[client] Completed handshake") | |
} | |
func signersLocalKey() []ssh.Signer { | |
certSigner, err := ssh.NewCertSigner(userCert, userSigner) | |
check(err) | |
return []ssh.Signer{certSigner} | |
} | |
func signersKeyring() []ssh.Signer { | |
ag := agent.NewKeyring() | |
check(ag.Add(agent.AddedKey{ | |
PrivateKey: userKey, | |
Certificate: userCert, | |
})) | |
signers, err := ag.Signers() | |
check(err) | |
return signers | |
} | |
func signersRemoteAgent() []ssh.Signer { | |
ag := agent.NewKeyring() | |
check(ag.Add(agent.AddedKey{ | |
Certificate: userCert, | |
PrivateKey: userKey, | |
})) | |
client, server := connutil.AsyncPipe() | |
go func() { | |
check(agent.ServeAgent(ag, server)) | |
}() | |
signers, err := agent.NewClient(client).Signers() | |
check(err) | |
return signers | |
} | |
func main() { | |
clientConn, serverConn := connutil.AsyncPipe() | |
go server(serverConn) | |
// client(clientConn, signersLocalKey()) // this works | |
// client(clientConn, signersKeyring()) // this works too | |
client(clientConn, signersRemoteAgent()) // this fails: ssh: handshake failed: agent: unsupported algorithm "ecdsa-sha2-nistp256" | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment