# Phase 3: Vehicle Access
# Time complexity tests
# Author: Norbert Lovinger; xlovin00@vutbr.cz
# Date: 16th May 2023

from Cryptodome.Hash import SHA3_256
from Cryptodome.PublicKey import RSA
from Cryptodome.Signature import pkcs1_15
import time

class Vehicle:
    def __init__(self, brand_name, number_plate):
        self.brand_name = brand_name
        self.number_plate = number_plate
    
    def sign(self, key):
        hash_obj = SHA3_256.new()
        hash_obj.update(f"{self.brand_name}:{self.number_plate}".encode())

        signature = pkcs1_15.new(key).sign(hash_obj)
        return signature
    
    def verify(self, signature, key):
        hash_obj = SHA3_256.new()
        hash_obj.update(f"{self.brand_name}:{self.number_plate}".encode())

        try:
            pkcs1_15.new(key).verify(hash_obj, signature)
            print("Signature verified successfully!")
            return True
        except ValueError:
            print("Signature not verified.")
            return False

class User:    
    def verify_vehicle(self, vehicle, signatures, key):
        hash_obj = SHA3_256.new()
        hash_obj.update(f"{vehicle.brand_name}:{vehicle.number_plate}".encode())
        for signature in signatures:
            try:
                pkcs1_15.new(key).verify(hash_obj, signature)
                print("Signature verified successfully!")
                return True
            except ValueError:
                continue

        print("The selected vehicle's signature could not be verified.")
        return False

# Generate the group signature keys
group_key = RSA.generate(4096)

# Create a user
user = User()

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

def test_sign():
    fleet = []
    for i in range(100):
        vehicle = Vehicle(f"Vehicle {i}", f"ID_00{i}")
        fleet.append(vehicle)

    signatures = []
    for vehicle in fleet:
        signature = vehicle.sign(group_key)
        signatures.append(signature)
vehicle_sign_time = average_time(test_sign,10)
print(f"Average time for signing 100 vehicle-fleet using RSA Group Signature: {vehicle_sign_time:.6f} milliseconds.")

fleets = []
for i in range(100):
    v = Vehicle(f"Vehicle {i}", f"ID_00{i}")
    fleets.append(v)
selected_v = fleets[99]
signs = []
for v in fleets:
    s = v.sign(group_key)
    signs.append(s)

def user_verify():    
    user.verify_vehicle(selected_v, signs, group_key.publickey())
vehicle_verify_time = average_time(user_verify,10)
print(f"Average time for verifying signature of 1 vehicle from 100 vehicles fleet: {vehicle_verify_time:.6f} milliseconds.")
