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 <agl@golang.org>
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 @@
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 @@
"log"
"math/big"
+ "golang.org/x/crypto/ed25519"
"golang.org/x/crypto/ssh"
)
@@ -175,6 +176,15 @@
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 @@
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 @@
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 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 @@
if err := addCertToAgent(testPrivateKeys[keyType], cert); err != nil {
t.Fatalf("%v", err)
}
+ if err := addCertToAgentSock(testPrivateKeys[keyType], cert); err != nil {
+ t.Fatalf("%v", err)
+ }
}
}