From b023605412ff8dd0d5992f870f2b7ef502753f2a Mon Sep 17 00:00:00 2001 From: Loup Vaillant Date: Mon, 9 Oct 2017 23:42:30 +0200 Subject: [PATCH] Added crypto_sign 2 pass interface Also refined the crypto_check incremental interface (again). Having to pass arguments in the final() function we already passed to init() is cumbersome and error prone. I removed this nonsense. --- src/monocypher.c | 97 +++++++++++++++++++++++++++++++----------------- src/monocypher.h | 40 +++++++++++++++----- 2 files changed, 92 insertions(+), 45 deletions(-) diff --git a/src/monocypher.c b/src/monocypher.c index 1318dfa..5ce78aa 100644 --- a/src/monocypher.c +++ b/src/monocypher.c @@ -1474,48 +1474,62 @@ void crypto_sign_public_key(u8 public_key[32], ge_tobytes(public_key, &A); } -void crypto_sign(u8 signature[64], - const u8 secret_key[32], - const u8 public_key[32], - const u8 *message, size_t message_size) +void crypto_sign_init1(crypto_sign_ctx *ctx, + const u8 secret_key[32], + const u8 public_key[32]) { - u8 a[64], *prefix = a + 32; + u8 *a = ctx->buf; + u8 *prefix = ctx->buf + 32; HASH(a, secret_key, 32); trim_scalar(a); - u8 pk_buf[32]; - const u8 *pk = public_key; if (public_key == 0) { - crypto_sign_public_key(pk_buf, secret_key); - pk = pk_buf; + crypto_sign_public_key(ctx->pk, secret_key); + } else { + FOR (i, 0, 32) { + ctx->pk[i] = public_key[i]; + } } // Constructs the "random" nonce from the secret key and message. // An actual random number would work just fine, and would save us // the trouble of hashing the message twice. If we did that // however, the user could fuck it up and reuse the nonce. - u8 r[64]; - HASH_CTX ctx; - HASH_INIT (&ctx); - HASH_UPDATE(&ctx, prefix , 32 ); - HASH_UPDATE(&ctx, message, message_size); - HASH_FINAL (&ctx, r); + HASH_INIT (&(ctx->hash)); + HASH_UPDATE(&(ctx->hash), prefix , 32); +} + +void crypto_sign_update(crypto_sign_ctx *ctx, const u8 *msg, size_t msg_size) +{ + HASH_UPDATE(&(ctx->hash), msg, msg_size); +} + +void crypto_sign_init2(crypto_sign_ctx *ctx) +{ + u8 *r = ctx->buf + 32; + u8 *half_sig = ctx->buf + 64; + HASH_FINAL(&(ctx->hash), r); reduce(r); // first half of the signature = "random" nonce times basepoint ge R; - u8 half_sig[32]; ge_scalarmult_base(&R, r); ge_tobytes(half_sig, &R); // Hash R, the public key, and the message together. // It cannot be done in paralell with the first hash. + HASH_INIT (&ctx->hash); + HASH_UPDATE(&ctx->hash, half_sig, 32); + HASH_UPDATE(&ctx->hash, ctx->pk , 32); +} + +void crypto_sign_final(crypto_sign_ctx *ctx, u8 signature[64]) +{ + u8 *a = ctx->buf; + u8 *r = ctx->buf + 32; + u8 *half_sig = ctx->buf + 64; u8 h_ram[64]; - HASH_INIT (&ctx); - HASH_UPDATE(&ctx, half_sig, 32 ); - HASH_UPDATE(&ctx, pk , 32 ); - HASH_UPDATE(&ctx, message , message_size); - HASH_FINAL (&ctx, h_ram); + HASH_FINAL(&(ctx->hash), h_ram); reduce(h_ram); // reduce the hash modulo L i64 s[64]; // s = r + h_ram * a @@ -1532,6 +1546,19 @@ void crypto_sign(u8 signature[64], modL(signature + 32, s); // second half of the signature = s } +void crypto_sign(u8 signature[64], + const u8 secret_key[32], + const u8 public_key[32], + const u8 *message, size_t message_size) +{ + crypto_sign_ctx ctx; + crypto_sign_init1 (&ctx, secret_key, public_key); + crypto_sign_update(&ctx, message, message_size); + crypto_sign_init2 (&ctx); + crypto_sign_update(&ctx, message, message_size); + crypto_sign_final (&ctx, signature); +} + int crypto_check_public_key(const u8 public_key[32]) { ge A; // wasted result. @@ -1542,32 +1569,32 @@ void crypto_check_init(crypto_check_ctx *ctx, const u8 signature[64], const u8 public_key[32]) { - HASH_INIT(ctx); - HASH_UPDATE(ctx, signature , 32); - HASH_UPDATE(ctx, public_key, 32); + FOR (i, 0, 64) { ctx->sig[i] = signature [i]; } + FOR (i, 0, 32) { ctx->pk [i] = public_key[i]; } + HASH_INIT (&(ctx->hash)); + HASH_UPDATE(&(ctx->hash), signature , 32); + HASH_UPDATE(&(ctx->hash), public_key, 32); } void crypto_check_update(crypto_check_ctx *ctx, const u8 *msg, size_t msg_size) { - HASH_UPDATE(ctx, msg , msg_size); + HASH_UPDATE(&(ctx->hash), msg , msg_size); } -int crypto_check_final(crypto_check_ctx *ctx, - const u8 signature[64], - const u8 public_key[32]) +int crypto_check_final(crypto_check_ctx *ctx) { ge p, sB, diff, A; u8 h_ram[64], R_check[32]; - if (ge_frombytes_neg(&A, public_key)) { // -A + if (ge_frombytes_neg(&A, ctx->pk)) { // -A return -1; } - HASH_FINAL(ctx, h_ram); + HASH_FINAL(&(ctx->hash), h_ram); reduce(h_ram); - ge_scalarmult(&p, &A, h_ram); // p = -A*h_ram - ge_scalarmult_base(&sB, signature + 32); - ge_add(&diff, &p, &sB); // diff = s - A*h_ram + ge_scalarmult(&p, &A, h_ram); // p = -A*h_ram + ge_scalarmult_base(&sB, ctx->sig + 32); + ge_add(&diff, &p, &sB); // diff = s - A*h_ram ge_tobytes(R_check, &diff); - return crypto_memcmp(signature, R_check, 32); // R == s - A*h_ram ? OK : fail + return crypto_memcmp(ctx->sig, R_check, 32); // R == s - A*h_ram ? OK : fail } int crypto_check(const u8 signature[64], @@ -1577,7 +1604,7 @@ int crypto_check(const u8 signature[64], crypto_check_ctx ctx; crypto_check_init(&ctx, signature, public_key); crypto_check_update(&ctx, message, message_size); - return crypto_check_final(&ctx, signature, public_key); + return crypto_check_final(&ctx); } //////////////////// diff --git a/src/monocypher.h b/src/monocypher.h index 4822ce2..9264128 100644 --- a/src/monocypher.h +++ b/src/monocypher.h @@ -130,20 +130,42 @@ void crypto_x25519_public_key(uint8_t public_key[32], void crypto_sign_public_key(uint8_t public_key[32], const uint8_t secret_key[32]); +#ifdef ED25519_SHA512 +typedef crypto_sha512_ctx crypto_hash_ctx; +#else +typedef crypto_blake2b_ctx crypto_hash_ctx; +#endif + +typedef struct { + crypto_hash_ctx hash; + uint8_t buf[96]; + uint8_t pk [32]; +} crypto_sign_ctx; + +void crypto_sign_init1(crypto_sign_ctx *ctx, + const uint8_t secret_key[32], + const uint8_t public_key[32]); + +void crypto_sign_update(crypto_sign_ctx *ctx, + const uint8_t *message, size_t message_size); + +void crypto_sign_init2(crypto_sign_ctx *ctx); + +void crypto_sign_final(crypto_sign_ctx *ctx, uint8_t signature[64]); + void crypto_sign(uint8_t signature [64], const uint8_t secret_key[32], const uint8_t public_key[32], // optional, may be 0 const uint8_t *message, size_t message_size); - -#ifdef ED25519_SHA512 -typedef crypto_sha512_ctx crypto_check_ctx; -#else -typedef crypto_blake2b_ctx crypto_check_ctx; -#endif - int crypto_check_public_key(const uint8_t public_key[32]); +typedef struct { + crypto_hash_ctx hash; + uint8_t sig[64]; + uint8_t pk [32]; +} crypto_check_ctx; + void crypto_check_init(crypto_check_ctx *ctx, const uint8_t signature[64], const uint8_t public_key[32]); @@ -151,9 +173,7 @@ void crypto_check_init(crypto_check_ctx *ctx, void crypto_check_update(crypto_check_ctx *ctx, const uint8_t *message, size_t message_size); -int crypto_check_final(crypto_check_ctx *ctx, - const uint8_t signature[64], - const uint8_t public_key[32]); +int crypto_check_final(crypto_check_ctx *ctx); int crypto_check(const uint8_t signature [64], const uint8_t public_key[32], -- 2.47.3