From 9e87006a9b8aedae8b59fd41610ffb68a52f00bb Mon Sep 17 00:00:00 2001 From: Bogdan Opanchuk Date: Fri, 19 Mar 2021 15:53:35 -0700 Subject: [PATCH] Add back performance tests --- tests/metrics/reencryption_benchmark.py | 102 ++++++++++++++++++++++++ tests/metrics/reencryption_firehose.py | 54 +++++++++++++ 2 files changed, 156 insertions(+) create mode 100644 tests/metrics/reencryption_benchmark.py create mode 100644 tests/metrics/reencryption_firehose.py diff --git a/tests/metrics/reencryption_benchmark.py b/tests/metrics/reencryption_benchmark.py new file mode 100644 index 0000000..3476ad0 --- /dev/null +++ b/tests/metrics/reencryption_benchmark.py @@ -0,0 +1,102 @@ +import os +import time + +import pytest + +import umbral as umbral_py +import umbral_pre as umbral_rs + + +# Faster +# (M, N) # | +FRAG_VALUES = ((1, 1), # | + (2, 3), # | + (5, 8), # | + (6, 10), # | + (10, 30), # | + # (20, 30), # | # FIXME: CircleCi build killed + # (10, 100) # | + # | + ) # | +# Slower + + +def __standard_encryption_api(umbral) -> tuple: + + delegating_sk = umbral.SecretKey.random() + delegating_pk = umbral.PublicKey.from_secret_key(delegating_sk) + + signing_sk = umbral.SecretKey.random() + + receiving_sk = umbral.SecretKey.random() + receiving_pk = umbral.PublicKey.from_secret_key(receiving_sk) + + plain_data = os.urandom(32) + capsule, ciphertext = umbral.encrypt(delegating_pk, plain_data) + + return delegating_sk, receiving_pk, signing_sk, ciphertext, capsule + + +# +# KFrag Generation Benchmarks +# + + +@pytest.mark.benchmark(group="Reencryption Key Generation Performance", + disable_gc=True, + warmup=True, + warmup_iterations=10) +@pytest.mark.parametrize("m, n", FRAG_VALUES) +@pytest.mark.parametrize("umbral", [umbral_py, umbral_rs], ids=["python", "rust"]) +def test_generate_kfrags_performance(benchmark, m: int, n: int, umbral) -> None: + + def __setup(): + delegating_sk, receiving_pk, signing_sk, ciphertext, capsule = __standard_encryption_api(umbral) + return (delegating_sk, receiving_pk, signing_sk, m, n, True, True), {} + + benchmark.pedantic(umbral.generate_kfrags, setup=__setup, rounds=1000) + assert True # ensure function finishes and succeeds. + + +# +# Reencryption Benchmarks +# + +@pytest.mark.benchmark(group="Reencryption Performance", + timer=time.perf_counter, + disable_gc=True, + warmup=True, + warmup_iterations=10) +@pytest.mark.parametrize("m, n", ((6, 10), )) +@pytest.mark.parametrize("umbral", [umbral_py, umbral_rs], ids=["python", "rust"]) +def test_random_frag_reencryption_performance(benchmark, m: int, n: int, umbral) -> None: + + def __setup(): + delegating_sk, receiving_pk, signing_sk, ciphertext, capsule = __standard_encryption_api(umbral) + kfrags = umbral.generate_kfrags(delegating_sk, receiving_pk, signing_sk, m, n, True, True) + one_kfrag, *remaining_kfrags = kfrags + return (capsule, one_kfrag), {} + + benchmark.pedantic(umbral.reencrypt, setup=__setup, rounds=1000) + assert True # ensure function finishes and succeeds. + + +@pytest.mark.benchmark(group="Reencryption Performance", + timer=time.perf_counter, + disable_gc=True, + min_time=0.00005, + max_time=0.005, + min_rounds=7, + warmup=True, + warmup_iterations=10) +@pytest.mark.parametrize("m, n", ((6, 10), )) +@pytest.mark.parametrize("umbral", [umbral_py, umbral_rs], ids=["python", "rust"]) +def test_single_frag_reencryption_performance(benchmark, m: int, n: int, umbral) -> None: + + delegating_sk, receiving_pk, signing_sk, ciphertext, capsule = __standard_encryption_api(umbral) + kfrags = umbral.generate_kfrags(delegating_sk, receiving_pk, signing_sk, m, n, True, True) + one_kfrag, *remaining_kfrags = kfrags + args, kwargs = (capsule, one_kfrag), {} + + benchmark.pedantic(umbral.reencrypt, args=args, kwargs=kwargs, iterations=20, rounds=100) + assert True # ensure function finishes and succeeds. diff --git a/tests/metrics/reencryption_firehose.py b/tests/metrics/reencryption_firehose.py new file mode 100644 index 0000000..defe6be --- /dev/null +++ b/tests/metrics/reencryption_firehose.py @@ -0,0 +1,54 @@ +import os +import sys + +sys.path.append(os.path.abspath(os.getcwd())) + +from typing import Tuple, List + +import umbral + + +REENCRYPTIONS = 1000 + + +def __produce_kfrags_and_capsule(m: int, n: int) -> Tuple[List[umbral.KeyFrag], umbral.Capsule]: + + delegating_sk = umbral.SecretKey.random() + delegating_pk = umbral.PublicKey.from_secret_key(delegating_sk) + + signing_sk = umbral.SecretKey.random() + + receiving_sk = umbral.SecretKey.random() + receiving_pk = umbral.PublicKey.from_secret_key(receiving_sk) + + plain_data = os.urandom(32) + capsule, ciphertext = umbral.encrypt(delegating_pk, plain_data) + + kfrags = umbral.generate_kfrags(delegating_sk, receiving_pk, signing_sk, m, n) + + return kfrags, capsule + + +def firehose(m: int=6, n: int=10) -> None: + + print("Making kfrags...") + kfrags, capsule = __produce_kfrags_and_capsule(m=m, n=n) + one_kfrag, *remaining_kfrags = kfrags + + print('Re-encrypting...') + successful_reencryptions = 0 + for iteration in range(int(REENCRYPTIONS)): + + _cfrag = umbral.reencrypt(capsule, one_kfrag) # <<< REENCRYPTION HAPPENS HERE + + successful_reencryptions += 1 + if iteration % 20 == 0: + print('Performed {} Re-encryptions...'.format(iteration)) + + failure_message = "A Reencryption failed. {} of {} succeeded".format(successful_reencryptions, REENCRYPTIONS) + assert successful_reencryptions == REENCRYPTIONS, failure_message + print("Successfully performed {} reencryptions".format(successful_reencryptions), end='\n') + + +if __name__ == "__main__": + firehose() # do