-
Notifications
You must be signed in to change notification settings - Fork 207
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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.
- Loading branch information
Showing
15 changed files
with
1,924 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
/********************************************************************** | ||
* Copyright (c) 2014, 2015 Pieter Wuille, Gregory Maxwell * | ||
* Distributed under the MIT software license, see the accompanying * | ||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* | ||
**********************************************************************/ | ||
|
||
#include <stdint.h> | ||
|
||
#include "include/secp256k1.h" | ||
#include "util.h" | ||
#include "bench.h" | ||
|
||
typedef struct { | ||
secp256k1_context_t* ctx; | ||
unsigned char commit[33]; | ||
unsigned char proof[5134]; | ||
unsigned char blind[32]; | ||
int len; | ||
int min_bits; | ||
uint64_t v; | ||
} bench_rangeproof_t; | ||
|
||
static void bench_rangeproof_setup(void* arg) { | ||
int i; | ||
uint64_t minv; | ||
uint64_t maxv; | ||
bench_rangeproof_t *data = (bench_rangeproof_t*)arg; | ||
|
||
data->v = 0; | ||
for (i = 0; i < 32; i++) data->blind[i] = i + 1; | ||
CHECK(secp256k1_pedersen_commit(data->ctx, data->commit, data->blind, data->v)); | ||
data->len = 5134; | ||
CHECK(secp256k1_rangeproof_sign(data->ctx, data->proof, &data->len, 0, data->commit, data->blind, data->commit, 0, data->min_bits, data->v)); | ||
CHECK(secp256k1_rangeproof_verify(data->ctx, &minv, &maxv, data->commit, data->proof, data->len)); | ||
} | ||
|
||
static void bench_rangeproof(void* arg) { | ||
int i; | ||
bench_rangeproof_t *data = (bench_rangeproof_t*)arg; | ||
|
||
for (i = 0; i < 1000; i++) { | ||
int j; | ||
uint64_t minv; | ||
uint64_t maxv; | ||
j = secp256k1_rangeproof_verify(data->ctx, &minv, &maxv, data->commit, data->proof, data->len); | ||
for (j = 0; j < 4; j++) { | ||
data->proof[j + 2 + 32 *((data->min_bits + 1) >> 1) - 4] = (i >> 8)&255; | ||
} | ||
} | ||
} | ||
|
||
int main(void) { | ||
bench_rangeproof_t data; | ||
|
||
data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_COMMIT | SECP256K1_CONTEXT_RANGEPROOF); | ||
|
||
data.min_bits = 32; | ||
|
||
run_benchmark("rangeproof_verif_bit", bench_rangeproof, bench_rangeproof_setup, NULL, &data, 10, 1000 * data.min_bits); | ||
|
||
secp256k1_context_destroy(data.ctx); | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
/********************************************************************** | ||
* Copyright (c) 2014, 2015 Gregory Maxwell * | ||
* Distributed under the MIT software license, see the accompanying * | ||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* | ||
**********************************************************************/ | ||
|
||
|
||
#ifndef _SECP256K1_BORROMEAN_H_ | ||
#define _SECP256K1_BORROMEAN_H_ | ||
|
||
#include "scalar.h" | ||
#include "field.h" | ||
#include "group.h" | ||
#include "ecmult.h" | ||
#include "ecmult_gen.h" | ||
|
||
int secp256k1_borromean_verify(const secp256k1_ecmult_context_t* ecmult_ctx, secp256k1_scalar_t *evalues, const unsigned char *e0, const secp256k1_scalar_t *s, | ||
const secp256k1_gej_t *pubs, const int *rsizes, int nrings, const unsigned char *m, int mlen); | ||
|
||
int secp256k1_borromean_sign(const secp256k1_ecmult_context_t* ecmult_ctx, const secp256k1_ecmult_gen_context_t *ecmult_gen_ctx, | ||
unsigned char *e0, secp256k1_scalar_t *s, const secp256k1_gej_t *pubs, const secp256k1_scalar_t *k, const secp256k1_scalar_t *sec, | ||
const int *rsizes, const int *secidx, int nrings, const unsigned char *m, int mlen); | ||
|
||
#endif |
Oops, something went wrong.