summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--paramiko/ed25519key.py24
-rw-r--r--paramiko/pkey.py36
-rw-r--r--tests/test_pkey.py4
-rw-r--r--tests/test_rsa_openssh_nopad.key27
4 files changed, 56 insertions, 35 deletions
diff --git a/paramiko/ed25519key.py b/paramiko/ed25519key.py
index 96cff7d0..b584f521 100644
--- a/paramiko/ed25519key.py
+++ b/paramiko/ed25519key.py
@@ -21,32 +21,12 @@ from cryptography.hazmat.primitives.ciphers import Cipher
import nacl.signing
-import six
-
from paramiko.message import Message
-from paramiko.pkey import PKey
+from paramiko.pkey import PKey, OPENSSH_AUTH_MAGIC, _unpad_openssh
from paramiko.py3compat import b
from paramiko.ssh_exception import SSHException, PasswordRequiredException
-OPENSSH_AUTH_MAGIC = b"openssh-key-v1\x00"
-
-
-def unpad(data):
- # At the moment, this is only used for unpadding private keys on disk. This
- # really ought to be made constant time (possibly by upstreaming this logic
- # into pyca/cryptography).
- padding_length = six.indexbytes(data, -1)
- 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(padding_length):
- if six.indexbytes(data, i - padding_length) != i + 1:
- raise SSHException("Invalid key")
- return data[:-padding_length]
-
-
class Ed25519Key(PKey):
"""
Representation of an `Ed25519 <https://ed25519.cr.yp.to/>`_ key.
@@ -155,7 +135,7 @@ class Ed25519Key(PKey):
decryptor.update(private_ciphertext) + decryptor.finalize()
)
- message = Message(unpad(private_data))
+ message = Message(_unpad_openssh(private_data))
if message.get_int() != message.get_int():
raise SSHException("Invalid key")
diff --git a/paramiko/pkey.py b/paramiko/pkey.py
index c6beef51..3a07426f 100644
--- a/paramiko/pkey.py
+++ b/paramiko/pkey.py
@@ -27,6 +27,7 @@ from hashlib import md5
import re
import struct
+import six
import bcrypt
from cryptography.hazmat.backends import default_backend
@@ -35,18 +36,29 @@ from cryptography.hazmat.primitives.ciphers import algorithms, modes, Cipher
from paramiko import util
from paramiko.common import o600
-from paramiko.py3compat import (
- u,
- encodebytes,
- decodebytes,
- b,
- string_types,
- byte_ord,
-)
+from paramiko.py3compat import u, b, encodebytes, decodebytes, string_types
from paramiko.ssh_exception import SSHException, PasswordRequiredException
from paramiko.message import Message
+OPENSSH_AUTH_MAGIC = b"openssh-key-v1\x00"
+
+
+def _unpad_openssh(data):
+ # At the moment, this is only used for unpadding private keys on disk. This
+ # really ought to be made constant time (possibly by upstreaming this logic
+ # into pyca/cryptography).
+ padding_length = six.indexbytes(data, -1)
+ 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(padding_length):
+ if six.indexbytes(data, i - padding_length) != i + 1:
+ raise SSHException("Invalid key")
+ return data[:-padding_length]
+
+
class PKey(object):
"""
Base class for public keys.
@@ -395,8 +407,8 @@ class PKey(object):
raise SSHException("base64 decoding error: {}".format(e))
# read data struct
- auth_magic = data[:14]
- if auth_magic != b("openssh-key-v1"):
+ auth_magic = data[:15]
+ if auth_magic != OPENSSH_AUTH_MAGIC:
raise SSHException("unexpected OpenSSH key header encountered")
cstruct = self._uint32_cstruct_unpack(data[15:], "sssur")
@@ -466,9 +478,7 @@ class PKey(object):
"OpenSSH private key file checkints do not match"
)
- # Remove padding
- padlen = byte_ord(keydata[len(keydata) - 1])
- return keydata[: len(keydata) - padlen]
+ return _unpad_openssh(keydata)
def _uint32_cstruct_unpack(self, data, strformat):
"""
diff --git a/tests/test_pkey.py b/tests/test_pkey.py
index 17893ca2..8d88545a 100644
--- a/tests/test_pkey.py
+++ b/tests/test_pkey.py
@@ -494,6 +494,10 @@ class KeyTest(unittest.TestCase):
finally:
os.remove(newfile)
+ def test_load_openssh_format_RSA_nopad(self):
+ # check just not exploding with 'Invalid key'
+ RSAKey.from_private_key_file(_support("test_rsa_openssh_nopad.key"))
+
def test_stringification(self):
key = RSAKey.from_private_key_file(_support("test_rsa.key"))
comparable = TEST_KEY_BYTESTR_2 if PY2 else TEST_KEY_BYTESTR_3
diff --git a/tests/test_rsa_openssh_nopad.key b/tests/test_rsa_openssh_nopad.key
new file mode 100644
index 00000000..61ac1b19
--- /dev/null
+++ b/tests/test_rsa_openssh_nopad.key
@@ -0,0 +1,27 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn
+NhAAAAAwEAAQAAAQEAnyMwWSwrbJxxQZWMJO5xR6eAA9De4t3GViqDRaQt/BgsvzZ14SUz
+aOL/A370fKxhx/JLIOOGA0o5B0/ct+CL7XFqMi5r5+iA9VcIeYKKtoAkrEvRnagNW0WVWx
+thTnE01g8Pb7fDqzI2cBuBNZ2vGNm2m4UTGC8/kl/0ES1V3KqA7lPlTrkTYg9L/ornvVHc
+c8gEbMwx9XXVRzbWiuDE176ojrudY9CZduVSOgW+HK3rKkqLBs/91jv0zUK0oqTQBLR7E2
+V2GWPDU4BjlHTtYr0jpKOGDr1DLu4+NiD/mX+tGMdH6ehbDii0kXmOUaZjs4OxuK3XA/gi
+KZLdj1jQQwAAA7iNnvAVjZ7wFQAAAAdzc2gtcnNhAAABAQCfIzBZLCtsnHFBlYwk7nFHp4
+AD0N7i3cZWKoNFpC38GCy/NnXhJTNo4v8DfvR8rGHH8ksg44YDSjkHT9y34IvtcWoyLmvn
+6ID1Vwh5goq2gCSsS9GdqA1bRZVbG2FOcTTWDw9vt8OrMjZwG4E1na8Y2babhRMYLz+SX/
+QRLVXcqoDuU+VOuRNiD0v+iue9UdxzyARszDH1ddVHNtaK4MTXvqiOu51j0Jl25VI6Bb4c
+resqSosGz/3WO/TNQrSipNAEtHsTZXYZY8NTgGOUdO1ivSOko4YOvUMu7j42IP+Zf60Yx0
+fp6FsOKLSReY5RpmOzg7G4rdcD+CIpkt2PWNBDAAAAAwEAAQAAAQEAnmMbn+VCYxth7fC2
+R5u6y6J+201sSUiKOwCdHxdFXX+CKd4+fRPVkzM6tXQKSnwX5jXVaKqLm4KoOArYl3q6Sl
+1zYParF2plz8oL+URgYzwvQ/1CaDP29zzOZptdwgESoWrj5kF0UlPrsrDtbTvAJm+qPCe6
+1XtRPpKaDO6eYr0PM2QTElZy3mDBUBvu816LdG/ZtnB9g5UsocT5mmhpHTHdjrpwNu5TBe
+ACVodDn5Fu66OlrrnQi4IPCAWKJ1YuzEkZqLhs1L3oMHACsmzrLjzW74SjY4kWTTvGiC6i
+tDoycycThk9EGLGNso99Q1fe84/OZUff7aI3yK9KvLL7oQAAAIEAh2+XrJXSBx/v9E3aJH
+ncgQH1snXr7LcSRqcWicHdbm8JsOTT3TkyXHGlSZ2rr/Y0u5V1ZSO6roJLrAHsDJzx0x0U
+xE/5mpzhD+yIKQwnWkZFLzYEnYDFdXDMzmghUIik9AW7n9dtS8UtVFGaL6Vs2YCOuLqeT9
+nZUkm3UUZ+7QIAAACBAM23DFjQ0/Op2ri7fJA2qFBdXqoJdNHuyYEIrKbB6XaaSUz52+IB
+MbccxEz3vPsHh69tZoJ+xZNbFJe9wdmbF+DQpoukHkJnzpk/pUq8LjQMzZfwv41X8zqaq4
+AOA7g27Rk8aKewhCXjhkr0hHEaSiuqIIindFaFti5sQMi2mtkXAAAAgQDGCXkpuKZK61p9
+L6G5yZSQBCgVtm0iQEbyDXWHjy/GqLtxJjqdyaRK57hXGjbzgJJraSy+sNP9uv2QOvyZvB
+3XaPWwUYVQ34WyibCqqUaPiHxX7T1lZV+asbwgbmSqYtH5dUEJ8zT572mCwxnRjX63PwDo
+5vBbR/qAW5lvRYsltQAAAAFh
+-----END OPENSSH PRIVATE KEY-----