github.com/SmartMeshFoundation/Spectrum@v0.0.0-20220621030607-452a266fee1e/crypto/secp256k1/ext.h (about)

     1  // Copyright 2015 The Spectrum Authors
     2  // This file is part of the Spectrum library.
     3  //
     4  // The Spectrum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The Spectrum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the Spectrum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // secp256k1_context_create_sign_verify creates a context for signing and signature verification.
    18  static secp256k1_context* secp256k1_context_create_sign_verify() {
    19  	return secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
    20  }
    21  
    22  // secp256k1_ext_ecdsa_recover recovers the public key of an encoded compact signature.
    23  //
    24  // Returns: 1: recovery was successful
    25  //          0: recovery was not successful
    26  // Args:    ctx:        pointer to a context object (cannot be NULL)
    27  //  Out:    pubkey_out: the serialized 65-byte public key of the signer (cannot be NULL)
    28  //  In:     sigdata:    pointer to a 65-byte signature with the recovery id at the end (cannot be NULL)
    29  //          msgdata:    pointer to a 32-byte message (cannot be NULL)
    30  static int secp256k1_ext_ecdsa_recover(
    31  	const secp256k1_context* ctx,
    32  	unsigned char *pubkey_out,
    33  	const unsigned char *sigdata,
    34  	const unsigned char *msgdata
    35  ) {
    36  	secp256k1_ecdsa_recoverable_signature sig;
    37  	secp256k1_pubkey pubkey;
    38  
    39  	if (!secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &sig, sigdata, (int)sigdata[64])) {
    40  		return 0;
    41  	}
    42  	if (!secp256k1_ecdsa_recover(ctx, &pubkey, &sig, msgdata)) {
    43  		return 0;
    44  	}
    45  	size_t outputlen = 65;
    46  	return secp256k1_ec_pubkey_serialize(ctx, pubkey_out, &outputlen, &pubkey, SECP256K1_EC_UNCOMPRESSED);
    47  }
    48  
    49  // secp256k1_ext_ecdsa_verify verifies an encoded compact signature.
    50  //
    51  // Returns: 1: signature is valid
    52  //          0: signature is invalid
    53  // Args:    ctx:        pointer to a context object (cannot be NULL)
    54  //  In:     sigdata:    pointer to a 64-byte signature (cannot be NULL)
    55  //          msgdata:    pointer to a 32-byte message (cannot be NULL)
    56  //          pubkeydata: pointer to public key data (cannot be NULL)
    57  //          pubkeylen:  length of pubkeydata
    58  static int secp256k1_ext_ecdsa_verify(
    59  	const secp256k1_context* ctx,
    60  	const unsigned char *sigdata,
    61  	const unsigned char *msgdata,
    62  	const unsigned char *pubkeydata,
    63  	size_t pubkeylen
    64  ) {
    65  	secp256k1_ecdsa_signature sig;
    66  	secp256k1_pubkey pubkey;
    67  
    68  	if (!secp256k1_ecdsa_signature_parse_compact(ctx, &sig, sigdata)) {
    69  		return 0;
    70  	}
    71  	if (!secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeydata, pubkeylen)) {
    72  		return 0;
    73  	}
    74  	return secp256k1_ecdsa_verify(ctx, &sig, msgdata, &pubkey);
    75  }
    76  
    77  // secp256k1_ext_reencode_pubkey decodes then encodes a public key. It can be used to
    78  // convert between public key formats. The input/output formats are chosen depending on the
    79  // length of the input/output buffers.
    80  //
    81  // Returns: 1: conversion successful
    82  //          0: conversion unsuccessful
    83  // Args:    ctx:        pointer to a context object (cannot be NULL)
    84  //  Out:    out:        output buffer that will contain the reencoded key (cannot be NULL)
    85  //  In:     outlen:     length of out (33 for compressed keys, 65 for uncompressed keys)
    86  //          pubkeydata: the input public key (cannot be NULL)
    87  //          pubkeylen:  length of pubkeydata
    88  static int secp256k1_ext_reencode_pubkey(
    89  	const secp256k1_context* ctx,
    90  	unsigned char *out,
    91  	size_t outlen,
    92  	const unsigned char *pubkeydata,
    93  	size_t pubkeylen
    94  ) {
    95  	secp256k1_pubkey pubkey;
    96  
    97  	if (!secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeydata, pubkeylen)) {
    98  		return 0;
    99  	}
   100  	unsigned int flag = (outlen == 33) ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED;
   101  	return secp256k1_ec_pubkey_serialize(ctx, out, &outlen, &pubkey, flag);
   102  }
   103  
   104  // secp256k1_ext_scalar_mul multiplies a point by a scalar in constant time.
   105  //
   106  // Returns: 1: multiplication was successful
   107  //          0: scalar was invalid (zero or overflow)
   108  // Args:    ctx:      pointer to a context object (cannot be NULL)
   109  //  Out:    point:    the multiplied point (usually secret)
   110  //  In:     point:    pointer to a 64-byte public point,
   111  //                    encoded as two 256bit big-endian numbers.
   112  //          scalar:   a 32-byte scalar with which to multiply the point
   113  int secp256k1_ext_scalar_mul(const secp256k1_context* ctx, unsigned char *point, const unsigned char *scalar) {
   114  	int ret = 0;
   115  	int overflow = 0;
   116  	secp256k1_fe feX, feY;
   117  	secp256k1_gej res;
   118  	secp256k1_ge ge;
   119  	secp256k1_scalar s;
   120  	ARG_CHECK(point != NULL);
   121  	ARG_CHECK(scalar != NULL);
   122  	(void)ctx;
   123  
   124  	secp256k1_fe_set_b32(&feX, point);
   125  	secp256k1_fe_set_b32(&feY, point+32);
   126  	secp256k1_ge_set_xy(&ge, &feX, &feY);
   127  	secp256k1_scalar_set_b32(&s, scalar, &overflow);
   128  	if (overflow || secp256k1_scalar_is_zero(&s)) {
   129  		ret = 0;
   130  	} else {
   131  		secp256k1_ecmult_const(&res, &ge, &s);
   132  		secp256k1_ge_set_gej(&ge, &res);
   133  		/* Note: can't use secp256k1_pubkey_save here because it is not constant time. */
   134  		secp256k1_fe_normalize(&ge.x);
   135  		secp256k1_fe_normalize(&ge.y);
   136  		secp256k1_fe_get_b32(point, &ge.x);
   137  		secp256k1_fe_get_b32(point+32, &ge.y);
   138  		ret = 1;
   139  	}
   140  	secp256k1_scalar_clear(&s);
   141  	return ret;
   142  }