Skip to content
Open
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ bench
bench_ecmult
bench_generator
bench_rangeproof
bench_whitelist
bench_internal
tests
exhaustive_tests
Expand Down Expand Up @@ -60,4 +61,4 @@ src/stamp-h1
libsecp256k1.pc
contrib/gh-pr-create.sh

example_musig
example_musig
9 changes: 9 additions & 0 deletions include/secp256k1_rangeproof.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@ extern "C" {

#include <stdint.h>

/** Length of a message that can be embedded into a maximally-sized rangeproof
*
* It is not be possible to fit a message of this size into a non-maximally-sized
* rangeproof, but it is guaranteed that any embeddable message can fit into an
* array of this size. This constant is intended to be used for memory allocations
* and sanity checks.
*/
#define SECP256K1_RANGEPROOF_MAX_MESSAGE_LEN 3968

/** Opaque data structure that stores a Pedersen commitment
*
* The exact representation of data inside is implementation defined and not
Expand Down
2 changes: 1 addition & 1 deletion src/modules/rangeproof/borromean.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ int secp256k1_borromean_verify(secp256k1_scalar *evalues, const unsigned char *e
const secp256k1_gej *pubs, const size_t *rsizes, size_t nrings, const unsigned char *m, size_t mlen);

int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx,
unsigned char *e0, secp256k1_scalar *s, const secp256k1_gej *pubs, const secp256k1_scalar *k, const secp256k1_scalar *sec,
unsigned char *e0, secp256k1_scalar *s, const secp256k1_gej *pubs, const secp256k1_scalar *sec,
const size_t *rsizes, const size_t *secidx, size_t nrings, const unsigned char *m, size_t mlen);

#endif
12 changes: 8 additions & 4 deletions src/modules/rangeproof/borromean_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ int secp256k1_borromean_verify(secp256k1_scalar *evalues, const unsigned char *e
}

int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx,
unsigned char *e0, secp256k1_scalar *s, const secp256k1_gej *pubs, const secp256k1_scalar *k, const secp256k1_scalar *sec,
unsigned char *e0, secp256k1_scalar *s, const secp256k1_gej *pubs, const secp256k1_scalar *sec,
const size_t *rsizes, const size_t *secidx, size_t nrings, const unsigned char *m, size_t mlen) {
secp256k1_gej rgej;
secp256k1_ge rge;
Expand All @@ -125,7 +125,6 @@ int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx,
VERIFY_CHECK(e0 != NULL);
VERIFY_CHECK(s != NULL);
VERIFY_CHECK(pubs != NULL);
VERIFY_CHECK(k != NULL);
VERIFY_CHECK(sec != NULL);
VERIFY_CHECK(rsizes != NULL);
VERIFY_CHECK(secidx != NULL);
Expand All @@ -135,7 +134,8 @@ int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx,
count = 0;
for (i = 0; i < nrings; i++) {
VERIFY_CHECK(INT_MAX - count > rsizes[i]);
secp256k1_ecmult_gen(ecmult_gen_ctx, &rgej, &k[i]);
/* We have been provided an s value that we will just overwrite, so use it as a nonce */
secp256k1_ecmult_gen(ecmult_gen_ctx, &rgej, &s[count + secidx[i]]);
secp256k1_ge_set_gej(&rge, &rgej);
if (secp256k1_gej_is_infinity(&rgej)) {
return 0;
Expand Down Expand Up @@ -165,6 +165,10 @@ int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx,
secp256k1_sha256_finalize(&sha256_e0, e0);
count = 0;
for (i = 0; i < nrings; i++) {
/* We have been provided an s value that we will just overwrite, so use it as a nonce */
secp256k1_scalar k = s[count + secidx[i]];
secp256k1_scalar_clear(&s[count + secidx[i]]);

VERIFY_CHECK(INT_MAX - count > rsizes[i]);
secp256k1_borromean_hash(tmp, m, mlen, e0, 32, i, 0);
secp256k1_scalar_set_b32(&ens, tmp, &overflow);
Expand All @@ -186,7 +190,7 @@ int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx,
}
secp256k1_scalar_mul(&s[count + j], &ens, &sec[i]);
secp256k1_scalar_negate(&s[count + j], &s[count + j]);
secp256k1_scalar_add(&s[count + j], &s[count + j], &k[i]);
secp256k1_scalar_add(&s[count + j], &s[count + j], &k);
if (secp256k1_scalar_is_zero(&s[count + j])) {
return 0;
}
Expand Down
13 changes: 9 additions & 4 deletions src/modules/rangeproof/main_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,17 +231,22 @@ int secp256k1_pedersen_blind_generator_blind_sum(const secp256k1_context* ctx, c

int secp256k1_rangeproof_info(const secp256k1_context* ctx, int *exp, int *mantissa,
uint64_t *min_value, uint64_t *max_value, const unsigned char *proof, size_t plen) {
secp256k1_rangeproof_header header;
size_t offset;
uint64_t scale;
ARG_CHECK(exp != NULL);
ARG_CHECK(mantissa != NULL);
ARG_CHECK(min_value != NULL);
ARG_CHECK(max_value != NULL);
ARG_CHECK(proof != NULL);
offset = 0;
scale = 1;
(void)ctx;
return secp256k1_rangeproof_getheader_impl(&offset, exp, mantissa, &scale, min_value, max_value, proof, plen);
if (!secp256k1_rangeproof_header_parse(&header, &offset, proof, plen)) {
return 0;
}
*exp = header.exp;
*mantissa = header.mantissa;
*min_value = header.min_value;
*max_value = header.max_value;
return 1;
}

int secp256k1_rangeproof_rewind(const secp256k1_context* ctx,
Expand Down
73 changes: 73 additions & 0 deletions src/modules/rangeproof/rangeproof.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,79 @@
#include "ecmult.h"
#include "ecmult_gen.h"

/** Structure representing data directly encoded into a rangeproof header
*
* A rangeproof is a proof, associated with a Pedersen commitment, that a
* "proven value" in is the range [0, 2^mantissa - 1]. The committed value
* is related to the proven value by the contents of this header, as
*
* committed = min_value + 10^exp * proven
*/
typedef struct secp256k1_rangeproof_header {
/** Power of ten to multiply the proven value by, or -1 for an exact proof
*
* Encoded in the header. */
int exp;
/** Number of bits used to represent the proven value. Will be 0 for an exact proof.
*
* Encoded in the header. */
size_t mantissa;
/** 10 to the power of exp, or 1 for a proof of an exact value.
*
* Implied by `exp`, not encoded. */
uint64_t scale;
/** Minimum value for the range (added to the proven value).
*
* Encoded in the header. */
uint64_t min_value;
/** Maximum value for the range (min_value + 10^exp * 2^mantissa - 1).
*
* Implied by `min_value`, `exp`, `mantissa`. Not encoded. */
uint64_t max_value;
/** Number of rings to use in the underlying borromean ring signature
*
* Implied by `mantissa`. Not encoded. */
size_t n_rings;
/** Number of public keys to use in the underlying borromean ring signature
*
* Implied by `mantissa`. Not encoded. */
size_t n_pubs;
/** Number of keys in each ring
*
* Implied by `mantissa`. Not encoded. */
size_t rsizes[32];
} secp256k1_rangeproof_header;

/** Parses out a rangeproof header from a rangeproof and fills in all fields
*
* Returns: 1 on success, 0 on failure
* Out: header: the parsed header
* offset: the number of bytes of `proof` that the header occupied
* In: proof: the proof to parse the header out of
* plen: the length of the proof
*/
static int secp256k1_rangeproof_header_parse(
secp256k1_rangeproof_header* header,
size_t* offset,
const unsigned char* proof,
size_t plen
);

/** Serializes out a rangeproof header which has at least `exp`, `min_value` and `mantissa` set
*
* Returns: 1 on success, 0 on failure
* Out: proof: the buffer to serialize into
* offset: the number of bytes of `proof` that the header occupies
* In: plen: the length of the proof buffer
* header: the header to serialize
*/
static int secp256k1_rangeproof_header_serialize(
unsigned char* proof,
size_t plen,
size_t* offset,
const secp256k1_rangeproof_header* header
);

static int secp256k1_rangeproof_verify_impl(const secp256k1_ecmult_gen_context* ecmult_gen_ctx,
unsigned char *blindout, uint64_t *value_out, unsigned char *message_out, size_t *outlen, const unsigned char *nonce,
uint64_t *min_value, uint64_t *max_value, const secp256k1_ge *commit, const unsigned char *proof, size_t plen,
Expand Down
Loading