summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPierce Lopez <pierce.lopez@gmail.com>2019-12-05 18:06:10 -0500
committerPierce Lopez <pierce.lopez@gmail.com>2019-12-05 18:41:22 -0500
commit8b59b04c20609167c187b652016bdb7a942bb7a0 (patch)
treefab0e30eb64a2ee3ced155cd84ccc06d452a8575
parent5a4a0a213312e95f6b9c34b8728e016f2f2b31e1 (diff)
downloadparamiko-8b59b04c20609167c187b652016bdb7a942bb7a0.tar.gz
fix loading new openssh private key format when no padding
-rw-r--r--paramiko/ed25519key.py24
-rw-r--r--paramiko/pkey.py36
2 files changed, 25 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):
"""