From 8eb2775f958ccdb3c4fcb06047a19b985ad5f26a Mon Sep 17 00:00:00 2001 From: Shashank Veerapaneni Date: Thu, 4 May 2017 19:24:59 +0530 Subject: refactor files --- paramiko/kex_ecdh_nist.py | 114 ++++++++++++++++++++++++++++++++++++++++++++++ paramiko/kex_nistp256.py | 102 ----------------------------------------- paramiko/kex_nistp384.py | 9 ---- paramiko/kex_nistp521.py | 9 ---- paramiko/transport.py | 4 +- tests/test_kex.py | 10 ++-- 6 files changed, 120 insertions(+), 128 deletions(-) create mode 100644 paramiko/kex_ecdh_nist.py delete mode 100644 paramiko/kex_nistp256.py delete mode 100644 paramiko/kex_nistp384.py delete mode 100644 paramiko/kex_nistp521.py diff --git a/paramiko/kex_ecdh_nist.py b/paramiko/kex_ecdh_nist.py new file mode 100644 index 00000000..8961dd14 --- /dev/null +++ b/paramiko/kex_ecdh_nist.py @@ -0,0 +1,114 @@ +""" +Ephemeral Elliptic Curve Diffie-Hellman (ECDH) key exchange +RFC 5656, Section 4 +""" + +from hashlib import sha256, sha384, sha512 +from paramiko.message import Message +from paramiko.py3compat import byte_chr, long +from paramiko.ssh_exception import SSHException +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives.asymmetric import ec +from binascii import hexlify + +_MSG_KEXECDH_INIT, _MSG_KEXECDH_REPLY = range(30, 32) +c_MSG_KEXECDH_INIT, c_MSG_KEXECDH_REPLY = [byte_chr(c) for c in range(30, 32)] + + +class KexNistp256(): + + name = "ecdh-sha2-nistp256" + hash_algo = sha256 + curve = ec.SECP256R1() + + def __init__(self, transport): + self.transport = transport + #private key, client public and server public keys + self.P = long(0) + self.Q_C = None + self.Q_S = None + + def start_kex(self): + self._generate_key_pair() + if self.transport.server_mode: + self.transport._expect_packet(_MSG_KEXECDH_INIT) + return + m = Message() + m.add_byte(c_MSG_KEXECDH_INIT) + #SEC1: V2.0 2.3.3 Elliptic-Curve-Point-to-Octet-String Conversion + m.add_string(self.Q_C.public_numbers().encode_point()) + self.transport._send_message(m) + self.transport._expect_packet(_MSG_KEXECDH_REPLY) + + def parse_next(self, ptype, m): + if self.transport.server_mode and (ptype == _MSG_KEXECDH_INIT): + return self._parse_kexecdh_init(m) + elif not self.transport.server_mode and (ptype == _MSG_KEXECDH_REPLY): + return self._parse_kexecdh_reply(m) + raise SSHException('KexECDH asked to handle packet type %d' % ptype) + + def _generate_key_pair(self): + self.P = ec.generate_private_key(self.curve, default_backend()) + if self.transport.server_mode: + self.Q_S = self.P.public_key() + return + self.Q_C = self.P.public_key() + + def _parse_kexecdh_init(self, m): + Q_C_bytes = m.get_string() + self.Q_C = ec.EllipticCurvePublicNumbers.from_encoded_point(self.curve, Q_C_bytes) + K_S = self.transport.get_server_key().asbytes() + K = self.P.exchange(ec.ECDH(), self.Q_C.public_key(default_backend())) + K = long(hexlify(K), 16) + #compute exchange hash + hm = Message() + hm.add(self.transport.remote_version, self.transport.local_version, + self.transport.remote_kex_init, self.transport.local_kex_init) + hm.add_string(K_S) + hm.add_string(Q_C_bytes) + #SEC1: V2.0 2.3.3 Elliptic-Curve-Point-to-Octet-String Conversion + hm.add_string(self.Q_S.public_numbers().encode_point()) + hm.add_mpint(long(K)) + H = self.hash_algo(hm.asbytes()).digest() + self.transport._set_K_H(K, H) + sig = self.transport.get_server_key().sign_ssh_data(H) + #construct reply + m = Message() + m.add_byte(c_MSG_KEXECDH_REPLY) + m.add_string(K_S) + m.add_string(self.Q_S.public_numbers().encode_point()) + m.add_string(sig) + self.transport._send_message(m) + self.transport._activate_outbound() + + def _parse_kexecdh_reply(self, m): + K_S = m.get_string() + Q_S_bytes = m.get_string() + self.Q_S = ec.EllipticCurvePublicNumbers.from_encoded_point(self.curve, Q_S_bytes) + sig = m.get_binary() + K = self.P.exchange(ec.ECDH(), self.Q_S.public_key(default_backend())) + K = long(hexlify(K), 16) + #compute exchange hash and verify signature + hm = Message() + hm.add(self.transport.local_version, self.transport.remote_version, + self.transport.local_kex_init, self.transport.remote_kex_init) + hm.add_string(K_S) + #SEC1: V2.0 2.3.3 Elliptic-Curve-Point-to-Octet-String Conversion + hm.add_string(self.Q_C.public_numbers().encode_point()) + hm.add_string(Q_S_bytes) + hm.add_mpint(K) + self.transport._set_K_H(K, self.hash_algo(hm.asbytes()).digest()) + self.transport._verify_key(K_S, sig) + self.transport._activate_outbound() + + +class KexNistp384(KexNistp256): + name = "ecdh-sha2-nistp384" + hash_algo = sha384 + curve = ec.SECP384R1() + + +class KexNistp521(KexNistp256): + name = "ecdh-sha2-nistp521" + hash_algo = sha512 + curve = ec.SECP521R1() diff --git a/paramiko/kex_nistp256.py b/paramiko/kex_nistp256.py deleted file mode 100644 index 6ac7c141..00000000 --- a/paramiko/kex_nistp256.py +++ /dev/null @@ -1,102 +0,0 @@ -""" -Ephemeral Elliptic Curve Diffie-Hellman (ECDH) key exchange -RFC 5656, Section 4 -""" - -from hashlib import sha256 -from paramiko.message import Message -from paramiko.py3compat import byte_chr, long -from paramiko.ssh_exception import SSHException -from cryptography.hazmat.backends import default_backend -from cryptography.hazmat.primitives.asymmetric import ec -from binascii import hexlify - -_MSG_KEXECDH_INIT, _MSG_KEXECDH_REPLY = range(30, 32) -c_MSG_KEXECDH_INIT, c_MSG_KEXECDH_REPLY = [byte_chr(c) for c in range(30, 32)] - - -class KexNistp256(): - - name = "ecdh-sha2-nistp256" - hash_algo = sha256 - curve = ec.SECP256R1() - - def __init__(self, transport): - self.transport = transport - #private key, client public and server public keys - self.P = long(0) - self.Q_C = None - self.Q_S = None - - def start_kex(self): - self._generate_key_pair() - if self.transport.server_mode: - self.transport._expect_packet(_MSG_KEXECDH_INIT) - return - m = Message() - m.add_byte(c_MSG_KEXECDH_INIT) - #SEC1: V2.0 2.3.3 Elliptic-Curve-Point-to-Octet-String Conversion - m.add_string(self.Q_C.public_numbers().encode_point()) - self.transport._send_message(m) - self.transport._expect_packet(_MSG_KEXECDH_REPLY) - - def parse_next(self, ptype, m): - if self.transport.server_mode and (ptype == _MSG_KEXECDH_INIT): - return self._parse_kexecdh_init(m) - elif not self.transport.server_mode and (ptype == _MSG_KEXECDH_REPLY): - return self._parse_kexecdh_reply(m) - raise SSHException('KexECDH asked to handle packet type %d' % ptype) - - def _generate_key_pair(self): - self.P = ec.generate_private_key(self.curve, default_backend()) - if self.transport.server_mode: - self.Q_S = self.P.public_key() - return - self.Q_C = self.P.public_key() - - def _parse_kexecdh_init(self, m): - Q_C_bytes = m.get_string() - self.Q_C = ec.EllipticCurvePublicNumbers.from_encoded_point(self.curve, Q_C_bytes) - K_S = self.transport.get_server_key().asbytes() - K = self.P.exchange(ec.ECDH(), self.Q_C.public_key(default_backend())) - K = long(hexlify(K), 16) - #compute exchange hash - hm = Message() - hm.add(self.transport.remote_version, self.transport.local_version, - self.transport.remote_kex_init, self.transport.local_kex_init) - hm.add_string(K_S) - hm.add_string(Q_C_bytes) - #SEC1: V2.0 2.3.3 Elliptic-Curve-Point-to-Octet-String Conversion - hm.add_string(self.Q_S.public_numbers().encode_point()) - hm.add_mpint(long(K)) - H = self.hash_algo(hm.asbytes()).digest() - self.transport._set_K_H(K, H) - sig = self.transport.get_server_key().sign_ssh_data(H) - #construct reply - m = Message() - m.add_byte(c_MSG_KEXECDH_REPLY) - m.add_string(K_S) - m.add_string(self.Q_S.public_numbers().encode_point()) - m.add_string(sig) - self.transport._send_message(m) - self.transport._activate_outbound() - - def _parse_kexecdh_reply(self, m): - K_S = m.get_string() - Q_S_bytes = m.get_string() - self.Q_S = ec.EllipticCurvePublicNumbers.from_encoded_point(self.curve, Q_S_bytes) - sig = m.get_binary() - K = self.P.exchange(ec.ECDH(), self.Q_S.public_key(default_backend())) - K = long(hexlify(K), 16) - #compute exchange hash and verify signature - hm = Message() - hm.add(self.transport.local_version, self.transport.remote_version, - self.transport.local_kex_init, self.transport.remote_kex_init) - hm.add_string(K_S) - #SEC1: V2.0 2.3.3 Elliptic-Curve-Point-to-Octet-String Conversion - hm.add_string(self.Q_C.public_numbers().encode_point()) - hm.add_string(Q_S_bytes) - hm.add_mpint(K) - self.transport._set_K_H(K, self.hash_algo(hm.asbytes()).digest()) - self.transport._verify_key(K_S, sig) - self.transport._activate_outbound() diff --git a/paramiko/kex_nistp384.py b/paramiko/kex_nistp384.py deleted file mode 100644 index cdd23a5e..00000000 --- a/paramiko/kex_nistp384.py +++ /dev/null @@ -1,9 +0,0 @@ -from hashlib import sha384 -from paramiko.kex_nistp256 import KexNistp256 -from cryptography.hazmat.primitives.asymmetric import ec - - -class KexNistp384(KexNistp256): - name = "ecdh-sha2-nistp384" - hash_algo = sha384 - curve = ec.SECP384R1() diff --git a/paramiko/kex_nistp521.py b/paramiko/kex_nistp521.py deleted file mode 100644 index 352fe8c9..00000000 --- a/paramiko/kex_nistp521.py +++ /dev/null @@ -1,9 +0,0 @@ -from hashlib import sha512 -from paramiko.kex_nistp256 import KexNistp256 -from cryptography.hazmat.primitives.asymmetric import ec - - -class KexNistp521(KexNistp256): - name = "ecdh-sha2-nistp521" - hash_algo = sha512 - curve = ec.SECP521R1() diff --git a/paramiko/transport.py b/paramiko/transport.py index 8775e434..6b11dbc7 100644 --- a/paramiko/transport.py +++ b/paramiko/transport.py @@ -55,9 +55,7 @@ from paramiko.dsskey import DSSKey from paramiko.kex_gex import KexGex, KexGexSHA256 from paramiko.kex_group1 import KexGroup1 from paramiko.kex_group14 import KexGroup14 -from paramiko.kex_nistp256 import KexNistp256 -from paramiko.kex_nistp384 import KexNistp384 -from paramiko.kex_nistp521 import KexNistp521 +from paramiko.kex_ecdh_nist import KexNistp256, KexNistp384, KexNistp521 from paramiko.kex_gss import KexGSSGex, KexGSSGroup1, KexGSSGroup14, NullHostKey from paramiko.message import Message from paramiko.packet import Packetizer, NeedRekeyException diff --git a/tests/test_kex.py b/tests/test_kex.py index 619b2722..b7f588f7 100644 --- a/tests/test_kex.py +++ b/tests/test_kex.py @@ -29,7 +29,7 @@ from paramiko.kex_group1 import KexGroup1 from paramiko.kex_gex import KexGex, KexGexSHA256 from paramiko import Message from paramiko.common import byte_chr -from paramiko.kex_nistp256 import KexNistp256 +from paramiko.kex_ecdh_nist import KexNistp256 from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.asymmetric import ec @@ -391,7 +391,7 @@ class KexTest (unittest.TestCase): transport.server_mode = False kex = KexNistp256(transport) kex.start_kex() - self.assertEqual((paramiko.kex_nistp256._MSG_KEXECDH_REPLY,), transport._expect) + self.assertEqual((paramiko.kex_ecdh_nist._MSG_KEXECDH_REPLY,), transport._expect) #fake reply msg = Message() @@ -400,7 +400,7 @@ class KexTest (unittest.TestCase): msg.add_string(Q_S) msg.add_string('fake-sig') msg.rewind() - kex.parse_next(paramiko.kex_nistp256._MSG_KEXECDH_REPLY, msg) + kex.parse_next(paramiko.kex_ecdh_nist._MSG_KEXECDH_REPLY, msg) H = b'BAF7CE243A836037EB5D2221420F35C02B9AB6C957FE3BDE3369307B9612570A' self.assertEqual(K, kex.transport._K) self.assertEqual(H, hexlify(transport._H).upper()) @@ -413,7 +413,7 @@ class KexTest (unittest.TestCase): transport.server_mode = True kex = KexNistp256(transport) kex.start_kex() - self.assertEqual((paramiko.kex_nistp256._MSG_KEXECDH_INIT,), transport._expect) + self.assertEqual((paramiko.kex_ecdh_nist._MSG_KEXECDH_INIT,), transport._expect) #fake init msg=Message() @@ -421,7 +421,7 @@ class KexTest (unittest.TestCase): H = b'2EF4957AFD530DD3F05DBEABF68D724FACC060974DA9704F2AEE4C3DE861E7CA' msg.add_string(Q_C) msg.rewind() - kex.parse_next(paramiko.kex_nistp256._MSG_KEXECDH_INIT, msg) + kex.parse_next(paramiko.kex_ecdh_nist._MSG_KEXECDH_INIT, msg) self.assertEqual(K, transport._K) self.assertTrue(transport._activated) self.assertEqual(H, hexlify(transport._H).upper()) -- cgit v1.2.3