diff --git a/src/ed25519.h b/src/ed25519.h index 8924659..ec27282 100644 --- a/src/ed25519.h +++ b/src/ed25519.h @@ -30,6 +30,10 @@ int ED25519_DECLSPEC ed25519_verify(const unsigned char *signature, const unsign void ED25519_DECLSPEC ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, const unsigned char *scalar); void ED25519_DECLSPEC ed25519_key_exchange(unsigned char *shared_secret, const unsigned char *public_key, const unsigned char *private_key); +void * ED25519_DECLSPEC ed25519_verify_begin(const unsigned char *signature, const unsigned char *public_key); +void ED25519_DECLSPEC ed25519_verify_update(void * hash, const unsigned char *message, size_t message_len); +int ED25519_DECLSPEC ed25519_verify_end(void * hash, const unsigned char *signature); + #ifdef __cplusplus } diff --git a/src/verify.c b/src/verify.c index 32f988e..d1b1ad8 100644 --- a/src/verify.c +++ b/src/verify.c @@ -1,3 +1,6 @@ +#include +#include + #include "ed25519.h" #include "sha512.h" #include "ge.h" @@ -64,7 +67,7 @@ int ed25519_verify(const unsigned char *signature, const unsigned char *message, sha512_update(&hash, public_key, 32); sha512_update(&hash, message, message_len); sha512_final(&hash, h); - + sc_reduce(h); ge_double_scalarmult_vartime(&R, h, &A, signature + 32); ge_tobytes(checker, &R); @@ -75,3 +78,55 @@ int ed25519_verify(const unsigned char *signature, const unsigned char *message, return 1; } + +typedef struct context_ +{ + sha512_context hash; + ge_p3 A; +} context; + +void * ed25519_verify_begin(const unsigned char *signature, const unsigned char *public_key) { + ge_p3 A; + + if (signature[63] & 224) { + return NULL; + } + + if (ge_frombytes_negate_vartime(&A, public_key) != 0) { + return NULL; + } + + context * ctx = (context*) malloc(sizeof(context)); + + memcpy(&ctx->A, &A, sizeof(A)); + + sha512_init(&ctx->hash); + sha512_update(&ctx->hash, signature, 32); + sha512_update(&ctx->hash, public_key, 32); + + return ctx; +} + +void ed25519_verify_update(void * ctx, const unsigned char *message, size_t message_len) { + sha512_update(&((context*)ctx)->hash, message, message_len); +} + +int ed25519_verify_end(void * ctx, const unsigned char *signature) { + unsigned char h[64]; + unsigned char checker[32]; + ge_p2 R; + + sha512_final(&((context*)ctx)->hash, h); + + sc_reduce(h); + ge_double_scalarmult_vartime(&R, h, &((context*)ctx)->A, signature + 32); + ge_tobytes(checker, &R); + + free(ctx); + + if (!consttime_equal(checker, signature)) { + return 0; + } + + return 1; +}