From 811831de4c4dd03a0b8737233af3b36852386373 Mon Sep 17 00:00:00 2001 From: Peter Moody Date: Mon, 20 Jun 2016 18:10:02 -0700 Subject: [PATCH] agent: add agent server support for ed25519 keys. the client library already supports them. Fixes golang/go#16096 Change-Id: Iaa117ee31f706301e8b24c2775f5a604ef005440 Reviewed-on: https://go-review.googlesource.com/24285 Reviewed-by: Adam Langley --- ssh/agent/client.go | 6 +++--- ssh/agent/server.go | 31 +++++++++++++++++++++++++++++++ ssh/agent/server_test.go | 18 ++++++++++++++++++ 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/ssh/agent/client.go b/ssh/agent/client.go index a75668d..ecfd7c5 100644 --- a/ssh/agent/client.go +++ b/ssh/agent/client.go @@ -594,12 +594,12 @@ func (c *client) insertCert(s interface{}, cert *ssh.Certificate, comment string Comments: comment, Constraints: constraints, }) - case ed25519.PrivateKey: + case *ed25519.PrivateKey: req = ssh.Marshal(ed25519CertMsg{ Type: cert.Type(), CertBytes: cert.Marshal(), - Pub: []byte(k)[32:], - Priv: []byte(k), + Pub: []byte(*k)[32:], + Priv: []byte(*k), Comments: comment, Constraints: constraints, }) diff --git a/ssh/agent/server.go b/ssh/agent/server.go index c562fa6..092fd8f 100644 --- a/ssh/agent/server.go +++ b/ssh/agent/server.go @@ -16,6 +16,7 @@ import ( "log" "math/big" + "golang.org/x/crypto/ed25519" "golang.org/x/crypto/ssh" ) @@ -175,6 +176,15 @@ func parseRSAKey(req []byte) (*AddedKey, error) { return &AddedKey{PrivateKey: priv, Comment: k.Comments}, nil } +func parseEd25519Key(req []byte) (*AddedKey, error) { + var k ed25519KeyMsg + if err := ssh.Unmarshal(req, &k); err != nil { + return nil, err + } + priv := ed25519.PrivateKey(k.Priv) + return &AddedKey{PrivateKey: &priv, Comment: k.Comments}, nil +} + func parseDSAKey(req []byte) (*AddedKey, error) { var k dsaKeyMsg if err := ssh.Unmarshal(req, &k); err != nil { @@ -219,6 +229,23 @@ func unmarshalECDSA(curveName string, keyBytes []byte, privScalar *big.Int) (pri return priv, nil } +func parseEd25519Cert(req []byte) (*AddedKey, error) { + var k ed25519CertMsg + if err := ssh.Unmarshal(req, &k); err != nil { + return nil, err + } + pubKey, err := ssh.ParsePublicKey(k.CertBytes) + if err != nil { + return nil, err + } + priv := ed25519.PrivateKey(k.Priv) + cert, ok := pubKey.(*ssh.Certificate) + if !ok { + return nil, errors.New("agent: bad ED25519 certificate") + } + return &AddedKey{PrivateKey: &priv, Certificate: cert, Comment: k.Comments}, nil +} + func parseECDSAKey(req []byte) (*AddedKey, error) { var k ecdsaKeyMsg if err := ssh.Unmarshal(req, &k); err != nil { @@ -367,12 +394,16 @@ func (s *server) insertIdentity(req []byte) error { addedKey, err = parseDSAKey(req) case ssh.KeyAlgoECDSA256, ssh.KeyAlgoECDSA384, ssh.KeyAlgoECDSA521: addedKey, err = parseECDSACert(req) + case ssh.KeyAlgoED25519: + addedKey, err = parseEd25519Key(req) case ssh.CertAlgoRSAv01: addedKey, err = parseRSACert(req) case ssh.CertAlgoDSAv01: addedKey, err = parseDSACert(req) case ssh.CertAlgoECDSA256v01, ssh.CertAlgoECDSA384v01, ssh.CertAlgoECDSA521v01: addedKey, err = parseECDSACert(req) + case ssh.CertAlgoED25519v01: + addedKey, err = parseEd25519Cert(req) default: return fmt.Errorf("agent: not implemented: %q", record.Type) } diff --git a/ssh/agent/server_test.go b/ssh/agent/server_test.go index c324d6c..b5e92a6 100644 --- a/ssh/agent/server_test.go +++ b/ssh/agent/server_test.go @@ -153,6 +153,21 @@ func TestKeyTypes(t *testing.T) { } } +func addCertToAgentSock(key crypto.PrivateKey, cert *ssh.Certificate) error { + a, b, err := netPipe() + if err != nil { + return err + } + agentServer := NewKeyring() + go ServeAgent(agentServer, a) + + agentClient := NewClient(b) + if err := agentClient.Add(AddedKey{PrivateKey: key, Certificate: cert}); err != nil { + return fmt.Errorf("add: %v", err) + } + return verifyKey(agentClient) +} + func addCertToAgent(key crypto.PrivateKey, cert *ssh.Certificate) error { sshAgent := NewKeyring() if err := sshAgent.Add(AddedKey{PrivateKey: key, Certificate: cert}); err != nil { @@ -182,5 +197,8 @@ func TestCertTypes(t *testing.T) { if err := addCertToAgent(testPrivateKeys[keyType], cert); err != nil { t.Fatalf("%v", err) } + if err := addCertToAgentSock(testPrivateKeys[keyType], cert); err != nil { + t.Fatalf("%v", err) + } } }