Exemple #1
0
    def out_SETSHAREDKEY(self):
        assert (self.received_public_key)
        assert (not self.sent_unacked_shared_key)
        assert (not self.server_valid_shared_key)
        assert (not self.client_acked_shared_key)

        def generate_session_key(num_bytes=CryptoHandler.MIN_AES_KEY_SIZE * 2):
            ## encrypt converts its argument to a long, so the
            ## MSB should *always* be non-zero or D(E(K)) != K
            key_head = "\x00"
            key_tail = GLOBAL_RAND_POOL.read(num_bytes - 1)

            while (ord(key_head) == 0):
                key_head = GLOBAL_RAND_POOL.read(1)

            return (key_head + key_tail)

        ## note: server will use HASH(RAW) as key and echo back HASH(HASH(RAW))
        ## hence we send ENCODE(ENCRYPT(RAW)) and use HASH(RAW) on our side too
        aes_key_raw = generate_session_key()
        aes_key_sig = SECURE_HASH_FUNC(aes_key_raw)
        aes_key_enc = self.rsa_cipher_obj.encrypt_encode_bytes(aes_key_raw)

        ## make a copy of the previous key (if any) since
        ## we still need it to decrypt SHAREDKEY response
        ## etc
        self.session_keys[(self.session_key_id + 0) %
                          NUM_SESSION_KEYS] = self.aes_cipher_obj.get_key()
        self.session_keys[(self.session_key_id + 1) %
                          NUM_SESSION_KEYS] = aes_key_sig.digest()

        ## wrap around when we reach the largest allowed id
        self.session_key_id += 1
        self.session_key_id %= NUM_SESSION_KEYS

        print("[SETSHAREDKEY][time=%d::iter=%d] client_key_sig=%s" %
              (time.time(), self.iters,
               ENCODE_FUNC(SECURE_HASH_FUNC(aes_key_sig.digest()).digest())))

        ## when re-negotiating a key during an established session,
        ## reset_session_state() makes this false but we need it to
        ## be true temporarily to get the message out
        self.client_acked_shared_key = self.use_secure_session()

        ## ENCODE(ENCRYPT_RSA(AES_KEY, RSA_PUB_KEY))
        self.Send("SETSHAREDKEY %s" % aes_key_enc)

        self.client_acked_shared_key = False
        self.sent_unacked_shared_key = True
    def out_SETSHAREDKEY(self):
        assert self.received_public_key
        assert not self.sent_unacked_shared_key
        assert not self.server_valid_shared_key
        assert not self.client_acked_shared_key

        def generate_session_key(num_bytes=CryptoHandler.MIN_AES_KEY_SIZE * 2):
            ## encrypt converts its argument to a long, so the
            ## MSB should *always* be non-zero or D(E(K)) != K
            key_head = "\x00"
            key_tail = GLOBAL_RAND_POOL.read(num_bytes - 1)

            while ord(key_head) == 0:
                key_head = GLOBAL_RAND_POOL.read(1)

            return key_head + key_tail

            ## note: server will use HASH(RAW) as key and echo back HASH(HASH(RAW))
            ## hence we send ENCODE(ENCRYPT(RAW)) and use HASH(RAW) on our side too

        aes_key_raw = generate_session_key()
        aes_key_sig = SECURE_HASH_FUNC(aes_key_raw)
        aes_key_enc = self.rsa_cipher_obj.encrypt_encode_bytes(aes_key_raw)

        ## make a copy of the previous key (if any) since
        ## we still need it to decrypt SHAREDKEY response
        ## etc
        self.session_keys[(self.session_key_id + 0) % NUM_SESSION_KEYS] = self.aes_cipher_obj.get_key()
        self.session_keys[(self.session_key_id + 1) % NUM_SESSION_KEYS] = aes_key_sig.digest()

        ## wrap around when we reach the largest allowed id
        self.session_key_id += 1
        self.session_key_id %= NUM_SESSION_KEYS

        print (
            "[SETSHAREDKEY][time=%d::iter=%d] client_key_sig=%s"
            % (time.time(), self.iters, ENCODE_FUNC(SECURE_HASH_FUNC(aes_key_sig.digest()).digest()))
        )

        ## when re-negotiating a key during an established session,
        ## reset_session_state() makes this false but we need it to
        ## be true temporarily to get the message out
        self.client_acked_shared_key = self.use_secure_session()

        ## ENCODE(ENCRYPT_RSA(AES_KEY, RSA_PUB_KEY))
        self.Send("SETSHAREDKEY %s" % aes_key_enc)

        self.client_acked_shared_key = False
        self.sent_unacked_shared_key = True
Exemple #3
0
	def in_SHAREDKEY(self, key_status, key_digest, extra_data = ""):
		assert(self.received_public_key)
		assert(self.sent_unacked_shared_key)
		assert(not self.server_valid_shared_key)
		assert(not self.client_acked_shared_key)

		print("[SHAREDKEY][time=%d::iter=%d] %s %s %s" % (time.time(), self.iters, key_status, key_digest, extra_data))

		can_send_ack_shared_key = False

		if (key_status == "INITSESS"):
			## special case during first session-key exchange
			assert(not self.use_secure_session())
			assert(len(self.session_keys[self.session_key_id]) != 0)

			self.set_session_key(self.session_keys[self.session_key_id])
			return

		elif (key_status == "ACCEPTED"):
			server_key_sig = SAFE_DECODE_FUNC(key_digest)
			client_key_sha = SECURE_HASH_FUNC(self.session_keys[self.session_key_id])
			client_key_sig = client_key_sha.digest()

			print("\tserver_key_sig=%s\n\tclient_key_sig=%s (id=%d)" % (ENCODE_FUNC(server_key_sig), ENCODE_FUNC(client_key_sig), self.session_key_id))

			## server considers key valid and has accepted it
			## now check for data manipulation or corruption
			## before sending back our final acknowledgement
			self.server_valid_shared_key = True

			can_send_ack_shared_key = (server_key_sig == client_key_sig)

		elif (key_status == "DISABLED"):
			self.reset_session_state()
			self.set_session_key("")

			## never sent, no longer supported by server
			assert(False)
			return

		if (not can_send_ack_shared_key):
			## if this was triggered during an actual key RE-negotiation
			## (much more unlikely) the client's only option would be to
			## disconnect and initialize a new session
			assert(key_status != "ACCEPTED")

			self.sent_unacked_shared_key = False
			self.server_valid_shared_key = False
			self.client_acked_shared_key = False

			## try again with a new session key
			##
			## this assumes we did NOT get an ACCEPTED, which
			## would indicate data corruption or manipulation
			self.out_SETSHAREDKEY()
		else:
			## let server know it can begin sending secure data
			self.out_ACKSHAREDKEY()