aboutsummaryrefslogtreecommitdiff
path: root/ssh/keys.go
diff options
context:
space:
mode:
authorMariano Cano <mariano@smallstep.com>2020-02-07 20:41:00 +0000
committerFilippo Valsorda <filippo@golang.org>2020-02-07 20:58:29 +0000
commita95e85b341fd3d114b379054ba41d2d1006beee4 (patch)
tree797fa8829fe5adbaeb18f5dbf92d8d815fb14f4d /ssh/keys.go
parenta0c6ece9d31a0ebfbd3ddf2d290cfb1265ba47c7 (diff)
downloadgo-x-crypto-a95e85b341fd3d114b379054ba41d2d1006beee4.tar.xz
ssh: support ECDSA private keys in OpenSSH format
This adds support for parsing OpenSSH ECDSA private keys. It implements parsing for P-256, P-384, and P-521 keys. Fixes golang/go#36722 Change-Id: I77c8e0a23ed6353f6667686cc79ec14661cb10db GitHub-Last-Rev: 2324b920d080fc7ac35fbcf0a79e25161b6a7f82 GitHub-Pull-Request: golang/crypto#114 Reviewed-on: https://go-review.googlesource.com/c/crypto/+/215540 Reviewed-by: Filippo Valsorda <filippo@golang.org> Run-TryBot: Filippo Valsorda <filippo@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
Diffstat (limited to 'ssh/keys.go')
-rw-r--r--ssh/keys.go51
1 files changed, 51 insertions, 0 deletions
diff --git a/ssh/keys.go b/ssh/keys.go
index 5377ec8..d63cbf6 100644
--- a/ssh/keys.go
+++ b/ssh/keys.go
@@ -1366,6 +1366,57 @@ func parseOpenSSHPrivateKey(key []byte, decrypt openSSHDecryptFunc) (crypto.Priv
pk := ed25519.PrivateKey(make([]byte, ed25519.PrivateKeySize))
copy(pk, key.Priv)
return &pk, nil
+ case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521:
+ key := struct {
+ Curve string
+ Pub []byte
+ D *big.Int
+ Comment string
+ Pad []byte `ssh:"rest"`
+ }{}
+
+ if err := Unmarshal(pk1.Rest, &key); err != nil {
+ return nil, err
+ }
+
+ if err := checkOpenSSHKeyPadding(key.Pad); err != nil {
+ return nil, err
+ }
+
+ var curve elliptic.Curve
+ switch key.Curve {
+ case "nistp256":
+ curve = elliptic.P256()
+ case "nistp384":
+ curve = elliptic.P384()
+ case "nistp521":
+ curve = elliptic.P521()
+ default:
+ return nil, errors.New("ssh: unhandled elliptic curve: " + key.Curve)
+ }
+
+ X, Y := elliptic.Unmarshal(curve, key.Pub)
+ if X == nil || Y == nil {
+ return nil, errors.New("ssh: failed to unmarshal public key")
+ }
+
+ if key.D.Cmp(curve.Params().N) >= 0 {
+ return nil, errors.New("ssh: scalar is out of range")
+ }
+
+ x, y := curve.ScalarBaseMult(key.D.Bytes())
+ if x.Cmp(X) != 0 || y.Cmp(Y) != 0 {
+ return nil, errors.New("ssh: public key does not match private key")
+ }
+
+ return &ecdsa.PrivateKey{
+ PublicKey: ecdsa.PublicKey{
+ Curve: curve,
+ X: X,
+ Y: Y,
+ },
+ D: key.D,
+ }, nil
default:
return nil, errors.New("ssh: unhandled key type")
}