Beispiel #1
0
    def recv_message(self, debug=False):
        """
        Reading socket and receiving message from server. Check the CRC32.
        """
        if debug:
            packet = self.sock.recv(1024)  # reads how many bytes to read
            hexdump(packet)

        packet_length_data = self.sock.recv(4)  # reads how many bytes to read

        if len(packet_length_data) < 4:
            raise Exception("Nothing in the socket!")
        packet_length = struct.unpack("<I", packet_length_data)[0]
        packet = self.sock.recv(packet_length -
                                4)  # read the rest of bytes from socket

        # check the CRC32
        if not crc32(packet_length_data + packet[0:-4]) == struct.unpack(
                '<I', packet[-4:])[0]:
            raise Exception("CRC32 was not correct!")
        x = struct.unpack("<I", packet[:4])
        auth_key_id = packet[4:12]
        if auth_key_id == b'\x00\x00\x00\x00\x00\x00\x00\x00':
            # No encryption - Plain text
            (message_id, message_length) = struct.unpack("<QI", packet[12:24])
            data = packet[24:24 + message_length]
        elif auth_key_id == self.auth_key_id:
            pass
            message_key = packet[12:28]
            encrypted_data = packet[28:-4]
            aes_key, aes_iv = self.aes_calculate(message_key,
                                                 direction="from server")
            decrypted_data = crypt.ige_decrypt(encrypted_data, aes_key, aes_iv)
            assert decrypted_data[0:8] == self.server_salt
            assert decrypted_data[8:16] == self.session_id
            message_id = decrypted_data[16:24]
            seq_no = struct.unpack("<I", decrypted_data[24:28])[0]
            message_data_length = struct.unpack("<I", decrypted_data[28:32])[0]
            data = decrypted_data[32:32 + message_data_length]
        else:
            raise Exception("Got unknown auth_key id")
        return data
Beispiel #2
0
    def recv_message(self, debug=False):
        """
        Reading socket and receiving message from server. Check the CRC32.
        """
        if debug:
            packet = self.sock.recv(1024)  # reads how many bytes to read
            hexdump(packet)

        packet_length_data = self.sock.recv(4)  # reads how many bytes to read

        if len(packet_length_data) < 4:
            raise Exception("Nothing in the socket!")
        packet_length = struct.unpack("<I", packet_length_data)[0]
        packet = self.sock.recv(packet_length - 4)  # read the rest of bytes from socket

        # check the CRC32
        if not crc32(packet_length_data + packet[0:-4]) == struct.unpack('<I', packet[-4:])[0]:
            raise Exception("CRC32 was not correct!")
        x = struct.unpack("<I", packet[:4])
        auth_key_id = packet[4:12]
        if auth_key_id == b'\x00\x00\x00\x00\x00\x00\x00\x00':
            # No encryption - Plain text
            (message_id, message_length) = struct.unpack("<QI", packet[12:24])
            data = packet[24:24+message_length]
        elif auth_key_id == self.auth_key_id:
            pass
            message_key = packet[12:28]
            encrypted_data = packet[28:-4]
            aes_key, aes_iv = self.aes_calculate(message_key, direction="from server")
            decrypted_data = crypt.ige_decrypt(encrypted_data, aes_key, aes_iv)
            assert decrypted_data[0:8] == self.server_salt
            assert decrypted_data[8:16] == self.session_id
            message_id = decrypted_data[16:24]
            seq_no = struct.unpack("<I", decrypted_data[24:28])[0]
            message_data_length = struct.unpack("<I", decrypted_data[28:32])[0]
            data = decrypted_data[32:32+message_data_length]
        else:
            raise Exception("Got unknown auth_key id")
        return data
Beispiel #3
0
    def create_auth_key(self):
        rand_nonce = os.urandom(16)
        req_pq = rpc.req_pq(rand_nonce).get_bytes()
        self.send_message(req_pq)
        resPQ = rpc.resPQ(self.recv_message())
        assert rand_nonce == resPQ.nonce

        public_key_fingerprint = resPQ.server_public_key_fingerprints[0]
        pq = bytes_to_long(resPQ.pq)

        [p, q] = prime.primefactors(pq)
        (p, q) = (q, p) if p > q else (p, q)
        assert p*q == pq and p < q

        print("Factorization %d = %d * %d" % (pq, p, q))

        p_bytes = long_to_bytes(p)
        q_bytes = long_to_bytes(q)
        key = RSA.importKey(self.rsa_key)
        new_nonce = os.urandom(32)

        p_q_inner_data = rpc.p_q_inner_data(pq=resPQ.pq, p=p_bytes, q=q_bytes,
                                            server_nonce=resPQ.server_nonce,
                                            nonce=resPQ.nonce,
                                            new_nonce=new_nonce)

        data = p_q_inner_data.get_bytes()
        assert p_q_inner_data.nonce == resPQ.nonce

        sha_digest = SHA.new(data).digest()
        random_bytes = os.urandom(255-len(data)-len(sha_digest))
        to_encrypt = sha_digest + data + random_bytes
        encrypted_data = key.encrypt(to_encrypt, 0)[0]

        req_DH_params = rpc.req_DH_params(p=p_bytes, q=q_bytes,
                                          nonce=resPQ.nonce,
                                          server_nonce=resPQ.server_nonce,
                                          public_key_fingerprint=public_key_fingerprint,
                                          encrypted_data=encrypted_data)
        data = req_DH_params.get_bytes()

        self.send_message(data)
        data = self.recv_message(debug=False)

        server_DH_params = rpc.server_DH_params(data)
        assert resPQ.nonce == server_DH_params.nonce
        assert resPQ.server_nonce == server_DH_params.server_nonce

        encrypted_answer = server_DH_params.encrypted_answer

        tmp_aes_key = SHA.new(new_nonce + resPQ.server_nonce).digest() + SHA.new(resPQ.server_nonce + new_nonce).digest()[0:12]
        tmp_aes_iv = SHA.new(resPQ.server_nonce + new_nonce).digest()[12:20] + SHA.new(new_nonce + new_nonce).digest() + new_nonce[0:4]

        answer_with_hash = crypt.ige_decrypt(encrypted_answer, tmp_aes_key, tmp_aes_iv)

        answer_hash = answer_with_hash[:20]
        answer = answer_with_hash[20:]

        server_DH_inner_data = rpc.server_DH_inner_data(answer)
        assert resPQ.nonce == server_DH_inner_data.nonce
        assert resPQ.server_nonce == server_DH_inner_data.server_nonce

        dh_prime_str = server_DH_inner_data.dh_prime
        g = server_DH_inner_data.g
        g_a_str = server_DH_inner_data.g_a
        server_time = server_DH_inner_data.server_time
        self.timedelta = server_time - time()

        dh_prime = bytes_to_long(dh_prime_str)
        g_a = bytes_to_long(g_a_str)

        assert prime.isprime(dh_prime)
        retry_id = 0
        b_str = os.urandom(256)
        b = bytes_to_long(b_str)
        g_b = pow(g, b, dh_prime)

        g_b_str = long_to_bytes(g_b)

        client_DH_inner_data = rpc.client_DH_inner_data(nonce=resPQ.nonce,
                                        server_nonce=resPQ.server_nonce,
                                        retry_id=retry_id,
                                        g_b=g_b_str)

        data = client_DH_inner_data.get_bytes()

        data_with_sha = SHA.new(data).digest()+data
        data_with_sha_padded = data_with_sha + os.urandom(-len(data_with_sha) % 16)
        encrypted_data = crypt.ige_encrypt(data_with_sha_padded, tmp_aes_key, tmp_aes_iv)

        for i in range(1, self.AUTH_MAX_RETRY): # retry when dh_gen_retry or dh_gen_fail
            set_client_DH_params = rpc.set_client_DH_params(nonce=resPQ.nonce,
                                                            server_nonce=resPQ.server_nonce,
                                                            encrypted_data=encrypted_data)
            self.send_message(set_client_DH_params.get_bytes())
            Set_client_DH_params_answer = rpc.set_client_DH_params_answer(self.recv_message())

            # print Set_client_DH_params_answer
            auth_key = pow(g_a, b, dh_prime)
            auth_key_str = long_to_bytes(auth_key)
            auth_key_sha = SHA.new(auth_key_str).digest()
            auth_key_aux_hash = auth_key_sha[:8]

            new_nonce_hash1 = SHA.new(new_nonce+b'\x01'+auth_key_aux_hash).digest()[-16:]
            new_nonce_hash2 = SHA.new(new_nonce+b'\x02'+auth_key_aux_hash).digest()[-16:]
            new_nonce_hash3 = SHA.new(new_nonce+b'\x03'+auth_key_aux_hash).digest()[-16:]

            assert Set_client_DH_params_answer.nonce == resPQ.nonce
            assert Set_client_DH_params_answer.server_nonce == resPQ.server_nonce

            if Set_client_DH_params_answer.status == 'ok':
                assert Set_client_DH_params_answer.new_nonce_hash == new_nonce_hash1
                print("Diffie Hellman key exchange processed successfully")

                self.server_salt = strxor(new_nonce[0:8], resPQ.server_nonce[0:8])
                self.auth_key = auth_key_str
                self.auth_key_id = auth_key_sha[-8:]
                print("Auth key generated")
                return "Auth Ok"
            elif Set_client_DH_params_answer.status == 'retry':
                assert Set_client_DH_params_answer.new_nonce_hash == new_nonce_hash2
                print ("Retry Auth")
            elif Set_client_DH_params_answer.status == 'fail':
                assert Set_client_DH_params_answer.new_nonce_hash == new_nonce_hash3
                print("Auth Failed")
                raise Exception("Auth Failed")
            else:
                raise Exception("Response Error")
Beispiel #4
0
    def create_auth_key(self):
        rand_nonce = os.urandom(16)
        req_pq = rpc.req_pq(rand_nonce).get_bytes()
        self.send_message(req_pq)
        resPQ = rpc.resPQ(self.recv_message())
        assert rand_nonce == resPQ.nonce

        public_key_fingerprint = resPQ.server_public_key_fingerprints[0]
        pq = bytes_to_long(resPQ.pq)

        [p, q] = prime.primefactors(pq)
        (p, q) = (q, p) if p > q else (p, q)
        assert p * q == pq and p < q

        print("Factorization %d = %d * %d" % (pq, p, q))

        p_bytes = long_to_bytes(p)
        q_bytes = long_to_bytes(q)
        key = RSA.importKey(self.rsa_key)
        new_nonce = os.urandom(32)

        p_q_inner_data = rpc.p_q_inner_data(pq=resPQ.pq,
                                            p=p_bytes,
                                            q=q_bytes,
                                            server_nonce=resPQ.server_nonce,
                                            nonce=resPQ.nonce,
                                            new_nonce=new_nonce)

        data = p_q_inner_data.get_bytes()
        assert p_q_inner_data.nonce == resPQ.nonce

        sha_digest = SHA.new(data).digest()
        random_bytes = os.urandom(255 - len(data) - len(sha_digest))
        to_encrypt = sha_digest + data + random_bytes
        encrypted_data = key.encrypt(to_encrypt, 0)[0]

        req_DH_params = rpc.req_DH_params(
            p=p_bytes,
            q=q_bytes,
            nonce=resPQ.nonce,
            server_nonce=resPQ.server_nonce,
            public_key_fingerprint=public_key_fingerprint,
            encrypted_data=encrypted_data)
        data = req_DH_params.get_bytes()

        self.send_message(data)
        data = self.recv_message(debug=False)

        server_DH_params = rpc.server_DH_params(data)
        assert resPQ.nonce == server_DH_params.nonce
        assert resPQ.server_nonce == server_DH_params.server_nonce

        encrypted_answer = server_DH_params.encrypted_answer

        tmp_aes_key = SHA.new(new_nonce + resPQ.server_nonce).digest(
        ) + SHA.new(resPQ.server_nonce + new_nonce).digest()[0:12]
        tmp_aes_iv = SHA.new(resPQ.server_nonce + new_nonce).digest(
        )[12:20] + SHA.new(new_nonce + new_nonce).digest() + new_nonce[0:4]

        answer_with_hash = crypt.ige_decrypt(encrypted_answer, tmp_aes_key,
                                             tmp_aes_iv)

        answer_hash = answer_with_hash[:20]
        answer = answer_with_hash[20:]

        server_DH_inner_data = rpc.server_DH_inner_data(answer)
        assert resPQ.nonce == server_DH_inner_data.nonce
        assert resPQ.server_nonce == server_DH_inner_data.server_nonce

        dh_prime_str = server_DH_inner_data.dh_prime
        g = server_DH_inner_data.g
        g_a_str = server_DH_inner_data.g_a
        server_time = server_DH_inner_data.server_time
        self.timedelta = server_time - time()

        dh_prime = bytes_to_long(dh_prime_str)
        g_a = bytes_to_long(g_a_str)

        assert prime.isprime(dh_prime)
        retry_id = 0
        b_str = os.urandom(256)
        b = bytes_to_long(b_str)
        g_b = pow(g, b, dh_prime)

        g_b_str = long_to_bytes(g_b)

        client_DH_inner_data = rpc.client_DH_inner_data(
            nonce=resPQ.nonce,
            server_nonce=resPQ.server_nonce,
            retry_id=retry_id,
            g_b=g_b_str)

        data = client_DH_inner_data.get_bytes()

        data_with_sha = SHA.new(data).digest() + data
        data_with_sha_padded = data_with_sha + os.urandom(
            -len(data_with_sha) % 16)
        encrypted_data = crypt.ige_encrypt(data_with_sha_padded, tmp_aes_key,
                                           tmp_aes_iv)

        for i in range(
                1,
                self.AUTH_MAX_RETRY):  # retry when dh_gen_retry or dh_gen_fail
            set_client_DH_params = rpc.set_client_DH_params(
                nonce=resPQ.nonce,
                server_nonce=resPQ.server_nonce,
                encrypted_data=encrypted_data)
            self.send_message(set_client_DH_params.get_bytes())
            Set_client_DH_params_answer = rpc.set_client_DH_params_answer(
                self.recv_message())

            # print Set_client_DH_params_answer
            auth_key = pow(g_a, b, dh_prime)
            auth_key_str = long_to_bytes(auth_key)
            auth_key_sha = SHA.new(auth_key_str).digest()
            auth_key_aux_hash = auth_key_sha[:8]

            new_nonce_hash1 = SHA.new(new_nonce + b'\x01' +
                                      auth_key_aux_hash).digest()[-16:]
            new_nonce_hash2 = SHA.new(new_nonce + b'\x02' +
                                      auth_key_aux_hash).digest()[-16:]
            new_nonce_hash3 = SHA.new(new_nonce + b'\x03' +
                                      auth_key_aux_hash).digest()[-16:]

            assert Set_client_DH_params_answer.nonce == resPQ.nonce
            assert Set_client_DH_params_answer.server_nonce == resPQ.server_nonce

            if Set_client_DH_params_answer.status == 'ok':
                assert Set_client_DH_params_answer.new_nonce_hash == new_nonce_hash1
                print("Diffie Hellman key exchange processed successfully")

                self.server_salt = strxor(new_nonce[0:8],
                                          resPQ.server_nonce[0:8])
                self.auth_key = auth_key_str
                self.auth_key_id = auth_key_sha[-8:]
                print("Auth key generated")
                return "Auth Ok"
            elif Set_client_DH_params_answer.status == 'retry':
                assert Set_client_DH_params_answer.new_nonce_hash == new_nonce_hash2
                print("Retry Auth")
            elif Set_client_DH_params_answer.status == 'fail':
                assert Set_client_DH_params_answer.new_nonce_hash == new_nonce_hash3
                print("Auth Failed")
                raise Exception("Auth Failed")
            else:
                raise Exception("Response Error")