# built-ins import secrets import timeit import statistics # third-party import pytest import timeit # internals import main # TODO: @pytest.mark.slow or something to exclude this test unless explicitly requested def test_sha3_timing(echo): User = main.admin.User User.delete().where(User.name == 'test').execute() password = secrets.token_hex(32) u = User.register('test', password) times = {} #repeats = 10000 repeats = 100000 stmt = "User.login('test', password)" t = timeit.Timer(stmt, globals=locals()) times['pw_correct'] = t.repeat(repeat=repeats, number=1) #for length in range(1, 32 + 1): #for length in [4, 8, 16, 32]: for length in [4, 32]: password_wrong = secrets.token_hex(length) stmt = "User.login('test', password_wrong)" t = timeit.Timer(stmt, globals=locals()) times[f'pw_incorrect_{length}'] = t.repeat(repeat=repeats, number=1) #for length in range(1, 32 + 1): #for length in [4, 8, 16, 32]: for length in [4, 32]: password_wrong = secrets.token_hex(length) stmt = "User.login('doesnotexist', password_wrong)" t = timeit.Timer(stmt, globals=locals()) times[f'user_incorrect_{length}'] = t.repeat(repeat=repeats, number=1) u.delete_instance() mins = [] maxs = [] spreads = [] means = [] medians = [] echo("Timing sidechannel test:") for key, timings in times.items(): mins.append(min(timings)) maxs.append(max(timings)) spreads.append(maxs[-1] - mins[-1]) means.append(statistics.mean(timings)) medians.append(statistics.median(timings)) echo(f"{key}: min {min(timings)}, max {max(timings)}, spread {max(timings) - min(timings)}, mean {statistics.mean(timings)}, median {statistics.median(timings)}") spread_min = max(mins) - min(mins) spread_max = max(maxs) - min(maxs) spread_spread = max(spreads) - min(spreads) spread_mean = max(means) - min(means) spread_median = max(medians) - min(medians) echo(f"spread min: {spread_min}") echo(f"spread max: {spread_max}") echo(f"spread spread: {spread_spread}") echo(f"spread mean: {spread_mean}") echo(f"spread median: {spread_median}") assert spread_min < 0.001, "spread for minimum execution time too large" assert spread_max < 0.001, "spread for maximum execution time too large" assert spread_spread < 0.001, "spread for execution time spread too large" assert spread_mean < 0.01, "spread for mean execution time too large" assert spread_median < 0.01, "spread for median execution time too large"