From: Loup Vaillant Date: Wed, 26 Apr 2017 15:31:26 +0000 (+0200) Subject: added comparison tests with libsodium X-Git-Url: https://git.codecow.com/?a=commitdiff_plain;h=e42ee95db30f21704d685dae86084a89fd3b0d12;p=Monocypher.git added comparison tests with libsodium --- diff --git a/.gitignore b/.gitignore index 4dc4674..31bde7a 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ *.o *.gch test -speed_blake2b +sodium +rename_* diff --git a/makefile b/makefile index d096ad3..f09ea76 100644 --- a/makefile +++ b/makefile @@ -2,20 +2,44 @@ CC=gcc CFLAGS=-O2 -Wall -Wextra -std=c11 -pedantic .PHONY: all clean +# disable implicit rules +.SUFFIXES: -all: test +all: test sodium clean: - rm -f *.o *.gch test + rm -f *.o *.gch test rename_* -test: test.o monocypher.o sha512.o +# Test suite based on test vectors +test: test.c monocypher.o sha512.o $(CC) $(CFLAGS) -o $@ $^ -test.o: test.c - $(CC) $(CFLAGS) -c $^ +# Test suite based on comparison with libsodium +C_SODIUM_FLAGS=$$(pkg-config --cflags libsodium) +LD_SODIUM_FLAGS=$$(pkg-config --libs libsodium) +sodium: sodium.c rename_monocypher.o rename_sha512.o + $(CC) $(CFLAGS) -o $@ $^ $(C_SODIUM_FLAGS) $(LD_SODIUM_FLAGS) + +# compile monocypher +# use -DED25519_SHA512 for ed25519 compatibility +rename_monocypher.o: rename_monocypher.c rename_monocypher.h rename_sha512.h + $(CC) $(CFLAGS) -c $^ -DED25519_SHA512 +monocypher.o: monocypher.c monocypher.h sha512.h + $(CC) $(CFLAGS) -c $^ -DED25519_SHA512 +# compile sha512. Only used for ed15519 compatibility sha512.o: sha512.c sha512.h $(CC) $(CFLAGS) -c $^ +rename_sha512.o: rename_sha512.c rename_sha512.h + $(CC) $(CFLAGS) -c $^ -monocypher.o: monocypher.c monocypher.h - $(CC) $(CFLAGS) -c $^ -DED25519_SHA512 +# change the "crypto_" prefix to the "rename_" prefix, so you can use +# monocypher with other crypto libraries without conflict. +rename_%.c: %.c + sed 's/crypto_/rename_/g' <$^ >$@ + sed 's/monocypher.h/rename_monocypher.h/' -i $@ + sed 's/sha512.h/rename_sha512.h/' -i $@ +rename_%.h: %.h + sed 's/crypto_/rename_/g' <$^ >$@ + sed 's/monocypher.h/rename_monocypher.h/' -i $@ + sed 's/sha512.h/rename_sha512.h/' -i $@ diff --git a/monocypher.h b/monocypher.h index 1495c3d..e5a8f10 100644 --- a/monocypher.h +++ b/monocypher.h @@ -112,9 +112,9 @@ void crypto_x25519_public_key(uint8_t public_key[32], const uint8_t secret_key[32]); -/////////////// -/// Ed25519 /// -/////////////// +///////////// +/// EdDSA /// +///////////// void crypto_sign_public_key(uint8_t public_key[32], const uint8_t secret_key[32]); diff --git a/sodium.c b/sodium.c new file mode 100644 index 0000000..f2f5348 --- /dev/null +++ b/sodium.c @@ -0,0 +1,162 @@ +#include +#include +#include +#include "rename_monocypher.h" +#include "rename_sha512.h" +#include + +#define FOR(i, start, end) for (size_t (i) = (start); (i) < (end); (i)++) +#define sv static void +typedef int8_t i8; +typedef uint8_t u8; +typedef uint32_t u32; +typedef int32_t i32; +typedef int64_t i64; +typedef uint64_t u64; + +// Deterministic "random" number generator, so we can make "random", yet +// reproducible tests. To change the random stream, change the seed. +void random(u8 *stream, u8 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); +} + +static int chacha20(void) +{ + u8 key[32], nonce[8], in[256], mono[256], sodium[256]; + int status = 0; + FOR (size, 0, 256) FOR(i, 0, 10) { + random(key, 32); + random(nonce, 8); + random(in, size); + rename_chacha_ctx ctx; + rename_chacha20_init(&ctx, key, nonce); + rename_chacha20_encrypt(&ctx, mono, in, size); + crypto_stream_chacha20_xor(sodium, in, size, nonce, key); + status |= rename_memcmp(mono, sodium, size); + } + printf("%s: Chacha20\n", status != 0 ? "FAILED" : "OK"); + return status; +} + +static int poly1305(void) +{ + u8 key[32], in[256], mono[16], sodium[16]; + int status = 0; + FOR (size, 0, 256) FOR(i, 0, 10) { + random(key, 32); + random(in, size); + rename_poly1305_auth(mono, in, size, key); + crypto_onetimeauth(sodium, in, size, key); + status |= rename_memcmp(mono, sodium, 16); + } + printf("%s: Poly1305\n", status != 0 ? "FAILED" : "OK"); + return status; +} + +static int blake2b(void) +{ + u8 key[32], in[256], mono[64], sodium[64]; + int status = 0; + FOR (size, 0, 256) FOR(key_size, 0, 32) FOR(hash_size, 1, 64) { + random(key , key_size); + random(in , size); + rename_blake2b_general(mono, hash_size, key, key_size, in, size); + crypto_generichash(sodium, hash_size, in, size, key, key_size); + status |= rename_memcmp(mono, sodium, hash_size); + } + printf("%s: Blake2b\n", status != 0 ? "FAILED" : "OK"); + return status; +} + +static int argon2i(void) +{ + u8 work_area[1024*1024], password[16], salt[crypto_pwhash_SALTBYTES], + mono[32], sodium[32]; + int status = 0; + FOR (nb_blocks, 8, 1024) { + random(password, 16); + random(salt , 16); + rename_argon2i(mono, 32, work_area, nb_blocks, 3, + password, crypto_pwhash_SALTBYTES, salt, 16, 0, 0, 0, 0); + if (crypto_pwhash(sodium, 32, (char*)password, 16, salt, + 3, nb_blocks * 1024, crypto_pwhash_ALG_DEFAULT)) { + printf("Libsodium Argon2i failed to execute\n"); + } + status |= rename_memcmp(mono, sodium, 32); + } + printf("%s: Argon2i\n", status != 0 ? "FAILED" : "OK"); + return status; +} + +static int x25519() +{ + u8 sk1[32], pk1_mono[32], pk1_sodium[32]; + u8 sk2[32], pk2_mono[32], pk2_sodium[32]; + u8 shared_mono[32], shared_sodium[32]; + int status = 0; + FOR (i, 0, 255) { + random(sk1, 32); + random(sk2, 32); + rename_x25519_public_key(pk1_mono, sk1); + rename_x25519_public_key(pk2_mono, sk2); + crypto_scalarmult_base(pk1_sodium, sk1); + crypto_scalarmult_base(pk2_sodium, sk2); + rename_x25519 (shared_mono , sk1, pk2_mono); + if (crypto_scalarmult(shared_sodium, sk1, pk2_sodium)) { + printf("Libsodium scalarmult rejected the public key\n"); + } + status |= rename_memcmp(pk1_mono , pk1_sodium, 32); + status |= rename_memcmp(pk2_mono , pk2_sodium, 32); + status |= rename_memcmp(shared_mono, shared_sodium, 32); + } + printf("%s: x25519\n", status != 0 ? "FAILED" : "OK"); + return status; +} + +static int edDSA() +{ + u8 sk[32], sk_sodium[64], pk_mono[32], pk_sodium[32]; + u8 msg[255], sig_mono[64], sig_sodium[64]; + int status = 0; + FOR (size, 0, 255) { + // public keys + random(sk, 32); + rename_sign_public_key(pk_mono, sk); + crypto_sign_seed_keypair(pk_sodium, sk_sodium, sk); + status |= rename_memcmp(pk_mono, pk_sodium, 32); + // signatures + random(msg, size); + rename_sign(sig_mono, sk, pk_mono, msg, size); + crypto_sign_detached(sig_sodium, 0, msg, size, sk_sodium); + status |= rename_memcmp(sig_mono, sig_sodium, 64); + } + printf("%s: EdDSA\n", status != 0 ? "FAILED" : "OK"); + return status; +} + + +int main(void) +{ + if (sodium_init() == -1) { + printf("Libsodium init failed. Abort. No test performed\n"); + return 1; + } + int status = 0; + status |= chacha20(); + status |= poly1305(); + status |= blake2b(); + status |= argon2i(); + status |= x25519(); + status |= edDSA(); + printf(status ? "TESTS FAILED\n" : "ALL TESTS OK\n"); + return status; +}