]> git.codecow.com Git - Monocypher.git/commitdiff
Added crypto_sign 2 pass interface
authorLoup Vaillant <loup@loup-vaillant.fr>
Mon, 9 Oct 2017 21:42:30 +0000 (23:42 +0200)
committerLoup Vaillant <loup@loup-vaillant.fr>
Mon, 9 Oct 2017 21:42:30 +0000 (23:42 +0200)
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
src/monocypher.h

index 1318dfac5e423446845ae4d9338f4e779f45a3ae..5ce78aa288293413056134da8a58d7c9634bb54c 100644 (file)
@@ -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);
 }
 
 ////////////////////
index 4822ce28a2df784f68f36ffce983e23244e03cd4..926412896229c4c679d27f3121c4ee9d5eb079d1 100644 (file)
@@ -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],