diff options
| author | Mariano Cano <mariano@smallstep.com> | 2020-02-07 20:41:00 +0000 |
|---|---|---|
| committer | Filippo Valsorda <filippo@golang.org> | 2020-02-07 20:58:29 +0000 |
| commit | a95e85b341fd3d114b379054ba41d2d1006beee4 (patch) | |
| tree | 797fa8829fe5adbaeb18f5dbf92d8d815fb14f4d /ssh/keys.go | |
| parent | a0c6ece9d31a0ebfbd3ddf2d290cfb1265ba47c7 (diff) | |
| download | go-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.go | 51 |
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") } |
