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.
This commit is contained in:
Gregory Maxwell
2015-08-05 19:04:14 +02:00
committed by Andrew Poelstra
parent efc61dc0ca
commit ae1e576f67
15 changed files with 1939 additions and 0 deletions

View File

@@ -19,6 +19,11 @@
#include "hash_impl.h"
#include "scratch_impl.h"
#ifdef ENABLE_MODULE_RANGEPROOF
# include "modules/rangeproof/pedersen.h"
# include "modules/rangeproof/rangeproof.h"
#endif
#define ARG_CHECK(cond) do { \
if (EXPECT(!(cond), 0)) { \
secp256k1_callback_call(&ctx->illegal_callback, #cond); \
@@ -52,6 +57,10 @@ static const secp256k1_callback default_error_callback = {
struct secp256k1_context_struct {
secp256k1_ecmult_context ecmult_ctx;
secp256k1_ecmult_gen_context ecmult_gen_ctx;
#ifdef ENABLE_MODULE_RANGEPROOF
secp256k1_pedersen_context pedersen_ctx;
secp256k1_rangeproof_context rangeproof_ctx;
#endif
secp256k1_callback illegal_callback;
secp256k1_callback error_callback;
};
@@ -78,6 +87,10 @@ secp256k1_context* secp256k1_context_create(unsigned int flags) {
secp256k1_ecmult_context_init(&ret->ecmult_ctx);
secp256k1_ecmult_gen_context_init(&ret->ecmult_gen_ctx);
#ifdef ENABLE_MODULE_RANGEPROOF
secp256k1_pedersen_context_init(&ret->pedersen_ctx);
secp256k1_rangeproof_context_init(&ret->rangeproof_ctx);
#endif
if (flags & SECP256K1_FLAGS_BIT_CONTEXT_SIGN) {
secp256k1_ecmult_gen_context_build(&ret->ecmult_gen_ctx, &ret->error_callback);
@@ -95,6 +108,10 @@ secp256k1_context* secp256k1_context_clone(const secp256k1_context* ctx) {
ret->error_callback = ctx->error_callback;
secp256k1_ecmult_context_clone(&ret->ecmult_ctx, &ctx->ecmult_ctx, &ctx->error_callback);
secp256k1_ecmult_gen_context_clone(&ret->ecmult_gen_ctx, &ctx->ecmult_gen_ctx, &ctx->error_callback);
#ifdef ENABLE_MODULE_RANGEPROOF
secp256k1_pedersen_context_clone(&ret->pedersen_ctx, &ctx->pedersen_ctx, &ctx->error_callback);
secp256k1_rangeproof_context_clone(&ret->rangeproof_ctx, &ctx->rangeproof_ctx, &ctx->error_callback);
#endif
return ret;
}
@@ -103,6 +120,10 @@ void secp256k1_context_destroy(secp256k1_context* ctx) {
if (ctx != NULL) {
secp256k1_ecmult_context_clear(&ctx->ecmult_ctx);
secp256k1_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx);
#ifdef ENABLE_MODULE_RANGEPROOF
secp256k1_pedersen_context_clear(&ctx->pedersen_ctx);
secp256k1_rangeproof_context_clear(&ctx->rangeproof_ctx);
#endif
free(ctx);
}
@@ -607,3 +628,7 @@ int secp256k1_ec_pubkey_combine(const secp256k1_context* ctx, secp256k1_pubkey *
#ifdef ENABLE_MODULE_RECOVERY
# include "modules/recovery/main_impl.h"
#endif
#ifdef ENABLE_MODULE_RANGEPROOF
# include "modules/rangeproof/main_impl.h"
#endif