def test_1_encode(self): msg = Message() msg.add_int(23) msg.add_int(123789456) msg.add_string("q") msg.add_string("hello") msg.add_string("x" * 1000) self.assertEqual(msg.asbytes(), self.__a) msg = Message() msg.add_boolean(True) msg.add_boolean(False) msg.add_byte(byte_chr(0xf3)) msg.add_bytes(zero_byte + byte_chr(0x3f)) msg.add_list(["huey", "dewey", "louie"]) self.assertEqual(msg.asbytes(), self.__b) msg = Message() msg.add_int64(5) msg.add_int64(0xf5e4d3c2b109) msg.add_mpint(17) msg.add_mpint(0xf5e4d3c2b109) msg.add_mpint(-0x65e4d3c2b109) self.assertEqual(msg.asbytes(), self.__c)
def test_encode(self): msg = Message() msg.add_int(23) msg.add_int(123789456) msg.add_string('q') msg.add_string('hello') msg.add_string('x' * 1000) self.assertEqual(msg.asbytes(), self.__a) msg = Message() msg.add_boolean(True) msg.add_boolean(False) msg.add_byte(byte_chr(0xf3)) msg.add_bytes(zero_byte + byte_chr(0x3f)) msg.add_list(['huey', 'dewey', 'louie']) self.assertEqual(msg.asbytes(), self.__b) msg = Message() msg.add_int64(5) msg.add_int64(0xf5e4d3c2b109) msg.add_mpint(17) msg.add_mpint(0xf5e4d3c2b109) msg.add_mpint(-0x65e4d3c2b109) self.assertEqual(msg.asbytes(), self.__c)
def make_certificate(ca_key, duration_hours, real_name, username, host, now, expiry): """http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?rev=1.9""" pkey = paramiko.RSAKey.from_private_key(StringIO(ca_key)) principals = Message() principals.add_string(username) principals = principals.asbytes() m = Message() m.add_string('*****@*****.**') m.add_string(sha1(str(random.random())).hexdigest()) m.add_mpint(pkey.e) m.add_mpint(pkey.n) m.add_int64(0) # serial m.add_int(SSH_CERT_TYPE_USER) m.add_string(real_name) m.add_string(principals) m.add_int64(int(now.strftime("%s"))) m.add_int64(int(expiry.strftime("%s"))) m.add_string("") # critical_options m.add_string("") # extensions m.add_string("") # reserved m.add_string(pkey.asbytes()) key = RSA.construct((long(pkey.n), long(pkey.e), long(pkey.d))) h = SHA.new(m.asbytes()) signer = PKCS1_v1_5.new(key) signature = signer.sign(h) sig_message = Message() sig_message.add_string("ssh-rsa") sig_message.add_string(signature) m.add_string(sig_message.asbytes()) return "[email protected] {0} {1}@{2}".format(base64.b64encode(m.asbytes()), username, host)
def _send_sign_data(self, msg): logger.debug('Sending signed data...') blob = msg.get_string() data = msg.get_string() flags = msg.get_int() logger.debug('Key blob:') for l in hexdump.hexdump(blob, result='generator'): logger.debug(l) # logger.debug('Data to be signed:') # for l in hexdump.hexdump(data, result='generator'): # logger.debug(l) # # logger.debug('Flags: %X', flags) signed_data = self._sign_data(blob, data) if not signed_data: self._send_failure() return sign_blob = Message() sign_blob.add_string('ssh-rsa') sign_blob.add_string(signed_data) msg = Message() # add response byte msg.add_byte(byte_chr(SSH_AGENT_SIGN_RESPONSE)) # add signed blob msg.add_string(sign_blob.asbytes()) self._send_reply(msg)
def _parse_kexdh_gex_init(self, m): self.e = m.get_mpint() if (self.e < 1) or (self.e > self.p - 1): raise SSHException('Client kex "e" is out of range') self._generate_x() self.f = pow(self.g, self.x, self.p) K = pow(self.e, self.x, self.p) key = self.transport.get_server_key().asbytes() # okay, build up the hash H of (V_C || V_S || I_C || I_S || K_S || min || n || max || p || g || e || f || K) hm = Message() hm.add(self.transport.remote_version, self.transport.local_version, self.transport.remote_kex_init, self.transport.local_kex_init, key) if not self.old_style: hm.add_int(self.min_bits) hm.add_int(self.preferred_bits) if not self.old_style: hm.add_int(self.max_bits) hm.add_mpint(self.p) hm.add_mpint(self.g) hm.add_mpint(self.e) hm.add_mpint(self.f) hm.add_mpint(K) H = self.hash_algo(hm.asbytes()).digest() self.transport._set_K_H(K, H) # sign it sig = self.transport.get_server_key().sign_ssh_data(H) # send reply m = Message() m.add_byte(c_MSG_KEXDH_GEX_REPLY) m.add_string(key) m.add_mpint(self.f) m.add_string(sig) self.transport._send_message(m) self.transport._activate_outbound()
def _parse_kexecdh_init(self, m): peer_key_bytes = m.get_string() peer_key = X25519PublicKey.from_public_bytes(peer_key_bytes) K = self._perform_exchange(peer_key) K = long(binascii.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, ) server_key_bytes = self.transport.get_server_key().asbytes() exchange_key_bytes = self.key.public_key().public_bytes( serialization.Encoding.Raw, serialization.PublicFormat.Raw) hm.add_string(server_key_bytes) hm.add_string(peer_key_bytes) hm.add_string(exchange_key_bytes) hm.add_mpint(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(server_key_bytes) m.add_string(exchange_key_bytes) m.add_string(sig) self.transport._send_message(m) self.transport._activate_outbound()
def test_add(self): msg = Message() msg.add(5) msg.add(True) msg.add('cat') msg.add(['a', 'b']) self.assertEqual(msg.asbytes(), self.__d)
def _parse_kexecdh_reply(self, m): K_S = m.get_string() Q_S_bytes = m.get_string() self.Q_S = ec.EllipticCurvePublicKey.from_encoded_point( self.curve, Q_S_bytes ) sig = m.get_binary() K = self.P.exchange(ec.ECDH(), self.Q_S) 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_bytes( serialization.Encoding.X962, serialization.PublicFormat.UncompressedPoint, ) ) 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()
def _parse_kexdh_init(self, m): # server mode self.e = m.get_mpint() if (self.e < 1) or (self.e > P - 1): raise SSHException('Client kex "e" is out of range') K = pow(self.e, self.x, P) key = self.transport.get_server_key().asbytes() # okay, build up the hash H of (V_C || V_S || I_C || I_S || K_S || e || f || K) 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(key) hm.add_mpint(self.e) hm.add_mpint(self.f) hm.add_mpint(K) H = SHA.new(hm.asbytes()).digest() self.transport._set_K_H(K, H) # sign it sig = self.transport.get_server_key().sign_ssh_data( self.transport.rng, H) # send reply m = Message() m.add_byte(c_MSG_KEXDH_REPLY) m.add_string(key) m.add_mpint(self.f) m.add_string(sig) self.transport._send_message(m) self.transport._activate_outbound()
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): peer_host_key_bytes = m.get_string() peer_key_bytes = m.get_string() sig = m.get_binary() peer_key = X25519PublicKey.from_public_bytes(peer_key_bytes) K = self._perform_exchange(peer_key) K = long(binascii.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(peer_host_key_bytes) hm.add_string(self.key.public_key().public_bytes( serialization.Encoding.Raw, serialization.PublicFormat.Raw)) hm.add_string(peer_key_bytes) hm.add_mpint(K) self.transport._set_K_H(K, self.hash_algo(hm.asbytes()).digest()) self.transport._verify_key(peer_host_key_bytes, sig) self.transport._activate_outbound()
def _parse_kexdh_init(self, m): # server mode self.e = m.get_mpint() if (self.e < 1) or (self.e > P - 1): raise SSHException('Client kex "e" is out of range') K = pow(self.e, self.x, P) key = self.transport.get_server_key().asbytes() # okay, build up the hash H of (V_C || V_S || I_C || I_S || K_S || e || f || K) 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(key) hm.add_mpint(self.e) hm.add_mpint(self.f) hm.add_mpint(K) H = SHA.new(hm.asbytes()).digest() self.transport._set_K_H(K, H) # sign it sig = self.transport.get_server_key().sign_ssh_data(self.transport.rng, H) # send reply m = Message() m.add_byte(c_MSG_KEXDH_REPLY) m.add_string(key) m.add_mpint(self.f) m.add_string(sig) self.transport._send_message(m) self.transport._activate_outbound()
def _parse_kexdh_gex_reply(self, m): host_key = m.get_string() self.f = m.get_mpint() sig = m.get_string() if (self.f < 1) or (self.f > self.p - 1): raise SSHException('Server kex "f" is out of range') K = pow(self.f, self.x, self.p) # okay, build up the hash H of (V_C || V_S || I_C || I_S || K_S || min || n || max || p || g || e || f || K) hm = Message() hm.add(self.transport.local_version, self.transport.remote_version, self.transport.local_kex_init, self.transport.remote_kex_init, host_key) if not self.old_style: hm.add_int(self.min_bits) hm.add_int(self.preferred_bits) if not self.old_style: hm.add_int(self.max_bits) hm.add_mpint(self.p) hm.add_mpint(self.g) hm.add_mpint(self.e) hm.add_mpint(self.f) hm.add_mpint(K) self.transport._set_K_H(K, self.hash_algo(hm.asbytes()).digest()) self.transport._verify_key(host_key, sig) self.transport._activate_outbound()
def _parse_kexdh_gex_reply(self, m): host_key = m.get_string() self.f = m.get_mpint() sig = m.get_string() if (self.f < 1) or (self.f > self.p - 1): raise SSHException('Server kex "f" is out of range') K = pow(self.f, self.x, self.p) # okay, build up the hash H of # (V_C || V_S || I_C || I_S || K_S || min || n || max || p || g || e || f || K) # noqa hm = Message() hm.add( self.transport.local_version, self.transport.remote_version, self.transport.local_kex_init, self.transport.remote_kex_init, host_key, ) if not self.old_style: hm.add_int(self.min_bits) hm.add_int(self.preferred_bits) if not self.old_style: hm.add_int(self.max_bits) hm.add_mpint(self.p) hm.add_mpint(self.g) hm.add_mpint(self.e) hm.add_mpint(self.f) hm.add_mpint(K) self.transport._set_K_H(K, self.hash_algo(hm.asbytes()).digest()) self.transport._verify_key(host_key, sig) self.transport._activate_outbound()
def _gen_pem(self): msg = Message() msg.add_string('ssh-rsa') exp, mod = self._fetch_material() msg.add_string(bigint_to_bytes(exp)) msg.add_string(bigint_to_bytes(mod, extra_bytes=1)) self._pub_key_bytes = msg.asbytes()
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()
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_kexgss_gex_init(self, m): """ Parse the SSH2_MSG_KEXGSS_INIT message (server mode). :param `Message` m: The content of the SSH2_MSG_KEXGSS_INIT message """ client_token = m.get_string() self.e = m.get_mpint() if (self.e < 1) or (self.e > self.p - 1): raise SSHException('Client kex "e" is out of range') self._generate_x() self.f = pow(self.g, self.x, self.p) K = pow(self.e, self.x, self.p) self.transport.host_key = NullHostKey() key = self.transport.host_key.__str__() # okay, build up the hash H of # (V_C || V_S || I_C || I_S || K_S || min || n || max || p || g || e || f || K) # noqa hm = Message() hm.add( self.transport.remote_version, self.transport.local_version, self.transport.remote_kex_init, self.transport.local_kex_init, key, ) hm.add_int(self.min_bits) hm.add_int(self.preferred_bits) hm.add_int(self.max_bits) hm.add_mpint(self.p) hm.add_mpint(self.g) hm.add_mpint(self.e) hm.add_mpint(self.f) hm.add_mpint(K) H = sha1(hm.asbytes()).digest() self.transport._set_K_H(K, H) srv_token = self.kexgss.ssh_accept_sec_context(self.gss_host, client_token) m = Message() if self.kexgss._gss_srv_ctxt_status: mic_token = self.kexgss.ssh_get_mic(self.transport.session_id, gss_kex=True) m.add_byte(c_MSG_KEXGSS_COMPLETE) m.add_mpint(self.f) m.add_string(mic_token) if srv_token is not None: m.add_boolean(True) m.add_string(srv_token) else: m.add_boolean(False) self.transport._send_message(m) self.transport.gss_kex_used = True self.transport._activate_outbound() else: m.add_byte(c_MSG_KEXGSS_CONTINUE) m.add_string(srv_token) self.transport._send_message(m) self.transport._expect_packet(MSG_KEXGSS_CONTINUE, MSG_KEXGSS_COMPLETE, MSG_KEXGSS_ERROR)
def asbytes(self): m = Message() m.add_string('ssh-dss') m.add_mpint(self.p) m.add_mpint(self.q) m.add_mpint(self.g) m.add_mpint(self.y) return m.asbytes()
def asbytes(self): if self.can_sign(): v = self._signing_key.verify_key else: v = self._verifying_key m = Message() m.add_string("ssh-ed25519") m.add_string(v.encode()) return m.asbytes()
def test_3_add(self): msg = Message() msg.add(5) msg.add(0x1122334455) msg.add(0xf00000000000000000) msg.add(True) msg.add('cat') msg.add(['a', 'b']) self.assertEqual(msg.asbytes(), self.__d)
def test_3_add(self): msg = Message() msg.add(5) msg.add(0x1122334455) msg.add(0xf00000000000000000) msg.add(True) msg.add("cat") msg.add(["a", "b"]) self.assertEqual(msg.asbytes(), self.__d)
def asbytes(self): public_bytes = self._verifying_key.public_bytes( serialization.Encoding.Raw, serialization.PublicFormat.Raw, ) m = Message() m.add_string("ssh-ed25519") m.add_string(public_bytes) return m.asbytes()
def asagentbytes(self): m = Message() m.add_string('ssh-rsa') m.add_mpint(self.public_numbers.n) m.add_mpint(self.public_numbers.e) m.add_mpint(self.key.private_numbers().d) m.add_mpint(self.key.private_numbers().iqmp) m.add_mpint(self.key.private_numbers().p) m.add_mpint(self.key.private_numbers().q) return m.asbytes()
def asbytes(self): key = self.verifying_key m = Message() m.add_string('ecdsa-sha2-nistp256') m.add_string('nistp256') point_str = four_byte + key.to_string() m.add_string(point_str) return m.asbytes()
def _parse_kexgss_gex_init(self, m): """ Parse the SSH2_MSG_KEXGSS_INIT message (server mode). :param `Message` m: The content of the SSH2_MSG_KEXGSS_INIT message """ client_token = m.get_string() self.e = m.get_mpint() if (self.e < 1) or (self.e > self.p - 1): raise SSHException('Client kex "e" is out of range') self._generate_x() self.f = pow(self.g, self.x, self.p) K = pow(self.e, self.x, self.p) self.transport.host_key = NullHostKey() key = self.transport.host_key.__str__() # okay, build up the hash H of # (V_C || V_S || I_C || I_S || K_S || min || n || max || p || g || e || f || K) # noqa hm = Message() hm.add(self.transport.remote_version, self.transport.local_version, self.transport.remote_kex_init, self.transport.local_kex_init, key) hm.add_int(self.min_bits) hm.add_int(self.preferred_bits) hm.add_int(self.max_bits) hm.add_mpint(self.p) hm.add_mpint(self.g) hm.add_mpint(self.e) hm.add_mpint(self.f) hm.add_mpint(K) H = sha1(hm.asbytes()).digest() self.transport._set_K_H(K, H) srv_token = self.kexgss.ssh_accept_sec_context(self.gss_host, client_token) m = Message() if self.kexgss._gss_srv_ctxt_status: mic_token = self.kexgss.ssh_get_mic(self.transport.session_id, gss_kex=True) m.add_byte(c_MSG_KEXGSS_COMPLETE) m.add_mpint(self.f) m.add_string(mic_token) if srv_token is not None: m.add_boolean(True) m.add_string(srv_token) else: m.add_boolean(False) self.transport._send_message(m) self.transport.gss_kex_used = True self.transport._activate_outbound() else: m.add_byte(c_MSG_KEXGSS_CONTINUE) m.add_string(srv_token) self.transport._send_message(m) self.transport._expect_packet(MSG_KEXGSS_CONTINUE, MSG_KEXGSS_COMPLETE, MSG_KEXGSS_ERROR)
def _get_session_blob(self, key, service, username): m = Message() m.add_string(self.transport.session_id) m.add_byte(cMSG_USERAUTH_REQUEST) m.add_string(username) m.add_string(service) m.add_string('publickey') m.add_boolean(True) m.add_string(key.get_name()) m.add_string(key) return m.asbytes()
def _get_session_blob(self, key, service, username, algorithm): m = Message() m.add_string(self.transport.session_id) m.add_byte(cMSG_USERAUTH_REQUEST) m.add_string(username) m.add_string(service) m.add_string("publickey") m.add_boolean(True) _, bits = self._get_key_type_and_bits(key) m.add_string(algorithm) m.add_string(bits) return m.asbytes()
def _parse_kexgss_complete(self, m): """ Parse the SSH2_MSG_KEXGSS_COMPLETE message (client mode). :param `Message` m: The content of the SSH2_MSG_KEXGSS_COMPLETE message """ if self.transport.host_key is None: self.transport.host_key = NullHostKey() self.f = m.get_mpint() mic_token = m.get_string() # This must be TRUE, if there is a GSS-API token in this message. bool = m.get_boolean() srv_token = None if bool: srv_token = m.get_string() if (self.f < 1) or (self.f > self.p - 1): raise SSHException('Server kex "f" is out of range') K = pow(self.f, self.x, self.p) # okay, build up the hash H of # (V_C || V_S || I_C || I_S || K_S || min || n || max || p || g || e || f || K) # noqa hm = Message() hm.add( self.transport.local_version, self.transport.remote_version, self.transport.local_kex_init, self.transport.remote_kex_init, self.transport.host_key.__str__(), ) if not self.old_style: hm.add_int(self.min_bits) hm.add_int(self.preferred_bits) if not self.old_style: hm.add_int(self.max_bits) hm.add_mpint(self.p) hm.add_mpint(self.g) hm.add_mpint(self.e) hm.add_mpint(self.f) hm.add_mpint(K) H = sha1(hm.asbytes()).digest() self.transport._set_K_H(K, H) if srv_token is not None: self.kexgss.ssh_init_sec_context( target=self.gss_host, recv_token=srv_token ) self.kexgss.ssh_check_mic(mic_token, H) else: self.kexgss.ssh_check_mic(mic_token, H) self.transport.gss_kex_used = True self.transport._activate_outbound()
def _parse_kexgss_complete(self, m): """ Parse the SSH2_MSG_KEXGSS_COMPLETE message (client mode). :param `Message` m: The content of the SSH2_MSG_KEXGSS_COMPLETE message """ if self.transport.host_key is None: self.transport.host_key = NullHostKey() self.f = m.get_mpint() mic_token = m.get_string() # This must be TRUE, if there is a GSS-API token in this message. bool = m.get_boolean() srv_token = None if bool: srv_token = m.get_string() if (self.f < 1) or (self.f > self.p - 1): raise SSHException('Server kex "f" is out of range') K = pow(self.f, self.x, self.p) # okay, build up the hash H of # (V_C || V_S || I_C || I_S || K_S || min || n || max || p || g || e || f || K) # noqa hm = Message() hm.add( self.transport.local_version, self.transport.remote_version, self.transport.local_kex_init, self.transport.remote_kex_init, self.transport.host_key.__str__(), ) if not self.old_style: hm.add_int(self.min_bits) hm.add_int(self.preferred_bits) if not self.old_style: hm.add_int(self.max_bits) hm.add_mpint(self.p) hm.add_mpint(self.g) hm.add_mpint(self.e) hm.add_mpint(self.f) hm.add_mpint(K) H = sha1(hm.asbytes()).digest() self.transport._set_K_H(K, H) if srv_token is not None: self.kexgss.ssh_init_sec_context(target=self.gss_host, recv_token=srv_token) self.kexgss.ssh_check_mic(mic_token, H) else: self.kexgss.ssh_check_mic(mic_token, H) self.transport.gss_kex_used = True self.transport._activate_outbound()
def _get_session_blob(self, key, service, username): m = Message() m.add_string(self.transport.session_id) m.add_byte(cMSG_USERAUTH_REQUEST) m.add_string(username) m.add_string(service) m.add_string('publickey') m.add_boolean(True) # Use certificate contents, if available, plain pubkey otherwise if key.public_blob: m.add_string(key.public_blob.key_type) m.add_string(key.public_blob.key_blob) else: m.add_string(key.get_name()) m.add_string(key) return m.asbytes()
def asbytes(self): key = self.verifying_key m = Message() m.add_string('ecdsa-sha2-nistp256') m.add_string('nistp256') numbers = key.public_numbers() x_bytes = deflate_long(numbers.x, add_sign_padding=False) x_bytes = b'\x00' * (len(x_bytes) - key.curve.key_size // 8) + x_bytes y_bytes = deflate_long(numbers.y, add_sign_padding=False) y_bytes = b'\x00' * (len(y_bytes) - key.curve.key_size // 8) + y_bytes point_str = four_byte + x_bytes + y_bytes m.add_string(point_str) return m.asbytes()
def asbytes(self): key = self.verifying_key numbers = key.public_numbers() key_size_bytes = (key.curve.key_size + 7) // 8 x_bytes = deflate_long(numbers.x, add_sign_padding=False) x_bytes = b'\x00' * (key_size_bytes - len(x_bytes)) + x_bytes y_bytes = deflate_long(numbers.y, add_sign_padding=False) y_bytes = b'\x00' * (key_size_bytes - len(y_bytes)) + y_bytes point_str = four_byte + x_bytes + y_bytes m = Message() m.add_string(self.ecdsa_curve.key_format_identifier) m.add_string(self.ecdsa_curve.nist_name) m.add_string(point_str) return m.asbytes()
def _parse_kexc25519_init(self, m): # server mode # Only one field in the client's message, which is their public key Q_C_bytes = m.get_string() self.Q_C = x25519.X25519PublicKey.from_public_bytes(Q_C_bytes) # Compute shared secret K = self.P.exchange(self.Q_C) K = long(hexlify(K), 16) # Prepare hostkey K_S = self.transport.get_server_key().asbytes() # Compute initial transport key 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) hm.add_string( self.Q_S.public_bytes(encoding=Encoding.Raw, format=PublicFormat.Raw)) hm.add_mpint(K) H = self.hash_algo(hm.asbytes()).digest() self.transport._set_K_H(K, H) # Compute signature sig = self.transport.get_server_key().sign_ssh_data(H) # construct reply m = Message() m.add_byte(c_MSG_KEXC25519_REPLY) m.add_string(K_S) m.add_string( self.Q_S.public_bytes(encoding=Encoding.Raw, format=PublicFormat.Raw)) m.add_string(sig) self.transport._send_message(m) self.transport._activate_outbound()
def asbytes(self): key = self.verifying_key m = Message() m.add_string(self.ecdsa_curve.key_format_identifier) m.add_string(self.ecdsa_curve.nist_name) numbers = key.public_numbers() key_size_bytes = (key.curve.key_size + 7) // 8 x_bytes = deflate_long(numbers.x, add_sign_padding=False) x_bytes = b'\x00' * (key_size_bytes - len(x_bytes)) + x_bytes y_bytes = deflate_long(numbers.y, add_sign_padding=False) y_bytes = b'\x00' * (key_size_bytes - len(y_bytes)) + y_bytes point_str = four_byte + x_bytes + y_bytes m.add_string(point_str) return m.asbytes()
def _parse_kexdh_reply(self, m): # client mode host_key = m.get_string() self.f = m.get_mpint() if (self.f < 1) or (self.f > P - 1): raise SSHException('Server kex "f" is out of range') sig = m.get_binary() K = pow(self.f, self.x, P) # okay, build up the hash H of (V_C || V_S || I_C || I_S || K_S || e || f || K) 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(host_key) hm.add_mpint(self.e) hm.add_mpint(self.f) hm.add_mpint(K) self.transport._set_K_H(K, SHA.new(hm.asbytes()).digest()) self.transport._verify_key(host_key, sig) self.transport._activate_outbound()
def _parse_kexecdh_init(self, m): Q_C_bytes = m.get_string() self.Q_C = ec.EllipticCurvePublicKey.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) 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_bytes( serialization.Encoding.X962, serialization.PublicFormat.UncompressedPoint, )) 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, self.transport.host_key_type) # construct reply m = Message() m.add_byte(c_MSG_KEXECDH_REPLY) m.add_string(K_S) m.add_string( self.Q_S.public_bytes( serialization.Encoding.X962, serialization.PublicFormat.UncompressedPoint, )) m.add_string(sig) self.transport._send_message(m) self.transport._activate_outbound()
def sign(self, ca_key, nonce): """ Sign this certificate with the specified ``ca_key``. The ``ca_key`` must include a private key and be able to sign data. The ``nonce`` must be provided. Usually this would be something random, i.e. from os.urandom(32), but can any string. Testing re-used the nonce from the existing certificate to verify that re-signing results in the same certificate :param .PKey ca_key: The key to use as a CA for signing the certificate :param str nonce: A string to random data to use in the signing of the certificate :raises SSHException: If the ca_key cannot be used for signing. """ if not ca_key.can_sign(): err = "Provided key cannot be used for signing" raise SSHException(err) new_bytes = self.generate_body(ca_key, nonce) sig = ca_key.sign_ssh_data(new_bytes) # If the key used to sign the data was a paramiko.Agent.AgentKey, the # results are a string/binary sequence. If a paramiko.pkey.PKey was # used, then the result is a Message. Convert to a string as needed. if type(sig) == Message: sig = sig.asbytes() msg = Message() msg.add_bytes(new_bytes) msg.add_string(sig) # Set new values on self after the signing process has been completed # and the new certificate is ready. self.nonce = nonce self.signature = sig self.signature_key = ca_key.asbytes() self._body_bytes = new_bytes self._bytes = msg.asbytes()
def asbytes(self): m = Message() m.add_string('ssh-rsa') m.add_mpint(self.e) m.add_mpint(self.n) return m.asbytes()
def asbytes(self): m = Message() m.add_string('ssh-rsa') m.add_mpint(self.public_numbers.e) m.add_mpint(self.public_numbers.n) return m.asbytes()
def _sigencode(self, r, s, order): msg = Message() msg.add_mpint(r) msg.add_mpint(s) return msg.asbytes()