]> git.codecow.com Git - Monocypher.git/commitdiff
added speed benchmark against libsodium
authorLoup Vaillant <loup@loup-vaillant.fr>
Thu, 6 Jul 2017 19:57:17 +0000 (21:57 +0200)
committerLoup Vaillant <loup@loup-vaillant.fr>
Thu, 6 Jul 2017 19:57:17 +0000 (21:57 +0200)
.gitignore
makefile
tests/speed.c [new file with mode: 0644]

index 8614aa6199a6f6c41c63fbfef2c59f8775889ec5..dc1b95e0562de09540a98b90eb30997eeae81fc9 100644 (file)
@@ -9,4 +9,5 @@ properties
 vectors
 sodium
 donna
+speed
 rename_*
index 6d377d0c2125a6a0b71e52dc796a6f5e3690dc3d..0b22e37bdfda20f41f31a287f124b08615cadd18 100644 (file)
--- a/makefile
+++ b/makefile
@@ -1,5 +1,6 @@
 # compile with any of the following
-CC=gcc -std=c99
+CC=gcc -std=gnu99
+#CC=gcc -std=c99
 #CC=gcc -std=c11
 #CC=g++ -std=c++98
 #CC=g++ -std=c++11
@@ -60,6 +61,10 @@ LD_SODIUM_FLAGS=$$(pkg-config --libs libsodium)
 sodium: tests/sodium.c bin/rename_monocypher.o bin/rename_sha512.o
        $(CC) $(CFLAGS) -o $@ $^ $(C_SODIUM_FLAGS) $(LD_SODIUM_FLAGS)
 
+# Speed benchmark
+speed: tests/speed.c bin/rename_monocypher.o bin/rename_sha512.o
+       $(CC) $(CFLAGS) -o $@ $^ $(C_SODIUM_FLAGS) $(LD_SODIUM_FLAGS)
+
 # Test edDSA/blake2b by comparing with the donna implementation
 # Note: we're using Blake2b, the default hash for monocypher edDSA
 donna: tests/donna.c bin/classic_monocypher.o bin/donna.o
diff --git a/tests/speed.c b/tests/speed.c
new file mode 100644 (file)
index 0000000..f6a2715
--- /dev/null
@@ -0,0 +1,275 @@
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sodium.h>
+#include "rename_monocypher.h"
+
+#define FOR(i, start, end) for (size_t (i) = (start); (i) < (end); (i)++)
+typedef uint8_t u8;
+typedef uint64_t u64;
+typedef struct timespec timespec;
+
+#define SIZE (1024 * 1024 * 4)
+
+// Deterministic "random" number generator, so we can make "random", yet
+// reproducible tests.  To change the random stream, change the seed.
+void p_random(u8 *stream, size_t size)
+{
+    static rename_chacha_ctx ctx;
+    static int is_init = 0;
+    if (!is_init) {
+        static const u8 seed[32] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+                                    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+        rename_chacha20_init(&ctx, seed, seed);
+        is_init = 1;
+    }
+    rename_chacha20_stream(&ctx, stream, size);
+}
+
+timespec diff(timespec start, timespec end)
+{
+    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;
+}
+
+int speed(timespec ref, timespec t)
+{
+    u64 ref_u = ref.tv_sec * 1000000000 + ref.tv_nsec;
+    u64 t_u   = t  .tv_sec * 1000000000 + t  .tv_nsec;
+    return (100 * ref_u) / t_u; // assuming t_u is never zero
+}
+
+#define TIMESTAMP(t)                            \
+    timespec t;                                 \
+    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t)
+
+#define TIMING_START(duration)                      \
+    timespec duration; duration.tv_sec = 3600 * 24; \
+    FOR (i, 0, 10) {                                \
+        TIMESTAMP(start)
+
+#define TIMING_END(duration)                    \
+    TIMESTAMP(end);                             \
+    duration = min(diff(start, end), duration); \
+    }                                           \
+
+#define TIMING_RESULT(name, result_size)                          \
+    if (rename_memcmp(mono, sodium, result_size) != 0) {          \
+        printf(name " benchmark failed (different results)\n");   \
+    }                                                             \
+    return speed(libsodium, monocypher)
+
+
+static int 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  sodium[SIZE];
+
+    TIMING_START(monocypher);
+    rename_chacha_ctx ctx;
+    rename_chacha20_init(&ctx, key, nonce);
+    rename_chacha20_encrypt(&ctx, mono, in, SIZE);
+    TIMING_END(monocypher);
+
+    TIMING_START(libsodium);
+    crypto_stream_chacha20_xor(sodium, in, SIZE, nonce, key);
+    TIMING_END(libsodium);
+
+    TIMING_RESULT("Chacha20", SIZE);
+}
+
+static int poly1305(void)
+{
+    static u8  in    [SIZE];  p_random(in   , SIZE);
+    static u8  key   [  32];  p_random(key  ,   32);
+    static u8  mono  [  16];
+    static u8  sodium[  16];
+
+    TIMING_START(monocypher);
+    rename_poly1305_auth(mono, in, SIZE, key);
+    TIMING_END(monocypher);
+
+    TIMING_START(libsodium);
+    crypto_onetimeauth(sodium, in, SIZE, key);
+    TIMING_END(libsodium);
+
+    TIMING_RESULT("Poly1305", 16);
+}
+
+static int blake2b(void)
+{
+    static u8 in    [SIZE];  p_random(in , SIZE);
+    static u8 key   [  32];  p_random(key,   32);
+    static u8 mono  [  64];
+    static u8 sodium[  64];
+
+    TIMING_START(monocypher);
+    rename_blake2b_general(mono, 64, key, 32, in, SIZE);
+    TIMING_END(monocypher);
+
+    TIMING_START(libsodium);
+    crypto_generichash(sodium, 64, in, SIZE, key, 32);
+    TIMING_END(libsodium);
+
+    TIMING_RESULT("Blake2b", 64);
+}
+
+static int argon2i(void)
+{
+    size_t    nb_blocks = SIZE / 1024;
+    static u8 work_area[SIZE];
+    static u8 password [  16];  p_random(password, 32);
+    static u8 salt     [  16];  p_random(salt    , 32);
+    static u8 mono     [  32];
+    static u8 sodium   [  32];
+
+    TIMING_START(monocypher);
+    rename_argon2i(mono, 32, work_area, nb_blocks, 3,
+                   password, 16, salt, 16, 0, 0, 0, 0);
+    TIMING_END(monocypher);
+
+    TIMING_START(libsodium);
+    if (crypto_pwhash(sodium, 32, (char*)password, 16, salt,
+                      3, nb_blocks * 1024, crypto_pwhash_ALG_DEFAULT)) {
+        printf("Libsodium Argon2i failed to execute\n");
+    }
+    TIMING_END(libsodium);
+
+    TIMING_RESULT("Argon2i", 32);
+}
+
+static int x25519(void)
+{
+    u8 mono_in  [32] = {9};
+    u8 mono     [32] = {9};
+    u8 sodium_in[32] = {9};
+    u8 sodium   [32] = {9};
+
+    TIMING_START(monocypher);
+    FOR (i, 0, 250) {
+        u8 tmp[32];
+        if (rename_x25519(tmp, mono, mono_in)) {
+            printf("Monocypher x25519 rejected public key\n");
+        }
+        FOR (i, 0, 32) { mono_in[i] = mono[i]; }
+        FOR (i, 0, 32) { mono   [i] = tmp [i]; }
+    }
+    TIMING_END(monocypher);
+
+    TIMING_START(libsodium);
+    FOR (i, 0, 250) {
+        u8 tmp[32];
+        if (crypto_scalarmult(tmp, sodium, sodium_in)) {
+            printf("Libsodium x25519 rejected public key\n");
+        }
+        FOR (i, 0, 32) { sodium_in[i] = sodium[i]; }
+        FOR (i, 0, 32) { sodium   [i] = tmp   [i]; }
+    }
+    TIMING_END(libsodium);
+
+    TIMING_RESULT("x25519", 32);
+}
+
+static int ed25519(void)
+{
+    u8 sk       [32];   p_random(sk, 32);
+    u8 sk_sodium[64];
+    u8 pk       [64];
+    crypto_sign_seed_keypair(pk, sk_sodium, sk);
+
+    u8 mono_in  [64] = {9};
+    u8 sodium_in[64] = {9};
+    u8 mono     [64];
+    u8 sodium   [64];
+
+    TIMING_START(monocypher);
+    FOR (i, 0, 250) {
+        rename_sign(mono, sk, pk, mono_in, 64);
+        FOR (i, 0, 64) { mono_in[i] = mono[i]; }
+    }
+    TIMING_END(monocypher);
+
+    TIMING_START(libsodium);
+    FOR (i, 0, 250) {
+        crypto_sign_detached(sodium, 0, sodium_in, 64, sk_sodium);
+        FOR (i, 0, 64) { sodium_in[i] = sodium[i]; }
+    }
+    TIMING_END(libsodium);
+
+    TIMING_RESULT("ed25519", 64);
+}
+
+static int ed_check(void)
+{
+    u8 sk       [32];  p_random(sk, 32);
+    u8 sk_sodium[64];
+    u8 pk       [64];
+    crypto_sign_seed_keypair(pk, sk_sodium, sk);
+
+    u8 input    [64];  p_random(input, 32);
+    u8 mono     [1] = {0};
+    u8 sodium   [1] = {0};
+
+    TIMING_START(monocypher);
+    FOR (i, 0, 250) {
+        if (rename_check(input, pk, input, 64)) {
+            mono[0]++;
+        }
+    }
+    TIMING_END(monocypher);
+
+    TIMING_START(libsodium);
+    FOR (i, 0, 250) {
+        if (crypto_sign_verify_detached(input, input, 64, pk)) {
+            sodium[0]++;
+        }
+    }
+    TIMING_END(libsodium);
+
+    TIMING_RESULT("ed_check", 1);
+}
+
+static void print(const char *name, int result)
+{
+    printf("%s: ", name);
+    if (result == 100) {
+        printf("As fast as Libsodium\n");
+    } else if (result <  100) {
+        printf("%d%% slower than Libsodium\n" , 100 - result);
+    }
+    else {
+        printf("%d%% FASTER than Libsodium!!\n", result - 100);
+    }
+}
+
+
+int main()
+{
+    print("Chacha20", chacha20());
+    print("Poly1305", poly1305());
+    print("Blake2b ", blake2b ());
+    print("Argon2i ", argon2i ());
+    print("x25519  ", x25519  ());
+    print("ed25519 ", ed25519 ());
+    print("ed_check", ed_check());
+    return 0;
+}