# Phase 1: User Authentication
# Time complexity tests
# Author: Norbert Lovinger; xlovin00@vutbr.cz
# Date: 16th May 2023

import time
import hashlib
from pqcrypto.sign.dilithium4 import generate_keypair, sign as dsign, verify as dverify
from dataclasses import dataclass

@dataclass
class ABC:
    issuer: str
    attributes: dict
    signature = None

    def sign(self, secret_key):
        h = f"{self.issuer}:{self.attributes}"
        hashed = hashlib.sha3_256(h.encode()).digest()
        message = bytes(hashed)
        self.signature = dsign(secret_key,message)

    def verify(self, public_key):
        h = f"{self.issuer}:{self.attributes}"
        hashed = hashlib.sha3_256(h.encode()).digest()
        return dverify(public_key,hashed,self.signature)

@dataclass
class User:
    name: str
    email: str
    phone: str
    age: int
    driving_license: str

    def pseudonymize(self):
        self.name = hashlib.sha3_256(self.name.encode()).hexdigest()
        self.email = hashlib.sha3_256(self.email.encode()).hexdigest()
        self.phone = hashlib.sha3_256(self.phone.encode()).hexdigest()

    def get_attributes(self):
        return {
            'age': self.age,
            'driving_license': self.driving_license,
            'name': self.name,
            'email': self.email,
            'phone': self.phone
        }

@dataclass
class ServiceOperator:
    name: str
    public_key = None
    secret_key = None

    def verify(self, user, abc):
        user.pseudonymize()

        if not abc.verify(self.public_key):
            print(f"Verification unsuccessful: Invalid signature.")
            return      

        if user.age >= 18 and user.driving_license == 'valid':
            print(f"Verification successful for user {user.name} by service {self.name}.")
        else:
            print(f"Verification unsuccessful for user {user.name} by service {self.name}.")

    def generate_keys(self):
        public_key, secret_key = generate_keypair()
        self.public_key = public_key
        self.secret_key = secret_key

# Performance tests
def average_time(func):
    total_time = 0
    for i in range(10000):
        start_time = time.time()
        func()
        end_time = time.time()
        total_time += end_time - start_time
    return total_time / 10000

def test_pseudonymize():
    user = User('Norbert Lovinger', 'xlovin00@vutbr.cz', '+1234567890', 25, 'valid')
    user.pseudonymize()
pseudonymize_time = average_time(test_pseudonymize)

def test_sign():
        user = User('Norbert Lovinger', 'xlovin00@vutbr.cz', '+1234567890', 25, 'valid')
        service = ServiceOperator('Car Sharing Service')
        service.generate_keys()      
        hashed = hashlib.sha3_256(str(user.age).encode() + user.driving_license.encode()).digest()
        message = bytes(hashed)
        signature_verify = dsign(service.secret_key,message)
pqsign_time = average_time(test_sign)

def test_verify():
        user = User('Norbert Lovinger', 'xlovin00@vutbr.cz', '+1234567890', 25, 'valid')
        service = ServiceOperator('Car Sharing Service')
        service.generate_keys()
        abc = ABC('Example Issuer', user.get_attributes())
        abc.sign(service.secret_key)
        hashed = hashlib.sha3_256(str(user.age).encode() + user.driving_license.encode()).digest()
        dverify(service.public_key,hashed,abc.signature)
verify_time = average_time(test_verify)

print(f"Average time for pseudonymize user data: {pseudonymize_time:.6f} milliseconds.")
print(f"Average time for PQ sign: {pqsign_time:.6f} milliseconds.")
print(f"Average time for PQ verify: {verify_time:.6f} milliseconds.")