Created
February 4, 2020 04:47
-
-
Save maraino/5329cc8fd3c67c0e7782b8a68f02e424 to your computer and use it in GitHub Desktop.
SSH EC Keys Patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
commit fc346d83bb0cca8b617358b275cb678a41aaeb4f | |
Author: Mariano Cano <[email protected]> | |
Date: Mon Jan 20 17:33:23 2020 | |
ssh: support for ecdsa keys using openssh format. | |
This adds support for parsing OpenSSH ECDSA private keys. It | |
implements parsing for P-256, P-384, and P-521 unencrypted keys. | |
Change-Id: I77c8e0a23ed6353f6667686cc79ec14661cb10db | |
GitHub-Last-Rev: 6bd278cb1ead0017ee01f3abf636b35df42692d2 | |
GitHub-Pull-Request: golang/crypto#114 | |
diff --git a/ssh/keys.go b/ssh/keys.go | |
index 5377ec8..b20116b 100644 | |
--- a/ssh/keys.go | |
+++ b/ssh/keys.go | |
@@ -1366,6 +1366,59 @@ 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 | |
+ Priv []byte | |
+ 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") | |
+ } | |
+ | |
+ N := curve.Params().N | |
+ X, Y := elliptic.Unmarshal(curve, key.Pub) | |
+ if X == nil || Y == nil { | |
+ return nil, errors.New("ssh: failed to unmarshal elliptic curve") | |
+ } | |
+ | |
+ D := new(big.Int).SetBytes(key.Priv) | |
+ if D.Cmp(N) >= 0 { | |
+ return nil, errors.New("ssh: scalar is out of range") | |
+ } | |
+ | |
+ x, y := curve.ScalarBaseMult(key.Priv) | |
+ if x.Cmp(X) != 0 || y.Cmp(Y) != 0 { | |
+ return nil, errors.New("ssh: public key does not match") | |
+ } | |
+ | |
+ return &ecdsa.PrivateKey{ | |
+ PublicKey: ecdsa.PublicKey{ | |
+ Curve: curve, | |
+ X: X, | |
+ Y: Y, | |
+ }, | |
+ D: D, | |
+ }, nil | |
default: | |
return nil, errors.New("ssh: unhandled key type") | |
} | |
diff --git a/ssh/testdata/keys.go b/ssh/testdata/keys.go | |
index 72cfaa0..a7da078 100644 | |
--- a/ssh/testdata/keys.go | |
+++ b/ssh/testdata/keys.go | |
@@ -113,6 +113,37 @@ pY2QA+P3QlrKxT/VWUMjHUbNNdYfJm48xu0SGNMRdKMAAABBAORh2NP/06JUV3J9W/2Hju | |
X1ViJuqqcQnJPVzpgSL826EC2xwOECTqoY8uvFpUdD7CtpksIxNVqRIhuNOlz0lqEAAABB | |
ANkaHTTaPojClO0dKJ/Zjs7pWOCGliebBYprQ/Y4r9QLBkC/XaWMS26gFIrjgC7D2Rv+rZ | |
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-----`), | |
"user": []byte(`-----BEGIN EC PRIVATE KEY----- | |
MHcCAQEEILYCAeq8f7V4vSSypRw7pxy8yz3V5W4qg8kSC3zJhqpQoAoGCCqGSM49 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment