From: Loup Vaillant Date: Tue, 19 Sep 2017 22:16:25 +0000 (+0200) Subject: Restored the speed benchmark X-Git-Url: https://git.codecow.com/?a=commitdiff_plain;h=3c6285945252750f441740bf274f07cbfddb677e;p=Monocypher.git Restored the speed benchmark The benchmark now gives absolute speeds instead of comparisons against other libraries. This is more useful that way: the important information is whether Monocypher is fast *enough*. This also increases portability, so end users can actually run the benchmark themselves. Besides, we can always add Libsodium and TweetNaCl benchmarks later. --- diff --git a/dist/makefile b/dist/makefile index 0902d19..dff6525 100644 --- a/dist/makefile +++ b/dist/makefile @@ -21,16 +21,22 @@ CC=gcc -std=gnu99 # speed tests don't work with -std=cxx, they need the POSIX ex #TODO maybe just use the environment variable? CFLAGS= -pedantic -Wall -Wextra -O3 -march=native -g -.PHONY: all clean install test +.PHONY: all clean install test speed all: lib/libmonocypher.a lib/libmonocypher.so +clean: + rm -rf lib/ + rm -f *.out + +# TODO +# install: + test: test.out ./test.out -clean: - rm -rf lib/ - rm -f test.out +speed: speed.out + ./speed.out # Monocypher libraries lib/libmonocypher.a: lib/monocypher.o @@ -42,17 +48,16 @@ lib/%.o: src/%.c src/%.h @mkdir -p $(@D) $(CC) $(CFLAGS) -I src -fPIC -c -o $@ $< -# Test libraries +# Test & speed libraries lib/utils.o: tests/utils.c tests/utils.h - @mkdir -p $(@D) - $(CC) $(CFLAGS) -I src -fPIC -c -o $@ $< -lib/test.o: tests/test.c tests/utils.h \ - tests/vectors.h \ - src/monocypher.h \ - src/sha512.h +lib/test.o : tests/test.c tests/utils.h src/monocypher.h src/sha512.h tests/vectors.h +lib/speed.o: tests/speed.c tests/utils.h src/monocypher.h src/sha512.h +lib/utils.o lib/test.o lib/speed.o: @mkdir -p $(@D) $(CC) $(CFLAGS) -I src -fPIC -c -o $@ $< -# test executable -test.out: lib/test.o lib/monocypher.o lib/sha512.o lib/utils.o +# test & speed executables +test.out : lib/test.o lib/monocypher.o lib/sha512.o lib/utils.o +speed.out: lib/speed.o lib/monocypher.o lib/sha512.o lib/utils.o +test.out speed.out: $(CC) $(CFLAGS) -I src -o $@ $^ diff --git a/dist/tests/speed.c b/dist/tests/speed.c index 63bb3f8..3ce663b 100644 --- a/dist/tests/speed.c +++ b/dist/tests/speed.c @@ -9,25 +9,41 @@ typedef struct timespec timespec; // TODO: provide a user defined buffer size -#define SIZE (1024 * 1024) +#define KILOBYTE 1024 +#define MEGABYTE (1024 * KILOBYTE) +#define SIZE MEGABYTE +#define DIVIDER (MEGABYTE / SIZE) -// TODO: provide a Mb/s absolute speed -speed_t speed(timespec ref, timespec t) +timespec diff(timespec start, timespec end) { - u64 ref_u = ref.tv_sec * 1000000000 + ref.tv_nsec; - u64 t_u = t .tv_sec * 1000000000 + t .tv_nsec; - speed_t s; - s.ratio = (100 * ref_u) / t_u; // assuming t_u is never zero - s.time = t_u ; - s.ref = ref_u ; - return s; + timespec duration; + duration.tv_sec = end.tv_sec - start.tv_sec; + duration.tv_nsec = end.tv_nsec - start.tv_nsec; + if (duration.tv_nsec < 0) { + duration.tv_nsec += 1000000000; + duration.tv_sec -= 1; + } + return duration; +} + +timespec min(timespec a, timespec b) +{ + if (a.tv_sec < b.tv_sec || + (a.tv_sec == b.tv_sec && a.tv_nsec < b.tv_nsec)) { + return a; + } + return b; +} + +u64 speed(timespec duration) +{ + static const u64 giga = 1000000000; + return giga / (duration.tv_nsec + duration.tv_sec * giga); } -static void print(const char *name, speed_t result, const char *lib_name) +static void print(const char *name, u64 speed, const char *unit) { - printf("%s: %4d Mb/s vs %4d Mb/s\n", name, - 1000000 / result.time, - 1000000 / result.ref); + printf("%s: %4" PRIu64 " %s\n", name, speed, unit); } // TODO: adjust this crap @@ -39,109 +55,121 @@ static void print(const char *name, speed_t result, const char *lib_name) timespec duration; \ duration.tv_sec = 3600 * 24; \ duration.tv_nsec = 0; \ - FOR (i, 0, 30) { \ + FOR (i, 0, 50) { \ TIMESTAMP(start); -#define TIMING_END(duration) \ +#define TIMING_END \ TIMESTAMP(end); \ - duration = min(diff(start, end), duration); \ - } + duration = diff(start, end); \ + } /* end FOR*/ \ + return speed(duration) -#define TIMING_RESULT(name, result_size) \ - if (crypto_memcmp(mono, sodium, result_size) != 0) { \ - printf(name " benchmark failed (different results)\n"); \ - } \ - return speed(libsodium, monocypher) - -static speed_t chacha20(void) +static u64 chacha20(void) { static u8 in [SIZE]; p_random(in , SIZE); static u8 key [ 32]; p_random(key , 32); static u8 nonce [ 8]; p_random(nonce, 8); - static u8 mono [SIZE]; + static u8 out [SIZE]; TIMING_START { crypto_chacha_ctx ctx; crypto_chacha20_init(&ctx, key, nonce); - crypto_chacha20_encrypt(&ctx, mono, in, SIZE); + crypto_chacha20_encrypt(&ctx, out, in, SIZE); + } + TIMING_END; +} + +static u64 poly1305(void) +{ + static u8 in [SIZE]; p_random(in , SIZE); + static u8 key [ 32]; p_random(key , 32); + static u8 out [ 16]; + + TIMING_START { + crypto_poly1305_auth(out, in, SIZE, key); } TIMING_END; } -static speed_t poly1305(void) +static u64 authenticated(void) { static u8 in [SIZE]; p_random(in , SIZE); static u8 key [ 32]; p_random(key , 32); - static u8 mono [ 16]; + static u8 nonce [ 8]; p_random(nonce, 8); + static u8 out [SIZE]; + static u8 mac [ 16]; TIMING_START { - crypto_poly1305_auth(mono, in, SIZE, key); + crypto_lock(mac, out, key, nonce, in, SIZE); } TIMING_END; } -static speed_t blake2b(void) +static u64 blake2b(void) { - static u8 in [SIZE]; p_random(in , SIZE); - static u8 key [ 32]; p_random(key, 32); - static u8 mono [ 64]; + static u8 in [SIZE]; p_random(in , SIZE); + static u8 key [ 32]; p_random(key, 32); + static u8 hash[ 64]; - TIMING_START(monocypher) { - crypto_blake2b_general(mono, 64, key, 32, in, SIZE); + TIMING_START { + crypto_blake2b_general(hash, 64, key, 32, in, SIZE); } TIMING_END; } -// TODO: don't just rely on SIZE, add a HARDNESS parameter -static speed_t argon2i(void) +static u64 argon2i(void) { - size_t nb_blocks = SIZE / 1024; - static u8 work_area[SIZE]; - static u8 password [ 16]; p_random(password, 16); - static u8 salt [ 16]; p_random(salt , 16); - static u8 mono [ 32]; + size_t nb_blocks = 1024; + static u8 work_area[MEGABYTE]; + static u8 password [ 16]; p_random(password, 16); + static u8 salt [ 16]; p_random(salt , 16); + static u8 hash [ 32]; TIMING_START { - crypto_argon2i(mono, 32, work_area, nb_blocks, 3, + crypto_argon2i(hash, 32, work_area, nb_blocks, 3, password, 16, salt, 16, 0, 0, 0, 0); } TIMING_END; } -// TODO: change TIMING_END to print scalarmult per second -static speed_t x25519(void) +static u64 x25519(void) { - u8 mono_in [32] = {9}; - u8 mono [32] = {9}; + u8 in [32] = {9}; + u8 out [32] = {9}; TIMING_START { - if (crypto_x25519(mono, mono, mono_in)) { + if (crypto_x25519(out, out, in)) { printf("Monocypher x25519 rejected public key\n"); } } TIMING_END; } -// TODO: change TIMING_END to print signature/check per second -static void ed25519(void) +static u64 edDSA_sign(void) { - u8 sk [32]; p_random(sk, 32); - u8 pk [64]; - crypto_sign_seed_keypair(pk, sk_sodium, sk); + u8 sk [32]; p_random(sk, 32); + u8 pk [32]; crypto_sign_public_key(pk, sk); + u8 message [64]; p_random(message, 64); + u8 signature [64]; - u8 message [64]; p_random(message, 64); - u8 mono_sig [64]; - - // Signature speed TIMING_START { - crypto_sign(mono_sig, sk, pk, message, 64); + crypto_sign(signature, sk, pk, message, 64); } TIMING_END; +} + +static u64 edDSA_check(void) +{ + u8 sk [32]; p_random(sk, 32); + u8 pk [32]; crypto_sign_public_key(pk, sk); + u8 message [64]; p_random(message, 64); + u8 signature [64]; - // Verification speed (for correct signatures) - TIMING_START(monocypher_chk) { - if (crypto_check(mono_sig, pk, message, 64)) { + crypto_sign(signature, sk, pk, message, 64); + + TIMING_START { + if (crypto_check(signature, pk, message, 64)) { printf("Monocypher verification failed\n"); } } @@ -150,13 +178,14 @@ static void ed25519(void) int main() { - chacha20(); - poly1305(); - blake2b(); - argon2i(); - x25519(); - ed25519(); - + print("Chacha20 ", chacha20() / DIVIDER, "Mb/s" ); + print("Poly1305 ", poly1305() / DIVIDER, "Mb/s" ); + print("Auth'd encryption", authenticated() / DIVIDER, "Mb/s" ); + print("Blake2b ", blake2b() / DIVIDER, "Mb/s" ); + print("Argon2i ", argon2i() , "Mb/s (3 passes)" ); + print("x25519 ", x25519() , "exchanges per second"); + print("EdDSA(sign) ", edDSA_sign() , "signatures per second"); + print("EdDSA(check) ", edDSA_check() , "checks per second"); printf("\n"); return 0; }