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. 8
      iguana/secp256k1/include/secp256k1_rangeproof.h
  8. 40
      iguana/secp256k1/include/secp256k1_recovery.h
  9. 99
      iguana/secp256k1/include/secp256k1_schnorr.h
  10. 64
      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. 509
      iguana/secp256k1/src/modules/rangeproof/rangeproof_impl.h
  17. 8
      iguana/secp256k1/src/modules/schnorr/schnorr_impl.h
  18. 4
      iguana/secp256k1/src/modules/schnorr/tests_impl.h
  19. 19
      iguana/secp256k1/src/secp256k1.c
  20. 2
      iguana/secp256k1/src/testrand_impl.h
  21. 2
      iguana/tests/getreceivedbyaddress
  22. 25
      iguana/tests/json_extract.c
  23. 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); 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);
}
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
} }

8
iguana/secp256k1/include/secp256k1_rangeproof.h

@ -49,7 +49,7 @@ SECP256K1_WARN_UNUSED_RESULT int secp256k1_pedersen_blind_sum(
/** Verify a tally of pedersen commitments /** Verify a tally of pedersen commitments
* Returns 1: commitments successfully sum to zero. * Returns 1: commitments successfully sum to zero.
* 0: Commitments do not sum to zero or other error. * 0: Commitments do not sum to zero or other error.
* In: ctx: pointer to a context object, initialized for Pedersen commitment (cannot be NULL) * In: ctx: pointer to a context object, initialized for Pedersen commitment (cannot be NULL)
* commits: pointer to pointers to 33-byte character arrays for the commitments. (cannot be NULL if pcnt is non-zero) * commits: pointer to pointers to 33-byte character arrays for the commitments. (cannot be NULL if pcnt is non-zero)
* pcnt: number of commitments pointed to by commits. * pcnt: number of commitments pointed to by commits.
* ncommits: pointer to pointers to 33-byte character arrays for negative commitments. (cannot be NULL if ncnt is non-zero) * ncommits: pointer to pointers to 33-byte character arrays for negative commitments. (cannot be NULL if ncnt is non-zero)
@ -146,7 +146,7 @@ SECP256K1_WARN_UNUSED_RESULT int secp256k1_rangeproof_rewind(
* *
*/ */
SECP256K1_WARN_UNUSED_RESULT int secp256k1_rangeproof_sign( SECP256K1_WARN_UNUSED_RESULT int secp256k1_rangeproof_sign(
const secp256k1_context* ctx, const secp256k1_context *ctx,
unsigned char *proof, unsigned char *proof,
int *plen, int *plen,
uint64_t min_value, uint64_t min_value,
@ -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.
@ -170,7 +170,7 @@ SECP256K1_WARN_UNUSED_RESULT int secp256k1_rangeproof_sign(
* max_value: pointer to an unsigned int64 which will be updated with the maximum value that commit could have. (cannot be NULL) * max_value: pointer to an unsigned int64 which will be updated with the maximum value that commit could have. (cannot be NULL)
*/ */
SECP256K1_WARN_UNUSED_RESULT int secp256k1_rangeproof_info( SECP256K1_WARN_UNUSED_RESULT int secp256k1_rangeproof_info(
const secp256k1_context* ctx, const secp256k1_context *ctx,
int *exp, int *exp,
int *mantissa, int *mantissa,
uint64_t *min_value, uint64_t *min_value,

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(

64
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

509
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. */ {
secp256k1_rangeproof_recover_x(blind, &s_orig[0], &ev[0], &s[0]); // With only a single proof, we can only recover the blinding factor.
if (v) { secp256k1_rangeproof_recover_x(blind,&s_orig[0],&ev[0],&s[0]);
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_rangeproof_ch32xor(tmp,&prep[npub * 32]);
secp256k1_scalar_get_b32(tmp, &stmp); for (b = 0; b < 32 && offset < *mlen; b++)
secp256k1_rangeproof_ch32xor(tmp, &prep[npub * 32]); message[offset++] = tmp[b];
for (b = 0; b < 32 && offset < *mlen; b++) {
m[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,60 +634,48 @@ 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;
} }

8
iguana/secp256k1/src/modules/schnorr/schnorr_impl.h

@ -80,10 +80,10 @@ static int secp256k1_schnorr_sig_sign(const secp256k1_ecmult_gen_context* ctx, u
secp256k1_fe_normalize(&Ra.y); secp256k1_fe_normalize(&Ra.y);
if (secp256k1_fe_is_odd(&Ra.y)) { if (secp256k1_fe_is_odd(&Ra.y)) {
/* R's y coordinate is odd, which is not allowed (see rationale above). /* R's y coordinate is odd, which is not allowed (see rationale above).
Force it to be even by negating the nonce. Note that this even works Force it to be even by negating the nonce. Note that this even works
for multiparty signing, as the R point is known to all participants, for multiparty signing, as the R point is known to all participants,
which can all decide to flip the sign in unison, resulting in the which can all decide to flip the sign in unison, resulting in the
overall R point to be negated too. */ overall R point to be negated too. */
secp256k1_scalar_negate(&n, &n); secp256k1_scalar_negate(&n, &n);
} }
secp256k1_fe_normalize(&Ra.x); secp256k1_fe_normalize(&Ra.x);

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