diff options
author | Mark Adams <mark@markadams.me> | 2014-12-12 23:13:12 -0600 |
---|---|---|
committer | Mark Adams <mark@markadams.me> | 2014-12-13 08:38:11 -0600 |
commit | 78a7d1c4c63737c4eae0c22207a00141a44402d3 (patch) | |
tree | 99b63769c2260fd888450e49ec8d25e26c1566d8 /src | |
parent | be42d096746ca211d0e1b21874017e75765dc40b (diff) | |
download | cryptography-78a7d1c4c63737c4eae0c22207a00141a44402d3.tar.gz cryptography-78a7d1c4c63737c4eae0c22207a00141a44402d3.tar.bz2 cryptography-78a7d1c4c63737c4eae0c22207a00141a44402d3.zip |
Added load_ssh_rsa_public_key to hazmat.primitives.serialization to allow for loading of OpenSSH RSA public keys
Also added load_ssh_public_key as a generic method that can be later extended to support more public key algorithms.
Diffstat (limited to 'src')
-rw-r--r-- | src/cryptography/hazmat/primitives/serialization.py | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/src/cryptography/hazmat/primitives/serialization.py b/src/cryptography/hazmat/primitives/serialization.py index b9cf5967..0f07e41f 100644 --- a/src/cryptography/hazmat/primitives/serialization.py +++ b/src/cryptography/hazmat/primitives/serialization.py @@ -4,9 +4,13 @@ from __future__ import absolute_import, division, print_function +import base64 +import struct import warnings from cryptography import utils +from cryptography.exceptions import UnsupportedAlgorithm +from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicNumbers def load_pem_traditional_openssl_private_key(data, password, backend): @@ -39,3 +43,46 @@ def load_pem_private_key(data, password, backend): def load_pem_public_key(data, backend): return backend.load_pem_public_key(data) + + +def load_ssh_public_key(data, backend): + if not data.startswith(b'ssh-'): + raise ValueError('SSH-formatted keys must begin with ssh-') + + if not data.startswith(b'ssh-rsa'): + raise UnsupportedAlgorithm('Only RSA keys are currently supported.') + + return load_ssh_rsa_public_key(data, backend) + + +def load_ssh_rsa_public_key(data, backend): + if not data.startswith(b'ssh-rsa '): + raise ValueError('SSH-formatted RSA keys must begin with ssh-rsa') + + parts = data.split(b' ') + data = base64.b64decode(parts[1]) + + cert_data = [] + + while len(data) > 0: + str_len = struct.unpack('>I', data[0:4])[0] + cert_data.append(data[4:4 + str_len]) + data = data[4 + str_len:] + + e = _bytes_to_int(cert_data[1]) + n = _bytes_to_int(cert_data[2]) + return backend.load_rsa_public_numbers(RSAPublicNumbers(e, n)) + + +def _bytes_to_int(data): + if len(data) % 4 != 0: + # Pad the bytes with 0x00 to a block size of 4 + data = (b'\x00' * (4 - (len(data) % 4))) + data + + result = 0 + + while len(data) > 0: + result = (result << 32) + struct.unpack('>I', data[0:4])[0] + data = data[4:] + + return result |