Browse Source

test

release/v0.1
jl777 9 years ago
parent
commit
6cc6b01325
  1. 4
      iguana/iguana777.c
  2. 484
      iguana/iguana_secp.c
  3. 5
      iguana/iguana_unspents.c
  4. 14
      iguana/main.c
  5. 134
      iguana/secp256k1/include/secp256k1.h
  6. 10
      iguana/secp256k1/include/secp256k1_ecdh.h
  7. 2
      iguana/secp256k1/include/secp256k1_rangeproof.h
  8. 40
      iguana/secp256k1/include/secp256k1_recovery.h
  9. 99
      iguana/secp256k1/include/secp256k1_schnorr.h
  10. 62
      iguana/secp256k1/src/bench_rangeproof.c
  11. 24
      iguana/secp256k1/src/libsecp256k1-config.h
  12. 7
      iguana/secp256k1/src/modules/rangeproof/borromean.h
  13. 99
      iguana/secp256k1/src/modules/rangeproof/borromean_impl.h
  14. 25
      iguana/secp256k1/src/modules/rangeproof/main_impl.h
  15. 13
      iguana/secp256k1/src/modules/rangeproof/rangeproof.h
  16. 487
      iguana/secp256k1/src/modules/rangeproof/rangeproof_impl.h
  17. 4
      iguana/secp256k1/src/modules/schnorr/tests_impl.h
  18. 19
      iguana/secp256k1/src/secp256k1.c
  19. 2
      iguana/secp256k1/src/testrand_impl.h
  20. 2
      iguana/tests/getreceivedbyaddress
  21. 25
      iguana/tests/json_extract.c
  22. 1
      iguana/tests/make_jsoncmp

4
iguana/iguana777.c

@ -16,6 +16,8 @@
#include "iguana777.h" #include "iguana777.h"
#include "secp256k1/include/secp256k1.h" #include "secp256k1/include/secp256k1.h"
#include "secp256k1/include/secp256k1_schnorr.h"
#include "secp256k1/include/secp256k1_rangeproof.h"
const char *Hardcoded_coins[][3] = { { "BTC", "bitcoin", "0" }, { "BTCD", "BitcoinDark", "129" }, { "VPN", "VPNcoin", "129" }, { "LTC", "litecoin", "129" } , { "endmarker", "", "" } }; const char *Hardcoded_coins[][3] = { { "BTC", "bitcoin", "0" }, { "BTCD", "BitcoinDark", "129" }, { "VPN", "VPNcoin", "129" }, { "LTC", "litecoin", "129" } , { "endmarker", "", "" } };
@ -75,6 +77,8 @@ struct iguana_info *iguana_coinadd(const char *symbol,cJSON *argjson)
} }
coin->chain = iguana_chainfind((char *)symbol,argjson,1); coin->chain = iguana_chainfind((char *)symbol,argjson,1);
coin->ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); coin->ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
secp256k1_pedersen_context_initialize(coin->ctx);
secp256k1_rangeproof_context_initialize(coin->ctx);
strcpy(coin->symbol,symbol); strcpy(coin->symbol,symbol);
iguana_initcoin(coin,argjson); iguana_initcoin(coin,argjson);
} }

484
iguana/iguana_secp.c

@ -19,30 +19,30 @@
#include <stdlib.h> #include <stdlib.h>
#include "../includes/curve25519.h" #include "../includes/curve25519.h"
#include "secp256k1/include/secp256k1.h" #include "secp256k1/include/secp256k1.h"
#include "secp256k1/include/secp256k1_ecdh.h"
#include "secp256k1/include/secp256k1_schnorr.h"
#include "secp256k1/include/secp256k1_rangeproof.h"
#include "secp256k1/include/secp256k1_recovery.h" #include "secp256k1/include/secp256k1_recovery.h"
#define bits256_nonz(a) (((a).ulongs[0] | (a).ulongs[1] | (a).ulongs[2] | (a).ulongs[3]) != 0)
//#include "../../secp256k1-zkp/include/secp256k1.h" #define SECP_ENSURE_CTX int32_t flag = 0; if ( ctx == 0 ) { ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); secp256k1_pedersen_context_initialize(ctx); secp256k1_rangeproof_context_initialize(ctx); flag++; } else flag = 0; if ( ctx != 0 )
//#include "../../secp256k1-zkp/include/secp256k1_recovery.h" #define ENDSECP_ENSURE_CTX if ( flag != 0 ) secp256k1_context_destroy(ctx);
bits256 bitcoin_randkey(secp256k1_context *ctx) bits256 bitcoin_randkey(secp256k1_context *ctx)
{ {
int32_t i,flag = 0; bits256 privkey; int32_t i; bits256 privkey;
if ( ctx == 0 ) SECP_ENSURE_CTX
ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY), flag++;
if ( ctx != 0 )
{ {
for (i=0; i<100; i++) for (i=0; i<100; i++)
{ {
privkey = rand256(0); privkey = rand256(0);
if ( secp256k1_ec_seckey_verify(ctx,privkey.bytes) > 0 ) if ( secp256k1_ec_seckey_verify(ctx,privkey.bytes) > 0 )
{ {
if ( flag != 0 ) ENDSECP_ENSURE_CTX
secp256k1_context_destroy(ctx);
return(privkey); return(privkey);
} }
} }
if ( flag != 0 ) ENDSECP_ENSURE_CTX
secp256k1_context_destroy(ctx);
} }
fprintf(stderr,"couldnt generate valid bitcoin privkey. something is REALLY wrong. exiting\n"); fprintf(stderr,"couldnt generate valid bitcoin privkey. something is REALLY wrong. exiting\n");
exit(-1); exit(-1);
@ -50,11 +50,9 @@ bits256 bitcoin_randkey(secp256k1_context *ctx)
bits256 bitcoin_pubkey33(secp256k1_context *ctx,uint8_t *data,bits256 privkey) bits256 bitcoin_pubkey33(secp256k1_context *ctx,uint8_t *data,bits256 privkey)
{ {
int32_t flag=0; size_t plen; bits256 pubkey; secp256k1_pubkey secppub; size_t plen; bits256 pubkey; secp256k1_pubkey secppub;
memset(pubkey.bytes,0,sizeof(pubkey)); memset(pubkey.bytes,0,sizeof(pubkey));
if ( ctx == 0 ) SECP_ENSURE_CTX
ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY), flag++;
if ( ctx != 0 )
{ {
if ( secp256k1_ec_seckey_verify(ctx,privkey.bytes) == 0 ) if ( secp256k1_ec_seckey_verify(ctx,privkey.bytes) == 0 )
{ {
@ -68,8 +66,7 @@ bits256 bitcoin_pubkey33(secp256k1_context *ctx,uint8_t *data,bits256 privkey)
if ( plen == 33 ) if ( plen == 33 )
memcpy(pubkey.bytes,data+1,sizeof(pubkey)); memcpy(pubkey.bytes,data+1,sizeof(pubkey));
} }
if ( flag != 0 ) ENDSECP_ENSURE_CTX
secp256k1_context_destroy(ctx);
} }
return(pubkey); return(pubkey);
} }
@ -77,12 +74,10 @@ bits256 bitcoin_pubkey33(secp256k1_context *ctx,uint8_t *data,bits256 privkey)
int32_t bitcoin_sign(void *ctx,char *symbol,uint8_t *sig,bits256 txhash2,bits256 privkey,int32_t recoverflag) int32_t bitcoin_sign(void *ctx,char *symbol,uint8_t *sig,bits256 txhash2,bits256 privkey,int32_t recoverflag)
{ {
int32_t fCompressed = 1; int32_t fCompressed = 1;
secp256k1_ecdsa_signature SIG; secp256k1_ecdsa_recoverable_signature rSIG; bits256 extra_entropy,seed; int32_t flag = 0,recid,retval = -1; size_t siglen = 72; secp256k1_pubkey SECPUB,CHECKPUB; secp256k1_ecdsa_signature SIG; secp256k1_ecdsa_recoverable_signature rSIG; bits256 extra_entropy,seed; int32_t recid,retval = -1; size_t siglen = 72; secp256k1_pubkey SECPUB,CHECKPUB;
seed = rand256(0); seed = rand256(0);
extra_entropy = rand256(0); extra_entropy = rand256(0);
if ( ctx == 0 ) SECP_ENSURE_CTX
ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY), flag++;
if ( ctx != 0 )
{ {
if ( secp256k1_ec_seckey_verify(ctx,privkey.bytes) == 0 ) if ( secp256k1_ec_seckey_verify(ctx,privkey.bytes) == 0 )
{ {
@ -120,19 +115,16 @@ int32_t bitcoin_sign(void *ctx,char *symbol,uint8_t *sig,bits256 txhash2,bits256
} }
} }
} }
if ( flag != 0 ) ENDSECP_ENSURE_CTX
secp256k1_context_destroy(ctx);
} }
return(retval); return(retval);
} }
int32_t bitcoin_recoververify(void *ctx,char *symbol,uint8_t *sig65,bits256 messagehash2,uint8_t *pubkey) int32_t bitcoin_recoververify(void *ctx,char *symbol,uint8_t *sig65,bits256 messagehash2,uint8_t *pubkey)
{ {
size_t plen; int32_t retval = -1,flag = 0; secp256k1_pubkey PUB; secp256k1_ecdsa_signature SIG; secp256k1_ecdsa_recoverable_signature rSIG; int32_t retval = -1; size_t plen; secp256k1_pubkey PUB; secp256k1_ecdsa_signature SIG; secp256k1_ecdsa_recoverable_signature rSIG;
pubkey[0] = 0; pubkey[0] = 0;
if ( ctx == 0 ) SECP_ENSURE_CTX
ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY), flag++;
if ( ctx != 0 )
{ {
plen = (sig65[0] <= 31) ? 65 : 33; plen = (sig65[0] <= 31) ? 65 : 33;
secp256k1_ecdsa_recoverable_signature_parse_compact(ctx,&rSIG,sig65 + 1,0); secp256k1_ecdsa_recoverable_signature_parse_compact(ctx,&rSIG,sig65 + 1,0);
@ -144,18 +136,15 @@ int32_t bitcoin_recoververify(void *ctx,char *symbol,uint8_t *sig65,bits256 mess
retval = 0; retval = 0;
else printf("secp256k1_ecdsa_verify error\n"); else printf("secp256k1_ecdsa_verify error\n");
} else printf("secp256k1_ecdsa_recover error\n"); } else printf("secp256k1_ecdsa_recover error\n");
if ( flag != 0 ) ENDSECP_ENSURE_CTX
secp256k1_context_destroy(ctx);
} }
return(retval); return(retval);
} }
int32_t bitcoin_verify(void *ctx,uint8_t *sig,int32_t siglen,bits256 txhash2,uint8_t *pubkey,int32_t plen) int32_t bitcoin_verify(void *ctx,uint8_t *sig,int32_t siglen,bits256 txhash2,uint8_t *pubkey,int32_t plen)
{ {
int32_t flag=0,retval = -1; secp256k1_pubkey PUB; secp256k1_ecdsa_signature SIG; int32_t retval = -1; secp256k1_pubkey PUB; secp256k1_ecdsa_signature SIG;
if ( ctx == 0 ) SECP_ENSURE_CTX
ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY), flag++;
if ( ctx != 0 )
{ {
if ( secp256k1_ec_pubkey_parse(ctx,&PUB,pubkey,plen) > 0 ) if ( secp256k1_ec_pubkey_parse(ctx,&PUB,pubkey,plen) > 0 )
{ {
@ -163,12 +152,438 @@ int32_t bitcoin_verify(void *ctx,uint8_t *sig,int32_t siglen,bits256 txhash2,uin
if ( secp256k1_ecdsa_verify(ctx,&SIG,txhash2.bytes,&PUB) > 0 ) if ( secp256k1_ecdsa_verify(ctx,&SIG,txhash2.bytes,&PUB) > 0 )
retval = 0; retval = 0;
} }
if ( flag != 0 ) ENDSECP_ENSURE_CTX
secp256k1_context_destroy(ctx); }
return(retval);
}
bits256 bitcoin_sharedsecret(void *ctx,bits256 privkey,uint8_t *pubkey,int32_t plen)
{
int32_t retval = -1; bits256 shared; secp256k1_pubkey PUB;
memset(shared.bytes,0,sizeof(shared));
SECP_ENSURE_CTX
{
if ( secp256k1_ec_pubkey_parse(ctx,&PUB,pubkey,plen) > 0 )
{
if ( secp256k1_ecdh(ctx,shared.bytes,&PUB,privkey.bytes) > 0 )
retval = 0;
else memset(shared.bytes,0,sizeof(shared));
}
ENDSECP_ENSURE_CTX
}
return(shared);
}
int32_t bitcoin_schnorr_sign(void *ctx,uint8_t *sig64,bits256 txhash2,bits256 privkey)
{
int32_t retval = -1;
SECP_ENSURE_CTX
{
if ( secp256k1_schnorr_sign(ctx,sig64,txhash2.bytes,privkey.bytes,secp256k1_nonce_function_rfc6979,rand256(0).bytes) > 0 )
retval = 0;
ENDSECP_ENSURE_CTX
}
return(retval);
}
int32_t bitcoin_schnorr_verify(void *ctx,uint8_t *sig64,bits256 txhash2,uint8_t *pubkey,int32_t plen)
{
int32_t retval = -1; secp256k1_pubkey PUB;
SECP_ENSURE_CTX
{
if ( secp256k1_ec_pubkey_parse(ctx,&PUB,pubkey,plen) > 0 )
{
if ( secp256k1_schnorr_verify(ctx,sig64,txhash2.bytes,&PUB) > 0 )
retval = 0;
}
ENDSECP_ENSURE_CTX
}
return(retval);
}
int32_t bitcoin_schnorr_recover(void *ctx,uint8_t *pubkey,uint8_t *sig64,bits256 txhash2)
{
int32_t retval = -1; secp256k1_pubkey PUB; size_t plen;
SECP_ENSURE_CTX
{
if ( secp256k1_schnorr_recover(ctx,&PUB,sig64,txhash2.bytes) > 0 )
{
plen = 33;
secp256k1_ec_pubkey_serialize(ctx,pubkey,&plen,&PUB,SECP256K1_EC_COMPRESSED);
retval = 0;
}
ENDSECP_ENSURE_CTX
}
return(retval);
}
bits256 bitcoin_schnorr_noncepair(void *ctx,uint8_t *pubnonce,bits256 txhash2,bits256 privkey) //exchange
{
int32_t retval = -1; size_t plen; secp256k1_pubkey PUB; bits256 privnonce;
memset(privnonce.bytes,0,sizeof(privnonce));
pubnonce[0] = 0;
SECP_ENSURE_CTX
{
if ( secp256k1_schnorr_generate_nonce_pair(ctx,&PUB,privnonce.bytes,txhash2.bytes,privkey.bytes,secp256k1_nonce_function_rfc6979,rand256(0).bytes) > 0 )
{
plen = 33;
secp256k1_ec_pubkey_serialize(ctx,pubnonce,&plen,&PUB,SECP256K1_EC_COMPRESSED);
retval = 0;
}
ENDSECP_ENSURE_CTX
}
return(privnonce);
}
int32_t bitcoin_schnorr_partialsign(void *ctx,uint8_t *sig64,uint8_t *combined_pub,bits256 txhash2,bits256 privkey,bits256 privnonce,uint8_t *pubptrs[],int32_t n) // generate and exchange
{
int32_t bitcoin_pubkeylen(const uint8_t *pubkey);
int32_t i,retval = -1; secp256k1_pubkey PUBall,**PUBptrs; size_t plen;
SECP_ENSURE_CTX
{
PUBptrs = calloc(n,sizeof(*PUBptrs));
for (i=0; i<n; i++)
{
PUBptrs[i] = calloc(1,sizeof(secp256k1_pubkey));
if ( secp256k1_ec_pubkey_parse(ctx,PUBptrs[i],pubptrs[i],bitcoin_pubkeylen(pubptrs[i])) == 0 )
break;
}
if ( n > 0 && secp256k1_ec_pubkey_combine(ctx,&PUBall,(void *)PUBptrs,n) > 0 )
{
plen = 33;
if ( secp256k1_schnorr_partial_sign(ctx,sig64,txhash2.bytes,privkey.bytes,&PUBall,privnonce.bytes) > 0 )
{
secp256k1_ec_pubkey_serialize(ctx,combined_pub,&plen,&PUBall,SECP256K1_EC_COMPRESSED);
retval = 0;
}
}
free(PUBptrs);
ENDSECP_ENSURE_CTX
}
return(retval);
}
int32_t bitcoin_schnorr_combine(void *ctx,uint8_t *sig64,uint8_t *allpub,uint8_t **sigs,int32_t n,bits256 txhash2)
{
int32_t rc,retval = -1;
SECP_ENSURE_CTX
{
if ( (rc= secp256k1_schnorr_partial_combine(ctx,sig64,(void *)sigs,n)) > 0 )
{
if ( bitcoin_schnorr_recover(ctx,allpub,sig64,txhash2) == 0 )
{
if ( bitcoin_schnorr_verify(ctx,sig64,txhash2,allpub,33) == 0 )
retval = 0;
}
}
ENDSECP_ENSURE_CTX
}
return(retval);
}
int32_t bitcoin_pederson_commit(void *ctx,uint8_t *commit,bits256 blind,uint64_t value)
{
int32_t retval = -1;
SECP_ENSURE_CTX
{
if ( secp256k1_pedersen_commit(ctx,commit,blind.bytes,value) > 0 )
retval = 0;
ENDSECP_ENSURE_CTX
}
return(retval);
}
bits256 bitcoin_pederson_blindsum(void *ctx,bits256 **blindptrs,int32_t n,int32_t numpos)
{
bits256 blind_out;
memset(blind_out.bytes,0,sizeof(blind_out));
SECP_ENSURE_CTX
{
if ( secp256k1_pedersen_blind_sum(ctx,blind_out.bytes,(void *)blindptrs,n,numpos) == 0 )
memset(blind_out.bytes,0,sizeof(blind_out));
ENDSECP_ENSURE_CTX
}
return(blind_out);
}
int32_t bitcoin_pederson_tally(void *ctx,uint8_t **commits,int32_t n,int32_t numpos,int64_t excess)
{
int32_t retval = -1;
SECP_ENSURE_CTX
{
if ( secp256k1_pedersen_verify_tally(ctx,(void *)commits,numpos,(void *)&commits[numpos],n - numpos,excess) > 0 )
retval = 0;
ENDSECP_ENSURE_CTX
} }
return(retval); return(retval);
} }
int32_t bitcoin_rangeproof_message(void *ctx,uint8_t *blind_out,uint8_t *message,uint64_t *valuep,bits256 nonce,uint64_t *min_valuep,uint64_t *max_valuep,uint8_t *commit,uint8_t *proof,int32_t prooflen)
{
int32_t outlen = 0,retval = -1;
SECP_ENSURE_CTX
{
if ( secp256k1_rangeproof_rewind(ctx,blind_out,valuep,message,&outlen,nonce.bytes,min_valuep,max_valuep,commit,proof,prooflen) > 0 )
retval = outlen;
ENDSECP_ENSURE_CTX
}
return(retval);
}
uint64_t bitcoin_rangeverify(void *ctx,int32_t *exponentp,int32_t *mantissap,uint64_t *min_valuep,uint8_t *commit,uint8_t *proof,int32_t prooflen)
{
uint64_t max_value,retval = 0;
max_value = *min_valuep = *exponentp = *mantissap = 0;
if ( secp256k1_rangeproof_info(ctx,exponentp,mantissap,min_valuep,&max_value,proof,prooflen) > 0 )
{
if ( commit != 0 )
{
if ( secp256k1_rangeproof_verify(ctx,min_valuep,&max_value,commit,proof,prooflen) > 0 )
retval = max_value;
} else retval = max_value;
}
return(retval);
}
int32_t bitcoin_rangeproof(void *ctx,uint8_t *proof,uint8_t *commit,bits256 blind,bits256 nonce,uint64_t value,uint64_t min_value,int32_t exponent,int32_t min_bits)
{
int32_t prooflen=0 ,retval = -1; uint8_t message[4096];
SECP_ENSURE_CTX
{
if ( secp256k1_rangeproof_sign(ctx,proof,&prooflen,min_value,commit,blind.bytes,nonce.bytes,exponent,min_bits,value,message) > 0 )
retval = prooflen;
ENDSECP_ENSURE_CTX
}
return(retval);
}
/*
* The intended procedure for creating a multiparty signature is:
* - Each signer S[i] with private key x[i] and public key Q[i] runs
* secp256k1_schnorr_generate_nonce_pair to produce a pair (k[i],R[i]) of private/public nonces.
* - All signers communicate their public nonces to each other (revealing your
* private nonce can lead to discovery of your private key, so it should be considered secret).
* - All signers combine all the public nonces they received (excluding their
* own) using secp256k1_ec_pubkey_combine to obtain an Rall[i] = sum(R[0..i-1,i+1..n]).
* - All signers produce a partial signature using
* secp256k1_schnorr_partial_sign, passing in their own private key x[i],
* their own private nonce k[i], and the sum of the others' public nonces Rall[i].
* - All signers communicate their partial signatures to each other.
* - Someone combines all partial signatures using secp256k1_schnorr_partial_combine, to obtain a full signature.
* - The resulting signature is validatable using secp256k1_schnorr_verify, with
* public key equal to the result of secp256k1_ec_pubkey_combine of the signers' public keys (sum(Q[0..n])).
*
* Note that secp256k1_schnorr_partial_combine and secp256k1_ec_pubkey_combine
* function take their arguments in any order, and it is possible to
* pre-combine several inputs already with one call, and add more inputs later
* by calling the function again (they are commutative and associative).
*/
#ifdef test_schnorr
#include "secp256k1/src/util.h"
#include "secp256k1/src/hash_impl.h"
#include "secp256k1/src/testrand_impl.h"
void test_schnorr_threshold(void *ctx) {
unsigned char msg[32];
unsigned char sec[5][32];
secp256k1_pubkey pub[5];
unsigned char nonce[5][32];
secp256k1_pubkey pubnonce[5];
unsigned char sig[5][64];
const unsigned char* sigs[5];
unsigned char allsig[64];
const secp256k1_pubkey* pubs[5];
secp256k1_pubkey allpub;
int n, i;
int damage;
int ret = 0;
damage = secp256k1_rand_bits(1) ? (1 + secp256k1_rand_int(4)) : 0;
secp256k1_rand256_test(msg);
n = 2 + secp256k1_rand_int(4);
for (i = 0; i < n; i++) {
do {
secp256k1_rand256_test(sec[i]);
} while (!secp256k1_ec_seckey_verify(ctx, sec[i]));
CHECK(secp256k1_ec_pubkey_create(ctx, &pub[i], sec[i]));
CHECK(secp256k1_schnorr_generate_nonce_pair(ctx, &pubnonce[i], nonce[i], msg, sec[i], NULL, NULL));
pubs[i] = &pub[i];
}
if (damage == 1) {
nonce[secp256k1_rand_int(n)][secp256k1_rand_int(32)] ^= 1 + secp256k1_rand_int(255);
} else if (damage == 2) {
sec[secp256k1_rand_int(n)][secp256k1_rand_int(32)] ^= 1 + secp256k1_rand_int(255);
}
for (i = 0; i < n; i++) {
secp256k1_pubkey allpubnonce;
const secp256k1_pubkey *pubnonces[4];
int j;
for (j = 0; j < i; j++) {
pubnonces[j] = &pubnonce[j];
}
for (j = i + 1; j < n; j++) {
pubnonces[j - 1] = &pubnonce[j];
}
CHECK(secp256k1_ec_pubkey_combine(ctx, &allpubnonce, pubnonces, n - 1));
ret |= (secp256k1_schnorr_partial_sign(ctx, sig[i], msg, sec[i], &allpubnonce, nonce[i]) != 1) * 1;
sigs[i] = sig[i];
}
if (damage == 3) {
sig[secp256k1_rand_int(n)][secp256k1_rand_bits(6)] ^= 1 + secp256k1_rand_int(255);
}
ret |= (secp256k1_ec_pubkey_combine(ctx, &allpub, pubs, n) != 1) * 2;
if ((ret & 1) == 0) {
ret |= (secp256k1_schnorr_partial_combine(ctx, allsig, sigs, n) != 1) * 4;
}
if (damage == 4) {
allsig[secp256k1_rand_int(32)] ^= 1 + secp256k1_rand_int(255);
}
if ((ret & 7) == 0) {
ret |= (secp256k1_schnorr_verify(ctx, allsig, msg, &allpub) != 1) * 8;
}
CHECK((ret == 0) == (damage == 0));
}
#endif
int32_t iguana_pederson_test(void *ctx)
{
uint8_t commits[100][33],*commitptrs[100],proofs[100][5138]; uint16_t vouts[100]; int64_t min_value,values[100],totalpos,totalneg; bits256 txids[100],nonces[100],blinds[100],*blindptrs[100],blindsum; int32_t prooflens[100],i,r,pos,neg,numpos,exponent,min_bits,n,N = 100;
srand(100);
for (i=numpos=n=0; i<N; i++)
{
values[i] = rand();
vouts[i] = (rand() % 300);
txids[i] = rand256(0);
nonces[i] = rand256(0);
blinds[i] = rand256(0);
if ( bitcoin_pederson_commit(ctx,commits[i],blinds[i],values[i]) < 0 )
break;
if ( ((r= rand()) % 2) == 0 )
values[i] = -values[i];
else
{
exponent = 0;
min_bits = 64;
min_value = 0;
prooflens[i] = bitcoin_rangeproof(ctx,proofs[i],commits[i],blinds[i],nonces[i],values[i],min_value,exponent,min_bits);
printf("%d ",prooflens[i]);
numpos++;
}
n++;
}
if ( i != N )
{
printf("commit failure i.%d of N.%d\n",i,N);
return(-1);
}
for (totalpos=i=pos=0; i<N; i++)
{
if ( values[i] > 0 )
{
commitptrs[pos] = commits[i];
blindptrs[pos] = &blinds[i];
totalpos += values[i];
pos++;
}
}
if ( pos != numpos )
{
printf("pos.%d != numpos.%d\n",pos,numpos);
return(-1);
}
for (totalneg=i=neg=0; i<N; i++)
{
if ( values[i] < 0 )
{
commitptrs[numpos + neg] = commits[i];
blindptrs[numpos + neg] = &blinds[i];
totalneg -= values[i];
neg++;
}
}
if ( numpos+neg != N )
{
printf("numpos.%d + neg.%d != N.%d\n",numpos,neg,N);
return(-1);
}
blindsum = bitcoin_pederson_blindsum(ctx,blindptrs,N,numpos);
if ( bits256_nonz(blindsum) == 0 )
{
printf("error doing blindsum numpos.%d N.%d\n",numpos,N);
return(-2);
}
if ( bitcoin_pederson_tally(ctx,commitptrs,N,numpos,totalneg - totalpos) == 0 )
{
printf("error doing pederson tally\n");
return(-3);
} else printf("pederson tally matches\n");
return(0);
}
int32_t iguana_schnorr_test(void *ctx)
{
bits256 privnonces[100],privkeys[100],txhash2; uint8_t *sigs[100],allpub[100][33],sig64[100][64],allsig64[100][64],combined_pub[100][33],pubnonces[100][33],*pubptrs[100]; int32_t i,j,N,n,errs = 0;
iguana_pederson_test(ctx);
SECP_ENSURE_CTX
{
N = 100;
txhash2 = rand256(0);
for (i=0; i<N; i++)
{
privkeys[i] = bitcoin_randkey(ctx);
privnonces[i] = bitcoin_schnorr_noncepair(ctx,pubnonces[i],txhash2,privkeys[i]);
}
if ( i != N )
{
printf("error getting nonce pair\n");
exit(-1);
}
for (i=0; i<N; i++)
{
for (j=n=0; j<N; j++)
if ( j != i )
pubptrs[n++] = pubnonces[j];
if ( N > 1 )
{
if ( bitcoin_schnorr_partialsign(ctx,sig64[i],combined_pub[i],txhash2,privkeys[i],privnonces[i],pubptrs,N-1) < 0 )
errs++;
}
else
{
if ( bitcoin_schnorr_sign(ctx,sig64[0],txhash2,privkeys[0]) < 0 )
errs++;
}
}
if ( errs != 0 )
printf("partialsign errs.%d\n",errs);
for (i=0; i<N; i++)
{
sigs[i] = sig64[i];
continue;
for (j=0; j<64; j++)
printf("%02x",sig64[i][j]);
printf(" sig[%d]\n",i);
}
for (i=0; i<N; i++)
{
if ( bitcoin_schnorr_combine(ctx,allsig64[i],allpub[i],sigs,N,txhash2) < 0 )
errs++;
else if ( memcmp(allpub[i],allpub[0],33) != 0 )
errs++;
else if ( memcmp(allsig64[i],allsig64[0],33) != 0 )
errs++;
}
if ( errs != 0 )
printf("combine errs.%d\n",errs);
if ( bitcoin_schnorr_verify(ctx,allsig64[0],txhash2,allpub[0],33) < 0 )
errs++;
printf("schnorr errs.%d\n",errs);
ENDSECP_ENSURE_CTX
}
return(errs);
}
#ifdef oldway #ifdef oldway
#include "../includes/openssl/ec.h" #include "../includes/openssl/ec.h"
#include "../includes/openssl/ecdsa.h" #include "../includes/openssl/ecdsa.h"
@ -306,6 +721,7 @@ bits256 oldbitcoin_pubkey33(void *_ctx,uint8_t *data,bits256 privkey)
{ {
if ( secp256k1_ec_pubkey_create(ctx,&secppub,privkey.bytes) > 0 ) if ( secp256k1_ec_pubkey_create(ctx,&secppub,privkey.bytes) > 0 )
{ {
plen = 33;
secp256k1_ec_pubkey_serialize(ctx,data2,&plen,&secppub,1); secp256k1_ec_pubkey_serialize(ctx,data2,&plen,&secppub,1);
if ( memcmp(data2,data,plen) != 0 ) if ( memcmp(data2,data,plen) != 0 )
printf("pubkey compare error plen.%d\n",(int32_t)plen); printf("pubkey compare error plen.%d\n",(int32_t)plen);

5
iguana/iguana_unspents.c

@ -226,12 +226,13 @@ int64_t iguana_pkhashbalance(struct supernet_info *myinfo,struct iguana_info *co
int32_t iguana_pkhasharray(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *array,int32_t minconf,int32_t maxconf,int64_t *totalp,struct iguana_pkhash *P,int32_t max,uint8_t rmd160[20],char *coinaddr,uint8_t *pubkey33,int32_t lastheight,uint64_t *unspents,int32_t *numunspentsp,int32_t maxunspents) int32_t iguana_pkhasharray(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *array,int32_t minconf,int32_t maxconf,int64_t *totalp,struct iguana_pkhash *P,int32_t max,uint8_t rmd160[20],char *coinaddr,uint8_t *pubkey33,int32_t lastheight,uint64_t *unspents,int32_t *numunspentsp,int32_t maxunspents)
{ {
int32_t i,n,m,numunspents = *numunspentsp; int64_t spent,deposits,netbalance,total; uint32_t lastunspentind; struct iguana_pkhash *p,_p; struct iguana_ramchain *ramchain; struct iguana_bundle *bp; int32_t i,n,m,numunspents; int64_t spent,deposits,netbalance,total; uint32_t lastunspentind; struct iguana_pkhash *p,_p; struct iguana_ramchain *ramchain; struct iguana_bundle *bp;
if ( 0 && coin->RTramchain_busy != 0 ) if ( 0 && coin->RTramchain_busy != 0 )
{ {
printf("iguana_pkhasharray: unexpected access when RTramchain_busy\n"); printf("iguana_pkhasharray: unexpected access when RTramchain_busy\n");
return(-1); return(-1);
} }
numunspents = numunspentsp != 0 ? *numunspentsp : 0;
if ( lastheight == 0 ) if ( lastheight == 0 )
lastheight = IGUANA_MAXHEIGHT; lastheight = IGUANA_MAXHEIGHT;
if ( max > coin->bundlescount ) if ( max > coin->bundlescount )
@ -267,7 +268,7 @@ int32_t iguana_pkhasharray(struct supernet_info *myinfo,struct iguana_info *coin
} }
if ( numunspentsp != 0 ) if ( numunspentsp != 0 )
*numunspentsp = numunspents; *numunspentsp = numunspents;
printf("numunspents.%d [%d] max.%d\n",numunspents,*numunspentsp,maxunspents); printf("numunspents.%d max.%d\n",numunspents,maxunspents);
*totalp += total; *totalp += total;
return(n); return(n);
} }

14
iguana/main.c

@ -24,7 +24,8 @@
#include "iguana777.h" #include "iguana777.h"
#include "SuperNET.h" #include "SuperNET.h"
#include "secp256k1/include/secp256k1.h" #include "secp256k1/include/secp256k1.h"
//#include "../../secp256k1-zkp/include/secp256k1.h" #include "secp256k1/include/secp256k1_schnorr.h"
#include "secp256k1/include/secp256k1_rangeproof.h"
/*#undef fopen /*#undef fopen
#undef fclose #undef fclose
@ -141,7 +142,11 @@ void SuperNET_hex2str(char *str,uint8_t *hex,int32_t len)
struct supernet_info *SuperNET_MYINFO(char *passphrase) struct supernet_info *SuperNET_MYINFO(char *passphrase)
{ {
if ( MYINFO.ctx == 0 ) if ( MYINFO.ctx == 0 )
{
MYINFO.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); MYINFO.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
secp256k1_pedersen_context_initialize(MYINFO.ctx);
secp256k1_rangeproof_context_initialize(MYINFO.ctx);
}
if ( passphrase == 0 || passphrase[0] == 0 ) if ( passphrase == 0 || passphrase[0] == 0 )
return(&MYINFO); return(&MYINFO);
else else
@ -1136,13 +1141,18 @@ int maingen(int argc, char** argv)
void iguana_appletests(struct supernet_info *myinfo) void iguana_appletests(struct supernet_info *myinfo)
{ {
char *str; char *str;
void ztest(); ztest();
//iguana_chaingenesis(1,1403138561,0x1e0fffff,8359109,bits256_conv("fd1751cc6963d88feca94c0d01da8883852647a37a0a67ce254d62dd8c9d5b2b")); // BTCD //iguana_chaingenesis(1,1403138561,0x1e0fffff,8359109,bits256_conv("fd1751cc6963d88feca94c0d01da8883852647a37a0a67ce254d62dd8c9d5b2b")); // BTCD
//iguana_chaingenesis(1,1409839200,0x1e0fffff,64881664,bits256_conv("698a93a1cacd495a7a4fb3864ad8d06ed4421dedbc57f9aaad733ea53b1b5828")); // VPN //iguana_chaingenesis(1,1409839200,0x1e0fffff,64881664,bits256_conv("698a93a1cacd495a7a4fb3864ad8d06ed4421dedbc57f9aaad733ea53b1b5828")); // VPN
//char genesisblock[1024]; //char genesisblock[1024];
//iguana_chaingenesis(genesisblock,"sha256",1,1317972665,0x1e0ffff0,2084524493,bits256_conv("97ddfbbae6be97fd6cdf3e7ca13232a3afff2353e29badfab7f73011edd4ced9")); // LTC //iguana_chaingenesis(genesisblock,"sha256",1,1317972665,0x1e0ffff0,2084524493,bits256_conv("97ddfbbae6be97fd6cdf3e7ca13232a3afff2353e29badfab7f73011edd4ced9")); // LTC
if ( 1 ) if ( 1 )
{ {
//void ztest(); ztest();
//int proofmain(void);
//proofmain(); getchar();
//int32_t iguana_schnorr_test(void *ctx);
//iguana_schnorr_test(myinfo->ctx); getchar();
if ( 1 && (str= SuperNET_JSON(myinfo,cJSON_Parse("{\"RELAY\":1,\"VALIDATE\":1,\"prefetchlag\":-1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":64,\"newcoin\":\"BTCD\",\"active\":1,\"numhelpers\":4,\"poll\":1}"),0,myinfo->rpcport)) != 0 ) if ( 1 && (str= SuperNET_JSON(myinfo,cJSON_Parse("{\"RELAY\":1,\"VALIDATE\":1,\"prefetchlag\":-1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":64,\"newcoin\":\"BTCD\",\"active\":1,\"numhelpers\":4,\"poll\":1}"),0,myinfo->rpcport)) != 0 )
{ {
free(str); free(str);

134
iguana/secp256k1/include/secp256k1.h

@ -170,27 +170,21 @@ typedef int (*secp256k1_nonce_function)(
* Returns: a newly created context object. * Returns: a newly created context object.
* In: flags: which parts of the context to initialize. * In: flags: which parts of the context to initialize.
*/ */
SECP256K1_API secp256k1_context* secp256k1_context_create( SECP256K1_API secp256k1_context* secp256k1_context_create(unsigned int flags) SECP256K1_WARN_UNUSED_RESULT;
unsigned int flags
) SECP256K1_WARN_UNUSED_RESULT;
/** Copies a secp256k1 context object. /** Copies a secp256k1 context object.
* *
* Returns: a newly created context object. * Returns: a newly created context object.
* Args: ctx: an existing context to copy (cannot be NULL) * Args: ctx: an existing context to copy (cannot be NULL)
*/ */
SECP256K1_API secp256k1_context* secp256k1_context_clone( SECP256K1_API secp256k1_context* secp256k1_context_clone(const secp256k1_context* ctx) SECP256K1_ARG_NONNULL(1) SECP256K1_WARN_UNUSED_RESULT;
const secp256k1_context* ctx
) SECP256K1_ARG_NONNULL(1) SECP256K1_WARN_UNUSED_RESULT;
/** Destroy a secp256k1 context object. /** Destroy a secp256k1 context object.
* *
* The context pointer may not be used afterwards. * The context pointer may not be used afterwards.
* Args: ctx: an existing context to destroy (cannot be NULL) * Args: ctx: an existing context to destroy (cannot be NULL)
*/ */
SECP256K1_API void secp256k1_context_destroy( SECP256K1_API void secp256k1_context_destroy(secp256k1_context *ctx);
secp256k1_context* ctx
);
/** Set a callback function to be called when an illegal argument is passed to /** Set a callback function to be called when an illegal argument is passed to
* an API call. It will only trigger for violations that are mentioned * an API call. It will only trigger for violations that are mentioned
@ -212,11 +206,7 @@ SECP256K1_API void secp256k1_context_destroy(
* (NULL restores a default handler that calls abort). * (NULL restores a default handler that calls abort).
* data: the opaque pointer to pass to fun above. * data: the opaque pointer to pass to fun above.
*/ */
SECP256K1_API void secp256k1_context_set_illegal_callback( SECP256K1_API void secp256k1_context_set_illegal_callback(secp256k1_context* ctx,void (*fun)(const char* message, void* data),const void* data) SECP256K1_ARG_NONNULL(1);
secp256k1_context* ctx,
void (*fun)(const char* message, void* data),
const void* data
) SECP256K1_ARG_NONNULL(1);
/** Set a callback function to be called when an internal consistency check /** Set a callback function to be called when an internal consistency check
* fails. The default is crashing. * fails. The default is crashing.
@ -234,11 +224,7 @@ SECP256K1_API void secp256k1_context_set_illegal_callback(
* handler that calls abort). * handler that calls abort).
* data: the opaque pointer to pass to fun above. * data: the opaque pointer to pass to fun above.
*/ */
SECP256K1_API void secp256k1_context_set_error_callback( SECP256K1_API void secp256k1_context_set_error_callback(secp256k1_context *ctx,void (*fun)(const char *message,void *data),const void *data) SECP256K1_ARG_NONNULL(1);
secp256k1_context* ctx,
void (*fun)(const char* message, void* data),
const void* data
) SECP256K1_ARG_NONNULL(1);
/** Parse a variable-length public key into the pubkey object. /** Parse a variable-length public key into the pubkey object.
* *
@ -254,12 +240,7 @@ SECP256K1_API void secp256k1_context_set_error_callback(
* 0x03), uncompressed (65 bytes, header byte 0x04), or hybrid (65 bytes, header * 0x03), uncompressed (65 bytes, header byte 0x04), or hybrid (65 bytes, header
* byte 0x06 or 0x07) format public keys. * byte 0x06 or 0x07) format public keys.
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_parse( SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_parse(const secp256k1_context *ctx,secp256k1_pubkey *pubkey,const unsigned char *input,size_t inputlen) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
const secp256k1_context* ctx,
secp256k1_pubkey* pubkey,
const unsigned char *input,
size_t inputlen
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Serialize a pubkey object into a serialized byte sequence. /** Serialize a pubkey object into a serialized byte sequence.
* *
@ -276,13 +257,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_parse(
* flags: SECP256K1_EC_COMPRESSED if serialization should be in * flags: SECP256K1_EC_COMPRESSED if serialization should be in
* compressed format, otherwise SECP256K1_EC_UNCOMPRESSED. * compressed format, otherwise SECP256K1_EC_UNCOMPRESSED.
*/ */
SECP256K1_API int secp256k1_ec_pubkey_serialize( SECP256K1_API int secp256k1_ec_pubkey_serialize(const secp256k1_context *ctx,unsigned char *output,size_t *outputlen,const secp256k1_pubkey *pubkey,unsigned int flags) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
const secp256k1_context* ctx,
unsigned char *output,
size_t *outputlen,
const secp256k1_pubkey* pubkey,
unsigned int flags
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
/** Parse an ECDSA signature in compact (64 bytes) format. /** Parse an ECDSA signature in compact (64 bytes) format.
* *
@ -299,11 +274,7 @@ SECP256K1_API int secp256k1_ec_pubkey_serialize(
* S are zero, the resulting sig value is guaranteed to fail validation for any * S are zero, the resulting sig value is guaranteed to fail validation for any
* message and public key. * message and public key.
*/ */
SECP256K1_API int secp256k1_ecdsa_signature_parse_compact( SECP256K1_API int secp256k1_ecdsa_signature_parse_compact(const secp256k1_context *ctx,secp256k1_ecdsa_signature *sig,const unsigned char *input64) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
const secp256k1_context* ctx,
secp256k1_ecdsa_signature* sig,
const unsigned char *input64
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Parse a DER ECDSA signature. /** Parse a DER ECDSA signature.
* *
@ -320,12 +291,7 @@ SECP256K1_API int secp256k1_ecdsa_signature_parse_compact(
* encoded numbers are out of range, signature validation with it is * encoded numbers are out of range, signature validation with it is
* guaranteed to fail for every message and public key. * guaranteed to fail for every message and public key.
*/ */
SECP256K1_API int secp256k1_ecdsa_signature_parse_der( SECP256K1_API int secp256k1_ecdsa_signature_parse_der(const secp256k1_context *ctx,secp256k1_ecdsa_signature *sig,const unsigned char *input,size_t inputlen) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
const secp256k1_context* ctx,
secp256k1_ecdsa_signature* sig,
const unsigned char *input,
size_t inputlen
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Serialize an ECDSA signature in DER format. /** Serialize an ECDSA signature in DER format.
* *
@ -338,12 +304,7 @@ SECP256K1_API int secp256k1_ecdsa_signature_parse_der(
* if 0 was returned). * if 0 was returned).
* In: sig: a pointer to an initialized signature object * In: sig: a pointer to an initialized signature object
*/ */
SECP256K1_API int secp256k1_ecdsa_signature_serialize_der( SECP256K1_API int secp256k1_ecdsa_signature_serialize_der(const secp256k1_context *ctx,unsigned char *output,size_t *outputlen,const secp256k1_ecdsa_signature *sig) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
const secp256k1_context* ctx,
unsigned char *output,
size_t *outputlen,
const secp256k1_ecdsa_signature* sig
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
/** Serialize an ECDSA signature in compact (64 byte) format. /** Serialize an ECDSA signature in compact (64 byte) format.
* *
@ -354,11 +315,7 @@ SECP256K1_API int secp256k1_ecdsa_signature_serialize_der(
* *
* See secp256k1_ecdsa_signature_parse_compact for details about the encoding. * See secp256k1_ecdsa_signature_parse_compact for details about the encoding.
*/ */
SECP256K1_API int secp256k1_ecdsa_signature_serialize_compact( SECP256K1_API int secp256k1_ecdsa_signature_serialize_compact(const secp256k1_context *ctx,unsigned char *output64,const secp256k1_ecdsa_signature *sig) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
const secp256k1_context* ctx,
unsigned char *output64,
const secp256k1_ecdsa_signature* sig
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Verify an ECDSA signature. /** Verify an ECDSA signature.
* *
@ -378,12 +335,7 @@ SECP256K1_API int secp256k1_ecdsa_signature_serialize_compact(
* *
* For details, see the comments for that function. * For details, see the comments for that function.
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify( SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify(const secp256k1_context *ctx,const secp256k1_ecdsa_signature *sig,const unsigned char *msg32,const secp256k1_pubkey *pubkey) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
const secp256k1_context* ctx,
const secp256k1_ecdsa_signature *sig,
const unsigned char *msg32,
const secp256k1_pubkey *pubkey
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
/** Convert a signature to a normalized lower-S form. /** Convert a signature to a normalized lower-S form.
* *
@ -427,11 +379,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify(
* signatures come from a system that cannot enforce this property, * signatures come from a system that cannot enforce this property,
* secp256k1_ecdsa_signature_normalize must be called before verification. * secp256k1_ecdsa_signature_normalize must be called before verification.
*/ */
SECP256K1_API int secp256k1_ecdsa_signature_normalize( SECP256K1_API int secp256k1_ecdsa_signature_normalize(const secp256k1_context *ctx,secp256k1_ecdsa_signature *sigout,const secp256k1_ecdsa_signature *sigin) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3);
const secp256k1_context* ctx,
secp256k1_ecdsa_signature *sigout,
const secp256k1_ecdsa_signature *sigin
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3);
/** An implementation of RFC6979 (using HMAC-SHA256) as nonce generation function. /** An implementation of RFC6979 (using HMAC-SHA256) as nonce generation function.
* If a data pointer is passed, it is assumed to be a pointer to 32 bytes of * If a data pointer is passed, it is assumed to be a pointer to 32 bytes of
@ -456,14 +404,7 @@ SECP256K1_API extern const secp256k1_nonce_function secp256k1_nonce_function_def
* The created signature is always in lower-S form. See * The created signature is always in lower-S form. See
* secp256k1_ecdsa_signature_normalize for more details. * secp256k1_ecdsa_signature_normalize for more details.
*/ */
SECP256K1_API int secp256k1_ecdsa_sign( SECP256K1_API int secp256k1_ecdsa_sign(const secp256k1_context *ctx,secp256k1_ecdsa_signature *sig,const unsigned char *msg32,const unsigned char *seckey,secp256k1_nonce_function noncefp,const void *ndata) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
const secp256k1_context* ctx,
secp256k1_ecdsa_signature *sig,
const unsigned char *msg32,
const unsigned char *seckey,
secp256k1_nonce_function noncefp,
const void *ndata
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
/** Verify an ECDSA secret key. /** Verify an ECDSA secret key.
* *
@ -472,10 +413,7 @@ SECP256K1_API int secp256k1_ecdsa_sign(
* Args: ctx: pointer to a context object (cannot be NULL) * Args: ctx: pointer to a context object (cannot be NULL)
* In: seckey: pointer to a 32-byte secret key (cannot be NULL) * In: seckey: pointer to a 32-byte secret key (cannot be NULL)
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_verify( SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_verify(const secp256k1_context *ctx,const unsigned char *seckey) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);
const secp256k1_context* ctx,
const unsigned char *seckey
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);
/** Compute the public key for a secret key. /** Compute the public key for a secret key.
* *
@ -485,11 +423,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_verify(
* Out: pubkey: pointer to the created public key (cannot be NULL) * Out: pubkey: pointer to the created public key (cannot be NULL)
* In: seckey: pointer to a 32-byte private key (cannot be NULL) * In: seckey: pointer to a 32-byte private key (cannot be NULL)
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create( SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create(const secp256k1_context *ctx,secp256k1_pubkey *pubkey,const unsigned char *seckey) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
const secp256k1_context* ctx,
secp256k1_pubkey *pubkey,
const unsigned char *seckey
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Tweak a private key by adding tweak to it. /** Tweak a private key by adding tweak to it.
* Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for * Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for
@ -500,11 +434,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create(
* In/Out: seckey: pointer to a 32-byte private key. * In/Out: seckey: pointer to a 32-byte private key.
* In: tweak: pointer to a 32-byte tweak. * In: tweak: pointer to a 32-byte tweak.
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_add( SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_add(const secp256k1_context *ctx,unsigned char *seckey,const unsigned char *tweak) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
const secp256k1_context* ctx,
unsigned char *seckey,
const unsigned char *tweak
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Tweak a public key by adding tweak times the generator to it. /** Tweak a public key by adding tweak times the generator to it.
* Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for * Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for
@ -516,11 +446,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_add(
* In/Out: pubkey: pointer to a public key object. * In/Out: pubkey: pointer to a public key object.
* In: tweak: pointer to a 32-byte tweak. * In: tweak: pointer to a 32-byte tweak.
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_add( SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_add(const secp256k1_context *ctx,secp256k1_pubkey *pubkey,const unsigned char *tweak) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
const secp256k1_context* ctx,
secp256k1_pubkey *pubkey,
const unsigned char *tweak
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Tweak a private key by multiplying it by a tweak. /** Tweak a private key by multiplying it by a tweak.
* Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for * Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for
@ -529,11 +455,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_add(
* In/Out: seckey: pointer to a 32-byte private key. * In/Out: seckey: pointer to a 32-byte private key.
* In: tweak: pointer to a 32-byte tweak. * In: tweak: pointer to a 32-byte tweak.
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_mul( SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_mul(const secp256k1_context *ctx,unsigned char *seckey,const unsigned char *tweak) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
const secp256k1_context* ctx,
unsigned char *seckey,
const unsigned char *tweak
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Tweak a public key by multiplying it by a tweak value. /** Tweak a public key by multiplying it by a tweak value.
* Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for * Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for
@ -543,11 +465,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_mul(
* In/Out: pubkey: pointer to a public key obkect. * In/Out: pubkey: pointer to a public key obkect.
* In: tweak: pointer to a 32-byte tweak. * In: tweak: pointer to a 32-byte tweak.
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul( SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul(const secp256k1_context *ctx,secp256k1_pubkey *pubkey,const unsigned char *tweak) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
const secp256k1_context* ctx,
secp256k1_pubkey *pubkey,
const unsigned char *tweak
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Updates the context randomization. /** Updates the context randomization.
* Returns: 1: randomization successfully updated * Returns: 1: randomization successfully updated
@ -555,10 +473,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul(
* Args: ctx: pointer to a context object (cannot be NULL) * Args: ctx: pointer to a context object (cannot be NULL)
* In: seed32: pointer to a 32-byte random seed (NULL resets to initial state) * In: seed32: pointer to a 32-byte random seed (NULL resets to initial state)
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_context_randomize( SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_context_randomize(secp256k1_context *ctx,const unsigned char *seed32) SECP256K1_ARG_NONNULL(1);
secp256k1_context* ctx,
const unsigned char *seed32
) SECP256K1_ARG_NONNULL(1);
/** Add a number of public keys together. /** Add a number of public keys together.
* Returns: 1: the sum of the public keys is valid. * Returns: 1: the sum of the public keys is valid.
@ -569,12 +484,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_context_randomize(
* In: ins: pointer to array of pointers to public keys (cannot be NULL) * In: ins: pointer to array of pointers to public keys (cannot be NULL)
* n: the number of public keys to add together (must be at least 1) * n: the number of public keys to add together (must be at least 1)
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_combine( SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_combine(const secp256k1_context *ctx,secp256k1_pubkey *out,const secp256k1_pubkey * const *ins,size_t n) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
const secp256k1_context* ctx,
secp256k1_pubkey *out,
const secp256k1_pubkey * const * ins,
size_t n
) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
# ifdef __cplusplus # ifdef __cplusplus
} }

10
iguana/secp256k1/include/secp256k1_ecdh.h

@ -13,16 +13,10 @@ extern "C" {
* Args: ctx: pointer to a context object (cannot be NULL) * Args: ctx: pointer to a context object (cannot be NULL)
* Out: result: a 32-byte array which will be populated by an ECDH * Out: result: a 32-byte array which will be populated by an ECDH
* secret computed from the point and scalar * secret computed from the point and scalar
* In: pubkey: a pointer to a secp256k1_pubkey containing an * In: pubkey: a pointer to a secp256k1_pubkey containing an initialized public key
* initialized public key
* privkey: a 32-byte scalar with which to multiply the point * privkey: a 32-byte scalar with which to multiply the point
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdh( SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdh(const secp256k1_context *ctx,unsigned char *result,const secp256k1_pubkey *pubkey,const unsigned char *privkey) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
const secp256k1_context* ctx,
unsigned char *result,
const secp256k1_pubkey *pubkey,
const unsigned char *privkey
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
# ifdef __cplusplus # ifdef __cplusplus
} }

2
iguana/secp256k1/include/secp256k1_rangeproof.h

@ -155,7 +155,7 @@ SECP256K1_WARN_UNUSED_RESULT int secp256k1_rangeproof_sign(
const unsigned char *nonce, const unsigned char *nonce,
int exp, int exp,
int min_bits, int min_bits,
uint64_t value uint64_t value,unsigned char message[4096]
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6) SECP256K1_ARG_NONNULL(7); ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6) SECP256K1_ARG_NONNULL(7);
/** Extract some basic information from a range-proof. /** Extract some basic information from a range-proof.

40
iguana/secp256k1/include/secp256k1_recovery.h

@ -21,9 +21,7 @@ extern "C" {
* recoverability) will have identical representation, so they can be * recoverability) will have identical representation, so they can be
* memcmp'ed. * memcmp'ed.
*/ */
typedef struct { typedef struct { uint8_t data[65]; } secp256k1_ecdsa_recoverable_signature;
unsigned char data[65];
} secp256k1_ecdsa_recoverable_signature;
/** Parse a compact ECDSA signature (64 bytes + recovery id). /** Parse a compact ECDSA signature (64 bytes + recovery id).
* *
@ -33,12 +31,7 @@ typedef struct {
* In: input64: a pointer to a 64-byte compact signature * In: input64: a pointer to a 64-byte compact signature
* recid: the recovery id (0, 1, 2 or 3) * recid: the recovery id (0, 1, 2 or 3)
*/ */
SECP256K1_API int secp256k1_ecdsa_recoverable_signature_parse_compact( SECP256K1_API int secp256k1_ecdsa_recoverable_signature_parse_compact(const secp256k1_context *ctx,secp256k1_ecdsa_recoverable_signature *sig,const uint8_t *input64,int32_t recid) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
const secp256k1_context* ctx,
secp256k1_ecdsa_recoverable_signature* sig,
const unsigned char *input64,
int recid
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Convert a recoverable signature into a normal signature. /** Convert a recoverable signature into a normal signature.
* *
@ -46,11 +39,7 @@ SECP256K1_API int secp256k1_ecdsa_recoverable_signature_parse_compact(
* Out: sig: a pointer to a normal signature (cannot be NULL). * Out: sig: a pointer to a normal signature (cannot be NULL).
* In: sigin: a pointer to a recoverable signature (cannot be NULL). * In: sigin: a pointer to a recoverable signature (cannot be NULL).
*/ */
SECP256K1_API int secp256k1_ecdsa_recoverable_signature_convert( SECP256K1_API int secp256k1_ecdsa_recoverable_signature_convert(const secp256k1_context *ctx,secp256k1_ecdsa_signature *sig,const secp256k1_ecdsa_recoverable_signature *sigin) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
const secp256k1_context* ctx,
secp256k1_ecdsa_signature* sig,
const secp256k1_ecdsa_recoverable_signature* sigin
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Serialize an ECDSA signature in compact format (64 bytes + recovery id). /** Serialize an ECDSA signature in compact format (64 bytes + recovery id).
* *
@ -60,12 +49,7 @@ SECP256K1_API int secp256k1_ecdsa_recoverable_signature_convert(
* recid: a pointer to an integer to hold the recovery id (can be NULL). * recid: a pointer to an integer to hold the recovery id (can be NULL).
* In: sig: a pointer to an initialized signature object (cannot be NULL) * In: sig: a pointer to an initialized signature object (cannot be NULL)
*/ */
SECP256K1_API int secp256k1_ecdsa_recoverable_signature_serialize_compact( SECP256K1_API int secp256k1_ecdsa_recoverable_signature_serialize_compact(const secp256k1_context *ctx,uint8_t *output64,int32_t *recid,const secp256k1_ecdsa_recoverable_signature *sig) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
const secp256k1_context* ctx,
unsigned char *output64,
int *recid,
const secp256k1_ecdsa_recoverable_signature* sig
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
/** Create a recoverable ECDSA signature. /** Create a recoverable ECDSA signature.
* *
@ -78,14 +62,7 @@ SECP256K1_API int secp256k1_ecdsa_recoverable_signature_serialize_compact(
* noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used * noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used
* ndata: pointer to arbitrary data used by the nonce generation function (can be NULL) * ndata: pointer to arbitrary data used by the nonce generation function (can be NULL)
*/ */
SECP256K1_API int secp256k1_ecdsa_sign_recoverable( SECP256K1_API int secp256k1_ecdsa_sign_recoverable(const secp256k1_context *ctx,secp256k1_ecdsa_recoverable_signature *sig,const uint8_t *msg32,const uint8_t *seckey,secp256k1_nonce_function noncefp,const void *ndata) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
const secp256k1_context* ctx,
secp256k1_ecdsa_recoverable_signature *sig,
const unsigned char *msg32,
const unsigned char *seckey,
secp256k1_nonce_function noncefp,
const void *ndata
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
/** Recover an ECDSA public key from a signature. /** Recover an ECDSA public key from a signature.
* *
@ -96,12 +73,7 @@ SECP256K1_API int secp256k1_ecdsa_sign_recoverable(
* In: sig: pointer to initialized signature that supports pubkey recovery (cannot be NULL) * In: sig: pointer to initialized signature that supports pubkey recovery (cannot be NULL)
* msg32: the 32-byte message hash assumed to be signed (cannot be NULL) * msg32: the 32-byte message hash assumed to be signed (cannot be NULL)
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_recover( SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_recover(const secp256k1_context *ctx,secp256k1_pubkey *pubkey,const secp256k1_ecdsa_recoverable_signature *sig,const uint8_t *msg32) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
const secp256k1_context* ctx,
secp256k1_pubkey *pubkey,
const secp256k1_ecdsa_recoverable_signature *sig,
const unsigned char *msg32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
# ifdef __cplusplus # ifdef __cplusplus
} }

99
iguana/secp256k1/include/secp256k1_schnorr.h

@ -13,25 +13,14 @@ extern "C" {
* Returns: 1: signature created * Returns: 1: signature created
* 0: the nonce generation function failed, or the private key was * 0: the nonce generation function failed, or the private key was
* invalid. * invalid.
* Args: ctx: pointer to a context object, initialized for signing * Args: ctx: pointer to a context object, initialized for signing (cannot be NULL)
* (cannot be NULL) * Out: sig64: pointer to a 64-byte array where the signature will be placed (cannot be NULL)
* Out: sig64: pointer to a 64-byte array where the signature will be
* placed (cannot be NULL)
* In: msg32: the 32-byte message hash being signed (cannot be NULL) * In: msg32: the 32-byte message hash being signed (cannot be NULL)
* seckey: pointer to a 32-byte secret key (cannot be NULL) * seckey: pointer to a 32-byte secret key (cannot be NULL)
* noncefp:pointer to a nonce generation function. If NULL, * noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default
* secp256k1_nonce_function_default is used * ndata: pointer to arbitrary data used by the nonce generation function (can be NULL)
* ndata: pointer to arbitrary data used by the nonce generation
* function (can be NULL)
*/ */
SECP256K1_API int secp256k1_schnorr_sign( SECP256K1_API int secp256k1_schnorr_sign(const secp256k1_context *ctx,unsigned char *sig64,const unsigned char *msg32,const unsigned char *seckey,secp256k1_nonce_function noncefp,const void *ndata) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
const secp256k1_context* ctx,
unsigned char *sig64,
const unsigned char *msg32,
const unsigned char *seckey,
secp256k1_nonce_function noncefp,
const void *ndata
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
/** Verify a signature created by secp256k1_schnorr_sign. /** Verify a signature created by secp256k1_schnorr_sign.
* Returns: 1: correct signature * Returns: 1: correct signature
@ -41,60 +30,33 @@ SECP256K1_API int secp256k1_schnorr_sign(
* msg32: the 32-byte message hash being verified (cannot be NULL) * msg32: the 32-byte message hash being verified (cannot be NULL)
* pubkey: the public key to verify with (cannot be NULL) * pubkey: the public key to verify with (cannot be NULL)
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_schnorr_verify( SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_schnorr_verify(const secp256k1_context *ctx,const unsigned char *sig64,const unsigned char *msg32,const secp256k1_pubkey *pubkey) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
const secp256k1_context* ctx,
const unsigned char *sig64,
const unsigned char *msg32,
const secp256k1_pubkey *pubkey
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
/** Recover an EC public key from a Schnorr signature created using /** Recover an EC public key from a Schnorr signature created using secp256k1_schnorr_sign.
* secp256k1_schnorr_sign. * Returns: 1: public key successfully recovered (which guarantees a correct signature).
* Returns: 1: public key successfully recovered (which guarantees a correct
* signature).
* 0: otherwise. * 0: otherwise.
* Args: ctx: pointer to a context object, initialized for * Args: ctx: pointer to a context object, initialized for verification (cannot be NULL)
* verification (cannot be NULL) * Out: pubkey: pointer to a pubkey to set to the recovered public key (cannot be NULL).
* Out: pubkey: pointer to a pubkey to set to the recovered public key
* (cannot be NULL).
* In: sig64: signature as 64 byte array (cannot be NULL) * In: sig64: signature as 64 byte array (cannot be NULL)
* msg32: the 32-byte message hash assumed to be signed (cannot * msg32: the 32-byte message hash assumed to be signed (cannot be NULL)
* be NULL)
*/ */
SECP256K1_API int secp256k1_schnorr_recover( SECP256K1_API int secp256k1_schnorr_recover(const secp256k1_context *ctx,secp256k1_pubkey *pubkey,const unsigned char *sig64,const unsigned char *msg32) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
const secp256k1_context* ctx,
secp256k1_pubkey *pubkey,
const unsigned char *sig64,
const unsigned char *msg32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
/** Generate a nonce pair deterministically for use with /** Generate a nonce pair deterministically for use with secp256k1_schnorr_partial_sign.
* secp256k1_schnorr_partial_sign.
* Returns: 1: valid nonce pair was generated. * Returns: 1: valid nonce pair was generated.
* 0: otherwise (nonce generation function failed) * 0: otherwise (nonce generation function failed)
* Args: ctx: pointer to a context object, initialized for signing * Args: ctx: pointer to a context object, initialized for signing (cannot be NULL)
* (cannot be NULL)
* Out: pubnonce: public side of the nonce (cannot be NULL) * Out: pubnonce: public side of the nonce (cannot be NULL)
* privnonce32: private side of the nonce (32 byte) (cannot be NULL) * privnonce32: private side of the nonce (32 byte) (cannot be NULL)
* In: msg32: the 32-byte message hash assumed to be signed (cannot * In: msg32: the 32-byte message hash assumed to be signed (cannot be NULL)
* be NULL)
* sec32: the 32-byte private key (cannot be NULL) * sec32: the 32-byte private key (cannot be NULL)
* noncefp: pointer to a nonce generation function. If NULL, * noncefp: pointer to a nonce generation function. If NULL,
* secp256k1_nonce_function_default is used * secp256k1_nonce_function_default is used
* noncedata: pointer to arbitrary data used by the nonce generation * noncedata: pointer to arbitrary data used by the nonce generation function (can be NULL)
* function (can be NULL)
* *
* Do not use the output as a private/public key pair for signing/validation. * Do not use the output as a private/public key pair for signing/validation.
*/ */
SECP256K1_API int secp256k1_schnorr_generate_nonce_pair( SECP256K1_API int secp256k1_schnorr_generate_nonce_pair(const secp256k1_context *ctx,secp256k1_pubkey *pubnonce,unsigned char *privnonce32,const unsigned char *msg32,const unsigned char *sec32,secp256k1_nonce_function noncefp,const void *noncedata) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
const secp256k1_context* ctx,
secp256k1_pubkey *pubnonce,
unsigned char *privnonce32,
const unsigned char *msg32,
const unsigned char *sec32,
secp256k1_nonce_function noncefp,
const void* noncedata
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Produce a partial Schnorr signature, which can be combined using /** Produce a partial Schnorr signature, which can be combined using
* secp256k1_schnorr_partial_combine, to end up with a full signature that is * secp256k1_schnorr_partial_combine, to end up with a full signature that is
@ -103,8 +65,7 @@ SECP256K1_API int secp256k1_schnorr_generate_nonce_pair(
* 0: no valid signature exists with this combination of keys, nonces * 0: no valid signature exists with this combination of keys, nonces
* and message (chance around 1 in 2^128) * and message (chance around 1 in 2^128)
* -1: invalid private key, nonce, or public nonces. * -1: invalid private key, nonce, or public nonces.
* Args: ctx: pointer to context object, initialized for signing (cannot * Args: ctx: pointer to context object, initialized for signing (cannot be NULL)
* be NULL)
* Out: sig64: pointer to 64-byte array to put partial signature in * Out: sig64: pointer to 64-byte array to put partial signature in
* In: msg32: pointer to 32-byte message to sign * In: msg32: pointer to 32-byte message to sign
* sec32: pointer to 32-byte private key * sec32: pointer to 32-byte private key
@ -114,24 +75,18 @@ SECP256K1_API int secp256k1_schnorr_generate_nonce_pair(
* *
* The intended procedure for creating a multiparty signature is: * The intended procedure for creating a multiparty signature is:
* - Each signer S[i] with private key x[i] and public key Q[i] runs * - Each signer S[i] with private key x[i] and public key Q[i] runs
* secp256k1_schnorr_generate_nonce_pair to produce a pair (k[i],R[i]) of * secp256k1_schnorr_generate_nonce_pair to produce a pair (k[i],R[i]) of private/public nonces.
* private/public nonces.
* - All signers communicate their public nonces to each other (revealing your * - All signers communicate their public nonces to each other (revealing your
* private nonce can lead to discovery of your private key, so it should be * private nonce can lead to discovery of your private key, so it should be considered secret).
* considered secret).
* - All signers combine all the public nonces they received (excluding their * - All signers combine all the public nonces they received (excluding their
* own) using secp256k1_ec_pubkey_combine to obtain an * own) using secp256k1_ec_pubkey_combine to obtain an Rall[i] = sum(R[0..i-1,i+1..n]).
* Rall[i] = sum(R[0..i-1,i+1..n]).
* - All signers produce a partial signature using * - All signers produce a partial signature using
* secp256k1_schnorr_partial_sign, passing in their own private key x[i], * secp256k1_schnorr_partial_sign, passing in their own private key x[i],
* their own private nonce k[i], and the sum of the others' public nonces * their own private nonce k[i], and the sum of the others' public nonces Rall[i].
* Rall[i].
* - All signers communicate their partial signatures to each other. * - All signers communicate their partial signatures to each other.
* - Someone combines all partial signatures using * - Someone combines all partial signatures using secp256k1_schnorr_partial_combine, to obtain a full signature.
* secp256k1_schnorr_partial_combine, to obtain a full signature.
* - The resulting signature is validatable using secp256k1_schnorr_verify, with * - The resulting signature is validatable using secp256k1_schnorr_verify, with
* public key equal to the result of secp256k1_ec_pubkey_combine of the * public key equal to the result of secp256k1_ec_pubkey_combine of the signers' public keys (sum(Q[0..n])).
* signers' public keys (sum(Q[0..n])).
* *
* Note that secp256k1_schnorr_partial_combine and secp256k1_ec_pubkey_combine * Note that secp256k1_schnorr_partial_combine and secp256k1_ec_pubkey_combine
* function take their arguments in any order, and it is possible to * function take their arguments in any order, and it is possible to
@ -153,10 +108,8 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_schnorr_partial_sign(
* -1: some inputs were invalid, or the signatures were not created * -1: some inputs were invalid, or the signatures were not created
* using the same set of nonces * using the same set of nonces
* Args: ctx: pointer to a context object * Args: ctx: pointer to a context object
* Out: sig64: pointer to a 64-byte array to place the combined signature * Out: sig64: pointer to a 64-byte array to place the combined signature (cannot be NULL)
* (cannot be NULL) * In: sig64sin: pointer to an array of n pointers to 64-byte input signatures
* In: sig64sin: pointer to an array of n pointers to 64-byte input
* signatures
* n: the number of signatures to combine (at least 1) * n: the number of signatures to combine (at least 1)
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_schnorr_partial_combine( SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_schnorr_partial_combine(

62
iguana/secp256k1/src/bench_rangeproof.c

@ -6,35 +6,65 @@
#include <stdint.h> #include <stdint.h>
#include "include/secp256k1_rangeproof.h" #include "../include/secp256k1_rangeproof.h"
#include "util.h" #include "util.h"
#include "bench.h" #include "bench.h"
typedef struct { typedef struct {
secp256k1_context_t* ctx; secp256k1_context *ctx;
unsigned char commit[33]; unsigned char commit[33];
unsigned char proof[5134]; unsigned char proof[5134];
unsigned char message[4096];
unsigned char blind[32]; unsigned char blind[32];
int len; unsigned char nonce[32];
int prooflen;
int min_bits; int min_bits;
uint64_t v; uint64_t v;
} bench_rangeproof_t; } bench_rangeproof_t;
static void bench_rangeproof_setup(void* arg) { static void bench_rangeproof_setup(void* arg)
{
int i; int i;
uint64_t minv; uint64_t minv;
uint64_t maxv; uint64_t maxv;
bench_rangeproof_t *data = (bench_rangeproof_t *)arg; bench_rangeproof_t *data = (bench_rangeproof_t *)arg;
for (i = 0; i < 32; i++)
data->v = 0; {
for (i = 0; i < 32; i++) data->blind[i] = i + 1; data->blind[i] = rand();
data->nonce[i] = rand();
}
#define PRIVATEBITS 32
#define PUBLICDIGITS 0
#define ENCODEVALUE 2
data->v = ENCODEVALUE;
CHECK(secp256k1_pedersen_commit(data->ctx, data->commit, data->blind, data->v)); CHECK(secp256k1_pedersen_commit(data->ctx, data->commit, data->blind, data->v));
data->len = 5134; data->prooflen = 5134;
CHECK(secp256k1_rangeproof_sign(data->ctx, data->proof, &data->len, 0, data->commit, data->blind, data->commit, 0, data->min_bits, data->v)); for (i=0; i<data->prooflen; i++)
CHECK(secp256k1_rangeproof_verify(data->ctx, &minv, &maxv, data->commit, data->proof, data->len)); {
//data->proof[i] = i;
if ( i < sizeof(data->prooflen) )
data->message[i] = i;
}
CHECK(secp256k1_rangeproof_sign(data->ctx, data->proof, &data->prooflen,0, data->commit, data->blind, data->nonce, PUBLICDIGITS, data->min_bits, data->v,data->message));
//for (i=0; i<data->prooflen; i++)
// printf("%02x",data->proof[i]);
CHECK(secp256k1_rangeproof_verify(data->ctx, &minv, &maxv, data->commit, data->proof, data->prooflen));
printf(" proof.%d [%llx, %llx]\n",data->prooflen,(long long)minv,(long long)maxv);
uint8_t blindout[32],message_out[5134]; uint64_t value_out,min_value,max_value; int32_t outlen;
for (i=0; i<32; i++)
message_out[i] = 0;
CHECK(secp256k1_rangeproof_rewind(data->ctx,blindout,&value_out,message_out,&outlen,data->nonce,&min_value,&max_value,data->commit,data->proof,data->prooflen));
for (i=0; i<32; i++)
printf("%02x:%02x",data->blind[i],blindout[i]);
printf(" blind, ");
for (i=0; i<outlen; i++)
if ( message_out[i] != 0 )
printf("%02x",message_out[i]);
printf(" message.%d, [%llx, %llx] value %llx prooflen.%d\n",outlen,(long long)min_value,(long long)max_value,(long long)value_out,data->prooflen);
} }
static void bench_rangeproof(void* arg) { static void bench_rangeproof(void* arg)
{
int i; int i;
bench_rangeproof_t *data = (bench_rangeproof_t*)arg; bench_rangeproof_t *data = (bench_rangeproof_t*)arg;
@ -42,21 +72,23 @@ static void bench_rangeproof(void* arg) {
int j; int j;
uint64_t minv; uint64_t minv;
uint64_t maxv; uint64_t maxv;
j = secp256k1_rangeproof_verify(data->ctx, &minv, &maxv, data->commit, data->proof, data->len); j = secp256k1_rangeproof_verify(data->ctx, &minv, &maxv, data->commit, data->proof, data->prooflen);
for (j = 0; j < 4; j++) { for (j = 0; j < 4; j++)
{
data->proof[j + 2 + 32 *((data->min_bits + 1) >> 1) - 4] = (i >> 8)&255; data->proof[j + 2 + 32 *((data->min_bits + 1) >> 1) - 4] = (i >> 8)&255;
} }
} }
} }
int main(void) { int proofmain(void)
{
bench_rangeproof_t data; bench_rangeproof_t data;
data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
secp256k1_pedersen_context_initialize(data.ctx); secp256k1_pedersen_context_initialize(data.ctx);
secp256k1_rangeproof_context_initialize(data.ctx); secp256k1_rangeproof_context_initialize(data.ctx);
data.min_bits = 32; data.min_bits = PRIVATEBITS;
run_benchmark("rangeproof_verify_bit", bench_rangeproof, bench_rangeproof_setup, NULL, &data, 10, 1000 * data.min_bits); run_benchmark("rangeproof_verify_bit", bench_rangeproof, bench_rangeproof_setup, NULL, &data, 10, 1000 * data.min_bits);

24
iguana/secp256k1/src/libsecp256k1-config.h

@ -25,16 +25,16 @@
/* #undef ENABLE_OPENSSL_TESTS */ /* #undef ENABLE_OPENSSL_TESTS */
/* Define this symbol if __builtin_clzll is available */ /* Define this symbol if __builtin_clzll is available */
#define HAVE_BUILTIN_CLZLL 1 #define HAVE_BUILTIN_CLZLL 0 //1
/* Define this symbol if __builtin_expect is available */ /* Define this symbol if __builtin_expect is available */
#define HAVE_BUILTIN_EXPECT 1 #define HAVE_BUILTIN_EXPECT 0 //1
/* Define to 1 if you have the <dlfcn.h> header file. */ /* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1 #define HAVE_DLFCN_H 0 //1
/* Define to 1 if you have the <inttypes.h> header file. */ /* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1 #define HAVE_INTTYPES_H 0 //1
/* Define this symbol if libcrypto is installed */ /* Define this symbol if libcrypto is installed */
/* #undef HAVE_LIBCRYPTO */ /* #undef HAVE_LIBCRYPTO */
@ -43,28 +43,28 @@
/* #undef HAVE_LIBGMP */ /* #undef HAVE_LIBGMP */
/* Define to 1 if you have the <memory.h> header file. */ /* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1 #define HAVE_MEMORY_H 0 //1
/* Define to 1 if you have the <stdint.h> header file. */ /* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1 #define HAVE_STDINT_H 0 //1
/* Define to 1 if you have the <stdlib.h> header file. */ /* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1 #define HAVE_STDLIB_H 0 //1
/* Define to 1 if you have the <strings.h> header file. */ /* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1 #define HAVE_STRINGS_H 0 //1
/* Define to 1 if you have the <string.h> header file. */ /* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1 #define HAVE_STRING_H 0 //1
/* Define to 1 if you have the <sys/stat.h> header file. */ /* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1 #define HAVE_SYS_STAT_H 0 //1
/* Define to 1 if you have the <sys/types.h> header file. */ /* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1 #define HAVE_SYS_TYPES_H 0 //1
/* Define to 1 if you have the <unistd.h> header file. */ /* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1 #define HAVE_UNISTD_H 0 //1
/* Define to 1 if the system has the type `__int128'. */ /* Define to 1 if the system has the type `__int128'. */
/* #undef HAVE___INT128 */ /* #undef HAVE___INT128 */

7
iguana/secp256k1/src/modules/rangeproof/borromean.h

@ -14,11 +14,8 @@
#include "../../ecmult.h" #include "../../ecmult.h"
#include "../../ecmult_gen.h" #include "../../ecmult_gen.h"
int secp256k1_borromean_verify(const secp256k1_ecmult_context* ecmult_ctx, secp256k1_scalar *evalues, const unsigned char *e0, const secp256k1_scalar *s, int secp256k1_borromean_verify(const secp256k1_ecmult_context* ecmult_ctx, secp256k1_scalar *evalues, const unsigned char *e0, const secp256k1_scalar *s,const secp256k1_gej *pubs, const int *rsizes, int nrings, const unsigned char *m, int mlen);
const secp256k1_gej *pubs, const int *rsizes, int nrings, const unsigned char *m, int mlen);
int secp256k1_borromean_sign(const secp256k1_ecmult_context* ecmult_ctx, const secp256k1_ecmult_gen_context *ecmult_gen_ctx, int secp256k1_borromean_sign(const secp256k1_ecmult_context* ecmult_ctx, 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,const int *rsizes, const int *secidx, int nrings, const unsigned char *m, int mlen);
unsigned char *e0, secp256k1_scalar *s, const secp256k1_gej *pubs, const secp256k1_scalar *k, const secp256k1_scalar *sec,
const int *rsizes, const int *secidx, int nrings, const unsigned char *m, int mlen);
#endif #endif

99
iguana/secp256k1/src/modules/rangeproof/borromean_impl.h

@ -23,8 +23,8 @@
#define BE32(p) ((((p) & 0xFF) << 24) | (((p) & 0xFF00) << 8) | (((p) & 0xFF0000) >> 8) | (((p) & 0xFF000000) >> 24)) #define BE32(p) ((((p) & 0xFF) << 24) | (((p) & 0xFF00) << 8) | (((p) & 0xFF0000) >> 8) | (((p) & 0xFF000000) >> 24))
#endif #endif
SECP256K1_INLINE static void secp256k1_borromean_hash(unsigned char *hash, const unsigned char *m, int mlen, const unsigned char *e, int elen, SECP256K1_INLINE static void secp256k1_borromean_hash(unsigned char *hash, const unsigned char *m, int mlen, const unsigned char *e, int elen,int ridx, int eidx)
int ridx, int eidx) { {
uint32_t ring; uint32_t ring;
uint32_t epos; uint32_t epos;
secp256k1_sha256_t sha256_en; secp256k1_sha256_t sha256_en;
@ -52,18 +52,10 @@ SECP256K1_INLINE static void secp256k1_borromean_hash(unsigned char *hash, const
* | | r_i = r * | | r_i = r
* | return e_0 ==== H(r_{0..i}||m) * | return e_0 ==== H(r_{0..i}||m)
*/ */
int secp256k1_borromean_verify(const secp256k1_ecmult_context* ecmult_ctx, secp256k1_scalar *evalues, const unsigned char *e0, int secp256k1_borromean_verify(const secp256k1_ecmult_context *ecmult_ctx,secp256k1_scalar *evalues, const unsigned char *e0,const secp256k1_scalar *s,const secp256k1_gej *pubs,const int *rsizes,int nrings,const unsigned char *m,int mlen)
const secp256k1_scalar *s, const secp256k1_gej *pubs, const int *rsizes, int nrings, const unsigned char *m, int mlen) { {
secp256k1_gej rgej; secp256k1_gej rgej; secp256k1_ge rge; secp256k1_scalar ens; secp256k1_sha256_t sha256_e0;
secp256k1_ge rge; unsigned char tmp[33]; int i,j,count,overflow; size_t size;
secp256k1_scalar ens;
secp256k1_sha256_t sha256_e0;
unsigned char tmp[33];
int i;
int j;
int count;
size_t size;
int overflow;
VERIFY_CHECK(ecmult_ctx != NULL); VERIFY_CHECK(ecmult_ctx != NULL);
VERIFY_CHECK(e0 != NULL); VERIFY_CHECK(e0 != NULL);
VERIFY_CHECK(s != NULL); VERIFY_CHECK(s != NULL);
@ -73,31 +65,28 @@ int secp256k1_borromean_verify(const secp256k1_ecmult_context* ecmult_ctx, secp2
VERIFY_CHECK(m != NULL); VERIFY_CHECK(m != NULL);
count = 0; count = 0;
secp256k1_sha256_initialize(&sha256_e0); secp256k1_sha256_initialize(&sha256_e0);
for (i = 0; i < nrings; i++) { for (i = 0; i < nrings; i++)
{
VERIFY_CHECK(INT_MAX - count > rsizes[i]); VERIFY_CHECK(INT_MAX - count > rsizes[i]);
secp256k1_borromean_hash(tmp, m, mlen, e0, 32, i, 0); secp256k1_borromean_hash(tmp, m, mlen, e0, 32, i, 0);
secp256k1_scalar_set_b32(&ens, tmp, &overflow); secp256k1_scalar_set_b32(&ens, tmp, &overflow);
for (j = 0; j < rsizes[i]; j++) { for (j = 0; j < rsizes[i]; j++)
if (overflow || secp256k1_scalar_is_zero(&s[count]) || secp256k1_scalar_is_zero(&ens) || secp256k1_gej_is_infinity(&pubs[count])) { {
if (overflow || secp256k1_scalar_is_zero(&s[count]) || secp256k1_scalar_is_zero(&ens) || secp256k1_gej_is_infinity(&pubs[count]))
return 0; return 0;
} if (evalues) // If requested, save the challenges for proof rewind.*/
if (evalues) {
/*If requested, save the challenges for proof rewind.*/
evalues[count] = ens; evalues[count] = ens;
}
secp256k1_ecmult(ecmult_ctx, &rgej, &pubs[count], &ens, &s[count]); secp256k1_ecmult(ecmult_ctx, &rgej, &pubs[count], &ens, &s[count]);
if (secp256k1_gej_is_infinity(&rgej)) { if (secp256k1_gej_is_infinity(&rgej))
return 0; return 0;
} // OPT: loop can be hoisted and split to use batch inversion across all the rings; this would make it much faster.
/* OPT: loop can be hoisted and split to use batch inversion across all the rings; this would make it much faster. */
secp256k1_ge_set_gej_var(&rge, &rgej); secp256k1_ge_set_gej_var(&rge, &rgej);
secp256k1_eckey_pubkey_serialize(&rge, tmp, &size, 1); secp256k1_eckey_pubkey_serialize(&rge, tmp, &size, 1);
if (j != rsizes[i] - 1) { if (j != rsizes[i] - 1)
{
secp256k1_borromean_hash(tmp, m, mlen, tmp, 33, i, j + 1); secp256k1_borromean_hash(tmp, m, mlen, tmp, 33, i, j + 1);
secp256k1_scalar_set_b32(&ens, tmp, &overflow); secp256k1_scalar_set_b32(&ens, tmp, &overflow);
} else { } else secp256k1_sha256_write(&sha256_e0, tmp, size);
secp256k1_sha256_write(&sha256_e0, tmp, size);
}
count++; count++;
} }
} }
@ -106,19 +95,10 @@ int secp256k1_borromean_verify(const secp256k1_ecmult_context* ecmult_ctx, secp2
return memcmp(e0, tmp, 32) == 0; return memcmp(e0, tmp, 32) == 0;
} }
int secp256k1_borromean_sign(const secp256k1_ecmult_context* ecmult_ctx, const secp256k1_ecmult_gen_context *ecmult_gen_ctx, int secp256k1_borromean_sign(const secp256k1_ecmult_context* ecmult_ctx, 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,const int *rsizes, const int *secidx, int nrings, const unsigned char *m, int mlen)
unsigned char *e0, secp256k1_scalar *s, const secp256k1_gej *pubs, const secp256k1_scalar *k, const secp256k1_scalar *sec, {
const int *rsizes, const int *secidx, int nrings, const unsigned char *m, int mlen) { secp256k1_gej rgej; secp256k1_ge rge; secp256k1_scalar ens; secp256k1_sha256_t sha256_e0;
secp256k1_gej rgej; unsigned char tmp[33]; int i,j,count,overflow; size_t size;
secp256k1_ge rge;
secp256k1_scalar ens;
secp256k1_sha256_t sha256_e0;
unsigned char tmp[33];
int i;
int j;
int count;
size_t size;
int overflow;
VERIFY_CHECK(ecmult_ctx != NULL); VERIFY_CHECK(ecmult_ctx != NULL);
VERIFY_CHECK(ecmult_gen_ctx != NULL); VERIFY_CHECK(ecmult_gen_ctx != NULL);
VERIFY_CHECK(e0 != NULL); VERIFY_CHECK(e0 != NULL);
@ -132,28 +112,25 @@ int secp256k1_borromean_sign(const secp256k1_ecmult_context* ecmult_ctx, const s
VERIFY_CHECK(m != NULL); VERIFY_CHECK(m != NULL);
secp256k1_sha256_initialize(&sha256_e0); secp256k1_sha256_initialize(&sha256_e0);
count = 0; count = 0;
for (i = 0; i < nrings; i++) { for (i = 0; i < nrings; i++)
{
VERIFY_CHECK(INT_MAX - count > rsizes[i]); VERIFY_CHECK(INT_MAX - count > rsizes[i]);
secp256k1_ecmult_gen(ecmult_gen_ctx, &rgej, &k[i]); secp256k1_ecmult_gen(ecmult_gen_ctx, &rgej, &k[i]);
secp256k1_ge_set_gej(&rge, &rgej); secp256k1_ge_set_gej(&rge, &rgej);
if (secp256k1_gej_is_infinity(&rgej)) { if (secp256k1_gej_is_infinity(&rgej))
return 0; return 0;
}
secp256k1_eckey_pubkey_serialize(&rge, tmp, &size, 1); secp256k1_eckey_pubkey_serialize(&rge, tmp, &size, 1);
for (j = secidx[i] + 1; j < rsizes[i]; j++) { for (j = secidx[i] + 1; j < rsizes[i]; j++)
{
secp256k1_borromean_hash(tmp, m, mlen, tmp, 33, i, j); secp256k1_borromean_hash(tmp, m, mlen, tmp, 33, i, j);
secp256k1_scalar_set_b32(&ens, tmp, &overflow); secp256k1_scalar_set_b32(&ens, tmp, &overflow);
if (overflow || secp256k1_scalar_is_zero(&ens)) { if (overflow || secp256k1_scalar_is_zero(&ens))
return 0; return 0;
} /** The signing algorithm as a whole is not memory uniform so there is likely a cache sidechannel that leaks which members are non-forgeries. That the forgeries themselves are variable time may leave an additional privacy impacting timing side-channel, but not a key loss one.
/** The signing algorithm as a whole is not memory uniform so there is likely a cache sidechannel that
* leaks which members are non-forgeries. That the forgeries themselves are variable time may leave
* an additional privacy impacting timing side-channel, but not a key loss one.
*/ */
secp256k1_ecmult(ecmult_ctx, &rgej, &pubs[count + j], &ens, &s[count + j]); secp256k1_ecmult(ecmult_ctx, &rgej, &pubs[count + j], &ens, &s[count + j]);
if (secp256k1_gej_is_infinity(&rgej)) { if (secp256k1_gej_is_infinity(&rgej))
return 0; return 0;
}
secp256k1_ge_set_gej_var(&rge, &rgej); secp256k1_ge_set_gej_var(&rge, &rgej);
secp256k1_eckey_pubkey_serialize(&rge, tmp, &size, 1); secp256k1_eckey_pubkey_serialize(&rge, tmp, &size, 1);
} }
@ -163,32 +140,30 @@ int secp256k1_borromean_sign(const secp256k1_ecmult_context* ecmult_ctx, const s
secp256k1_sha256_write(&sha256_e0, m, mlen); secp256k1_sha256_write(&sha256_e0, m, mlen);
secp256k1_sha256_finalize(&sha256_e0, e0); secp256k1_sha256_finalize(&sha256_e0, e0);
count = 0; count = 0;
for (i = 0; i < nrings; i++) { for (i = 0; i < nrings; i++)
{
VERIFY_CHECK(INT_MAX - count > rsizes[i]); VERIFY_CHECK(INT_MAX - count > rsizes[i]);
secp256k1_borromean_hash(tmp, m, mlen, e0, 32, i, 0); secp256k1_borromean_hash(tmp, m, mlen, e0, 32, i, 0);
secp256k1_scalar_set_b32(&ens, tmp, &overflow); secp256k1_scalar_set_b32(&ens, tmp, &overflow);
if (overflow || secp256k1_scalar_is_zero(&ens)) { if (overflow || secp256k1_scalar_is_zero(&ens))
return 0; return 0;
} for (j = 0; j < secidx[i]; j++)
for (j = 0; j < secidx[i]; j++) { {
secp256k1_ecmult(ecmult_ctx, &rgej, &pubs[count + j], &ens, &s[count + j]); secp256k1_ecmult(ecmult_ctx, &rgej, &pubs[count + j], &ens, &s[count + j]);
if (secp256k1_gej_is_infinity(&rgej)) { if (secp256k1_gej_is_infinity(&rgej))
return 0; return 0;
}
secp256k1_ge_set_gej_var(&rge, &rgej); secp256k1_ge_set_gej_var(&rge, &rgej);
secp256k1_eckey_pubkey_serialize(&rge, tmp, &size, 1); secp256k1_eckey_pubkey_serialize(&rge, tmp, &size, 1);
secp256k1_borromean_hash(tmp, m, mlen, tmp, 33, i, j + 1); secp256k1_borromean_hash(tmp, m, mlen, tmp, 33, i, j + 1);
secp256k1_scalar_set_b32(&ens, tmp, &overflow); secp256k1_scalar_set_b32(&ens, tmp, &overflow);
if (overflow || secp256k1_scalar_is_zero(&ens)) { if (overflow || secp256k1_scalar_is_zero(&ens))
return 0; return 0;
} }
}
secp256k1_scalar_mul(&s[count + j], &ens, &sec[i]); secp256k1_scalar_mul(&s[count + j], &ens, &sec[i]);
secp256k1_scalar_negate(&s[count + j], &s[count + j]); 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[i]);
if (secp256k1_scalar_is_zero(&s[count + j])) { if (secp256k1_scalar_is_zero(&s[count + j]))
return 0; return 0;
}
count += rsizes[i]; count += rsizes[i];
} }
secp256k1_scalar_clear(&ens); secp256k1_scalar_clear(&ens);

25
iguana/secp256k1/src/modules/rangeproof/main_impl.h

@ -16,7 +16,8 @@ void secp256k1_pedersen_context_initialize(secp256k1_context* ctx) {
} }
/* Generates a pedersen commitment: *commit = blind * G + value * G2. The commitment is 33 bytes, the blinding factor is 32 bytes.*/ /* Generates a pedersen commitment: *commit = blind * G + value * G2. The commitment is 33 bytes, the blinding factor is 32 bytes.*/
int secp256k1_pedersen_commit(const secp256k1_context* ctx, unsigned char *commit, unsigned char *blind, uint64_t value) { int secp256k1_pedersen_commit(const secp256k1_context* ctx, unsigned char *commit, unsigned char *blind, uint64_t value)
{
secp256k1_gej rj; secp256k1_gej rj;
secp256k1_ge r; secp256k1_ge r;
secp256k1_scalar sec; secp256k1_scalar sec;
@ -126,10 +127,8 @@ int secp256k1_rangeproof_info(const secp256k1_context* ctx, int *exp, int *manti
return secp256k1_rangeproof_getheader_impl(&offset, exp, mantissa, &scale, min_value, max_value, proof, plen); return secp256k1_rangeproof_getheader_impl(&offset, exp, mantissa, &scale, min_value, max_value, proof, plen);
} }
int secp256k1_rangeproof_rewind(const secp256k1_context* ctx, int secp256k1_rangeproof_rewind(const secp256k1_context* ctx,unsigned char *blind_out, uint64_t *value_out, unsigned char *message_out, int *outlen, const unsigned char *nonce,uint64_t *min_value, uint64_t *max_value,const unsigned char *commit, const unsigned char *proof, int plen)
unsigned char *blind_out, uint64_t *value_out, unsigned char *message_out, int *outlen, const unsigned char *nonce, {
uint64_t *min_value, uint64_t *max_value,
const unsigned char *commit, const unsigned char *proof, int plen) {
ARG_CHECK(ctx != NULL); ARG_CHECK(ctx != NULL);
ARG_CHECK(commit != NULL); ARG_CHECK(commit != NULL);
ARG_CHECK(proof != NULL); ARG_CHECK(proof != NULL);
@ -139,12 +138,12 @@ int secp256k1_rangeproof_rewind(const secp256k1_context* ctx,
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
ARG_CHECK(secp256k1_pedersen_context_is_built(&ctx->pedersen_ctx)); ARG_CHECK(secp256k1_pedersen_context_is_built(&ctx->pedersen_ctx));
ARG_CHECK(secp256k1_rangeproof_context_is_built(&ctx->rangeproof_ctx)); ARG_CHECK(secp256k1_rangeproof_context_is_built(&ctx->rangeproof_ctx));
return secp256k1_rangeproof_verify_impl(&ctx->ecmult_ctx, &ctx->ecmult_gen_ctx, &ctx->pedersen_ctx, &ctx->rangeproof_ctx, return secp256k1_rangeproof_verify_impl(&ctx->ecmult_ctx, &ctx->ecmult_gen_ctx, &ctx->pedersen_ctx, &ctx->rangeproof_ctx,blind_out, value_out, message_out, outlen, nonce, min_value, max_value, commit, proof, plen);
blind_out, value_out, message_out, outlen, nonce, min_value, max_value, commit, proof, plen);
} }
int secp256k1_rangeproof_verify(const secp256k1_context* ctx, uint64_t *min_value, uint64_t *max_value, int secp256k1_rangeproof_verify(const secp256k1_context* ctx, uint64_t *min_value, uint64_t *max_value,
const unsigned char *commit, const unsigned char *proof, int plen) { const unsigned char *commit, const unsigned char *proof, int plen)
{
ARG_CHECK(ctx != NULL); ARG_CHECK(ctx != NULL);
ARG_CHECK(commit != NULL); ARG_CHECK(commit != NULL);
ARG_CHECK(proof != NULL); ARG_CHECK(proof != NULL);
@ -153,12 +152,11 @@ int secp256k1_rangeproof_verify(const secp256k1_context* ctx, uint64_t *min_valu
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
ARG_CHECK(secp256k1_pedersen_context_is_built(&ctx->pedersen_ctx)); ARG_CHECK(secp256k1_pedersen_context_is_built(&ctx->pedersen_ctx));
ARG_CHECK(secp256k1_rangeproof_context_is_built(&ctx->rangeproof_ctx)); ARG_CHECK(secp256k1_rangeproof_context_is_built(&ctx->rangeproof_ctx));
return secp256k1_rangeproof_verify_impl(&ctx->ecmult_ctx, NULL, &ctx->pedersen_ctx, &ctx->rangeproof_ctx, return secp256k1_rangeproof_verify_impl(&ctx->ecmult_ctx, NULL, &ctx->pedersen_ctx, &ctx->rangeproof_ctx,NULL, NULL, NULL, NULL, NULL, min_value, max_value, commit, proof, plen);
NULL, NULL, NULL, NULL, NULL, min_value, max_value, commit, proof, plen);
} }
int secp256k1_rangeproof_sign(const secp256k1_context* ctx, unsigned char *proof, int *plen, uint64_t min_value, int secp256k1_rangeproof_sign(const secp256k1_context *ctx, unsigned char *proof, int *plen,uint64_t min_value,const unsigned char *commit, const unsigned char *blind, const unsigned char *nonce,int exp,int min_bits, uint64_t value,unsigned char message[4096])
const unsigned char *commit, const unsigned char *blind, const unsigned char *nonce, int exp, int min_bits, uint64_t value){ {
ARG_CHECK(ctx != NULL); ARG_CHECK(ctx != NULL);
ARG_CHECK(proof != NULL); ARG_CHECK(proof != NULL);
ARG_CHECK(plen != NULL); ARG_CHECK(plen != NULL);
@ -169,8 +167,7 @@ int secp256k1_rangeproof_sign(const secp256k1_context* ctx, unsigned char *proof
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
ARG_CHECK(secp256k1_pedersen_context_is_built(&ctx->pedersen_ctx)); ARG_CHECK(secp256k1_pedersen_context_is_built(&ctx->pedersen_ctx));
ARG_CHECK(secp256k1_rangeproof_context_is_built(&ctx->rangeproof_ctx)); ARG_CHECK(secp256k1_rangeproof_context_is_built(&ctx->rangeproof_ctx));
return secp256k1_rangeproof_sign_impl(&ctx->ecmult_ctx, &ctx->ecmult_gen_ctx, &ctx->pedersen_ctx, &ctx->rangeproof_ctx, return secp256k1_rangeproof_sign_impl(&ctx->ecmult_ctx, &ctx->ecmult_gen_ctx, &ctx->pedersen_ctx, &ctx->rangeproof_ctx,proof, plen, min_value, commit, blind, nonce, exp, min_bits, value,message);
proof, plen, min_value, commit, blind, nonce, exp, min_bits, value);
} }
#endif #endif

13
iguana/secp256k1/src/modules/rangeproof/rangeproof.h

@ -10,22 +10,15 @@
#include "../../scalar.h" #include "../../scalar.h"
#include "../../group.h" #include "../../group.h"
typedef struct { typedef struct { secp256k1_ge_storage (*prec)[1005]; } secp256k1_rangeproof_context;
secp256k1_ge_storage (*prec)[1005];
} secp256k1_rangeproof_context;
static void secp256k1_rangeproof_context_init(secp256k1_rangeproof_context* ctx); static void secp256k1_rangeproof_context_init(secp256k1_rangeproof_context* ctx);
static void secp256k1_rangeproof_context_build(secp256k1_rangeproof_context* ctx, const secp256k1_callback* cb); static void secp256k1_rangeproof_context_build(secp256k1_rangeproof_context* ctx, const secp256k1_callback* cb);
static void secp256k1_rangeproof_context_clone(secp256k1_rangeproof_context *dst, static void secp256k1_rangeproof_context_clone(secp256k1_rangeproof_context *dst,const secp256k1_rangeproof_context* src, const secp256k1_callback* cb);
const secp256k1_rangeproof_context* src, const secp256k1_callback* cb);
static void secp256k1_rangeproof_context_clear(secp256k1_rangeproof_context* ctx); static void secp256k1_rangeproof_context_clear(secp256k1_rangeproof_context* ctx);
static int secp256k1_rangeproof_context_is_built(const secp256k1_rangeproof_context* ctx); static int secp256k1_rangeproof_context_is_built(const secp256k1_rangeproof_context* ctx);
static int secp256k1_rangeproof_verify_impl(const secp256k1_ecmult_context* ecmult_ctx, static int secp256k1_rangeproof_verify_impl(const secp256k1_ecmult_context* ecmult_ctx,
const secp256k1_ecmult_gen_context* ecmult_gen_ctx, const secp256k1_ecmult_gen_context* ecmult_gen_ctx,const secp256k1_pedersen_context* pedersen_ctx, const secp256k1_rangeproof_context* rangeproof_ctx,unsigned char *blindout, uint64_t *value_out, unsigned char *message_out, int *outlen, const unsigned char *nonce, uint64_t *min_value, uint64_t *max_value, const unsigned char *commit, const unsigned char *proof, int plen);
const secp256k1_pedersen_context* pedersen_ctx, const secp256k1_rangeproof_context* rangeproof_ctx,
unsigned char *blindout, uint64_t *value_out, unsigned char *message_out, int *outlen, const unsigned char *nonce,
uint64_t *min_value, uint64_t *max_value, const unsigned char *commit, const unsigned char *proof, int plen);
#endif #endif

487
iguana/secp256k1/src/modules/rangeproof/rangeproof_impl.h

@ -107,26 +107,24 @@ static void secp256k1_rangeproof_context_clone(secp256k1_rangeproof_context *dst
} }
} }
static void secp256k1_rangeproof_context_clear(secp256k1_rangeproof_context *ctx) { static void secp256k1_rangeproof_context_clear(secp256k1_rangeproof_context *ctx)
{
free(ctx->prec); free(ctx->prec);
ctx->prec = NULL; ctx->prec = NULL;
} }
SECP256K1_INLINE static void secp256k1_rangeproof_pub_expand(const secp256k1_rangeproof_context *ctx, secp256k1_gej *pubs, SECP256K1_INLINE static void secp256k1_rangeproof_pub_expand(const secp256k1_rangeproof_context *ctx, secp256k1_gej *pubs,int exp, int *rsizes, int rings)
int exp, int *rsizes, int rings) { {
secp256k1_ge ge; secp256k1_ge ge; secp256k1_ge_storage *basis; int i,j,npub;
secp256k1_ge_storage *basis;
int i;
int j;
int npub;
VERIFY_CHECK(exp < 19); VERIFY_CHECK(exp < 19);
if (exp < 0) { if (exp < 0)
exp = 0; exp = 0;
}
basis = &(*ctx->prec)[secp256k1_rangeproof_offsets[exp]]; basis = &(*ctx->prec)[secp256k1_rangeproof_offsets[exp]];
npub = 0; npub = 0;
for (i = 0; i < rings; i++) { for (i = 0; i < rings; i++)
for (j = 1; j < rsizes[i]; j++) { {
for (j = 1; j < rsizes[i]; j++)
{
secp256k1_ge_from_storage(&ge, &basis[i * 3 + j - 1]); secp256k1_ge_from_storage(&ge, &basis[i * 3 + j - 1]);
secp256k1_gej_add_ge_var(&pubs[npub + j], &pubs[npub], &ge, NULL); secp256k1_gej_add_ge_var(&pubs[npub + j], &pubs[npub], &ge, NULL);
} }
@ -134,18 +132,10 @@ SECP256K1_INLINE static void secp256k1_rangeproof_pub_expand(const secp256k1_ran
} }
} }
SECP256K1_INLINE static int secp256k1_rangeproof_genrand(secp256k1_scalar *sec, secp256k1_scalar *s, unsigned char *message, SECP256K1_INLINE static int secp256k1_rangeproof_genrand(secp256k1_scalar *sec, secp256k1_scalar *s, unsigned char *message,int *rsizes, int rings, const unsigned char *nonce, const unsigned char *commit, const unsigned char *proof, int len)
int *rsizes, int rings, const unsigned char *nonce, const unsigned char *commit, const unsigned char *proof, int len) { {
unsigned char tmp[32]; unsigned char tmp[32]; unsigned char rngseed[32 + 33 + 10]; secp256k1_rfc6979_hmac_sha256_t rng;
unsigned char rngseed[32 + 33 + 10]; secp256k1_scalar acc; int overflow,ret,i,j,b,npub;
secp256k1_rfc6979_hmac_sha256_t rng;
secp256k1_scalar acc;
int overflow;
int ret;
int i;
int j;
int b;
int npub;
VERIFY_CHECK(len <= 10); VERIFY_CHECK(len <= 10);
memcpy(rngseed, nonce, 32); memcpy(rngseed, nonce, 32);
memcpy(rngseed + 32, commit, 33); memcpy(rngseed + 32, commit, 33);
@ -154,22 +144,32 @@ SECP256K1_INLINE static int secp256k1_rangeproof_genrand(secp256k1_scalar *sec,
secp256k1_scalar_clear(&acc); secp256k1_scalar_clear(&acc);
npub = 0; npub = 0;
ret = 1; ret = 1;
for (i = 0; i < rings; i++) { for (i = 0; i < rings; i++)
if (i < rings - 1) { {
if (i < rings - 1)
{
secp256k1_rfc6979_hmac_sha256_generate(&rng, tmp, 32); secp256k1_rfc6979_hmac_sha256_generate(&rng, tmp, 32);
do { do
{
secp256k1_rfc6979_hmac_sha256_generate(&rng, tmp, 32); secp256k1_rfc6979_hmac_sha256_generate(&rng, tmp, 32);
secp256k1_scalar_set_b32(&sec[i], tmp, &overflow); secp256k1_scalar_set_b32(&sec[i], tmp, &overflow);
} while (overflow || secp256k1_scalar_is_zero(&sec[i])); } while (overflow || secp256k1_scalar_is_zero(&sec[i]));
secp256k1_scalar_add(&acc, &acc, &sec[i]); secp256k1_scalar_add(&acc, &acc, &sec[i]);
} else { }
else
{
secp256k1_scalar_negate(&acc, &acc); secp256k1_scalar_negate(&acc, &acc);
sec[i] = acc; sec[i] = acc;
} }
for (j = 0; j < rsizes[i]; j++) { for (j = 0; j < rsizes[i]; j++)
{
secp256k1_rfc6979_hmac_sha256_generate(&rng, tmp, 32); secp256k1_rfc6979_hmac_sha256_generate(&rng, tmp, 32);
if (message) { if (message)
for (b = 0; b < 32; b++) { {
for (b = 0; b < 32; b++)
{
if ( message[(i * 4 + j) * 32 + b] != 0 )
printf("(%02x-> %02x)",message[(i * 4 + j) * 32 + b],tmp[b]);
tmp[b] ^= message[(i * 4 + j) * 32 + b]; tmp[b] ^= message[(i * 4 + j) * 32 + b];
message[(i * 4 + j) * 32 + b] = tmp[b]; message[(i * 4 + j) * 32 + b] = tmp[b];
} }
@ -185,8 +185,8 @@ SECP256K1_INLINE static int secp256k1_rangeproof_genrand(secp256k1_scalar *sec,
return ret; return ret;
} }
SECP256K1_INLINE static int secp256k1_range_proveparams(uint64_t *v, int *rings, int *rsizes, int *npub, int *secidx, uint64_t *min_value, SECP256K1_INLINE static int secp256k1_range_proveparams(uint64_t *v,int *rings,int *rsizes,int *npub,int *secidx,uint64_t *min_value,int *mantissa, uint64_t *scale,int *exp,int *min_bits,uint64_t value)
int *mantissa, uint64_t *scale, int *exp, int *min_bits, uint64_t value) { {
int i; int i;
*rings = 1; *rings = 1;
rsizes[0] = 1; rsizes[0] = 1;
@ -194,22 +194,21 @@ SECP256K1_INLINE static int secp256k1_range_proveparams(uint64_t *v, int *rings,
*scale = 1; *scale = 1;
*mantissa = 0; *mantissa = 0;
*npub = 0; *npub = 0;
if (*min_value == UINT64_MAX) { if ( *min_value == UINT64_MAX ) // If the minimum value is the maximal representable value, then we cannot code a range.
/* If the minimum value is the maximal representable value, then we cannot code a range. */
*exp = -1; *exp = -1;
} if ( *exp >= 0 )
if (*exp >= 0) { {
int max_bits; int max_bits; uint64_t v2;
uint64_t v2; if ((*min_value && value > INT64_MAX) || (value && *min_value >= INT64_MAX))
if ((*min_value && value > INT64_MAX) || (value && *min_value >= INT64_MAX)) { {
/* If either value or min_value is >= 2^63-1 then the other must by zero to avoid overflowing the proven range. */ // If either value or min_value is >= 2^63-1 then the other must by zero to avoid overflowing the proven range.
return 0; return 0;
} }
max_bits = *min_value ? secp256k1_clz64_var(*min_value) : 64; max_bits = *min_value ? secp256k1_clz64_var(*min_value) : 64;
if (*min_bits > max_bits) { if (*min_bits > max_bits)
*min_bits = max_bits; *min_bits = max_bits;
} if (*min_bits > 61 || value > INT64_MAX)
if (*min_bits > 61 || value > INT64_MAX) { {
/** Ten is not a power of two, so dividing by ten and then representing in base-2 times ten /** Ten is not a power of two, so dividing by ten and then representing in base-2 times ten
* expands the representable range. The verifier requires the proven range is within 0..2**64. * expands the representable range. The verifier requires the proven range is within 0..2**64.
* For very large numbers (all over 2**63) we must change our exponent to compensate. * For very large numbers (all over 2**63) we must change our exponent to compensate.
@ -217,39 +216,39 @@ SECP256K1_INLINE static int secp256k1_range_proveparams(uint64_t *v, int *rings,
*/ */
*exp = 0; *exp = 0;
} }
/* Mask off the least significant digits, as requested. */ *v = value - *min_value; // Mask off the least significant digits, as requested.
*v = value - *min_value; // If the user has asked for more bits of proof then there is room for in the exponent, reduce the exponent.
/* If the user has asked for more bits of proof then there is room for in the exponent, reduce the exponent. */
v2 = *min_bits ? (UINT64_MAX>>(64-*min_bits)) : 0; v2 = *min_bits ? (UINT64_MAX>>(64-*min_bits)) : 0;
for (i = 0; i < *exp && (v2 <= UINT64_MAX / 10); i++) { for (i = 0; i < *exp && (v2 <= UINT64_MAX / 10); i++)
{
*v /= 10; *v /= 10;
v2 *= 10; v2 *= 10;
} }
*exp = i; *exp = i;
v2 = *v; v2 = *v;
for (i = 0; i < *exp; i++) { for (i = 0; i < *exp; i++)
{
v2 *= 10; v2 *= 10;
*scale *= 10; *scale *= 10;
} }
/* If the masked number isn't precise, compute the public offset. */ *min_value = value - v2; // If the masked number isn't precise, compute the public offset
*min_value = value - v2; *mantissa = *v ? 64 - secp256k1_clz64_var(*v) : 1; // How many bits do we need to represent our value?
/* How many bits do we need to represent our value? */ if (*min_bits > *mantissa) // If the user asked for more precision, give it to them.
*mantissa = *v ? 64 - secp256k1_clz64_var(*v) : 1;
if (*min_bits > *mantissa) {
/* If the user asked for more precision, give it to them. */
*mantissa = *min_bits; *mantissa = *min_bits;
} // Digits in radix-4, except for the last digit if our mantissa length is odd.
/* Digits in radix-4, except for the last digit if our mantissa length is odd. */
*rings = (*mantissa + 1) >> 1; *rings = (*mantissa + 1) >> 1;
for (i = 0; i < *rings; i++) { for (i = 0; i < *rings; i++)
{
rsizes[i] = ((i < *rings - 1) | (!(*mantissa&1))) ? 4 : 2; rsizes[i] = ((i < *rings - 1) | (!(*mantissa&1))) ? 4 : 2;
*npub += rsizes[i]; *npub += rsizes[i];
secidx[i] = (*v >> (i*2)) & 3; secidx[i] = (*v >> (i*2)) & 3;
} }
VERIFY_CHECK(*mantissa>0); VERIFY_CHECK(*mantissa>0);
VERIFY_CHECK((*v & ~(UINT64_MAX>>(64-*mantissa))) == 0); /* Did this get all the bits? */ VERIFY_CHECK((*v & ~(UINT64_MAX>>(64-*mantissa))) == 0); // Did this get all the bits?
} else { }
/* A proof for an exact value. */ else
{
// A proof for an exact value.
*exp = 0; *exp = 0;
*min_value = value; *min_value = value;
*v = 0; *v = 0;
@ -262,19 +261,20 @@ SECP256K1_INLINE static int secp256k1_range_proveparams(uint64_t *v, int *rings,
return 1; return 1;
} }
/* strawman interface, writes proof in proof, a buffer of plen, proves with respect to min_value the range for commit which has the provided blinding factor and value. */ // strawman interface, writes proof in proof, a buffer of plen, proves with respect to min_value the range for commit which has the provided blinding factor and value.
SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmult_context *ecmult_ctx, SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmult_context *ecmult_ctx,
const secp256k1_ecmult_gen_context *ecmult_gen_ctx,const secp256k1_pedersen_context *pedersen_ctx, const secp256k1_ecmult_gen_context *ecmult_gen_ctx,const secp256k1_pedersen_context *pedersen_ctx,
const secp256k1_rangeproof_context *rangeproof_ctx,unsigned char *proof,int *plen,uint64_t min_value, const secp256k1_rangeproof_context *rangeproof_ctx,unsigned char *proof,int *plen,uint64_t min_value,
const unsigned char *commit, const unsigned char *blind, const unsigned char *nonce, int exp, int min_bits, uint64_t value){ const unsigned char *commit,const unsigned char *blind,const unsigned char *nonce,int exp,int min_bits,uint64_t value,unsigned char message[4096])
{
secp256k1_gej pubs[128]; /* Candidate digits for our proof, most inferred. */ secp256k1_gej pubs[128]; /* Candidate digits for our proof, most inferred. */
secp256k1_scalar s[128]; /* Signatures in our proof, most forged. */ secp256k1_scalar s[128]; /* Signatures in our proof, most forged. */
secp256k1_scalar sec[32]; /* Blinding factors for the correct digits. */ secp256k1_scalar sec[32]; /* Blinding factors for the correct digits. */
secp256k1_scalar k[32]; /* Nonces for our non-forged signatures. */ secp256k1_scalar k[32]; /* Nonces for our non-forged signatures. */
secp256k1_scalar stmp; secp256k1_scalar stmp;
secp256k1_sha256_t sha256_m; secp256k1_sha256_t sha256_m;
unsigned char prep[4096]; ;
unsigned char tmp[33]; unsigned char tmp[33],prep[4096];
unsigned char *signs; /* Location of sign flags in the proof. */ unsigned char *signs; /* Location of sign flags in the proof. */
uint64_t v; uint64_t v;
uint64_t scale; /* scale = 10^exp. */ uint64_t scale; /* scale = 10^exp. */
@ -283,57 +283,60 @@ SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmul
int rsizes[32]; /* How many possible values there are for each place. */ int rsizes[32]; /* How many possible values there are for each place. */
int secidx[32]; /* Which digit is the correct one. */ int secidx[32]; /* Which digit is the correct one. */
int len; /* Number of bytes used so far. */ int len; /* Number of bytes used so far. */
int i; int i,overflow,npub,idx = 0;
int overflow;
int npub;
len = 0; len = 0;
if (*plen < 65 || min_value > value || min_bits > 64 || min_bits < 0 || exp < -1 || exp > 18) { if (*plen < 65 || min_value > value || min_bits > 64 || min_bits < 0 || exp < -1 || exp > 18)
return 0; return 0;
} if (!secp256k1_range_proveparams(&v, &rings, rsizes, &npub, secidx, &min_value, &mantissa, &scale, &exp, &min_bits, value))
if (!secp256k1_range_proveparams(&v, &rings, rsizes, &npub, secidx, &min_value, &mantissa, &scale, &exp, &min_bits, value)) {
return 0; return 0;
}
proof[len] = (rsizes[0] > 1 ? (64 | exp) : 0) | (min_value ? 32 : 0); proof[len] = (rsizes[0] > 1 ? (64 | exp) : 0) | (min_value ? 32 : 0);
len++; len++;
if (rsizes[0] > 1) { if (rsizes[0] > 1)
{
VERIFY_CHECK(mantissa > 0 && mantissa <= 64); VERIFY_CHECK(mantissa > 0 && mantissa <= 64);
proof[len] = mantissa - 1; proof[len] = mantissa - 1;
len++; len++;
} }
if (min_value) { if (min_value)
for (i = 0; i < 8; i++) { {
for (i = 0; i < 8; i++)
proof[len + i] = (min_value >> ((7-i) * 8)) & 255; proof[len + i] = (min_value >> ((7-i) * 8)) & 255;
}
len += 8; len += 8;
} }
/* Do we have enough room for the proof? */ // Do we have enough room for the proof?
if (*plen - len < 32 * (npub + rings - 1) + 32 + ((rings+6) >> 3)) { if (*plen - len < 32 * (npub + rings - 1) + 32 + ((rings+6) >> 3))
return 0; return 0;
}
secp256k1_sha256_initialize(&sha256_m); secp256k1_sha256_initialize(&sha256_m);
secp256k1_sha256_write(&sha256_m, commit, 33); secp256k1_sha256_write(&sha256_m, commit, 33);
secp256k1_sha256_write(&sha256_m, proof, len); secp256k1_sha256_write(&sha256_m, proof, len);
memset(prep, 0, 4096); memset(prep, 0, 4096);
/* Note, the data corresponding to the blinding factors must be zero. */ // Note, the data corresponding to the blinding factors must be zero.
if (rsizes[rings - 1] > 1) { if (rsizes[rings - 1] > 1) // Value encoding sidechannel
int idx; {
/* Value encoding sidechannel. */
idx = rsizes[rings - 1] - 1; idx = rsizes[rings - 1] - 1;
idx -= secidx[rings - 1] == idx; idx -= secidx[rings - 1] == idx;
idx = ((rings - 1) * 4 + idx) * 32; idx = ((rings - 1) * 4 + idx) * 32;
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++)
{
prep[8 + i + idx] = prep[16 + i + idx] = prep[24 + i + idx] = (v >> (56 - i * 8)) & 255; prep[8 + i + idx] = prep[16 + i + idx] = prep[24 + i + idx] = (v >> (56 - i * 8)) & 255;
prep[i + idx] = 0; prep[i + idx] = 0;
//printf("%02x ",(uint8_t)(v >> (56 - i * 8)) & 255);
} }
prep[idx] = 128; prep[idx] = 128;
//printf("idx.%d v.%llx\n",idx,(long long)v);
} }
if (!secp256k1_rangeproof_genrand(sec, s, prep, rsizes, rings, nonce, commit, proof, len)) { /*for (i=0; i<4096; i++)
return 0; {
if ( prep[i] != 0 )
printf("(%d:%02x) ",i,prep[i]);
} }
printf("prep\n");*/
if (!secp256k1_rangeproof_genrand(sec, s, prep, rsizes, rings, nonce, commit, proof, len))
return 0;
memset(prep, 0, 4096); memset(prep, 0, 4096);
for (i = 0; i < rings; i++) { for (i = 0; i < rings; i++)
/* Sign will overwrite the non-forged signature, move that random value into the nonce. */ {
// Sign will overwrite the non-forged signature, move that random value into the nonce.
k[i] = s[i * 4 + secidx[i]]; k[i] = s[i * 4 + secidx[i]];
secp256k1_scalar_clear(&s[i * 4 + secidx[i]]); secp256k1_scalar_clear(&s[i * 4 + secidx[i]]);
} }
@ -345,30 +348,29 @@ SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmul
*/ */
secp256k1_scalar_set_b32(&stmp, blind, &overflow); secp256k1_scalar_set_b32(&stmp, blind, &overflow);
secp256k1_scalar_add(&sec[rings - 1], &sec[rings - 1], &stmp); secp256k1_scalar_add(&sec[rings - 1], &sec[rings - 1], &stmp);
if (overflow || secp256k1_scalar_is_zero(&sec[rings - 1])) { if (overflow || secp256k1_scalar_is_zero(&sec[rings - 1]))
return 0; return 0;
}
signs = &proof[len]; signs = &proof[len];
/* We need one sign bit for each blinded value we send. */ // We need one sign bit for each blinded value we send.
for (i = 0; i < (rings + 6) >> 3; i++) { for (i = 0; i < (rings + 6) >> 3; i++)
{
signs[i] = 0; signs[i] = 0;
len++; len++;
} }
npub = 0; npub = 0;
for (i = 0; i < rings; i++) { for (i = 0; i < rings; i++)
/*OPT: Use the precomputed gen2 basis?*/ {
// OPT: Use the precomputed gen2 basis?
secp256k1_pedersen_ecmult(ecmult_gen_ctx, pedersen_ctx, &pubs[npub], &sec[i], ((uint64_t)secidx[i] * scale) << (i*2)); secp256k1_pedersen_ecmult(ecmult_gen_ctx, pedersen_ctx, &pubs[npub], &sec[i], ((uint64_t)secidx[i] * scale) << (i*2));
if (secp256k1_gej_is_infinity(&pubs[npub])) { if (secp256k1_gej_is_infinity(&pubs[npub]))
return 0; return 0;
} if (i < rings - 1)
if (i < rings - 1) { {
size_t size = 33; secp256k1_ge c; size_t size = 33;
secp256k1_ge c; // OPT: split loop and batch invert.
/*OPT: split loop and batch invert.*/
secp256k1_ge_set_gej_var(&c, &pubs[npub]); secp256k1_ge_set_gej_var(&c, &pubs[npub]);
if(!secp256k1_eckey_pubkey_serialize(&c, tmp, &size, 1)) { if(!secp256k1_eckey_pubkey_serialize(&c, tmp, &size, 1))
return 0; return 0;
}
secp256k1_sha256_write(&sha256_m, tmp, 33); secp256k1_sha256_write(&sha256_m, tmp, 33);
signs[i>>3] |= (tmp[0] == 3) << (i&7); signs[i>>3] |= (tmp[0] == 3) << (i&7);
memcpy(&proof[len], &tmp[1], 32); memcpy(&proof[len], &tmp[1], 32);
@ -378,11 +380,11 @@ SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmul
} }
secp256k1_rangeproof_pub_expand(rangeproof_ctx, pubs, exp, rsizes, rings); secp256k1_rangeproof_pub_expand(rangeproof_ctx, pubs, exp, rsizes, rings);
secp256k1_sha256_finalize(&sha256_m, tmp); secp256k1_sha256_finalize(&sha256_m, tmp);
if (!secp256k1_borromean_sign(ecmult_ctx, ecmult_gen_ctx, &proof[len], s, pubs, k, sec, rsizes, secidx, rings, tmp, 32)) { if (!secp256k1_borromean_sign(ecmult_ctx, ecmult_gen_ctx, &proof[len], s, pubs, k, sec, rsizes, secidx, rings, tmp, 32))
return 0; return 0;
}
len += 32; len += 32;
for (i = 0; i < npub; i++) { for (i = 0; i < npub; i++)
{
secp256k1_scalar_get_b32(&proof[len],&s[i]); secp256k1_scalar_get_b32(&proof[len],&s[i]);
len += 32; len += 32;
} }
@ -393,8 +395,8 @@ SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmul
} }
/* Computes blinding factor x given k, s, and the challenge e. */ /* Computes blinding factor x given k, s, and the challenge e. */
SECP256K1_INLINE static void secp256k1_rangeproof_recover_x(secp256k1_scalar *x, const secp256k1_scalar *k, const secp256k1_scalar *e, SECP256K1_INLINE static void secp256k1_rangeproof_recover_x(secp256k1_scalar *x, const secp256k1_scalar *k, const secp256k1_scalar *e,const secp256k1_scalar *s)
const secp256k1_scalar *s) { {
secp256k1_scalar stmp; secp256k1_scalar stmp;
secp256k1_scalar_negate(x, s); secp256k1_scalar_negate(x, s);
secp256k1_scalar_add(x, x, k); secp256k1_scalar_add(x, x, k);
@ -403,271 +405,228 @@ SECP256K1_INLINE static void secp256k1_rangeproof_recover_x(secp256k1_scalar *x,
} }
/* Computes ring's nonce given the blinding factor x, the challenge e, and the signature s. */ /* Computes ring's nonce given the blinding factor x, the challenge e, and the signature s. */
SECP256K1_INLINE static void secp256k1_rangeproof_recover_k(secp256k1_scalar *k, const secp256k1_scalar *x, const secp256k1_scalar *e, SECP256K1_INLINE static void secp256k1_rangeproof_recover_k(secp256k1_scalar *k, const secp256k1_scalar *x, const secp256k1_scalar *e,const secp256k1_scalar *s)
const secp256k1_scalar *s) { {
secp256k1_scalar stmp; secp256k1_scalar stmp;
secp256k1_scalar_mul(&stmp, x, e); secp256k1_scalar_mul(&stmp, x, e);
secp256k1_scalar_add(k, s, &stmp); secp256k1_scalar_add(k, s, &stmp);
} }
SECP256K1_INLINE static void secp256k1_rangeproof_ch32xor(unsigned char *x, const unsigned char *y) { SECP256K1_INLINE static void secp256k1_rangeproof_ch32xor(unsigned char *x, const unsigned char *y)
{
int i; int i;
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++)
{
//printf("(%02x %02x) ",x[i],y[i]);
x[i] ^= y[i]; x[i] ^= y[i];
} }
} }
SECP256K1_INLINE static int secp256k1_rangeproof_rewind_inner(secp256k1_scalar *blind,uint64_t *v, SECP256K1_INLINE static int secp256k1_rangeproof_rewind_inner(secp256k1_scalar *blind,uint64_t *v,
unsigned char *m, int *mlen, secp256k1_scalar *ev, secp256k1_scalar *s, unsigned char *message,int *mlen,secp256k1_scalar *ev,secp256k1_scalar *s,int *rsizes,int rings, const unsigned char *nonce,const unsigned char *commit,const unsigned char *proof,int len)
int *rsizes, int rings, const unsigned char *nonce, const unsigned char *commit, const unsigned char *proof, int len) { {
secp256k1_scalar s_orig[128]; unsigned char prep[4096]; unsigned char tmp[32]; uint64_t value; int offset,i,j,b,skip1,skip2,npub;
secp256k1_scalar sec[32]; secp256k1_scalar s_orig[128]; secp256k1_scalar sec[32]; secp256k1_scalar stmp;
secp256k1_scalar stmp;
unsigned char prep[4096];
unsigned char tmp[32];
uint64_t value;
int offset;
int i;
int j;
int b;
int skip1;
int skip2;
int npub;
npub = ((rings - 1) << 2) + rsizes[rings-1]; npub = ((rings - 1) << 2) + rsizes[rings-1];
VERIFY_CHECK(npub <= 128); VERIFY_CHECK(npub <= 128);
VERIFY_CHECK(npub >= 1); VERIFY_CHECK(npub >= 1);
memset(prep,0,4096); memset(prep,0,4096);
/* Reconstruct the provers random values. */ // Reconstruct the provers random values.
secp256k1_rangeproof_genrand(sec, s_orig, prep, rsizes, rings, nonce, commit, proof, len); secp256k1_rangeproof_genrand(sec, s_orig, prep, rsizes, rings, nonce, commit, proof, len);
*v = UINT64_MAX; *v = UINT64_MAX;
secp256k1_scalar_clear(blind); secp256k1_scalar_clear(blind);
if (rings == 1 && rsizes[0] == 1) { if ( rings == 1 && rsizes[0] == 1 )
/* With only a single proof, we can only recover the blinding factor. */ {
// With only a single proof, we can only recover the blinding factor.
secp256k1_rangeproof_recover_x(blind,&s_orig[0],&ev[0],&s[0]); secp256k1_rangeproof_recover_x(blind,&s_orig[0],&ev[0],&s[0]);
if (v) { if (v)
*v = 0; *v = 0;
} if (mlen)
if (mlen) {
*mlen = 0; *mlen = 0;
}
return 1; return 1;
} }
npub = (rings - 1) << 2; npub = (rings - 1) << 2;
for (j = 0; j < 2; j++) { for (j = 0; j < 2; j++)
{
int idx; int idx;
/* Look for a value encoding in the last ring. */ // Look for a value encoding in the last ring.
idx = npub + rsizes[rings - 1] - 1 - j; idx = npub + rsizes[rings - 1] - 1 - j;
secp256k1_scalar_get_b32(tmp, &s[idx]); secp256k1_scalar_get_b32(tmp, &s[idx]);
secp256k1_rangeproof_ch32xor(tmp, &prep[idx * 32]); secp256k1_rangeproof_ch32xor(tmp, &prep[idx * 32]);
if ((tmp[0] & 128) && (memcmp(&tmp[16], &tmp[24], 8) == 0) && (memcmp(&tmp[8], &tmp[16], 8) == 0)) { if ( (tmp[0] & 128) && memcmp(&tmp[16],&tmp[24],8) == 0 && memcmp(&tmp[8],&tmp[16],8) == 0 )
{
value = 0; value = 0;
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++)
value = (value << 8) + tmp[24 + i]; value = (value << 8) + tmp[24 + i];
} if (v)
if (v) {
*v = value; *v = value;
}
memcpy(&prep[idx * 32], tmp, 32); memcpy(&prep[idx * 32], tmp, 32);
break; break;
} }
} }
if (j > 1) { if ( j > 1 ) // Couldn't extract a value.
/* Couldn't extract a value. */ {
if (mlen) { if (mlen)
*mlen = 0; *mlen = 0;
}
return 0; return 0;
} }
skip1 = rsizes[rings - 1] - 1 - j; skip1 = rsizes[rings - 1] - 1 - j;
skip2 = ((value >> ((rings - 1) << 1)) & 3); skip2 = ((value >> ((rings - 1) << 1)) & 3);
if (skip1 == skip2) { if (skip1 == skip2)
/*Value is in wrong position.*/ {
if (mlen) { // Value is in wrong position.
if (mlen)
*mlen = 0; *mlen = 0;
}
return 0; return 0;
} }
skip1 += (rings - 1) << 2; skip1 += (rings - 1) << 2;
skip2 += (rings - 1) << 2; skip2 += (rings - 1) << 2;
/* Like in the rsize[] == 1 case, Having figured out which s is the one which was not forged, we can recover the blinding factor. */ // Like in the rsize[] == 1 case, Having figured out which s is the one which was not forged, we can recover the blinding factor.
secp256k1_rangeproof_recover_x(&stmp, &s_orig[skip2], &ev[skip2], &s[skip2]); secp256k1_rangeproof_recover_x(&stmp, &s_orig[skip2], &ev[skip2], &s[skip2]);
secp256k1_scalar_negate(&sec[rings - 1], &sec[rings - 1]); secp256k1_scalar_negate(&sec[rings - 1], &sec[rings - 1]);
secp256k1_scalar_add(blind, &stmp, &sec[rings - 1]); secp256k1_scalar_add(blind, &stmp, &sec[rings - 1]);
if (!m || !mlen || *mlen == 0) { if (!message || !mlen || *mlen == 0)
if (mlen) { {
if (mlen)
*mlen = 0; *mlen = 0;
} // FIXME: cleanup in early out/failure cases.
/* FIXME: cleanup in early out/failure cases. */
return 1; return 1;
} }
offset = 0; offset = 0;
npub = 0; npub = 0;
for (i = 0; i < rings; i++) { for (i = 0; i < rings; i++)
{
int idx; int idx;
idx = (value >> (i << 1)) & 3; idx = (value >> (i << 1)) & 3;
for (j = 0; j < rsizes[i]; j++) { for (j = 0; j < rsizes[i]; j++)
if (npub == skip1 || npub == skip2) { {
if ( npub == skip1 || npub == skip2 )
{
npub++; npub++;
continue; continue;
} }
if (idx == j) { if ( idx == j )
{
/** For the non-forged signatures the signature is calculated instead of random, instead we recover the prover's nonces. /** For the non-forged signatures the signature is calculated instead of random, instead we recover the prover's nonces.
* this could just as well recover the blinding factors and messages could be put there as is done for recovering the * this could just as well recover the blinding factors and messages could be put there as is done for recovering the
* blinding factor in the last ring, but it takes an inversion to recover x so it's faster to put the message data in k. * blinding factor in the last ring, but it takes an inversion to recover x so it's faster to put the message data in k.
*/ */
secp256k1_rangeproof_recover_k(&stmp,&sec[i],&ev[npub],&s[npub]); secp256k1_rangeproof_recover_k(&stmp,&sec[i],&ev[npub],&s[npub]);
} else { } else stmp = s[npub];
stmp = s[npub];
}
secp256k1_scalar_get_b32(tmp,&stmp); secp256k1_scalar_get_b32(tmp,&stmp);
secp256k1_rangeproof_ch32xor(tmp,&prep[npub * 32]); secp256k1_rangeproof_ch32xor(tmp,&prep[npub * 32]);
for (b = 0; b < 32 && offset < *mlen; b++) { for (b = 0; b < 32 && offset < *mlen; b++)
m[offset] = tmp[b]; message[offset++] = tmp[b];
offset++;
}
npub++; npub++;
} }
} }
*mlen = offset; *mlen = offset;
memset(prep,0,4096); memset(prep,0,4096);
for (i = 0; i < 128; i++) { for (i = 0; i < 128; i++)
secp256k1_scalar_clear(&s_orig[i]); secp256k1_scalar_clear(&s_orig[i]);
} for (i = 0; i < 32; i++)
for (i = 0; i < 32; i++) {
secp256k1_scalar_clear(&sec[i]); secp256k1_scalar_clear(&sec[i]);
}
secp256k1_scalar_clear(&stmp); secp256k1_scalar_clear(&stmp);
return 1; return 1;
} }
SECP256K1_INLINE static int secp256k1_rangeproof_getheader_impl(int *offset, int *exp, int *mantissa, uint64_t *scale, SECP256K1_INLINE static int secp256k1_rangeproof_getheader_impl(int *offset, int *exp, int *mantissa, uint64_t *scale, uint64_t *min_value, uint64_t *max_value, const unsigned char *proof, int plen)
uint64_t *min_value, uint64_t *max_value, const unsigned char *proof, int plen) { {
int i; int i,has_nz_range,has_min;
int has_nz_range; if (plen < 65 || ((proof[*offset] & 128) != 0))
int has_min;
if (plen < 65 || ((proof[*offset] & 128) != 0)) {
return 0; return 0;
}
has_nz_range = proof[*offset] & 64; has_nz_range = proof[*offset] & 64;
has_min = proof[*offset] & 32; has_min = proof[*offset] & 32;
*exp = -1; *exp = -1;
*mantissa = 0; *mantissa = 0;
if (has_nz_range) { if (has_nz_range)
{
*exp = proof[*offset] & 31; *exp = proof[*offset] & 31;
*offset += 1; *offset += 1;
if (*exp > 18) { if (*exp > 18)
return 0; return 0;
}
*mantissa = proof[*offset] + 1; *mantissa = proof[*offset] + 1;
if (*mantissa > 64) { if (*mantissa > 64)
return 0; return 0;
}
*max_value = UINT64_MAX>>(64-*mantissa); *max_value = UINT64_MAX>>(64-*mantissa);
} else { } else *max_value = 0;
*max_value = 0;
}
*offset += 1; *offset += 1;
*scale = 1; *scale = 1;
for (i = 0; i < *exp; i++) { for (i = 0; i < *exp; i++)
if (*max_value > UINT64_MAX / 10) { {
if (*max_value > UINT64_MAX / 10)
return 0; return 0;
}
*max_value *= 10; *max_value *= 10;
*scale *= 10; *scale *= 10;
} }
*min_value = 0; *min_value = 0;
if (has_min) { if (has_min)
if(plen - *offset < 8) { {
if(plen - *offset < 8)
return 0; return 0;
} // FIXME: Compact minvalue encoding?
/*FIXME: Compact minvalue encoding?*/ for (i = 0; i < 8; i++)
for (i = 0; i < 8; i++) {
*min_value = (*min_value << 8) | proof[*offset + i]; *min_value = (*min_value << 8) | proof[*offset + i];
}
*offset += 8; *offset += 8;
} }
if (*max_value > UINT64_MAX - *min_value) { if (*max_value > UINT64_MAX - *min_value)
return 0; return 0;
}
*max_value += *min_value; *max_value += *min_value;
return 1; return 1;
} }
/* Verifies range proof (len plen) for 33-byte commit, the min/max values proven are put in the min/max arguments; returns 0 on failure 1 on success.*/ // Verifies range proof (len plen) for 33-byte commit, the min/max values proven are put in the min/max arguments; returns 0 on failure 1 on success
SECP256K1_INLINE static int secp256k1_rangeproof_verify_impl(const secp256k1_ecmult_context* ecmult_ctx, SECP256K1_INLINE static int secp256k1_rangeproof_verify_impl(const secp256k1_ecmult_context *ecmult_ctx,const secp256k1_ecmult_gen_context *ecmult_gen_ctx,const secp256k1_pedersen_context *pedersen_ctx, const secp256k1_rangeproof_context *rangeproof_ctx,unsigned char *blindout,uint64_t *value_out, unsigned char *message_out,int *outlen,const unsigned char *nonce,uint64_t *min_value,uint64_t *max_value,const unsigned char *commit,const unsigned char *proof,int plen)
const secp256k1_ecmult_gen_context* ecmult_gen_ctx, {
const secp256k1_pedersen_context* pedersen_ctx, const secp256k1_rangeproof_context* rangeproof_ctx, secp256k1_gej accj,pubs[128]; secp256k1_ge c; secp256k1_sha256_t sha256_m;
unsigned char *blindout, uint64_t *value_out, unsigned char *message_out, int *outlen, const unsigned char *nonce, secp256k1_scalar s[128],evalues[128]; // Challenges, only used during proof rewind.
uint64_t *min_value, uint64_t *max_value, const unsigned char *commit, const unsigned char *proof, int plen) { int rsizes[32],ret,i,exp,mantissa,offset,rings,overflow,npub,offset_post_header;
secp256k1_gej accj; size_t size; uint64_t scale; unsigned char signs[31],m[33]; const unsigned char *e0;
secp256k1_gej pubs[128];
secp256k1_ge c;
secp256k1_scalar s[128];
secp256k1_scalar evalues[128]; /* Challenges, only used during proof rewind. */
secp256k1_sha256_t sha256_m;
int rsizes[32];
int ret;
int i;
size_t size;
int exp;
int mantissa;
int offset;
int rings;
int overflow;
int npub;
int offset_post_header;
uint64_t scale;
unsigned char signs[31];
unsigned char m[33];
const unsigned char *e0;
offset = 0; offset = 0;
if (!secp256k1_rangeproof_getheader_impl(&offset, &exp, &mantissa, &scale, min_value, max_value, proof, plen)) { if ( !secp256k1_rangeproof_getheader_impl(&offset, &exp, &mantissa, &scale, min_value, max_value, proof, plen) )
return 0; return 0;
}
offset_post_header = offset; offset_post_header = offset;
rings = 1; rings = 1;
rsizes[0] = 1; rsizes[0] = 1;
npub = 1; npub = 1;
if (mantissa != 0) { if (mantissa != 0)
{
rings = (mantissa >> 1); rings = (mantissa >> 1);
for (i = 0; i < rings; i++) { for (i = 0; i < rings; i++)
rsizes[i] = 4; rsizes[i] = 4;
}
npub = (mantissa >> 1) << 2; npub = (mantissa >> 1) << 2;
if (mantissa & 1) { if (mantissa & 1)
{
rsizes[rings] = 2; rsizes[rings] = 2;
npub += rsizes[rings]; npub += rsizes[rings];
rings++; rings++;
} }
} }
VERIFY_CHECK(rings <= 32); VERIFY_CHECK(rings <= 32);
if (plen - offset < 32 * (npub + rings - 1) + 32 + ((rings+6) >> 3)) { if (plen - offset < 32 * (npub + rings - 1) + 32 + ((rings+6) >> 3))
return 0; return 0;
}
secp256k1_sha256_initialize(&sha256_m); secp256k1_sha256_initialize(&sha256_m);
secp256k1_sha256_write(&sha256_m, commit, 33); secp256k1_sha256_write(&sha256_m, commit, 33);
secp256k1_sha256_write(&sha256_m, proof, offset); secp256k1_sha256_write(&sha256_m, proof, offset);
for(i = 0; i < rings - 1; i++) { for(i = 0; i < rings - 1; i++)
signs[i] = (proof[offset + (i >> 3)] & (1 << (i & 7))) != 0; signs[i] = (proof[offset + (i >> 3)] & (1 << (i & 7))) != 0;
}
offset += (rings + 6) >> 3; offset += (rings + 6) >> 3;
if ((rings - 1) & 7) { if ( (rings - 1) & 7 )
/* Number of coded blinded points is not a multiple of 8, force extra sign bits to 0 to reject mutation. */ {
if ((proof[offset - 1] >> ((rings - 1) & 7)) != 0) { // Number of coded blinded points is not a multiple of 8, force extra sign bits to 0 to reject mutation.
if ( (proof[offset - 1] >> ((rings - 1) & 7)) != 0 )
return 0; return 0;
} }
}
npub = 0; npub = 0;
secp256k1_gej_set_infinity(&accj); secp256k1_gej_set_infinity(&accj);
if (*min_value) { if (*min_value)
secp256k1_pedersen_ecmult_small(pedersen_ctx, &accj, *min_value); secp256k1_pedersen_ecmult_small(pedersen_ctx, &accj, *min_value);
} for(i = 0; i < rings - 1; i++)
for(i = 0; i < rings - 1; i++) { {
memcpy(&m[1], &proof[offset], 32); memcpy(&m[1], &proof[offset], 32);
m[0] = 2 + signs[i]; m[0] = 2 + signs[i];
if (!secp256k1_eckey_pubkey_parse(&c, m, 33)) { if (!secp256k1_eckey_pubkey_parse(&c, m, 33))
return 0; return 0;
}
secp256k1_sha256_write(&sha256_m, m, 33); secp256k1_sha256_write(&sha256_m, m, 33);
secp256k1_gej_set_ge(&pubs[npub], &c); secp256k1_gej_set_ge(&pubs[npub], &c);
secp256k1_gej_add_ge_var(&accj, &accj, &c, NULL); secp256k1_gej_add_ge_var(&accj, &accj, &c, NULL);
@ -675,61 +634,49 @@ SECP256K1_INLINE static int secp256k1_rangeproof_verify_impl(const secp256k1_ecm
npub += rsizes[i]; npub += rsizes[i];
} }
secp256k1_gej_neg(&accj, &accj); secp256k1_gej_neg(&accj, &accj);
if (!secp256k1_eckey_pubkey_parse(&c, commit, 33)) { if (!secp256k1_eckey_pubkey_parse(&c, commit, 33))
return 0; return 0;
}
secp256k1_gej_add_ge_var(&pubs[npub], &accj, &c, NULL); secp256k1_gej_add_ge_var(&pubs[npub], &accj, &c, NULL);
if (secp256k1_gej_is_infinity(&pubs[npub])) { if (secp256k1_gej_is_infinity(&pubs[npub]))
return 0; return 0;
}
secp256k1_rangeproof_pub_expand(rangeproof_ctx, pubs, exp, rsizes, rings); secp256k1_rangeproof_pub_expand(rangeproof_ctx, pubs, exp, rsizes, rings);
npub += rsizes[rings - 1]; npub += rsizes[rings - 1];
e0 = &proof[offset]; e0 = &proof[offset];
offset += 32; offset += 32;
for (i = 0; i < npub; i++) { for (i = 0; i < npub; i++)
{
secp256k1_scalar_set_b32(&s[i], &proof[offset], &overflow); secp256k1_scalar_set_b32(&s[i], &proof[offset], &overflow);
if (overflow) { if (overflow)
return 0; return 0;
}
offset += 32; offset += 32;
} }
if (offset != plen) { if (offset != plen) // Extra data found, reject
/*Extra data found, reject.*/
return 0; return 0;
}
secp256k1_sha256_finalize(&sha256_m, m); secp256k1_sha256_finalize(&sha256_m, m);
ret = secp256k1_borromean_verify(ecmult_ctx, nonce ? evalues : NULL, e0, s, pubs, rsizes, rings, m, 32); ret = secp256k1_borromean_verify(ecmult_ctx, nonce ? evalues : NULL, e0, s, pubs, rsizes, rings, m, 32);
if (ret && nonce) { if (ret && nonce) // Given the nonce, try rewinding the witness to recover its initial state
/* Given the nonce, try rewinding the witness to recover its initial state. */ {
secp256k1_scalar blind; secp256k1_scalar blind; unsigned char commitrec[33]; uint64_t vv;
unsigned char commitrec[33]; if (!ecmult_gen_ctx)
uint64_t vv;
if (!ecmult_gen_ctx) {
return 0; return 0;
} if (!secp256k1_rangeproof_rewind_inner(&blind, &vv, message_out, outlen, evalues, s, rsizes, rings, nonce, commit, proof, offset_post_header))
if (!secp256k1_rangeproof_rewind_inner(&blind, &vv, message_out, outlen, evalues, s, rsizes, rings, nonce, commit, proof, offset_post_header)) {
return 0; return 0;
} // Unwind apparently successful, see if the commitment can be reconstructed.
/* Unwind apparently successful, see if the commitment can be reconstructed. */ // FIXME: should check vv is in the mantissa's range.
/* FIXME: should check vv is in the mantissa's range. */
vv = (vv * scale) + *min_value; vv = (vv * scale) + *min_value;
secp256k1_pedersen_ecmult(ecmult_gen_ctx, pedersen_ctx, &accj, &blind, vv); secp256k1_pedersen_ecmult(ecmult_gen_ctx, pedersen_ctx, &accj, &blind, vv);
if (secp256k1_gej_is_infinity(&accj)) { if (secp256k1_gej_is_infinity(&accj))
return 0; return 0;
}
secp256k1_ge_set_gej(&c, &accj); secp256k1_ge_set_gej(&c, &accj);
size = 33; size = 33;
secp256k1_eckey_pubkey_serialize(&c, commitrec, &size, 1); secp256k1_eckey_pubkey_serialize(&c, commitrec, &size, 1);
if (size != 33 || memcmp(commitrec, commit, 33) != 0) { if (size != 33 || memcmp(commitrec, commit, 33) != 0)
return 0; return 0;
} if (blindout)
if (blindout) {
secp256k1_scalar_get_b32(blindout, &blind); secp256k1_scalar_get_b32(blindout, &blind);
} if (value_out)
if (value_out) {
*value_out = vv; *value_out = vv;
} }
}
return ret; return ret;
} }

4
iguana/secp256k1/src/modules/schnorr/tests_impl.h

@ -7,7 +7,9 @@
#ifndef SECP256K1_MODULE_SCHNORR_TESTS #ifndef SECP256K1_MODULE_SCHNORR_TESTS
#define SECP256K1_MODULE_SCHNORR_TESTS #define SECP256K1_MODULE_SCHNORR_TESTS
#include "include/secp256k1_schnorr.h" #include "../../../include/secp256k1_schnorr.h"
#include "../../../include/secp256k1.h"
void test_schnorr_end_to_end(void) { void test_schnorr_end_to_end(void) {
unsigned char privkey[32]; unsigned char privkey[32];

19
iguana/secp256k1/src/secp256k1.c

@ -545,32 +545,29 @@ int secp256k1_ec_pubkey_tweak_mul(const secp256k1_context* ctx, secp256k1_pubkey
return ret; return ret;
} }
int secp256k1_context_randomize(secp256k1_context* ctx, const unsigned char *seed32) { int secp256k1_context_randomize(secp256k1_context* ctx, const unsigned char *seed32)
{
VERIFY_CHECK(ctx != NULL); VERIFY_CHECK(ctx != NULL);
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, seed32); secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, seed32);
return 1; return 1;
} }
int secp256k1_ec_pubkey_combine(const secp256k1_context* ctx, secp256k1_pubkey *pubnonce, const secp256k1_pubkey * const *pubnonces, size_t n) { int secp256k1_ec_pubkey_combine(const secp256k1_context* ctx, secp256k1_pubkey *pubnonce, const secp256k1_pubkey * const *pubnonces, size_t n)
size_t i; {
secp256k1_gej Qj; size_t i; secp256k1_gej Qj; secp256k1_ge Q;
secp256k1_ge Q;
ARG_CHECK(pubnonce != NULL); ARG_CHECK(pubnonce != NULL);
memset(pubnonce, 0, sizeof(*pubnonce)); memset(pubnonce, 0, sizeof(*pubnonce));
ARG_CHECK(n >= 1); ARG_CHECK(n >= 1);
ARG_CHECK(pubnonces != NULL); ARG_CHECK(pubnonces != NULL);
secp256k1_gej_set_infinity(&Qj); secp256k1_gej_set_infinity(&Qj);
for (i = 0; i < n; i++)
for (i = 0; i < n; i++) { {
secp256k1_pubkey_load(ctx, &Q, pubnonces[i]); secp256k1_pubkey_load(ctx, &Q, pubnonces[i]);
secp256k1_gej_add_ge(&Qj, &Qj, &Q); secp256k1_gej_add_ge(&Qj, &Qj, &Q);
} }
if (secp256k1_gej_is_infinity(&Qj)) { if (secp256k1_gej_is_infinity(&Qj))
return 0; return 0;
}
secp256k1_ge_set_gej(&Q, &Qj); secp256k1_ge_set_gej(&Q, &Qj);
secp256k1_pubkey_save(pubnonce, &Q); secp256k1_pubkey_save(pubnonce, &Q);
return 1; return 1;

2
iguana/secp256k1/src/testrand_impl.h

@ -37,7 +37,7 @@ static uint32_t secp256k1_rand_bits(int bits) {
secp256k1_test_rng_integer |= (((uint64_t)secp256k1_rand32()) << secp256k1_test_rng_integer_bits_left); secp256k1_test_rng_integer |= (((uint64_t)secp256k1_rand32()) << secp256k1_test_rng_integer_bits_left);
secp256k1_test_rng_integer_bits_left += 32; secp256k1_test_rng_integer_bits_left += 32;
} }
ret = secp256k1_test_rng_integer; ret = (uint32_t)secp256k1_test_rng_integer;
secp256k1_test_rng_integer >>= bits; secp256k1_test_rng_integer >>= bits;
secp256k1_test_rng_integer_bits_left -= bits; secp256k1_test_rng_integer_bits_left -= bits;
ret &= ((~((uint32_t)0)) >> (32 - bits)); ret &= ((~((uint32_t)0)) >> (32 - bits));

2
iguana/tests/getreceivedbyaddress

@ -1 +1 @@
curl --url "http://127.0.0.1:7778" --data "{\"method\":\"getreceivedbyaddress\",\"params\":[\"17outUgtsnLkguDuXm14tcQ7dMbdD8KZGK\"]}" curl --url "http://127.0.0.1:7778" --data "{\"method\":\"getreceivedbyaddress\",\"params\":[\"$1\"]}"

25
iguana/tests/json_extract.c

@ -0,0 +1,25 @@
#include <stdio.h>
#include <stdint.h>
#include "../../includes/cJSON.h"
#include "../../crypto777/OS_portable.h"
int32_t main(int32_t argc,char **argv)
{
cJSON *filejson; char *fname,*filestr,*field; long filesize;
if ( argc > 2 )
{
fname = argv[1];
field = argv[2];
if ( (filestr= OS_filestr(&filesize,fname)) != 0 )
{
if ( (filejson= cJSON_Parse(filestr)) != 0 )
{
if ( jstr(filejson,field) != 0 )
printf("%s\n",jstr(filejson,field));
free_json(filejson);
} else fprintf(stderr,"cant parse.(%s)\n",filestr);
free(filestr);
} else fprintf(stderr,"cant load (%s)\n",fname);
} else fprintf(stderr,"argc.%d fname.(%s) error\n",argc,argv[1]);
}

1
iguana/tests/make_jsoncmp

@ -1 +1,2 @@
gcc -o jsoncmp jsoncmp.c ../../agents/libcrypto777.a -pthread -lm gcc -o jsoncmp jsoncmp.c ../../agents/libcrypto777.a -pthread -lm
gcc -o json_extract json_extract.c ../../agents/libcrypto777.a -pthread -lm

Loading…
Cancel
Save