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>
This commit is contained in:
committed by
Filippo Valsorda
parent
a0c6ece9d3
commit
a95e85b341
+51
@@ -1366,6 +1366,57 @@ func parseOpenSSHPrivateKey(key []byte, decrypt openSSHDecryptFunc) (crypto.Priv
|
|||||||
pk := ed25519.PrivateKey(make([]byte, ed25519.PrivateKeySize))
|
pk := ed25519.PrivateKey(make([]byte, ed25519.PrivateKeySize))
|
||||||
copy(pk, key.Priv)
|
copy(pk, key.Priv)
|
||||||
return &pk, nil
|
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:
|
default:
|
||||||
return nil, errors.New("ssh: unhandled key type")
|
return nil, errors.New("ssh: unhandled key type")
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+31
@@ -113,6 +113,37 @@ pY2QA+P3QlrKxT/VWUMjHUbNNdYfJm48xu0SGNMRdKMAAABBAORh2NP/06JUV3J9W/2Hju
|
|||||||
X1ViJuqqcQnJPVzpgSL826EC2xwOECTqoY8uvFpUdD7CtpksIxNVqRIhuNOlz0lqEAAABB
|
X1ViJuqqcQnJPVzpgSL826EC2xwOECTqoY8uvFpUdD7CtpksIxNVqRIhuNOlz0lqEAAABB
|
||||||
ANkaHTTaPojClO0dKJ/Zjs7pWOCGliebBYprQ/Y4r9QLBkC/XaWMS26gFIrjgC7D2Rv+rZ
|
ANkaHTTaPojClO0dKJ/Zjs7pWOCGliebBYprQ/Y4r9QLBkC/XaWMS26gFIrjgC7D2Rv+rZ
|
||||||
wSD0v0RcmkITP1ZR0AAAAYcHF1ZXJuYUBMdWNreUh5ZHJvLmxvY2FsAQID
|
wSD0v0RcmkITP1ZR0AAAAYcHF1ZXJuYUBMdWNreUh5ZHJvLmxvY2FsAQID
|
||||||
|
-----END OPENSSH PRIVATE KEY-----`),
|
||||||
|
"p256-openssh-format": []byte(`-----BEGIN OPENSSH PRIVATE KEY-----
|
||||||
|
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS
|
||||||
|
1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQSN5Ld/DFy8LJK0yrWg+Ryhq4/ifHry
|
||||||
|
QyCQeT4UXSB+UGdRct7kWA0hARbTaSCh+8U/Gs5O+IkDNoTKVsgxKUMQAAAAsO3C7nPtwu
|
||||||
|
5zAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBI3kt38MXLwskrTK
|
||||||
|
taD5HKGrj+J8evJDIJB5PhRdIH5QZ1Fy3uRYDSEBFtNpIKH7xT8azk74iQM2hMpWyDEpQx
|
||||||
|
AAAAAhAIHB48R+goZaiXndfYTrwk4BT1+MeLPC2/dwe0J5d1QDAAAAE21hcmlhbm9AZW5k
|
||||||
|
b3IubG9jYWwBAgME
|
||||||
|
-----END OPENSSH PRIVATE KEY-----`),
|
||||||
|
"p384-openssh-format": []byte(`-----BEGIN OPENSSH PRIVATE KEY-----
|
||||||
|
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAiAAAABNlY2RzYS
|
||||||
|
1zaGEyLW5pc3RwMzg0AAAACG5pc3RwMzg0AAAAYQTZb2VzEPs2NN/i1qHddKTVfwoIq3Tf
|
||||||
|
PeQ/kcWBvuCVJfIygvpm9MeusawEPuLSEXwiNDew+YHZ9xHIvFjCmZsLuEOzuh9t9KotwM
|
||||||
|
57H+7N+RDFzhM2j8hAaOuT5XDLKfUAAADgn/Sny5/0p8sAAAATZWNkc2Etc2hhMi1uaXN0
|
||||||
|
cDM4NAAAAAhuaXN0cDM4NAAAAGEE2W9lcxD7NjTf4tah3XSk1X8KCKt03z3kP5HFgb7glS
|
||||||
|
XyMoL6ZvTHrrGsBD7i0hF8IjQ3sPmB2fcRyLxYwpmbC7hDs7ofbfSqLcDOex/uzfkQxc4T
|
||||||
|
No/IQGjrk+Vwyyn1AAAAMQDg0hwGKB/9Eq+e2FeTspi8QHW5xTD6prqsHDFx4cKk0ccgFV
|
||||||
|
61dhFhD/8SEbYlHzEAAAATbWFyaWFub0BlbmRvci5sb2NhbAECAwQ=
|
||||||
|
-----END OPENSSH PRIVATE KEY-----`),
|
||||||
|
"p521-openssh-format": []byte(`-----BEGIN OPENSSH PRIVATE KEY-----
|
||||||
|
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAArAAAABNlY2RzYS
|
||||||
|
1zaGEyLW5pc3RwNTIxAAAACG5pc3RwNTIxAAAAhQQBKzI3QSp1a2e1zMulZl1uFF1Y2Dnv
|
||||||
|
LSIwEu837hOV1epYEgNveAhGNm57TuBqYtnZeVfd2pzaz7CKX6N4B33N1XABQ5Ngji7lF2
|
||||||
|
dUbmhNqJoMh43ioIsQNBaBenhmRpYP6f5k8P/7JZMIsLhkJk2hykb8maSZ+B3PYwPMNBdS
|
||||||
|
vP+0sHQAAAEYIsr2CCLK9ggAAAATZWNkc2Etc2hhMi1uaXN0cDUyMQAAAAhuaXN0cDUyMQ
|
||||||
|
AAAIUEASsyN0EqdWtntczLpWZdbhRdWNg57y0iMBLvN+4TldXqWBIDb3gIRjZue07gamLZ
|
||||||
|
2XlX3dqc2s+wil+jeAd9zdVwAUOTYI4u5RdnVG5oTaiaDIeN4qCLEDQWgXp4ZkaWD+n+ZP
|
||||||
|
D/+yWTCLC4ZCZNocpG/Jmkmfgdz2MDzDQXUrz/tLB0AAAAQgEdeH+im6iRcP/juTAoeSHo
|
||||||
|
ExLtWhgL4JYqRwcOnzCKuLOPjEY/HSOuc+HRrbN9rbjsq+PcPHYe1NnkzXk0IW8hxQAAAB
|
||||||
|
NtYXJpYW5vQGVuZG9yLmxvY2FsAQIDBAUGBw==
|
||||||
-----END OPENSSH PRIVATE KEY-----`),
|
-----END OPENSSH PRIVATE KEY-----`),
|
||||||
"user": []byte(`-----BEGIN EC PRIVATE KEY-----
|
"user": []byte(`-----BEGIN EC PRIVATE KEY-----
|
||||||
MHcCAQEEILYCAeq8f7V4vSSypRw7pxy8yz3V5W4qg8kSC3zJhqpQoAoGCCqGSM49
|
MHcCAQEEILYCAeq8f7V4vSSypRw7pxy8yz3V5W4qg8kSC3zJhqpQoAoGCCqGSM49
|
||||||
|
|||||||
Reference in New Issue
Block a user