|
|
@ -146,6 +146,105 @@ out: |
|
|
|
return(be_sz); |
|
|
|
} |
|
|
|
|
|
|
|
EC_KEY *bitcoin_privkeyset(uint8_t *oddevenp,bits256 *pubkeyp,bits256 privkey) |
|
|
|
{ |
|
|
|
BIGNUM *bn; BN_CTX *ctx = NULL; uint8_t *ptr,tmp[33]; EC_POINT *pub_key = NULL; const EC_GROUP *group; |
|
|
|
EC_KEY *KEY = EC_KEY_new_by_curve_name(NID_secp256k1); |
|
|
|
*oddevenp = 0; |
|
|
|
EC_KEY_set_conv_form(KEY,POINT_CONVERSION_COMPRESSED); |
|
|
|
{ |
|
|
|
if ( (group= EC_KEY_get0_group(KEY)) != 0 && (ctx= BN_CTX_new()) != 0 ) |
|
|
|
{ |
|
|
|
if ( (pub_key= EC_POINT_new(group)) != 0 ) |
|
|
|
{ |
|
|
|
if ( (bn= BN_bin2bn(privkey.bytes,sizeof(privkey),BN_new())) != 0 ) |
|
|
|
{ |
|
|
|
if ( EC_POINT_mul(group,pub_key,bn,NULL,NULL,ctx) > 0 ) |
|
|
|
{ |
|
|
|
EC_KEY_set_private_key(KEY,bn); |
|
|
|
EC_KEY_set_public_key(KEY,pub_key); |
|
|
|
ptr = tmp; |
|
|
|
i2o_ECPublicKey(KEY,&ptr); |
|
|
|
*oddevenp = tmp[0]; |
|
|
|
memcpy(pubkeyp->bytes,&tmp[1],sizeof(*pubkeyp)); |
|
|
|
} |
|
|
|
BN_clear_free(bn); |
|
|
|
} |
|
|
|
EC_POINT_free(pub_key); |
|
|
|
} |
|
|
|
BN_CTX_free(ctx); |
|
|
|
} |
|
|
|
} |
|
|
|
return(KEY); |
|
|
|
} |
|
|
|
|
|
|
|
bits256 bitcoin_pubkey33(uint8_t *data,bits256 privkey) |
|
|
|
{ |
|
|
|
uint8_t oddeven; bits256 pubkey; |
|
|
|
EC_KEY *KEY; |
|
|
|
if ( (KEY= bitcoin_privkeyset(&oddeven,&pubkey,privkey)) != 0 ) |
|
|
|
{ |
|
|
|
data[0] = oddeven; |
|
|
|
memcpy(data+1,pubkey.bytes,sizeof(pubkey)); |
|
|
|
EC_KEY_free(KEY); |
|
|
|
} |
|
|
|
return(pubkey); |
|
|
|
} |
|
|
|
|
|
|
|
int32_t bitcoin_sign(uint8_t *sig,int32_t maxlen,uint8_t *data,int32_t datalen,bits256 privkey) |
|
|
|
{ |
|
|
|
uint32_t siglen; EC_KEY *KEY; uint8_t oddeven; bits256 pubkey; int32_t retval = -1; |
|
|
|
if ( (KEY= bitcoin_privkeyset(&oddeven,&pubkey,privkey)) != 0 ) |
|
|
|
{ |
|
|
|
if ( ECDSA_sign(0,data,datalen,sig,&siglen,KEY) > 0 && siglen <= maxlen ) |
|
|
|
retval = siglen; |
|
|
|
EC_KEY_free(KEY); |
|
|
|
} |
|
|
|
return(retval); |
|
|
|
} |
|
|
|
|
|
|
|
int32_t bitcoin_verify(uint8_t *sig,int32_t siglen,uint8_t *data,int32_t datalen,EC_KEY *KEY,uint8_t *pubkey,int32_t len) |
|
|
|
{ |
|
|
|
ECDSA_SIG *esig; int32_t retval = -1; uint8_t tmp[33],*ptr,*sigptr = sig; EC_KEY *origkey = KEY; |
|
|
|
if ( len < 0 ) |
|
|
|
return(-1); |
|
|
|
if ( (esig= ECDSA_SIG_new()) != 0 ) |
|
|
|
{ |
|
|
|
if ( d2i_ECDSA_SIG(&esig,(const uint8_t **)&sigptr,siglen) != 0 ) |
|
|
|
{ |
|
|
|
if ( KEY != 0 || (KEY= EC_KEY_new_by_curve_name(NID_secp256k1)) != 0 ) |
|
|
|
{ |
|
|
|
EC_KEY_set_conv_form(KEY,POINT_CONVERSION_COMPRESSED); |
|
|
|
if ( len == 32 ) |
|
|
|
{ |
|
|
|
memcpy(tmp+1,pubkey,len); |
|
|
|
for (tmp[0]=2; tmp[0]<=3; tmp[0]++) |
|
|
|
{ |
|
|
|
ptr = tmp; |
|
|
|
o2i_ECPublicKey(&KEY,(const uint8_t **)&ptr,33); |
|
|
|
if ( ECDSA_do_verify(data,datalen,esig,KEY) > 0 ) |
|
|
|
{ |
|
|
|
retval = 0; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
ptr = pubkey; |
|
|
|
o2i_ECPublicKey(&KEY,(const uint8_t **)&ptr,len); |
|
|
|
if ( ECDSA_do_verify(data,datalen,esig,KEY) > 0 ) |
|
|
|
retval = 0; |
|
|
|
} |
|
|
|
if ( origkey == 0 ) |
|
|
|
EC_KEY_free(KEY); |
|
|
|
} |
|
|
|
} |
|
|
|
ECDSA_SIG_free(esig); |
|
|
|
} |
|
|
|
return(retval); |
|
|
|
} |
|
|
|
|
|
|
|
int32_t bitcoin_addr2rmd160(uint8_t *addrtypep,uint8_t rmd160[20],char *coinaddr) |
|
|
|
{ |
|
|
|
bits256 hash; uint8_t *buf,_buf[25]; int32_t len; |
|
|
@ -165,11 +264,11 @@ int32_t bitcoin_addr2rmd160(uint8_t *addrtypep,uint8_t rmd160[20],char *coinaddr |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
char hexaddr[64]; |
|
|
|
btc_convaddr(hexaddr,coinaddr); |
|
|
|
//char hexaddr[64];
|
|
|
|
//btc_convaddr(hexaddr,coinaddr);
|
|
|
|
//for (i=0; i<len; i++)
|
|
|
|
// printf("%02x ",buf[i]);
|
|
|
|
char str[65]; printf("\nhex.(%s) checkhash.(%s) len.%d mismatch %02x %02x %02x %02x vs %02x %02x %02x %02x (%s)\n",hexaddr,coinaddr,len,buf[len - 4]&0xff,buf[len - 3]&0xff,buf[len - 2]&0xff,buf[len - 1]&0xff,hash.bytes[31],hash.bytes[30],hash.bytes[29],hash.bytes[28],bits256_str(str,hash)); |
|
|
|
char str[65]; printf("\nhex checkhash.(%s) len.%d mismatch %02x %02x %02x %02x vs %02x %02x %02x %02x (%s)\n",coinaddr,len,buf[len - 4]&0xff,buf[len - 3]&0xff,buf[len - 2]&0xff,buf[len - 1]&0xff,hash.bytes[31],hash.bytes[30],hash.bytes[29],hash.bytes[28],bits256_str(str,hash)); |
|
|
|
} |
|
|
|
} |
|
|
|
return(0); |
|
|
@ -220,51 +319,6 @@ int32_t bitcoin_validaddress(struct iguana_info *coin,char *coinaddr) |
|
|
|
return(0); |
|
|
|
} |
|
|
|
|
|
|
|
EC_KEY *bitcoin_privkeyset(uint8_t *oddevenp,bits256 *pubkeyp,bits256 privkey) |
|
|
|
{ |
|
|
|
BIGNUM *bn; BN_CTX *ctx = NULL; uint8_t *ptr,tmp[33]; EC_POINT *pub_key = NULL; const EC_GROUP *group; |
|
|
|
EC_KEY *KEY = EC_KEY_new_by_curve_name(NID_secp256k1); |
|
|
|
*oddevenp = 0; |
|
|
|
EC_KEY_set_conv_form(KEY,POINT_CONVERSION_COMPRESSED); |
|
|
|
{ |
|
|
|
if ( (group= EC_KEY_get0_group(KEY)) != 0 && (ctx= BN_CTX_new()) != 0 ) |
|
|
|
{ |
|
|
|
if ( (pub_key= EC_POINT_new(group)) != 0 ) |
|
|
|
{ |
|
|
|
if ( (bn= BN_bin2bn(privkey.bytes,sizeof(privkey),BN_new())) != 0 ) |
|
|
|
{ |
|
|
|
if ( EC_POINT_mul(group,pub_key,bn,NULL,NULL,ctx) > 0 ) |
|
|
|
{ |
|
|
|
EC_KEY_set_private_key(KEY,bn); |
|
|
|
EC_KEY_set_public_key(KEY,pub_key); |
|
|
|
ptr = tmp; |
|
|
|
i2o_ECPublicKey(KEY,&ptr); |
|
|
|
*oddevenp = tmp[0]; |
|
|
|
memcpy(pubkeyp->bytes,&tmp[1],sizeof(*pubkeyp)); |
|
|
|
} |
|
|
|
BN_clear_free(bn); |
|
|
|
} |
|
|
|
EC_POINT_free(pub_key); |
|
|
|
} |
|
|
|
BN_CTX_free(ctx); |
|
|
|
} |
|
|
|
} |
|
|
|
return(KEY); |
|
|
|
} |
|
|
|
|
|
|
|
bits256 bitcoin_pubkey33(uint8_t *data,bits256 privkey) |
|
|
|
{ |
|
|
|
uint8_t oddeven; bits256 pubkey; |
|
|
|
EC_KEY *KEY; |
|
|
|
if ( (KEY= bitcoin_privkeyset(&oddeven,&pubkey,privkey)) != 0 ) |
|
|
|
{ |
|
|
|
data[0] = oddeven; |
|
|
|
memcpy(data+1,pubkey.bytes,sizeof(pubkey)); |
|
|
|
EC_KEY_free(KEY); |
|
|
|
} |
|
|
|
return(pubkey); |
|
|
|
} |
|
|
|
|
|
|
|
int32_t bitcoin_priv2wif(char *wifstr,bits256 privkey,uint8_t addrtype) |
|
|
|
{ |
|
|
|
uint8_t data[128]; bits256 hash; int32_t i; |
|
|
@ -277,10 +331,10 @@ int32_t bitcoin_priv2wif(char *wifstr,bits256 privkey,uint8_t addrtype) |
|
|
|
if ( bitcoin_base58encode(wifstr,data,33+4) == 0 ) |
|
|
|
return(-1); |
|
|
|
char str[65]; printf("(%s) -> wif.(%s) addrtype.%02x\n",bits256_str(str,privkey),wifstr,addrtype); |
|
|
|
return(0); |
|
|
|
return((int32_t)strlen(wifstr)); |
|
|
|
} |
|
|
|
|
|
|
|
/*int32_t bitcoin_wif2priv(uint8_t *addrtypep,uint8_t privkey[32],char *wifstr)
|
|
|
|
int32_t bitcoin_wif2priv(uint8_t *addrtypep,bits256 *privkeyp,char *wifstr) |
|
|
|
{ |
|
|
|
int32_t len = -1; bits256 hash; uint8_t buf[64]; |
|
|
|
if ( (len= bitcoin_base58decode(buf,wifstr)) >= 4 ) |
|
|
@ -288,96 +342,14 @@ int32_t bitcoin_priv2wif(char *wifstr,bits256 privkey,uint8_t addrtype) |
|
|
|
// validate with trailing hash, then remove hash
|
|
|
|
hash = bits256_doublesha256(0,buf,len - 4); |
|
|
|
*addrtypep = *buf; |
|
|
|
memcpy(rmd160,buf+1,20); |
|
|
|
memcpy(privkeyp,buf+1,32); |
|
|
|
if ( (buf[len - 4]&0xff) == hash.bytes[31] && (buf[len - 3]&0xff) == hash.bytes[30] &&(buf[len - 2]&0xff) == hash.bytes[29] &&(buf[len - 1]&0xff) == hash.bytes[28] ) |
|
|
|
{ |
|
|
|
//printf("coinaddr.(%s) valid checksum\n",coinaddr);
|
|
|
|
return(20); |
|
|
|
} |
|
|
|
} |
|
|
|
if ( (cstr= base58_decode_check(addrtypep,(const char *)wifstr)) != 0 ) |
|
|
|
{ |
|
|
|
init_hexbytes_noT((void *)privkey,(void *)cstr->str,cstr->len); |
|
|
|
if ( cstr->str[cstr->len-1] == 0x01 ) |
|
|
|
cstr->len--; |
|
|
|
memcpy(privkey,cstr->str,cstr->len); |
|
|
|
len = (int32_t)cstr->len; |
|
|
|
char tmp[138]; |
|
|
|
bitcoin_priv2wif(tmp,privkey,*addrtypep); |
|
|
|
printf("addrtype.%02x wifstr.(%llx) len.%d\n",*addrtypep,*(long long *)privkey,len); |
|
|
|
cstr_free(cstr,true); |
|
|
|
return(32); |
|
|
|
} |
|
|
|
return(len); |
|
|
|
}*/ |
|
|
|
|
|
|
|
struct iguana_waddress *iguana_waddresscalc(uint8_t pubtype,uint8_t wiftype,struct iguana_waddress *addr,bits256 privkey) |
|
|
|
{ |
|
|
|
memset(addr,0,sizeof(*addr)); |
|
|
|
addr->privkey = privkey; |
|
|
|
bitcoin_pubkey33(addr->pubkey,addr->privkey); |
|
|
|
calc_rmd160_sha256(addr->rmd160,addr->pubkey,33); |
|
|
|
bitcoin_address(addr->coinaddr,pubtype,addr->rmd160,sizeof(addr->rmd160)); |
|
|
|
if ( bitcoin_priv2wif(addr->wifstr,addr->privkey,wiftype) == 0 ) |
|
|
|
{ |
|
|
|
addr->wiftype = wiftype; |
|
|
|
addr->type = pubtype; |
|
|
|
return(addr); |
|
|
|
} |
|
|
|
return(0); |
|
|
|
} |
|
|
|
|
|
|
|
int32_t bitcoin_sign(uint8_t *sig,int32_t maxlen,uint8_t *data,int32_t datalen,bits256 privkey) |
|
|
|
{ |
|
|
|
uint32_t siglen; EC_KEY *KEY; uint8_t oddeven; bits256 pubkey; int32_t retval = -1; |
|
|
|
if ( (KEY= bitcoin_privkeyset(&oddeven,&pubkey,privkey)) != 0 ) |
|
|
|
{ |
|
|
|
if ( ECDSA_sign(0,data,datalen,sig,&siglen,KEY) > 0 && siglen <= maxlen ) |
|
|
|
retval = siglen; |
|
|
|
EC_KEY_free(KEY); |
|
|
|
} |
|
|
|
return(retval); |
|
|
|
} |
|
|
|
|
|
|
|
int32_t bitcoin_verify(uint8_t *sig,int32_t siglen,uint8_t *data,int32_t datalen,EC_KEY *KEY,uint8_t *pubkey,int32_t len) |
|
|
|
{ |
|
|
|
ECDSA_SIG *esig; int32_t retval = -1; uint8_t tmp[33],*ptr,*sigptr = sig; EC_KEY *origkey = KEY; |
|
|
|
if ( len < 0 ) |
|
|
|
return(-1); |
|
|
|
if ( (esig= ECDSA_SIG_new()) != 0 ) |
|
|
|
{ |
|
|
|
if ( d2i_ECDSA_SIG(&esig,(const uint8_t **)&sigptr,siglen) != 0 ) |
|
|
|
{ |
|
|
|
if ( KEY != 0 || (KEY= EC_KEY_new_by_curve_name(NID_secp256k1)) != 0 ) |
|
|
|
{ |
|
|
|
EC_KEY_set_conv_form(KEY,POINT_CONVERSION_COMPRESSED); |
|
|
|
if ( len == 32 ) |
|
|
|
{ |
|
|
|
memcpy(tmp+1,pubkey,len); |
|
|
|
for (tmp[0]=2; tmp[0]<=3; tmp[0]++) |
|
|
|
{ |
|
|
|
ptr = tmp; |
|
|
|
o2i_ECPublicKey(&KEY,(const uint8_t **)&ptr,33); |
|
|
|
if ( ECDSA_do_verify(data,datalen,esig,KEY) > 0 ) |
|
|
|
{ |
|
|
|
retval = 0; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
ptr = pubkey; |
|
|
|
o2i_ECPublicKey(&KEY,(const uint8_t **)&ptr,len); |
|
|
|
if ( ECDSA_do_verify(data,datalen,esig,KEY) > 0 ) |
|
|
|
retval = 0; |
|
|
|
} |
|
|
|
if ( origkey == 0 ) |
|
|
|
EC_KEY_free(KEY); |
|
|
|
} |
|
|
|
} |
|
|
|
ECDSA_SIG_free(esig); |
|
|
|
} |
|
|
|
return(retval); |
|
|
|
} |
|
|
|
|
|
|
|
int32_t iguana_parsevoutobj(struct iguana_info *coin,uint8_t *serialized,int32_t maxsize,struct iguana_msgvout *vout,cJSON *voutobj) |
|
|
@ -1286,7 +1258,7 @@ uint64_t bitcoin_parseunspent(struct iguana_info *coin,struct bitcoin_unspent *u |
|
|
|
wifstr = bitcoind_RPC(0,coin->symbol,coin->chain->serverport,coin->chain->userpass,"dumpprivkey",args); |
|
|
|
if ( wifstr != 0 ) |
|
|
|
{ |
|
|
|
btc_wif2priv(&addrtype,unspent->privkeys[0].bytes,wifstr); |
|
|
|
bitcoin_wif2priv(&addrtype,&unspent->privkeys[0],wifstr); |
|
|
|
//printf("wifstr.(%s) -> %s\n",wifstr,bits256_str(str,unspent->privkeys[0]));
|
|
|
|
free(wifstr); |
|
|
|
} else fprintf(stderr,"error (%s) cant find privkey\n",coinaddr); |
|
|
@ -1576,7 +1548,7 @@ char *_setVsigner(struct iguana_info *coin,struct vin_info *V,int32_t ind,char * |
|
|
|
{ |
|
|
|
uint8_t addrtype; |
|
|
|
decode_hex(V->signers[ind].pubkey,(int32_t)strlen(pubstr)/2,pubstr); |
|
|
|
btc_wif2priv(&addrtype,V->signers[ind].privkey.bytes,wifstr); |
|
|
|
bitcoin_wif2priv(&addrtype,&V->signers[ind].privkey,wifstr); |
|
|
|
if ( addrtype != coin->chain->pubtype ) |
|
|
|
return(clonestr("{\"error\":\"invalid wifA\"}")); |
|
|
|
else return(0); |
|
|
|