github.com/ethereumproject/go-ethereum@v5.5.2+incompatible/crypto/secp256k1/libsecp256k1/src/modules/schnorr/schnorr_impl.h (about)

     1  /***********************************************************************
     2   * Copyright (c) 2014-2015 Pieter Wuille                               *
     3   * Distributed under the MIT software license, see the accompanying    *
     4   * file COPYING or http://www.opensource.org/licenses/mit-license.php. *
     5   ***********************************************************************/
     6  
     7  #ifndef _SECP256K1_SCHNORR_IMPL_H_
     8  #define _SECP256K1_SCHNORR_IMPL_H_
     9  
    10  #include <string.h>
    11  
    12  #include "schnorr.h"
    13  #include "num.h"
    14  #include "field.h"
    15  #include "group.h"
    16  #include "ecmult.h"
    17  #include "ecmult_gen.h"
    18  
    19  /**
    20   * Custom Schnorr-based signature scheme. They support multiparty signing, public key
    21   * recovery and batch validation.
    22   *
    23   * Rationale for verifying R's y coordinate:
    24   * In order to support batch validation and public key recovery, the full R point must
    25   * be known to verifiers, rather than just its x coordinate. In order to not risk
    26   * being more strict in batch validation than normal validation, validators must be
    27   * required to reject signatures with incorrect y coordinate. This is only possible
    28   * by including a (relatively slow) field inverse, or a field square root. However,
    29   * batch validation offers potentially much higher benefits than this cost.
    30   *
    31   * Rationale for having an implicit y coordinate oddness:
    32   * If we commit to having the full R point known to verifiers, there are two mechanism.
    33   * Either include its oddness in the signature, or give it an implicit fixed value.
    34   * As the R y coordinate can be flipped by a simple negation of the nonce, we choose the
    35   * latter, as it comes with nearly zero impact on signing or validation performance, and
    36   * saves a byte in the signature.
    37   *
    38   * Signing:
    39   *   Inputs: 32-byte message m, 32-byte scalar key x (!=0), 32-byte scalar nonce k (!=0)
    40   *
    41   *   Compute point R = k * G. Reject nonce if R's y coordinate is odd (or negate nonce).
    42   *   Compute 32-byte r, the serialization of R's x coordinate.
    43   *   Compute scalar h = Hash(r || m). Reject nonce if h == 0 or h >= order.
    44   *   Compute scalar s = k - h * x.
    45   *   The signature is (r, s).
    46   *
    47   *
    48   * Verification:
    49   *   Inputs: 32-byte message m, public key point Q, signature: (32-byte r, scalar s)
    50   *
    51   *   Signature is invalid if s >= order.
    52   *   Signature is invalid if r >= p.
    53   *   Compute scalar h = Hash(r || m). Signature is invalid if h == 0 or h >= order.
    54   *   Option 1 (faster for single verification):
    55   *     Compute point R = h * Q + s * G. Signature is invalid if R is infinity or R's y coordinate is odd.
    56   *     Signature is valid if the serialization of R's x coordinate equals r.
    57   *   Option 2 (allows batch validation and pubkey recovery):
    58   *     Decompress x coordinate r into point R, with odd y coordinate. Fail if R is not on the curve.
    59   *     Signature is valid if R + h * Q + s * G == 0.
    60   */
    61  
    62  static int secp256k1_schnorr_sig_sign(const secp256k1_ecmult_gen_context* ctx, unsigned char *sig64, const secp256k1_scalar *key, const secp256k1_scalar *nonce, const secp256k1_ge *pubnonce, secp256k1_schnorr_msghash hash, const unsigned char *msg32) {
    63      secp256k1_gej Rj;
    64      secp256k1_ge Ra;
    65      unsigned char h32[32];
    66      secp256k1_scalar h, s;
    67      int overflow;
    68      secp256k1_scalar n;
    69  
    70      if (secp256k1_scalar_is_zero(key) || secp256k1_scalar_is_zero(nonce)) {
    71          return 0;
    72      }
    73      n = *nonce;
    74  
    75      secp256k1_ecmult_gen(ctx, &Rj, &n);
    76      if (pubnonce != NULL) {
    77          secp256k1_gej_add_ge(&Rj, &Rj, pubnonce);
    78      }
    79      secp256k1_ge_set_gej(&Ra, &Rj);
    80      secp256k1_fe_normalize(&Ra.y);
    81      if (secp256k1_fe_is_odd(&Ra.y)) {
    82          /* R's y coordinate is odd, which is not allowed (see rationale above).
    83             Force it to be even by negating the nonce. Note that this even works
    84             for multiparty signing, as the R point is known to all participants,
    85             which can all decide to flip the sign in unison, resulting in the
    86             overall R point to be negated too. */
    87          secp256k1_scalar_negate(&n, &n);
    88      }
    89      secp256k1_fe_normalize(&Ra.x);
    90      secp256k1_fe_get_b32(sig64, &Ra.x);
    91      hash(h32, sig64, msg32);
    92      overflow = 0;
    93      secp256k1_scalar_set_b32(&h, h32, &overflow);
    94      if (overflow || secp256k1_scalar_is_zero(&h)) {
    95          secp256k1_scalar_clear(&n);
    96          return 0;
    97      }
    98      secp256k1_scalar_mul(&s, &h, key);
    99      secp256k1_scalar_negate(&s, &s);
   100      secp256k1_scalar_add(&s, &s, &n);
   101      secp256k1_scalar_clear(&n);
   102      secp256k1_scalar_get_b32(sig64 + 32, &s);
   103      return 1;
   104  }
   105  
   106  static int secp256k1_schnorr_sig_verify(const secp256k1_ecmult_context* ctx, const unsigned char *sig64, const secp256k1_ge *pubkey, secp256k1_schnorr_msghash hash, const unsigned char *msg32) {
   107      secp256k1_gej Qj, Rj;
   108      secp256k1_ge Ra;
   109      secp256k1_fe Rx;
   110      secp256k1_scalar h, s;
   111      unsigned char hh[32];
   112      int overflow;
   113  
   114      if (secp256k1_ge_is_infinity(pubkey)) {
   115          return 0;
   116      }
   117      hash(hh, sig64, msg32);
   118      overflow = 0;
   119      secp256k1_scalar_set_b32(&h, hh, &overflow);
   120      if (overflow || secp256k1_scalar_is_zero(&h)) {
   121          return 0;
   122      }
   123      overflow = 0;
   124      secp256k1_scalar_set_b32(&s, sig64 + 32, &overflow);
   125      if (overflow) {
   126          return 0;
   127      }
   128      if (!secp256k1_fe_set_b32(&Rx, sig64)) {
   129          return 0;
   130      }
   131      secp256k1_gej_set_ge(&Qj, pubkey);
   132      secp256k1_ecmult(ctx, &Rj, &Qj, &h, &s);
   133      if (secp256k1_gej_is_infinity(&Rj)) {
   134          return 0;
   135      }
   136      secp256k1_ge_set_gej_var(&Ra, &Rj);
   137      secp256k1_fe_normalize_var(&Ra.y);
   138      if (secp256k1_fe_is_odd(&Ra.y)) {
   139          return 0;
   140      }
   141      return secp256k1_fe_equal_var(&Rx, &Ra.x);
   142  }
   143  
   144  static int secp256k1_schnorr_sig_recover(const secp256k1_ecmult_context* ctx, const unsigned char *sig64, secp256k1_ge *pubkey, secp256k1_schnorr_msghash hash, const unsigned char *msg32) {
   145      secp256k1_gej Qj, Rj;
   146      secp256k1_ge Ra;
   147      secp256k1_fe Rx;
   148      secp256k1_scalar h, s;
   149      unsigned char hh[32];
   150      int overflow;
   151  
   152      hash(hh, sig64, msg32);
   153      overflow = 0;
   154      secp256k1_scalar_set_b32(&h, hh, &overflow);
   155      if (overflow || secp256k1_scalar_is_zero(&h)) {
   156          return 0;
   157      }
   158      overflow = 0;
   159      secp256k1_scalar_set_b32(&s, sig64 + 32, &overflow);
   160      if (overflow) {
   161          return 0;
   162      }
   163      if (!secp256k1_fe_set_b32(&Rx, sig64)) {
   164          return 0;
   165      }
   166      if (!secp256k1_ge_set_xo_var(&Ra, &Rx, 0)) {
   167          return 0;
   168      }
   169      secp256k1_gej_set_ge(&Rj, &Ra);
   170      secp256k1_scalar_inverse_var(&h, &h);
   171      secp256k1_scalar_negate(&s, &s);
   172      secp256k1_scalar_mul(&s, &s, &h);
   173      secp256k1_ecmult(ctx, &Qj, &Rj, &h, &s);
   174      if (secp256k1_gej_is_infinity(&Qj)) {
   175          return 0;
   176      }
   177      secp256k1_ge_set_gej(pubkey, &Qj);
   178      return 1;
   179  }
   180  
   181  static int secp256k1_schnorr_sig_combine(unsigned char *sig64, int n, const unsigned char * const *sig64ins) {
   182      secp256k1_scalar s = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0);
   183      int i;
   184      for (i = 0; i < n; i++) {
   185          secp256k1_scalar si;
   186          int overflow;
   187          secp256k1_scalar_set_b32(&si, sig64ins[i] + 32, &overflow);
   188          if (overflow) {
   189              return -1;
   190          }
   191          if (i) {
   192              if (memcmp(sig64ins[i - 1], sig64ins[i], 32) != 0) {
   193                  return -1;
   194              }
   195          }
   196          secp256k1_scalar_add(&s, &s, &si);
   197      }
   198      if (secp256k1_scalar_is_zero(&s)) {
   199          return 0;
   200      }
   201      memcpy(sig64, sig64ins[0], 32);
   202      secp256k1_scalar_get_b32(sig64 + 32, &s);
   203      secp256k1_scalar_clear(&s);
   204      return 1;
   205  }
   206  
   207  #endif