2014-11-15 15:28:10 +00:00
|
|
|
/**********************************************************************
|
2015-02-03 17:27:00 -08:00
|
|
|
* Copyright (c) 2013-2015 Pieter Wuille *
|
2014-11-15 15:28:10 +00:00
|
|
|
* Distributed under the MIT software license, see the accompanying *
|
|
|
|
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
|
|
|
**********************************************************************/
|
2013-05-09 15:24:32 +02:00
|
|
|
|
2014-09-08 23:09:06 +02:00
|
|
|
#include "include/secp256k1.h"
|
2018-11-27 16:48:57 +01:00
|
|
|
#include "include/secp256k1_preallocated.h"
|
2014-09-08 23:09:06 +02:00
|
|
|
|
2014-08-18 23:07:46 +02:00
|
|
|
#include "util.h"
|
2014-03-07 01:11:01 +01:00
|
|
|
#include "num_impl.h"
|
|
|
|
#include "field_impl.h"
|
2014-10-28 04:08:15 -07:00
|
|
|
#include "scalar_impl.h"
|
2014-03-07 01:11:01 +01:00
|
|
|
#include "group_impl.h"
|
|
|
|
#include "ecmult_impl.h"
|
2015-05-13 17:31:47 -05:00
|
|
|
#include "ecmult_const_impl.h"
|
2014-10-26 03:42:24 -07:00
|
|
|
#include "ecmult_gen_impl.h"
|
2014-03-07 01:11:01 +01:00
|
|
|
#include "ecdsa_impl.h"
|
2014-10-27 02:57:27 -07:00
|
|
|
#include "eckey_impl.h"
|
2014-12-13 17:02:30 +01:00
|
|
|
#include "hash_impl.h"
|
2017-07-22 18:03:17 +00:00
|
|
|
#include "scratch_impl.h"
|
2013-03-31 06:34:15 +02:00
|
|
|
|
2016-07-07 00:47:41 +02:00
|
|
|
#ifdef ENABLE_MODULE_GENERATOR
|
|
|
|
# include "include/secp256k1_generator.h"
|
|
|
|
#endif
|
|
|
|
|
Pedersen commitments, borromean ring signatures, and ZK range proofs.
This commit adds three new cryptosystems to libsecp256k1:
Pedersen commitments are a system for making blinded commitments
to a value. Functionally they work like:
commit_b,v = H(blind_b || value_v),
except they are additively homorphic, e.g.
C(b1, v1) - C(b2, v2) = C(b1 - b2, v1 - v2) and
C(b1, v1) - C(b1, v1) = 0, etc.
The commitments themselves are EC points, serialized as 33 bytes.
In addition to the commit function this implementation includes
utility functions for verifying that a set of commitments sums
to zero, and for picking blinding factors that sum to zero.
If the blinding factors are uniformly random, pedersen commitments
have information theoretic privacy.
Borromean ring signatures are a novel efficient ring signature
construction for AND/OR admissions policies (the code here implements
an AND of ORs, each of any size). This construction requires
32 bytes of signature per pubkey used plus 32 bytes of constant
overhead. With these you can construct signatures like "Given pubkeys
A B C D E F G, the signer knows the discrete logs
satisifying (A || B) & (C || D || E) & (F || G)".
ZK range proofs allow someone to prove a pedersen commitment is in
a particular range (e.g. [0..2^64)) without revealing the specific
value. The construction here is based on the above borromean
ring signature and uses a radix-4 encoding and other optimizations
to maximize efficiency. It also supports encoding proofs with a
non-private base-10 exponent and minimum-value to allow trading
off secrecy for size and speed (or just avoiding wasting space
keeping data private that was already public due to external
constraints).
A proof for a 32-bit mantissa takes 2564 bytes, but 2048 bytes of
this can be used to communicate a private message to a receiver
who shares a secret random seed with the prover.
Also: get rid of precomputed H tables (Pieter Wuille)
2015-08-05 19:04:14 +02:00
|
|
|
#ifdef ENABLE_MODULE_RANGEPROOF
|
2016-07-04 13:04:57 +00:00
|
|
|
# include "include/secp256k1_rangeproof.h"
|
Pedersen commitments, borromean ring signatures, and ZK range proofs.
This commit adds three new cryptosystems to libsecp256k1:
Pedersen commitments are a system for making blinded commitments
to a value. Functionally they work like:
commit_b,v = H(blind_b || value_v),
except they are additively homorphic, e.g.
C(b1, v1) - C(b2, v2) = C(b1 - b2, v1 - v2) and
C(b1, v1) - C(b1, v1) = 0, etc.
The commitments themselves are EC points, serialized as 33 bytes.
In addition to the commit function this implementation includes
utility functions for verifying that a set of commitments sums
to zero, and for picking blinding factors that sum to zero.
If the blinding factors are uniformly random, pedersen commitments
have information theoretic privacy.
Borromean ring signatures are a novel efficient ring signature
construction for AND/OR admissions policies (the code here implements
an AND of ORs, each of any size). This construction requires
32 bytes of signature per pubkey used plus 32 bytes of constant
overhead. With these you can construct signatures like "Given pubkeys
A B C D E F G, the signer knows the discrete logs
satisifying (A || B) & (C || D || E) & (F || G)".
ZK range proofs allow someone to prove a pedersen commitment is in
a particular range (e.g. [0..2^64)) without revealing the specific
value. The construction here is based on the above borromean
ring signature and uses a radix-4 encoding and other optimizations
to maximize efficiency. It also supports encoding proofs with a
non-private base-10 exponent and minimum-value to allow trading
off secrecy for size and speed (or just avoiding wasting space
keeping data private that was already public due to external
constraints).
A proof for a 32-bit mantissa takes 2564 bytes, but 2048 bytes of
this can be used to communicate a private message to a receiver
who shares a secret random seed with the prover.
Also: get rid of precomputed H tables (Pieter Wuille)
2015-08-05 19:04:14 +02:00
|
|
|
# include "modules/rangeproof/pedersen.h"
|
|
|
|
# include "modules/rangeproof/rangeproof.h"
|
|
|
|
#endif
|
|
|
|
|
2015-07-18 16:29:10 -04:00
|
|
|
#define ARG_CHECK(cond) do { \
|
|
|
|
if (EXPECT(!(cond), 0)) { \
|
2015-09-21 20:57:54 +02:00
|
|
|
secp256k1_callback_call(&ctx->illegal_callback, #cond); \
|
2015-07-18 16:29:10 -04:00
|
|
|
return 0; \
|
|
|
|
} \
|
|
|
|
} while(0)
|
|
|
|
|
2019-03-04 13:09:45 +01:00
|
|
|
#define ARG_CHECK_NO_RETURN(cond) do { \
|
|
|
|
if (EXPECT(!(cond), 0)) { \
|
|
|
|
secp256k1_callback_call(&ctx->illegal_callback, #cond); \
|
|
|
|
} \
|
|
|
|
} while(0)
|
|
|
|
|
2019-03-04 15:36:35 +01:00
|
|
|
#ifndef USE_EXTERNAL_DEFAULT_CALLBACKS
|
2019-03-04 16:11:35 +01:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
2019-03-09 11:41:21 +01:00
|
|
|
static void secp256k1_default_illegal_callback_fn(const char* str, void* data) {
|
2015-07-18 16:29:10 -04:00
|
|
|
(void)data;
|
|
|
|
fprintf(stderr, "[libsecp256k1] illegal argument: %s\n", str);
|
|
|
|
abort();
|
|
|
|
}
|
2019-03-09 11:41:21 +01:00
|
|
|
static void secp256k1_default_error_callback_fn(const char* str, void* data) {
|
2015-07-18 16:29:10 -04:00
|
|
|
(void)data;
|
|
|
|
fprintf(stderr, "[libsecp256k1] internal consistency check failed: %s\n", str);
|
|
|
|
abort();
|
|
|
|
}
|
2019-03-04 15:36:35 +01:00
|
|
|
#else
|
2019-03-09 11:41:21 +01:00
|
|
|
void secp256k1_default_illegal_callback_fn(const char* str, void* data);
|
|
|
|
void secp256k1_default_error_callback_fn(const char* str, void* data);
|
2019-03-04 15:36:35 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
static const secp256k1_callback default_illegal_callback = {
|
2019-03-09 11:41:21 +01:00
|
|
|
secp256k1_default_illegal_callback_fn,
|
2019-03-04 15:36:35 +01:00
|
|
|
NULL
|
|
|
|
};
|
2015-07-18 16:29:10 -04:00
|
|
|
|
2015-09-21 20:57:54 +02:00
|
|
|
static const secp256k1_callback default_error_callback = {
|
2019-03-09 11:41:21 +01:00
|
|
|
secp256k1_default_error_callback_fn,
|
2015-07-18 16:29:10 -04:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2015-02-03 17:27:00 -08:00
|
|
|
struct secp256k1_context_struct {
|
2015-09-21 20:57:54 +02:00
|
|
|
secp256k1_ecmult_context ecmult_ctx;
|
|
|
|
secp256k1_ecmult_gen_context ecmult_gen_ctx;
|
|
|
|
secp256k1_callback illegal_callback;
|
|
|
|
secp256k1_callback error_callback;
|
2015-02-03 17:27:00 -08:00
|
|
|
};
|
|
|
|
|
2018-08-15 21:27:25 +00:00
|
|
|
static const secp256k1_context secp256k1_context_no_precomp_ = {
|
|
|
|
{ 0 },
|
|
|
|
{ 0 },
|
2019-03-09 11:41:21 +01:00
|
|
|
{ secp256k1_default_illegal_callback_fn, 0 },
|
|
|
|
{ secp256k1_default_error_callback_fn, 0 }
|
2018-08-15 21:27:25 +00:00
|
|
|
};
|
|
|
|
const secp256k1_context *secp256k1_context_no_precomp = &secp256k1_context_no_precomp_;
|
|
|
|
|
2018-10-22 16:23:09 +02:00
|
|
|
size_t secp256k1_context_preallocated_size(unsigned int flags) {
|
|
|
|
size_t ret = ROUND_TO_ALIGN(sizeof(secp256k1_context));
|
|
|
|
|
|
|
|
if (EXPECT((flags & SECP256K1_FLAGS_TYPE_MASK) != SECP256K1_FLAGS_TYPE_CONTEXT, 0)) {
|
|
|
|
secp256k1_callback_call(&default_illegal_callback,
|
|
|
|
"Invalid flags");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & SECP256K1_FLAGS_BIT_CONTEXT_SIGN) {
|
|
|
|
ret += SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE;
|
|
|
|
}
|
|
|
|
if (flags & SECP256K1_FLAGS_BIT_CONTEXT_VERIFY) {
|
|
|
|
ret += SECP256K1_ECMULT_CONTEXT_PREALLOCATED_SIZE;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2018-10-25 17:14:10 +02:00
|
|
|
size_t secp256k1_context_preallocated_clone_size(const secp256k1_context* ctx) {
|
|
|
|
size_t ret = ROUND_TO_ALIGN(sizeof(secp256k1_context));
|
2018-10-25 18:08:14 +02:00
|
|
|
VERIFY_CHECK(ctx != NULL);
|
2018-10-25 17:14:10 +02:00
|
|
|
if (secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)) {
|
|
|
|
ret += SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE;
|
|
|
|
}
|
|
|
|
if (secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)) {
|
|
|
|
ret += SECP256K1_ECMULT_CONTEXT_PREALLOCATED_SIZE;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2018-10-22 16:25:26 +02:00
|
|
|
secp256k1_context* secp256k1_context_preallocated_create(void* prealloc, unsigned int flags) {
|
|
|
|
void* const base = prealloc;
|
2018-10-25 18:08:14 +02:00
|
|
|
size_t prealloc_size;
|
|
|
|
secp256k1_context* ret;
|
2018-10-22 16:25:26 +02:00
|
|
|
|
2018-10-25 18:08:14 +02:00
|
|
|
VERIFY_CHECK(prealloc != NULL);
|
|
|
|
prealloc_size = secp256k1_context_preallocated_size(flags);
|
|
|
|
ret = (secp256k1_context*)manual_alloc(&prealloc, sizeof(secp256k1_context), base, prealloc_size);
|
2015-07-18 16:29:10 -04:00
|
|
|
ret->illegal_callback = default_illegal_callback;
|
|
|
|
ret->error_callback = default_error_callback;
|
2015-02-03 17:27:00 -08:00
|
|
|
|
2015-10-21 17:43:29 +02:00
|
|
|
if (EXPECT((flags & SECP256K1_FLAGS_TYPE_MASK) != SECP256K1_FLAGS_TYPE_CONTEXT, 0)) {
|
2015-09-29 14:10:38 +09:30
|
|
|
secp256k1_callback_call(&ret->illegal_callback,
|
|
|
|
"Invalid flags");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2015-02-03 17:27:00 -08:00
|
|
|
secp256k1_ecmult_context_init(&ret->ecmult_ctx);
|
|
|
|
secp256k1_ecmult_gen_context_init(&ret->ecmult_gen_ctx);
|
|
|
|
|
2015-10-21 17:43:29 +02:00
|
|
|
if (flags & SECP256K1_FLAGS_BIT_CONTEXT_SIGN) {
|
2018-10-22 16:25:26 +02:00
|
|
|
secp256k1_ecmult_gen_context_build(&ret->ecmult_gen_ctx, &prealloc);
|
2014-09-08 23:09:06 +02:00
|
|
|
}
|
2015-10-21 17:43:29 +02:00
|
|
|
if (flags & SECP256K1_FLAGS_BIT_CONTEXT_VERIFY) {
|
2018-10-22 16:25:26 +02:00
|
|
|
secp256k1_ecmult_context_build(&ret->ecmult_ctx, &prealloc);
|
2014-09-08 23:09:06 +02:00
|
|
|
}
|
2015-02-03 17:27:00 -08:00
|
|
|
|
2018-10-22 16:25:26 +02:00
|
|
|
return (secp256k1_context*) ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
secp256k1_context* secp256k1_context_create(unsigned int flags) {
|
|
|
|
size_t const prealloc_size = secp256k1_context_preallocated_size(flags);
|
|
|
|
secp256k1_context* ctx = (secp256k1_context*)checked_malloc(&default_error_callback, prealloc_size);
|
|
|
|
if (EXPECT(secp256k1_context_preallocated_create(ctx, flags) == NULL, 0)) {
|
|
|
|
free(ctx);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ctx;
|
2013-03-31 06:34:15 +02:00
|
|
|
}
|
|
|
|
|
2018-10-25 17:14:10 +02:00
|
|
|
secp256k1_context* secp256k1_context_preallocated_clone(const secp256k1_context* ctx, void* prealloc) {
|
2018-10-25 18:08:14 +02:00
|
|
|
size_t prealloc_size;
|
|
|
|
secp256k1_context* ret;
|
|
|
|
VERIFY_CHECK(ctx != NULL);
|
|
|
|
ARG_CHECK(prealloc != NULL);
|
|
|
|
|
|
|
|
prealloc_size = secp256k1_context_preallocated_clone_size(ctx);
|
|
|
|
ret = (secp256k1_context*)prealloc;
|
2018-10-22 16:25:26 +02:00
|
|
|
memcpy(ret, ctx, prealloc_size);
|
|
|
|
secp256k1_ecmult_gen_context_finalize_memcpy(&ret->ecmult_gen_ctx, &ctx->ecmult_gen_ctx);
|
|
|
|
secp256k1_ecmult_context_finalize_memcpy(&ret->ecmult_ctx, &ctx->ecmult_ctx);
|
2015-04-11 14:06:54 -05:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2018-10-25 17:14:10 +02:00
|
|
|
secp256k1_context* secp256k1_context_clone(const secp256k1_context* ctx) {
|
2018-10-25 18:08:14 +02:00
|
|
|
secp256k1_context* ret;
|
|
|
|
size_t prealloc_size;
|
|
|
|
|
|
|
|
VERIFY_CHECK(ctx != NULL);
|
|
|
|
prealloc_size = secp256k1_context_preallocated_clone_size(ctx);
|
|
|
|
ret = (secp256k1_context*)checked_malloc(&ctx->error_callback, prealloc_size);
|
2018-10-25 17:14:10 +02:00
|
|
|
ret = secp256k1_context_preallocated_clone(ctx, ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2018-10-22 16:25:26 +02:00
|
|
|
void secp256k1_context_preallocated_destroy(secp256k1_context* ctx) {
|
2019-03-04 13:09:45 +01:00
|
|
|
ARG_CHECK_NO_RETURN(ctx != secp256k1_context_no_precomp);
|
2015-09-23 21:56:04 +00:00
|
|
|
if (ctx != NULL) {
|
2015-09-21 17:21:35 +00:00
|
|
|
secp256k1_ecmult_context_clear(&ctx->ecmult_ctx);
|
|
|
|
secp256k1_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx);
|
2018-10-22 16:25:26 +02:00
|
|
|
}
|
|
|
|
}
|
2015-09-01 01:41:35 +00:00
|
|
|
|
2018-10-22 16:25:26 +02:00
|
|
|
void secp256k1_context_destroy(secp256k1_context* ctx) {
|
|
|
|
if (ctx != NULL) {
|
|
|
|
secp256k1_context_preallocated_destroy(ctx);
|
2015-09-21 17:21:35 +00:00
|
|
|
free(ctx);
|
|
|
|
}
|
2013-03-31 06:34:15 +02:00
|
|
|
}
|
|
|
|
|
2015-09-21 20:57:54 +02:00
|
|
|
void secp256k1_context_set_illegal_callback(secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data) {
|
2019-03-04 13:09:45 +01:00
|
|
|
ARG_CHECK_NO_RETURN(ctx != secp256k1_context_no_precomp);
|
2015-09-23 21:56:04 +00:00
|
|
|
if (fun == NULL) {
|
2019-03-09 11:41:21 +01:00
|
|
|
fun = secp256k1_default_illegal_callback_fn;
|
2015-09-21 17:21:35 +00:00
|
|
|
}
|
2015-07-18 16:29:10 -04:00
|
|
|
ctx->illegal_callback.fn = fun;
|
|
|
|
ctx->illegal_callback.data = data;
|
|
|
|
}
|
|
|
|
|
2015-09-21 20:57:54 +02:00
|
|
|
void secp256k1_context_set_error_callback(secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data) {
|
2019-03-04 13:09:45 +01:00
|
|
|
ARG_CHECK_NO_RETURN(ctx != secp256k1_context_no_precomp);
|
2015-09-23 21:56:04 +00:00
|
|
|
if (fun == NULL) {
|
2019-03-09 11:41:21 +01:00
|
|
|
fun = secp256k1_default_error_callback_fn;
|
2015-09-21 17:21:35 +00:00
|
|
|
}
|
2015-07-18 16:29:10 -04:00
|
|
|
ctx->error_callback.fn = fun;
|
|
|
|
ctx->error_callback.data = data;
|
|
|
|
}
|
|
|
|
|
2018-03-20 13:21:33 +00:00
|
|
|
secp256k1_scratch_space* secp256k1_scratch_space_create(const secp256k1_context* ctx, size_t max_size) {
|
2017-07-22 18:03:17 +00:00
|
|
|
VERIFY_CHECK(ctx != NULL);
|
2018-03-20 13:21:33 +00:00
|
|
|
return secp256k1_scratch_create(&ctx->error_callback, max_size);
|
2017-07-22 18:03:17 +00:00
|
|
|
}
|
|
|
|
|
2019-03-13 23:30:51 +00:00
|
|
|
void secp256k1_scratch_space_destroy(const secp256k1_context *ctx, secp256k1_scratch_space* scratch) {
|
|
|
|
VERIFY_CHECK(ctx != NULL);
|
|
|
|
secp256k1_scratch_destroy(&ctx->error_callback, scratch);
|
2017-07-22 18:03:17 +00:00
|
|
|
}
|
|
|
|
|
2015-09-21 20:57:54 +02:00
|
|
|
static int secp256k1_pubkey_load(const secp256k1_context* ctx, secp256k1_ge* ge, const secp256k1_pubkey* pubkey) {
|
|
|
|
if (sizeof(secp256k1_ge_storage) == 64) {
|
|
|
|
/* When the secp256k1_ge_storage type is exactly 64 byte, use its
|
|
|
|
* representation inside secp256k1_pubkey, as conversion is very fast.
|
2015-07-20 13:36:55 -04:00
|
|
|
* Note that secp256k1_pubkey_save must use the same representation. */
|
2015-09-21 20:57:54 +02:00
|
|
|
secp256k1_ge_storage s;
|
2017-06-22 23:31:23 -07:00
|
|
|
memcpy(&s, &pubkey->data[0], sizeof(s));
|
2015-07-20 13:36:55 -04:00
|
|
|
secp256k1_ge_from_storage(ge, &s);
|
|
|
|
} else {
|
|
|
|
/* Otherwise, fall back to 32-byte big endian for X and Y. */
|
2015-09-21 20:57:54 +02:00
|
|
|
secp256k1_fe x, y;
|
2015-07-20 13:36:55 -04:00
|
|
|
secp256k1_fe_set_b32(&x, pubkey->data);
|
|
|
|
secp256k1_fe_set_b32(&y, pubkey->data + 32);
|
|
|
|
secp256k1_ge_set_xy(ge, &x, &y);
|
|
|
|
}
|
2015-07-18 16:29:10 -04:00
|
|
|
ARG_CHECK(!secp256k1_fe_is_zero(&ge->x));
|
|
|
|
return 1;
|
2015-07-20 13:36:55 -04:00
|
|
|
}
|
|
|
|
|
2015-09-21 20:57:54 +02:00
|
|
|
static void secp256k1_pubkey_save(secp256k1_pubkey* pubkey, secp256k1_ge* ge) {
|
|
|
|
if (sizeof(secp256k1_ge_storage) == 64) {
|
|
|
|
secp256k1_ge_storage s;
|
2015-07-20 13:36:55 -04:00
|
|
|
secp256k1_ge_to_storage(&s, ge);
|
2017-06-22 23:31:23 -07:00
|
|
|
memcpy(&pubkey->data[0], &s, sizeof(s));
|
2015-07-20 13:36:55 -04:00
|
|
|
} else {
|
|
|
|
VERIFY_CHECK(!secp256k1_ge_is_infinity(ge));
|
|
|
|
secp256k1_fe_normalize_var(&ge->x);
|
|
|
|
secp256k1_fe_normalize_var(&ge->y);
|
|
|
|
secp256k1_fe_get_b32(pubkey->data, &ge->x);
|
|
|
|
secp256k1_fe_get_b32(pubkey->data + 32, &ge->y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-21 20:57:54 +02:00
|
|
|
int secp256k1_ec_pubkey_parse(const secp256k1_context* ctx, secp256k1_pubkey* pubkey, const unsigned char *input, size_t inputlen) {
|
|
|
|
secp256k1_ge Q;
|
2015-07-20 13:36:55 -04:00
|
|
|
|
2015-09-27 23:45:12 +00:00
|
|
|
VERIFY_CHECK(ctx != NULL);
|
|
|
|
ARG_CHECK(pubkey != NULL);
|
|
|
|
memset(pubkey, 0, sizeof(*pubkey));
|
|
|
|
ARG_CHECK(input != NULL);
|
2015-07-20 13:36:55 -04:00
|
|
|
if (!secp256k1_eckey_pubkey_parse(&Q, input, inputlen)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
secp256k1_pubkey_save(pubkey, &Q);
|
|
|
|
secp256k1_ge_clear(&Q);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2015-09-21 20:57:54 +02:00
|
|
|
int secp256k1_ec_pubkey_serialize(const secp256k1_context* ctx, unsigned char *output, size_t *outputlen, const secp256k1_pubkey* pubkey, unsigned int flags) {
|
|
|
|
secp256k1_ge Q;
|
2015-10-30 09:16:40 +00:00
|
|
|
size_t len;
|
|
|
|
int ret = 0;
|
2015-07-20 13:36:55 -04:00
|
|
|
|
2015-09-27 23:45:12 +00:00
|
|
|
VERIFY_CHECK(ctx != NULL);
|
|
|
|
ARG_CHECK(outputlen != NULL);
|
2015-11-05 06:01:56 +01:00
|
|
|
ARG_CHECK(*outputlen >= ((flags & SECP256K1_FLAGS_BIT_COMPRESSION) ? 33 : 65));
|
2015-10-30 09:16:40 +00:00
|
|
|
len = *outputlen;
|
|
|
|
*outputlen = 0;
|
|
|
|
ARG_CHECK(output != NULL);
|
|
|
|
memset(output, 0, len);
|
2015-09-27 23:45:12 +00:00
|
|
|
ARG_CHECK(pubkey != NULL);
|
2015-10-21 17:43:29 +02:00
|
|
|
ARG_CHECK((flags & SECP256K1_FLAGS_TYPE_MASK) == SECP256K1_FLAGS_TYPE_COMPRESSION);
|
2015-10-30 09:16:40 +00:00
|
|
|
if (secp256k1_pubkey_load(ctx, &Q, pubkey)) {
|
|
|
|
ret = secp256k1_eckey_pubkey_serialize(&Q, output, &len, flags & SECP256K1_FLAGS_BIT_COMPRESSION);
|
|
|
|
if (ret) {
|
|
|
|
*outputlen = len;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
2015-07-20 13:36:55 -04:00
|
|
|
}
|
|
|
|
|
2015-09-21 20:57:54 +02:00
|
|
|
static void secp256k1_ecdsa_signature_load(const secp256k1_context* ctx, secp256k1_scalar* r, secp256k1_scalar* s, const secp256k1_ecdsa_signature* sig) {
|
2015-08-27 03:09:23 +02:00
|
|
|
(void)ctx;
|
2015-09-21 20:57:54 +02:00
|
|
|
if (sizeof(secp256k1_scalar) == 32) {
|
|
|
|
/* When the secp256k1_scalar type is exactly 32 byte, use its
|
|
|
|
* representation inside secp256k1_ecdsa_signature, as conversion is very fast.
|
2015-08-27 03:09:23 +02:00
|
|
|
* Note that secp256k1_ecdsa_signature_save must use the same representation. */
|
|
|
|
memcpy(r, &sig->data[0], 32);
|
|
|
|
memcpy(s, &sig->data[32], 32);
|
|
|
|
} else {
|
|
|
|
secp256k1_scalar_set_b32(r, &sig->data[0], NULL);
|
|
|
|
secp256k1_scalar_set_b32(s, &sig->data[32], NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-21 20:57:54 +02:00
|
|
|
static void secp256k1_ecdsa_signature_save(secp256k1_ecdsa_signature* sig, const secp256k1_scalar* r, const secp256k1_scalar* s) {
|
|
|
|
if (sizeof(secp256k1_scalar) == 32) {
|
2015-08-27 03:09:23 +02:00
|
|
|
memcpy(&sig->data[0], r, 32);
|
|
|
|
memcpy(&sig->data[32], s, 32);
|
|
|
|
} else {
|
|
|
|
secp256k1_scalar_get_b32(&sig->data[0], r);
|
|
|
|
secp256k1_scalar_get_b32(&sig->data[32], s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-21 20:57:54 +02:00
|
|
|
int secp256k1_ecdsa_signature_parse_der(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) {
|
|
|
|
secp256k1_scalar r, s;
|
2015-07-26 16:00:55 +02:00
|
|
|
|
2016-04-26 15:49:02 +00:00
|
|
|
VERIFY_CHECK(ctx != NULL);
|
2015-07-18 16:29:10 -04:00
|
|
|
ARG_CHECK(sig != NULL);
|
|
|
|
ARG_CHECK(input != NULL);
|
2015-07-26 16:00:55 +02:00
|
|
|
|
2015-07-26 16:51:58 +02:00
|
|
|
if (secp256k1_ecdsa_sig_parse(&r, &s, input, inputlen)) {
|
2015-08-27 03:09:23 +02:00
|
|
|
secp256k1_ecdsa_signature_save(sig, &r, &s);
|
2015-07-26 16:00:55 +02:00
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
memset(sig, 0, sizeof(*sig));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-28 17:40:21 +02:00
|
|
|
int secp256k1_ecdsa_signature_parse_compact(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input64) {
|
|
|
|
secp256k1_scalar r, s;
|
|
|
|
int ret = 1;
|
|
|
|
int overflow = 0;
|
|
|
|
|
2016-04-26 15:49:02 +00:00
|
|
|
VERIFY_CHECK(ctx != NULL);
|
2015-09-28 17:40:21 +02:00
|
|
|
ARG_CHECK(sig != NULL);
|
|
|
|
ARG_CHECK(input64 != NULL);
|
|
|
|
|
|
|
|
secp256k1_scalar_set_b32(&r, &input64[0], &overflow);
|
|
|
|
ret &= !overflow;
|
|
|
|
secp256k1_scalar_set_b32(&s, &input64[32], &overflow);
|
|
|
|
ret &= !overflow;
|
|
|
|
if (ret) {
|
|
|
|
secp256k1_ecdsa_signature_save(sig, &r, &s);
|
|
|
|
} else {
|
|
|
|
memset(sig, 0, sizeof(*sig));
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-09-21 20:57:54 +02:00
|
|
|
int secp256k1_ecdsa_signature_serialize_der(const secp256k1_context* ctx, unsigned char *output, size_t *outputlen, const secp256k1_ecdsa_signature* sig) {
|
|
|
|
secp256k1_scalar r, s;
|
2015-07-26 16:00:55 +02:00
|
|
|
|
2016-04-26 15:49:02 +00:00
|
|
|
VERIFY_CHECK(ctx != NULL);
|
2015-07-18 16:29:10 -04:00
|
|
|
ARG_CHECK(output != NULL);
|
|
|
|
ARG_CHECK(outputlen != NULL);
|
|
|
|
ARG_CHECK(sig != NULL);
|
2015-07-26 16:00:55 +02:00
|
|
|
|
2015-08-27 03:09:23 +02:00
|
|
|
secp256k1_ecdsa_signature_load(ctx, &r, &s, sig);
|
2015-07-26 16:51:58 +02:00
|
|
|
return secp256k1_ecdsa_sig_serialize(output, outputlen, &r, &s);
|
2015-07-26 16:00:55 +02:00
|
|
|
}
|
|
|
|
|
2015-09-28 17:40:21 +02:00
|
|
|
int secp256k1_ecdsa_signature_serialize_compact(const secp256k1_context* ctx, unsigned char *output64, const secp256k1_ecdsa_signature* sig) {
|
|
|
|
secp256k1_scalar r, s;
|
|
|
|
|
2016-04-26 15:49:02 +00:00
|
|
|
VERIFY_CHECK(ctx != NULL);
|
2015-09-28 17:40:21 +02:00
|
|
|
ARG_CHECK(output64 != NULL);
|
|
|
|
ARG_CHECK(sig != NULL);
|
|
|
|
|
|
|
|
secp256k1_ecdsa_signature_load(ctx, &r, &s, sig);
|
|
|
|
secp256k1_scalar_get_b32(&output64[0], &r);
|
|
|
|
secp256k1_scalar_get_b32(&output64[32], &s);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2015-10-14 18:54:32 +02:00
|
|
|
int secp256k1_ecdsa_signature_normalize(const secp256k1_context* ctx, secp256k1_ecdsa_signature *sigout, const secp256k1_ecdsa_signature *sigin) {
|
|
|
|
secp256k1_scalar r, s;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
VERIFY_CHECK(ctx != NULL);
|
|
|
|
ARG_CHECK(sigin != NULL);
|
|
|
|
|
|
|
|
secp256k1_ecdsa_signature_load(ctx, &r, &s, sigin);
|
|
|
|
ret = secp256k1_scalar_is_high(&s);
|
|
|
|
if (sigout != NULL) {
|
|
|
|
if (ret) {
|
|
|
|
secp256k1_scalar_negate(&s, &s);
|
|
|
|
}
|
|
|
|
secp256k1_ecdsa_signature_save(sigout, &r, &s);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-09-21 20:57:54 +02:00
|
|
|
int secp256k1_ecdsa_verify(const secp256k1_context* ctx, const secp256k1_ecdsa_signature *sig, const unsigned char *msg32, const secp256k1_pubkey *pubkey) {
|
|
|
|
secp256k1_ge q;
|
|
|
|
secp256k1_scalar r, s;
|
|
|
|
secp256k1_scalar m;
|
2015-09-01 14:22:32 -04:00
|
|
|
VERIFY_CHECK(ctx != NULL);
|
2015-07-18 16:29:10 -04:00
|
|
|
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
|
|
|
|
ARG_CHECK(msg32 != NULL);
|
|
|
|
ARG_CHECK(sig != NULL);
|
|
|
|
ARG_CHECK(pubkey != NULL);
|
2014-08-18 23:07:46 +02:00
|
|
|
|
2014-11-26 17:26:39 +01:00
|
|
|
secp256k1_scalar_set_b32(&m, msg32, NULL);
|
2015-08-27 03:09:23 +02:00
|
|
|
secp256k1_ecdsa_signature_load(ctx, &r, &s, sig);
|
2015-10-14 18:54:32 +02:00
|
|
|
return (!secp256k1_scalar_is_high(&s) &&
|
|
|
|
secp256k1_pubkey_load(ctx, &q, pubkey) &&
|
2015-07-18 16:29:10 -04:00
|
|
|
secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &r, &s, &q, &m));
|
2013-03-16 15:51:55 +01:00
|
|
|
}
|
|
|
|
|
2017-06-22 23:31:23 -07:00
|
|
|
static SECP256K1_INLINE void buffer_append(unsigned char *buf, unsigned int *offset, const void *data, unsigned int len) {
|
|
|
|
memcpy(buf + *offset, data, len);
|
|
|
|
*offset += len;
|
|
|
|
}
|
|
|
|
|
2015-09-01 05:48:58 +00:00
|
|
|
static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) {
|
2015-07-24 15:44:49 +02:00
|
|
|
unsigned char keydata[112];
|
2017-06-22 23:31:23 -07:00
|
|
|
unsigned int offset = 0;
|
2017-09-27 15:01:26 -07:00
|
|
|
secp256k1_rfc6979_hmac_sha256 rng;
|
2015-01-25 17:32:08 +00:00
|
|
|
unsigned int i;
|
2015-07-08 18:10:25 -04:00
|
|
|
/* We feed a byte array to the PRNG as input, consisting of:
|
|
|
|
* - the private key (32 bytes) and message (32 bytes), see RFC 6979 3.2d.
|
|
|
|
* - optionally 32 extra bytes of data, see RFC 6979 3.6 Additional Data.
|
2015-10-19 23:35:29 +00:00
|
|
|
* - optionally 16 extra bytes with the algorithm name.
|
|
|
|
* Because the arguments have distinct fixed lengths it is not possible for
|
|
|
|
* different argument mixtures to emulate each other and result in the same
|
|
|
|
* nonces.
|
2015-07-08 18:10:25 -04:00
|
|
|
*/
|
2017-06-22 23:31:23 -07:00
|
|
|
buffer_append(keydata, &offset, key32, 32);
|
|
|
|
buffer_append(keydata, &offset, msg32, 32);
|
2015-07-08 18:10:25 -04:00
|
|
|
if (data != NULL) {
|
2017-06-22 23:31:23 -07:00
|
|
|
buffer_append(keydata, &offset, data, 32);
|
2015-07-08 18:10:25 -04:00
|
|
|
}
|
2015-07-24 15:44:49 +02:00
|
|
|
if (algo16 != NULL) {
|
2017-06-22 23:31:23 -07:00
|
|
|
buffer_append(keydata, &offset, algo16, 16);
|
2015-07-24 15:44:49 +02:00
|
|
|
}
|
2017-06-22 23:31:23 -07:00
|
|
|
secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, offset);
|
2015-07-08 18:10:25 -04:00
|
|
|
memset(keydata, 0, sizeof(keydata));
|
2015-01-25 17:32:08 +00:00
|
|
|
for (i = 0; i <= counter; i++) {
|
2014-12-13 18:06:33 +01:00
|
|
|
secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32);
|
|
|
|
}
|
|
|
|
secp256k1_rfc6979_hmac_sha256_finalize(&rng);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2015-09-21 20:57:54 +02:00
|
|
|
const secp256k1_nonce_function secp256k1_nonce_function_rfc6979 = nonce_function_rfc6979;
|
|
|
|
const secp256k1_nonce_function secp256k1_nonce_function_default = nonce_function_rfc6979;
|
2014-12-13 18:06:33 +01:00
|
|
|
|
2015-09-21 20:57:54 +02:00
|
|
|
int secp256k1_ecdsa_sign(const secp256k1_context* ctx, secp256k1_ecdsa_signature *signature, const unsigned char *msg32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void* noncedata) {
|
|
|
|
secp256k1_scalar r, s;
|
|
|
|
secp256k1_scalar sec, non, msg;
|
2015-08-27 03:09:23 +02:00
|
|
|
int ret = 0;
|
|
|
|
int overflow = 0;
|
2015-09-01 14:22:32 -04:00
|
|
|
VERIFY_CHECK(ctx != NULL);
|
2015-08-27 03:09:23 +02:00
|
|
|
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
|
|
|
|
ARG_CHECK(msg32 != NULL);
|
|
|
|
ARG_CHECK(signature != NULL);
|
|
|
|
ARG_CHECK(seckey != NULL);
|
|
|
|
if (noncefp == NULL) {
|
|
|
|
noncefp = secp256k1_nonce_function_default;
|
|
|
|
}
|
|
|
|
|
|
|
|
secp256k1_scalar_set_b32(&sec, seckey, &overflow);
|
|
|
|
/* Fail if the secret key is invalid. */
|
|
|
|
if (!overflow && !secp256k1_scalar_is_zero(&sec)) {
|
2016-10-21 03:50:10 -07:00
|
|
|
unsigned char nonce32[32];
|
2015-09-24 08:42:37 +00:00
|
|
|
unsigned int count = 0;
|
2015-08-27 03:09:23 +02:00
|
|
|
secp256k1_scalar_set_b32(&msg, msg32, NULL);
|
|
|
|
while (1) {
|
2015-09-01 05:48:58 +00:00
|
|
|
ret = noncefp(nonce32, msg32, seckey, NULL, (void*)noncedata, count);
|
2015-08-27 03:09:23 +02:00
|
|
|
if (!ret) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
secp256k1_scalar_set_b32(&non, nonce32, &overflow);
|
2015-09-24 08:42:37 +00:00
|
|
|
if (!overflow && !secp256k1_scalar_is_zero(&non)) {
|
2015-08-27 03:09:23 +02:00
|
|
|
if (secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &r, &s, &sec, &msg, &non, NULL)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
count++;
|
|
|
|
}
|
2016-10-21 03:50:10 -07:00
|
|
|
memset(nonce32, 0, 32);
|
2015-08-27 03:09:23 +02:00
|
|
|
secp256k1_scalar_clear(&msg);
|
|
|
|
secp256k1_scalar_clear(&non);
|
|
|
|
secp256k1_scalar_clear(&sec);
|
|
|
|
}
|
|
|
|
if (ret) {
|
|
|
|
secp256k1_ecdsa_signature_save(signature, &r, &s);
|
|
|
|
} else {
|
|
|
|
memset(signature, 0, sizeof(*signature));
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-09-21 20:57:54 +02:00
|
|
|
int secp256k1_ec_seckey_verify(const secp256k1_context* ctx, const unsigned char *seckey) {
|
|
|
|
secp256k1_scalar sec;
|
2015-01-25 17:32:08 +00:00
|
|
|
int ret;
|
2014-10-28 04:08:15 -07:00
|
|
|
int overflow;
|
2015-09-01 14:22:32 -04:00
|
|
|
VERIFY_CHECK(ctx != NULL);
|
2015-07-18 16:29:10 -04:00
|
|
|
ARG_CHECK(seckey != NULL);
|
2015-01-25 17:32:08 +00:00
|
|
|
|
2014-10-29 00:35:09 -07:00
|
|
|
secp256k1_scalar_set_b32(&sec, seckey, &overflow);
|
2015-09-24 08:42:37 +00:00
|
|
|
ret = !overflow && !secp256k1_scalar_is_zero(&sec);
|
2014-10-28 04:08:15 -07:00
|
|
|
secp256k1_scalar_clear(&sec);
|
2013-05-05 00:49:30 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-09-21 20:57:54 +02:00
|
|
|
int secp256k1_ec_pubkey_create(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *seckey) {
|
|
|
|
secp256k1_gej pj;
|
|
|
|
secp256k1_ge p;
|
|
|
|
secp256k1_scalar sec;
|
2015-02-17 00:10:12 -08:00
|
|
|
int overflow;
|
Eliminate multiple-returns from secp256k1.c.
Goto, multiple returns, continue, and/or multiple breaks in a
loop are often used to build complex or non-local control
flow in software.
(They're all basically the same thing, and anyone axiomatically
opposing goto and not the rest is probably cargo-culting from
the title of Dijkstra's essay without thinking hard about it.)
Personally, I think the current use of these constructs in the
code base is fine: no where are we using them to create control-
flow that couldn't easily be described in plain English, which
is hard to read or reason about, or which looks like a trap for
future developers.
Some, however, prefer a more rules based approach to software
quality. In particular, MISRA forbids all of these constructs,
and for good experience based reasons. Rules also have the
benefit of being machine checkable and surviving individual
developers.
(To be fair-- MISRA also has a process for accommodating code that
breaks the rules for good reason).
I think that in general we should also try to satisfy the rules-
based measures of software quality, except where there is an
objective reason not do: a measurable performance difference,
logic that turns to spaghetti, etc.
Changing out all the multiple returns in secp256k1.c appears to
be basically neutral: Some parts become slightly less clear,
some parts slightly more.
2015-02-17 01:01:48 -08:00
|
|
|
int ret = 0;
|
2015-09-01 14:22:32 -04:00
|
|
|
VERIFY_CHECK(ctx != NULL);
|
2015-07-18 16:29:10 -04:00
|
|
|
ARG_CHECK(pubkey != NULL);
|
2015-10-30 09:16:40 +00:00
|
|
|
memset(pubkey, 0, sizeof(*pubkey));
|
|
|
|
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
|
2015-07-18 16:29:10 -04:00
|
|
|
ARG_CHECK(seckey != NULL);
|
2014-08-18 23:07:46 +02:00
|
|
|
|
2015-02-17 00:10:12 -08:00
|
|
|
secp256k1_scalar_set_b32(&sec, seckey, &overflow);
|
2019-05-26 10:22:38 +00:00
|
|
|
ret = !overflow && !secp256k1_scalar_is_zero(&sec);
|
2015-10-19 23:30:27 +00:00
|
|
|
if (ret) {
|
|
|
|
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pj, &sec);
|
|
|
|
secp256k1_ge_set_gej(&p, &pj);
|
|
|
|
secp256k1_pubkey_save(pubkey, &p);
|
2015-07-13 13:09:00 +01:00
|
|
|
}
|
2015-10-19 23:30:27 +00:00
|
|
|
secp256k1_scalar_clear(&sec);
|
2015-07-13 13:09:00 +01:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-07-28 16:05:40 +00:00
|
|
|
int secp256k1_ec_privkey_negate(const secp256k1_context* ctx, unsigned char *seckey) {
|
|
|
|
secp256k1_scalar sec;
|
|
|
|
VERIFY_CHECK(ctx != NULL);
|
|
|
|
ARG_CHECK(seckey != NULL);
|
|
|
|
|
|
|
|
secp256k1_scalar_set_b32(&sec, seckey, NULL);
|
|
|
|
secp256k1_scalar_negate(&sec, &sec);
|
|
|
|
secp256k1_scalar_get_b32(seckey, &sec);
|
|
|
|
|
2019-05-15 15:55:01 +09:00
|
|
|
secp256k1_scalar_clear(&sec);
|
2016-07-28 16:05:40 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int secp256k1_ec_pubkey_negate(const secp256k1_context* ctx, secp256k1_pubkey *pubkey) {
|
|
|
|
int ret = 0;
|
|
|
|
secp256k1_ge p;
|
|
|
|
VERIFY_CHECK(ctx != NULL);
|
|
|
|
ARG_CHECK(pubkey != NULL);
|
|
|
|
|
|
|
|
ret = secp256k1_pubkey_load(ctx, &p, pubkey);
|
|
|
|
memset(pubkey, 0, sizeof(*pubkey));
|
|
|
|
if (ret) {
|
|
|
|
secp256k1_ge_neg(&p, &p);
|
|
|
|
secp256k1_pubkey_save(pubkey, &p);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-09-21 20:57:54 +02:00
|
|
|
int secp256k1_ec_privkey_tweak_add(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak) {
|
|
|
|
secp256k1_scalar term;
|
|
|
|
secp256k1_scalar sec;
|
Eliminate multiple-returns from secp256k1.c.
Goto, multiple returns, continue, and/or multiple breaks in a
loop are often used to build complex or non-local control
flow in software.
(They're all basically the same thing, and anyone axiomatically
opposing goto and not the rest is probably cargo-culting from
the title of Dijkstra's essay without thinking hard about it.)
Personally, I think the current use of these constructs in the
code base is fine: no where are we using them to create control-
flow that couldn't easily be described in plain English, which
is hard to read or reason about, or which looks like a trap for
future developers.
Some, however, prefer a more rules based approach to software
quality. In particular, MISRA forbids all of these constructs,
and for good experience based reasons. Rules also have the
benefit of being machine checkable and surviving individual
developers.
(To be fair-- MISRA also has a process for accommodating code that
breaks the rules for good reason).
I think that in general we should also try to satisfy the rules-
based measures of software quality, except where there is an
objective reason not do: a measurable performance difference,
logic that turns to spaghetti, etc.
Changing out all the multiple returns in secp256k1.c appears to
be basically neutral: Some parts become slightly less clear,
some parts slightly more.
2015-02-17 01:01:48 -08:00
|
|
|
int ret = 0;
|
2015-01-25 17:32:08 +00:00
|
|
|
int overflow = 0;
|
2015-09-01 14:22:32 -04:00
|
|
|
VERIFY_CHECK(ctx != NULL);
|
2015-07-18 16:29:10 -04:00
|
|
|
ARG_CHECK(seckey != NULL);
|
|
|
|
ARG_CHECK(tweak != NULL);
|
2014-08-18 23:07:46 +02:00
|
|
|
|
2014-10-29 00:35:09 -07:00
|
|
|
secp256k1_scalar_set_b32(&term, tweak, &overflow);
|
|
|
|
secp256k1_scalar_set_b32(&sec, seckey, NULL);
|
2014-10-27 03:27:55 -07:00
|
|
|
|
2015-09-24 08:42:37 +00:00
|
|
|
ret = !overflow && secp256k1_eckey_privkey_tweak_add(&sec, &term);
|
2015-10-21 04:17:05 +00:00
|
|
|
memset(seckey, 0, 32);
|
2013-05-27 01:18:48 +02:00
|
|
|
if (ret) {
|
2014-10-29 00:35:09 -07:00
|
|
|
secp256k1_scalar_get_b32(seckey, &sec);
|
2014-10-27 03:27:55 -07:00
|
|
|
}
|
|
|
|
|
2014-10-28 04:08:15 -07:00
|
|
|
secp256k1_scalar_clear(&sec);
|
|
|
|
secp256k1_scalar_clear(&term);
|
2013-05-27 01:18:48 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-09-21 20:57:54 +02:00
|
|
|
int secp256k1_ec_pubkey_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *tweak) {
|
|
|
|
secp256k1_ge p;
|
|
|
|
secp256k1_scalar term;
|
Eliminate multiple-returns from secp256k1.c.
Goto, multiple returns, continue, and/or multiple breaks in a
loop are often used to build complex or non-local control
flow in software.
(They're all basically the same thing, and anyone axiomatically
opposing goto and not the rest is probably cargo-culting from
the title of Dijkstra's essay without thinking hard about it.)
Personally, I think the current use of these constructs in the
code base is fine: no where are we using them to create control-
flow that couldn't easily be described in plain English, which
is hard to read or reason about, or which looks like a trap for
future developers.
Some, however, prefer a more rules based approach to software
quality. In particular, MISRA forbids all of these constructs,
and for good experience based reasons. Rules also have the
benefit of being machine checkable and surviving individual
developers.
(To be fair-- MISRA also has a process for accommodating code that
breaks the rules for good reason).
I think that in general we should also try to satisfy the rules-
based measures of software quality, except where there is an
objective reason not do: a measurable performance difference,
logic that turns to spaghetti, etc.
Changing out all the multiple returns in secp256k1.c appears to
be basically neutral: Some parts become slightly less clear,
some parts slightly more.
2015-02-17 01:01:48 -08:00
|
|
|
int ret = 0;
|
2015-01-25 17:32:08 +00:00
|
|
|
int overflow = 0;
|
2015-09-01 14:22:32 -04:00
|
|
|
VERIFY_CHECK(ctx != NULL);
|
2015-07-18 16:29:10 -04:00
|
|
|
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
|
|
|
|
ARG_CHECK(pubkey != NULL);
|
|
|
|
ARG_CHECK(tweak != NULL);
|
2014-08-18 23:07:46 +02:00
|
|
|
|
2014-11-26 17:26:39 +01:00
|
|
|
secp256k1_scalar_set_b32(&term, tweak, &overflow);
|
2015-10-21 04:17:05 +00:00
|
|
|
ret = !overflow && secp256k1_pubkey_load(ctx, &p, pubkey);
|
|
|
|
memset(pubkey, 0, sizeof(*pubkey));
|
|
|
|
if (ret) {
|
|
|
|
if (secp256k1_eckey_pubkey_tweak_add(&ctx->ecmult_ctx, &p, &term)) {
|
2015-07-20 13:36:55 -04:00
|
|
|
secp256k1_pubkey_save(pubkey, &p);
|
|
|
|
} else {
|
2015-10-21 04:17:05 +00:00
|
|
|
ret = 0;
|
Eliminate multiple-returns from secp256k1.c.
Goto, multiple returns, continue, and/or multiple breaks in a
loop are often used to build complex or non-local control
flow in software.
(They're all basically the same thing, and anyone axiomatically
opposing goto and not the rest is probably cargo-culting from
the title of Dijkstra's essay without thinking hard about it.)
Personally, I think the current use of these constructs in the
code base is fine: no where are we using them to create control-
flow that couldn't easily be described in plain English, which
is hard to read or reason about, or which looks like a trap for
future developers.
Some, however, prefer a more rules based approach to software
quality. In particular, MISRA forbids all of these constructs,
and for good experience based reasons. Rules also have the
benefit of being machine checkable and surviving individual
developers.
(To be fair-- MISRA also has a process for accommodating code that
breaks the rules for good reason).
I think that in general we should also try to satisfy the rules-
based measures of software quality, except where there is an
objective reason not do: a measurable performance difference,
logic that turns to spaghetti, etc.
Changing out all the multiple returns in secp256k1.c appears to
be basically neutral: Some parts become slightly less clear,
some parts slightly more.
2015-02-17 01:01:48 -08:00
|
|
|
}
|
2013-07-14 17:43:13 +02:00
|
|
|
}
|
2014-10-27 03:27:55 -07:00
|
|
|
|
2013-07-14 17:43:13 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-09-21 20:57:54 +02:00
|
|
|
int secp256k1_ec_privkey_tweak_mul(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak) {
|
|
|
|
secp256k1_scalar factor;
|
|
|
|
secp256k1_scalar sec;
|
Eliminate multiple-returns from secp256k1.c.
Goto, multiple returns, continue, and/or multiple breaks in a
loop are often used to build complex or non-local control
flow in software.
(They're all basically the same thing, and anyone axiomatically
opposing goto and not the rest is probably cargo-culting from
the title of Dijkstra's essay without thinking hard about it.)
Personally, I think the current use of these constructs in the
code base is fine: no where are we using them to create control-
flow that couldn't easily be described in plain English, which
is hard to read or reason about, or which looks like a trap for
future developers.
Some, however, prefer a more rules based approach to software
quality. In particular, MISRA forbids all of these constructs,
and for good experience based reasons. Rules also have the
benefit of being machine checkable and surviving individual
developers.
(To be fair-- MISRA also has a process for accommodating code that
breaks the rules for good reason).
I think that in general we should also try to satisfy the rules-
based measures of software quality, except where there is an
objective reason not do: a measurable performance difference,
logic that turns to spaghetti, etc.
Changing out all the multiple returns in secp256k1.c appears to
be basically neutral: Some parts become slightly less clear,
some parts slightly more.
2015-02-17 01:01:48 -08:00
|
|
|
int ret = 0;
|
2015-01-25 17:32:08 +00:00
|
|
|
int overflow = 0;
|
2015-09-01 14:22:32 -04:00
|
|
|
VERIFY_CHECK(ctx != NULL);
|
2015-07-18 16:29:10 -04:00
|
|
|
ARG_CHECK(seckey != NULL);
|
|
|
|
ARG_CHECK(tweak != NULL);
|
2014-08-18 23:07:46 +02:00
|
|
|
|
2014-10-29 00:35:09 -07:00
|
|
|
secp256k1_scalar_set_b32(&factor, tweak, &overflow);
|
|
|
|
secp256k1_scalar_set_b32(&sec, seckey, NULL);
|
2015-09-24 08:42:37 +00:00
|
|
|
ret = !overflow && secp256k1_eckey_privkey_tweak_mul(&sec, &factor);
|
2015-10-21 04:17:05 +00:00
|
|
|
memset(seckey, 0, 32);
|
2013-07-14 17:43:13 +02:00
|
|
|
if (ret) {
|
2014-10-29 00:35:09 -07:00
|
|
|
secp256k1_scalar_get_b32(seckey, &sec);
|
2014-10-27 03:27:55 -07:00
|
|
|
}
|
|
|
|
|
2014-10-28 04:08:15 -07:00
|
|
|
secp256k1_scalar_clear(&sec);
|
|
|
|
secp256k1_scalar_clear(&factor);
|
2013-07-14 17:43:13 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-09-21 20:57:54 +02:00
|
|
|
int secp256k1_ec_pubkey_tweak_mul(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *tweak) {
|
|
|
|
secp256k1_ge p;
|
|
|
|
secp256k1_scalar factor;
|
Eliminate multiple-returns from secp256k1.c.
Goto, multiple returns, continue, and/or multiple breaks in a
loop are often used to build complex or non-local control
flow in software.
(They're all basically the same thing, and anyone axiomatically
opposing goto and not the rest is probably cargo-culting from
the title of Dijkstra's essay without thinking hard about it.)
Personally, I think the current use of these constructs in the
code base is fine: no where are we using them to create control-
flow that couldn't easily be described in plain English, which
is hard to read or reason about, or which looks like a trap for
future developers.
Some, however, prefer a more rules based approach to software
quality. In particular, MISRA forbids all of these constructs,
and for good experience based reasons. Rules also have the
benefit of being machine checkable and surviving individual
developers.
(To be fair-- MISRA also has a process for accommodating code that
breaks the rules for good reason).
I think that in general we should also try to satisfy the rules-
based measures of software quality, except where there is an
objective reason not do: a measurable performance difference,
logic that turns to spaghetti, etc.
Changing out all the multiple returns in secp256k1.c appears to
be basically neutral: Some parts become slightly less clear,
some parts slightly more.
2015-02-17 01:01:48 -08:00
|
|
|
int ret = 0;
|
2015-01-25 17:32:08 +00:00
|
|
|
int overflow = 0;
|
2015-09-01 14:22:32 -04:00
|
|
|
VERIFY_CHECK(ctx != NULL);
|
2015-07-18 16:29:10 -04:00
|
|
|
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
|
|
|
|
ARG_CHECK(pubkey != NULL);
|
|
|
|
ARG_CHECK(tweak != NULL);
|
2014-08-18 23:07:46 +02:00
|
|
|
|
2014-11-26 17:26:39 +01:00
|
|
|
secp256k1_scalar_set_b32(&factor, tweak, &overflow);
|
2015-10-21 04:17:05 +00:00
|
|
|
ret = !overflow && secp256k1_pubkey_load(ctx, &p, pubkey);
|
|
|
|
memset(pubkey, 0, sizeof(*pubkey));
|
|
|
|
if (ret) {
|
|
|
|
if (secp256k1_eckey_pubkey_tweak_mul(&ctx->ecmult_ctx, &p, &factor)) {
|
2015-07-20 13:36:55 -04:00
|
|
|
secp256k1_pubkey_save(pubkey, &p);
|
|
|
|
} else {
|
2015-10-21 04:17:05 +00:00
|
|
|
ret = 0;
|
Eliminate multiple-returns from secp256k1.c.
Goto, multiple returns, continue, and/or multiple breaks in a
loop are often used to build complex or non-local control
flow in software.
(They're all basically the same thing, and anyone axiomatically
opposing goto and not the rest is probably cargo-culting from
the title of Dijkstra's essay without thinking hard about it.)
Personally, I think the current use of these constructs in the
code base is fine: no where are we using them to create control-
flow that couldn't easily be described in plain English, which
is hard to read or reason about, or which looks like a trap for
future developers.
Some, however, prefer a more rules based approach to software
quality. In particular, MISRA forbids all of these constructs,
and for good experience based reasons. Rules also have the
benefit of being machine checkable and surviving individual
developers.
(To be fair-- MISRA also has a process for accommodating code that
breaks the rules for good reason).
I think that in general we should also try to satisfy the rules-
based measures of software quality, except where there is an
objective reason not do: a measurable performance difference,
logic that turns to spaghetti, etc.
Changing out all the multiple returns in secp256k1.c appears to
be basically neutral: Some parts become slightly less clear,
some parts slightly more.
2015-02-17 01:01:48 -08:00
|
|
|
}
|
2013-05-27 01:18:48 +02:00
|
|
|
}
|
2014-10-27 03:27:55 -07:00
|
|
|
|
2013-05-27 01:18:48 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-09-21 20:57:54 +02:00
|
|
|
int secp256k1_context_randomize(secp256k1_context* ctx, const unsigned char *seed32) {
|
2015-09-01 14:22:32 -04:00
|
|
|
VERIFY_CHECK(ctx != NULL);
|
2019-01-27 13:17:37 +01:00
|
|
|
if (secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)) {
|
|
|
|
secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, seed32);
|
|
|
|
}
|
2015-04-15 21:35:50 +00:00
|
|
|
return 1;
|
|
|
|
}
|
2015-06-29 15:06:28 -05:00
|
|
|
|
2015-10-31 19:04:34 +00:00
|
|
|
int secp256k1_ec_pubkey_combine(const secp256k1_context* ctx, secp256k1_pubkey *pubnonce, const secp256k1_pubkey * const *pubnonces, size_t n) {
|
|
|
|
size_t i;
|
2015-09-21 20:57:54 +02:00
|
|
|
secp256k1_gej Qj;
|
|
|
|
secp256k1_ge Q;
|
2015-07-24 15:44:49 +02:00
|
|
|
|
|
|
|
ARG_CHECK(pubnonce != NULL);
|
2015-10-31 09:52:30 +00:00
|
|
|
memset(pubnonce, 0, sizeof(*pubnonce));
|
2015-07-24 15:44:49 +02:00
|
|
|
ARG_CHECK(n >= 1);
|
|
|
|
ARG_CHECK(pubnonces != NULL);
|
|
|
|
|
|
|
|
secp256k1_gej_set_infinity(&Qj);
|
|
|
|
|
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
secp256k1_pubkey_load(ctx, &Q, pubnonces[i]);
|
|
|
|
secp256k1_gej_add_ge(&Qj, &Qj, &Q);
|
|
|
|
}
|
|
|
|
if (secp256k1_gej_is_infinity(&Qj)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
secp256k1_ge_set_gej(&Q, &Qj);
|
|
|
|
secp256k1_pubkey_save(pubnonce, &Q);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2015-06-29 15:06:28 -05:00
|
|
|
#ifdef ENABLE_MODULE_ECDH
|
|
|
|
# include "modules/ecdh/main_impl.h"
|
|
|
|
#endif
|
2015-07-24 15:44:49 +02:00
|
|
|
|
2015-08-27 03:42:57 +02:00
|
|
|
#ifdef ENABLE_MODULE_RECOVERY
|
|
|
|
# include "modules/recovery/main_impl.h"
|
|
|
|
#endif
|
Pedersen commitments, borromean ring signatures, and ZK range proofs.
This commit adds three new cryptosystems to libsecp256k1:
Pedersen commitments are a system for making blinded commitments
to a value. Functionally they work like:
commit_b,v = H(blind_b || value_v),
except they are additively homorphic, e.g.
C(b1, v1) - C(b2, v2) = C(b1 - b2, v1 - v2) and
C(b1, v1) - C(b1, v1) = 0, etc.
The commitments themselves are EC points, serialized as 33 bytes.
In addition to the commit function this implementation includes
utility functions for verifying that a set of commitments sums
to zero, and for picking blinding factors that sum to zero.
If the blinding factors are uniformly random, pedersen commitments
have information theoretic privacy.
Borromean ring signatures are a novel efficient ring signature
construction for AND/OR admissions policies (the code here implements
an AND of ORs, each of any size). This construction requires
32 bytes of signature per pubkey used plus 32 bytes of constant
overhead. With these you can construct signatures like "Given pubkeys
A B C D E F G, the signer knows the discrete logs
satisifying (A || B) & (C || D || E) & (F || G)".
ZK range proofs allow someone to prove a pedersen commitment is in
a particular range (e.g. [0..2^64)) without revealing the specific
value. The construction here is based on the above borromean
ring signature and uses a radix-4 encoding and other optimizations
to maximize efficiency. It also supports encoding proofs with a
non-private base-10 exponent and minimum-value to allow trading
off secrecy for size and speed (or just avoiding wasting space
keeping data private that was already public due to external
constraints).
A proof for a 32-bit mantissa takes 2564 bytes, but 2048 bytes of
this can be used to communicate a private message to a receiver
who shares a secret random seed with the prover.
Also: get rid of precomputed H tables (Pieter Wuille)
2015-08-05 19:04:14 +02:00
|
|
|
|
2016-07-07 00:47:41 +02:00
|
|
|
#ifdef ENABLE_MODULE_GENERATOR
|
|
|
|
# include "modules/generator/main_impl.h"
|
|
|
|
#endif
|
|
|
|
|
Pedersen commitments, borromean ring signatures, and ZK range proofs.
This commit adds three new cryptosystems to libsecp256k1:
Pedersen commitments are a system for making blinded commitments
to a value. Functionally they work like:
commit_b,v = H(blind_b || value_v),
except they are additively homorphic, e.g.
C(b1, v1) - C(b2, v2) = C(b1 - b2, v1 - v2) and
C(b1, v1) - C(b1, v1) = 0, etc.
The commitments themselves are EC points, serialized as 33 bytes.
In addition to the commit function this implementation includes
utility functions for verifying that a set of commitments sums
to zero, and for picking blinding factors that sum to zero.
If the blinding factors are uniformly random, pedersen commitments
have information theoretic privacy.
Borromean ring signatures are a novel efficient ring signature
construction for AND/OR admissions policies (the code here implements
an AND of ORs, each of any size). This construction requires
32 bytes of signature per pubkey used plus 32 bytes of constant
overhead. With these you can construct signatures like "Given pubkeys
A B C D E F G, the signer knows the discrete logs
satisifying (A || B) & (C || D || E) & (F || G)".
ZK range proofs allow someone to prove a pedersen commitment is in
a particular range (e.g. [0..2^64)) without revealing the specific
value. The construction here is based on the above borromean
ring signature and uses a radix-4 encoding and other optimizations
to maximize efficiency. It also supports encoding proofs with a
non-private base-10 exponent and minimum-value to allow trading
off secrecy for size and speed (or just avoiding wasting space
keeping data private that was already public due to external
constraints).
A proof for a 32-bit mantissa takes 2564 bytes, but 2048 bytes of
this can be used to communicate a private message to a receiver
who shares a secret random seed with the prover.
Also: get rid of precomputed H tables (Pieter Wuille)
2015-08-05 19:04:14 +02:00
|
|
|
#ifdef ENABLE_MODULE_RANGEPROOF
|
|
|
|
# include "modules/rangeproof/main_impl.h"
|
|
|
|
#endif
|
2016-04-21 22:22:39 +00:00
|
|
|
|
|
|
|
#ifdef ENABLE_MODULE_WHITELIST
|
|
|
|
# include "modules/whitelist/main_impl.h"
|
|
|
|
#endif
|
2016-07-01 15:51:07 +00:00
|
|
|
|
|
|
|
#ifdef ENABLE_MODULE_SURJECTIONPROOF
|
|
|
|
# include "modules/surjection/main_impl.h"
|
|
|
|
#endif
|