summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJeff Forcier <jeff@bitprophet.org>2019-06-21 16:49:53 -0400
committerJeff Forcier <jeff@bitprophet.org>2019-06-21 16:49:53 -0400
commitfd30ddbd3bbf79c31e9458738766f254d520c65e (patch)
tree7e720e5a4e62ce001b1bf2a49df458a052e2d2f4
parent7f5a6c3f6d15876b7a2a7b298de14d8d807efad2 (diff)
parente5d052c4da3b9a966b1c6ee67c93157a3c55b871 (diff)
Merge branch '2.5'
-rw-r--r--paramiko/ed25519key.py8
-rw-r--r--sites/www/changelog.rst5
-rw-r--r--tests/test_ed25519-funky-padding.key7
-rw-r--r--tests/test_ed25519-funky-padding_password.key8
-rw-r--r--tests/test_pkey.py8
5 files changed, 33 insertions, 3 deletions
diff --git a/paramiko/ed25519key.py b/paramiko/ed25519key.py
index 68ada224..6e0d3ccf 100644
--- a/paramiko/ed25519key.py
+++ b/paramiko/ed25519key.py
@@ -37,10 +37,12 @@ def unpad(data):
# really ought to be made constant time (possibly by upstreaming this logic
# into pyca/cryptography).
padding_length = six.indexbytes(data, -1)
- if padding_length > 16:
+ if 0x20 <= padding_length < 0x7f:
+ return data # no padding, last byte part comment (printable ascii)
+ if padding_length > 15:
raise SSHException("Invalid key")
- for i in range(1, padding_length + 1):
- if six.indexbytes(data, -i) != (padding_length - i + 1):
+ for i in range(padding_length):
+ if six.indexbytes(data, i - padding_length) != i + 1:
raise SSHException("Invalid key")
return data[:-padding_length]
diff --git a/sites/www/changelog.rst b/sites/www/changelog.rst
index 4b377b9e..e2b809e0 100644
--- a/sites/www/changelog.rst
+++ b/sites/www/changelog.rst
@@ -2,6 +2,11 @@
Changelog
=========
+- :bug:`1306` (via :issue:`1400`) Fix Ed25519 key handling so certain key
+ comment lengths don't cause ``SSHException("Invalid key")`` (this was
+ technically a bug in how padding, or lack thereof, is
+ calculated/interpreted). Thanks to ``@parke`` for the bug report & Pierce
+ Lopez for the patch.
- :support:`1440` (with initial fixes via :issue:`1460`) Tweak many exception
classes so their string representations are more human-friendly; this also
includes incidental changes to some ``super()`` calls.
diff --git a/tests/test_ed25519-funky-padding.key b/tests/test_ed25519-funky-padding.key
new file mode 100644
index 00000000..f178ca45
--- /dev/null
+++ b/tests/test_ed25519-funky-padding.key
@@ -0,0 +1,7 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
+QyNTUxOQAAACAHzPvYoDSkMVX52/CbA2M2aSBS7R0wt/9b2n5n+osNygAAAJAHZ1meB2dZ
+ngAAAAtzc2gtZWQyNTUxOQAAACAHzPvYoDSkMVX52/CbA2M2aSBS7R0wt/9b2n5n+osNyg
+AAAEAIyamvYUpzCovQuUtLhz+fwE4qYQo+rTuUVIX4fmTzMAfM+9igNKQxVfnb8JsDYzZp
+IFLtHTC3/1vafmf6iw3KAAAADW15IGNvbW1lbnQgaXM=
+-----END OPENSSH PRIVATE KEY-----
diff --git a/tests/test_ed25519-funky-padding_password.key b/tests/test_ed25519-funky-padding_password.key
new file mode 100644
index 00000000..1b135d69
--- /dev/null
+++ b/tests/test_ed25519-funky-padding_password.key
@@ -0,0 +1,8 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABDo3dGRlE
+xKndv32nDnz2mHAAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIDcAVH8yDxoiqj0O
+rX3YTRMsnvJr+XdKJW16YQpxx8UvAAAAoI78IY+u8lYOzxAEO2N8qEVQH8b/m27yQhcSbK
+q1RvvuHmql3NoQvjYQe9/om4oqE+uesNRnoQGNplBHCeroD3ZcksXhLGDhwTh577NR+NQ+
+GNYAK5Ex7Va3Xgao5HUYtBQXlXbtzY1Q+71hcOlRVNnLUDvwShdCa9o6ETIOGcZl04fbzv
+Z3vC1C68G3+JMNFenAGYU+iQq0XENtpT6xAIU=
+-----END OPENSSH PRIVATE KEY-----
diff --git a/tests/test_pkey.py b/tests/test_pkey.py
index f7dabf26..749bb5f5 100644
--- a/tests/test_pkey.py
+++ b/tests/test_pkey.py
@@ -467,6 +467,14 @@ class KeyTest(unittest.TestCase):
)
self.assertNotEqual(key1.asbytes(), key2.asbytes())
+ def test_ed25519_funky_padding(self):
+ # Proves #1306 by just not exploding with 'Invalid key'.
+ Ed25519Key.from_private_key_file(_support("test_ed25519-funky-padding.key"))
+
+ def test_ed25519_funky_padding_with_passphrase(self):
+ # Proves #1306 by just not exploding with 'Invalid key'.
+ Ed25519Key.from_private_key_file(_support("test_ed25519-funky-padding_password.key"), b"asdf")
+
def test_ed25519_compare(self):
# verify that the private & public keys compare equal
key = Ed25519Key.from_private_key_file(_support("test_ed25519.key"))