Dilithium register, sign, verify rpc calls

This commit is contained in:
jl777
2019-02-23 22:07:14 -11:00
parent 74070330f5
commit 4220a1cc92
3 changed files with 206 additions and 66 deletions

View File

@@ -82,8 +82,9 @@ CClib_methods[] =
{ (char *)"musig", (char *)"send", (char *)"combined_pk amount", 2, 2, 'x', EVAL_MUSIG },
{ (char *)"musig", (char *)"spend", (char *)"sendtxid sig destpubkey", 3, 3, 'y', EVAL_MUSIG },
{ (char *)"dilithium", (char *)"keypair", (char *)"[hexseed]", 0, 1, 'K', EVAL_DILITHIUM },
{ (char *)"dilithium", (char *)"sign", (char *)"msg privkey", 2, 2, 'S', EVAL_DILITHIUM },
{ (char *)"dilithium", (char *)"verify", (char *)"msg sig pubtxid", 3, 3, 'V', EVAL_DILITHIUM },
{ (char *)"dilithium", (char *)"register", (char *)"handle, [hexseed]", 1, 2, 'R', EVAL_DILITHIUM },
{ (char *)"dilithium", (char *)"sign", (char *)"msg [hexseed]", 1, 2, 'S', EVAL_DILITHIUM },
{ (char *)"dilithium", (char *)"verify", (char *)"pubtxid msg sig", 3, 3, 'V', EVAL_DILITHIUM },
{ (char *)"dilithium", (char *)"send", (char *)"pubtxid amount", 2, 2, 'x', EVAL_DILITHIUM },
{ (char *)"dilithium", (char *)"spend", (char *)"sendtxid sig destpubkey", 3, 3, 'y', EVAL_DILITHIUM },
#endif
@@ -126,6 +127,7 @@ UniValue musig_verify(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue musig_send(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue musig_spend(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue dilithium_register(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue dilithium_send(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue dilithium_spend(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue dilithium_keypair(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
@@ -264,6 +266,8 @@ UniValue CClib_method(struct CCcontract_info *cp,char *method,char *jsonstr)
return(dilithium_spend(txfee,cp,params));
else if ( strcmp(method,"keypair") == 0 )
return(dilithium_keypair(txfee,cp,params));
else if ( strcmp(method,"register") == 0 )
return(dilithium_register(txfee,cp,params));
else if ( strcmp(method,"sign") == 0 )
return(dilithium_sign(txfee,cp,params));
else if ( strcmp(method,"verify") == 0 )
@@ -573,6 +577,26 @@ uint256 juint256(cJSON *obj)
return(revuint256(tmp));
}
int32_t cclib_parsepubkey(secp256k1_context *ctx,secp256k1_pubkey &spk,cJSON *item)
{
char *hexstr;
if ( (hexstr= jstr(item,0)) != 0 && is_hexstr(hexstr,0) == 66 )
{
CPubKey pk(ParseHex(hexstr));
if ( secp256k1_ec_pubkey_parse(ctx,&spk,pk.begin(),33) > 0 )
return(1);
} else return(-1);
}
int32_t cclib_parsehash(uint8_t *hash32,cJSON *item,int32_t len)
{
char *hexstr;
if ( (hexstr= jstr(item,0)) != 0 && is_hexstr(hexstr,0) == len*2 )
{
decode_hex(hash32,len,hexstr);
return(0);
} else return(-1);
}
#ifdef BUILD_ROGUE
#include "rogue_rpc.cpp"

View File

@@ -2841,58 +2841,195 @@ int32_t main(void)
}
#endif
#define DILITHIUM_TXFEE 10000
void calc_rmd160_sha256(uint8_t rmd160[20],uint8_t *data,int32_t datalen);
char *bitcoin_address(char *coinaddr,uint8_t addrtype,uint8_t *pubkey_or_rmd160,int32_t len);
CScript dilithium_registeropret(std::string handle,CPubKey pk,std::vector<uint8_t> bigpub)
{
CScript opret; uint8_t evalcode = EVAL_DILITHIUM;
opret << OP_RETURN << E_MARSHAL(ss << evalcode << 'R' << handle << pk << bigpub);
return(opret);
}
uint8_t dilithium_registeropretdecode(std::string &handle,CPubKey &pk,std::vector<uint8_t> &bigpub,CScript scriptPubKey)
{
std::vector<uint8_t> vopret; uint8_t e,f;
GetOpReturnData(scriptPubKey,vopret);
if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> handle; ss >> pk; ss >> bigpub) != 0 && e == EVAL_DILITHIUM && f == 'R' )
{
return(f);
}
return(0);
}
UniValue dilithium_rawtxresult(UniValue &result,std::string rawtx)
{
CTransaction tx;
if ( rawtx.size() > 0 )
{
result.push_back(Pair("hex",rawtx));
if ( DecodeHexTx(tx,rawtx) != 0 )
{
//if ( broadcastflag != 0 && myAddtomempool(tx) != 0 )
// RelayTransaction(tx);
result.push_back(Pair("txid",tx.GetHash().ToString()));
result.push_back(Pair("result","success"));
} else result.push_back(Pair("error","decode hex"));
} else result.push_back(Pair("error","couldnt finalize CCtx"));
return(result);
}
char *dilithium_addr(char *coinaddr,uint8_t *buf,int32_t len)
{
uint8_t rmd160[20],addrtype;
if ( len == CRYPTO_PUBLICKEYBYTES )
addrtype = 55;
else if ( len == CRYPTO_SECRETKEYBYTES )
addrtype = 63;
else
{
strcpy(coinaddr,"unexpected len.%d",len);
return(coinaddr);
}
calc_rmd160_sha256(rmd160,buf,len);
bitcoin_address(coinaddr,addrtype,rmd160,20);
return(coinaddr);
}
char *dilithium_hexstr(char *str,uint8_t *buf,int32_t len)
{
int32_t i;
for (i=0; i<len; i++)
sprintf(&str[i<<1],"%02x",buf[i]);
str[i<<1] = 0;
return(str);
}
int32_t dilithium_bigpubget(std::string &handle,CPubKey &pk33,uint8_t *pk,uint256 pubtxid)
{
CTransaction tx; uint256 hashBlock; int32_t numvouts; std::vector<uint8_t> bigpub;
if ( myGetTransaction(pubtxid,tx,hashBlock) != 0 && (numvouts= tx.vout.size()) > 1 )
{
if ( dilithium_registeropretdecode(handle,pk33,bigpub,tx.vout[numvouts-1].scriptPubKey) == 'R' && bigpub.size() == CRYPTO_PUBLICKEYBYTES )
{
memcpy(pk,&bigpub[0],CRYPTO_PUBLICKEYBYTES);
return(0);
} else return(-2);
}
return(-1);
}
UniValue dilithium_keypair(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
UniValue result(UniValue::VOBJ); uint8_t seed[SEEDBYTES],rmd160[20],pk[CRYPTO_PUBLICKEYBYTES],sk[CRYPTO_SECRETKEYBYTES]; char coinaddr[64],str[CRYPTO_SECRETKEYBYTES*2+1]; int32_t i,n,externalflag=0;
//randombytes(seed,SEEDBYTES);
UniValue result(UniValue::VOBJ); uint8_t seed[SEEDBYTES],pk[CRYPTO_PUBLICKEYBYTES],sk[CRYPTO_SECRETKEYBYTES]; char coinaddr[64],str[CRYPTO_SECRETKEYBYTES*2+1]; int32_t i,n,externalflag=0;
Myprivkey(seed);
if ( params != 0 && (n= cJSON_GetArraySize(params)) == 1 )
{
if ( musig_parsehash(seed,jitem(params,0),32) < 0 )
return(cclib_error(result,"error parsing seed"));
else externalflag = 1;
if ( cclib_parsehash(seed,jitem(params,0),32) < 0 )
{
randombytes(seed,SEEDBYTES);
result.push_back(Pair("status","using random high entropy seed"));
}
externalflag = 1;
}
_dilithium_keypair(pk,sk,seed);
for (i=0; i<sizeof(pk); i++)
sprintf(&str[i<<1],"%02x",pk[i]);
str[i<<1] = 0;
result.push_back(Pair("pubkey",str));
for (i=0; i<sizeof(sk); i++)
sprintf(&str[i<<1],"%02x",sk[i]);
str[i<<1] = 0;
result.push_back(Pair("privkey",str));
for (i=0; i<SEEDBYTES; i++)
sprintf(&str[i<<1],"%02x",seed[i]);
str[i<<1] = 0;
result.push_back(Pair("seed",str));
calc_rmd160_sha256(rmd160,pk,CRYPTO_PUBLICKEYBYTES);
bitcoin_address(coinaddr,55,rmd160,20);
result.push_back(Pair("pkaddr",coinaddr));
calc_rmd160_sha256(rmd160,sk,CRYPTO_SECRETKEYBYTES);
bitcoin_address(coinaddr,63,rmd160,20);
result.push_back(Pair("skaddr",coinaddr));
result.push_back(Pair("pubkey",dilithium_hexstr(str,pk,CRYPTO_PUBLICKEYBYTES)));
result.push_back(Pair("privkey",dilithium_hexstr(str,sk,CRYPTO_SECRETKEYBYTES)));
result.push_back(Pair("seed",dilithium_hexstr(str,seed,SEEDBYTES)));
result.push_back(Pair("pkaddr",dilithium_addr(coinaddr,pk,CRYPTO_PUBLICKEYBYTES)));
result.push_back(Pair("skaddr",dilithium_addr(coinaddr,sk,CRYPTO_SECRETKEYBYTES)));
if ( externalflag == 0 )
result.push_back(Pair("warning","test mode using privkey for -pubkey, only for testing. there is no point using quantum secure signing if you are using a privkey with a known secp256k1 pubkey!!"));
result.push_back(Pair("result","success"));
// make a tx that has pubkey in opreturn
return(result);
}
UniValue dilithium_register(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
UniValue result(UniValue::VOBJ); std::string rawtx; CPubKey mypk,dilithiumpk; uint8_t seed[SEEDBYTES],pk[CRYPTO_PUBLICKEYBYTES],sk[CRYPTO_SECRETKEYBYTES]; char coinaddr[64],str[CRYPTO_SECRETKEYBYTES*2+1]; std::vector<uint8_t> bigpub; int32_t i,n,warningflag = 0;
if ( txfee == 0 )
txfee = DILITHIUM_TXFEE;
mypk = pubkey2pk(Mypubkey());
dilithiumpk = GetUnspendable(cp,0);
if ( params != 0 && ((n= cJSON_GetArraySize(params)) == 1 || n == 2) )
{
std::string handle(jstr(jitem(params,0),0));
result.push_back(Pair("handle",handle));
if ( n == 2 || cclib_parsehash(seed,jitem(params,1),32) < 0 )
{
Myprivkey(seed);
result.push_back(Pair("warning","test mode using privkey for -pubkey, only for testing. there is no point using quantum secure signing if you are using a privkey with a known secp256k1 pubkey!!"));
}
_dilithium_keypair(pk,sk,seed);
result.push_back(Pair("seed",dilithium_hexstr(str,seed,SEEDBYTES)));
result.push_back(Pair("pkaddr",dilithium_addr(coinaddr,pk,CRYPTO_PUBLICKEYBYTES)));
result.push_back(Pair("skaddr",dilithium_addr(coinaddr,sk,CRYPTO_SECRETKEYBYTES)));
for (i=0; i<CRYPTO_PUBLICKEYBYTES; i++)
bigpub.push_pack(pk[i]);
if ( AddNormalinputs(mtx,mypk,3*txfee,64) >= 3*txfee )
{
mtx.vout.push_back(MakeCC1vout(cp->evalcode,txfee,dilithiumpk));
mtx.vout.push_back(MakeCC1vout(cp->evalcode,txfee,mypk));
rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,dilithium_registeropret('R',handle,mypk,bigpub));
return(musig_rawtxresult(result,rawtx));
} else return(cclib_error(result,"couldnt find enough funds"));
} else return(cclib_error(result,"not enough parameters"));
}
UniValue dilithium_sign(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
UniValue result(UniValue::VOBJ);
//_dilithium_sign(sm, &smlen, m, MLEN, sk); // 7.2
return(result);
UniValue result(UniValue::VOBJ); uint8_t seed[SEEDBYTES],msg[32],rmd160[20],pk[CRYPTO_PUBLICKEYBYTES],sk[CRYPTO_SECRETKEYBYTES]; char coinaddr[64],str[(32+CRYPTO_BYTES)*2+1],sm[32+CRYPTO_BYTES]; int32_t n,smlen;
if ( params != 0 && ((n= cJSON_GetArraySize(params)) == 1 || n == 2) )
{
if ( cclib_parsehash(msg,jitem(params,0),32) < 0 )
return(cclib_error(result,"couldnt parse message to sign"));
else if ( n == 2 || cclib_parsehash(seed,jitem(params,1),32) < 0 )
{
Myprivkey(seed);
result.push_back(Pair("warning","test mode using privkey for -pubkey, only for testing. there is no point using quantum secure signing if you are using a privkey with a known secp256k1 pubkey!!"));
}
_dilithium_keypair(pk,sk,seed);
result.push_back(Pair("msg32",dilithium_hexstr(str,msg,32)));
result.push_back(Pair("seed",dilithium_hexstr(str,seed,SEEDBYTES)));
result.push_back(Pair("pkaddr",dilithium_addr(coinaddr,pk,CRYPTO_PUBLICKEYBYTES)));
result.push_back(Pair("skaddr",dilithium_addr(coinaddr,sk,CRYPTO_SECRETKEYBYTES)));
_dilithium_sign(sm,&smlen,msg,32,sk);
if ( smlen == 32+CRYPTO_BYTES )
{
result.push_back(Pair("signature",dilithium_hexstr(str,sm,smlen)));
calc_rmd160_sha256(rmd160,sm,smlen);
result.push_back(Pair("sighash",dilithium_hexstr(str,rmd160,20)));
} else return(cclib_error(result,"unexpected signed message len"));
} else return(cclib_error(result,"not enough parameters"));
}
UniValue dilithium_verify(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
UniValue result(UniValue::VOBJ);
return(result);
UniValue result(UniValue::VOBJ); CPubKey pk33; uint8_t msg[32],msg2[32],pk[CRYPTO_PUBLICKEYBYTES]; uint256 pubtxid; char coinaddr[64],str[(32+CRYPTO_BYTES)*2+1],sm[32+CRYPTO_BYTES]; int32_t mlen,n;
if ( params != 0 && (n= cJSON_GetArraySize(params)) == 3 )
{
pubtxid = juint256(jitem(params,0));
if ( dilithium_bigpubget(handle,pk33,pk,pubtxid) < 0 )
return(cclib_error(result,"couldnt parse message to sign"));
else if ( cclib_parsehash(msg,jitem(params,1),32) < 0 )
return(cclib_error(result,"couldnt parse message to sign"));
else if ( cclib_parsehash(sm,jitem(params,2),32+CRYPTO_BYTES) < 0 )
return(cclib_error(result,"couldnt parse sig"));
else if ( _dilithium_verify(msg2,&mlen,sm,smlen,pk) < 0 )
return(cclib_error(result,"dilithium verify error"));
else if ( mlen != 32 )
return(cclib_error(result,"message len mismatch"));
else if ( memcmp(msg2,msg,32) != 0 )
return(cclib_error(result,"message content mismatch"));
result.push_back(Pair("msg32",dilithium_hexstr(str,msg,32)));
result.push_back(Pair("handle",handle));
result.push_back(Pair("pkaddr",dilithium_addr(coinaddr,pk,CRYPTO_PUBLICKEYBYTES)));
result.push_back(Pair("result","success"));
return(result);
} else return(cclib_error(result,"not enough parameters"));
}
UniValue dilithium_send(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)

View File

@@ -362,27 +362,6 @@ UniValue musig_calcmsg(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
} else return(cclib_error(result,"couldnt parse params"));
}
int32_t musig_parsepubkey(secp256k1_context *ctx,secp256k1_pubkey &spk,cJSON *item)
{
char *hexstr;
if ( (hexstr= jstr(item,0)) != 0 && is_hexstr(hexstr,0) == 66 )
{
CPubKey pk(ParseHex(hexstr));
if ( secp256k1_ec_pubkey_parse(ctx,&spk,pk.begin(),33) > 0 )
return(1);
} else return(-1);
}
int32_t musig_parsehash(uint8_t *hash32,cJSON *item,int32_t len)
{
char *hexstr;
if ( (hexstr= jstr(item,0)) != 0 && is_hexstr(hexstr,0) == len*2 )
{
decode_hex(hash32,len,hexstr);
return(0);
} else return(-1);
}
UniValue musig_combine(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
static secp256k1_context *ctx;
@@ -395,7 +374,7 @@ UniValue musig_combine(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
//fprintf(stderr,"n.%d args.(%s)\n",n,jprint(params,0));
for (i=0; i<n; i++)
{
if ( musig_parsepubkey(ctx,spk,jitem(params,i)) < 0 )
if ( cclib_parsepubkey(ctx,spk,jitem(params,i)) < 0 )
return(cclib_error(result,"error parsing pk"));
pubkeys.push_back(spk);
}
@@ -434,11 +413,11 @@ UniValue musig_session(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
if ( MUSIG != 0 )
musig_infofree(MUSIG), MUSIG = 0;
MUSIG = musig_infocreate(myind,num);
if ( musig_parsepubkey(ctx,MUSIG->combined_pk,jitem(params,2)) < 0 )
if ( cclib_parsepubkey(ctx,MUSIG->combined_pk,jitem(params,2)) < 0 )
return(cclib_error(result,"error parsing combined_pubkey"));
else if ( musig_parsehash(MUSIG->pkhash,jitem(params,3),32) < 0 )
else if ( cclib_parsehash(MUSIG->pkhash,jitem(params,3),32) < 0 )
return(cclib_error(result,"error parsing pkhash"));
else if ( musig_parsehash(MUSIG->msg,jitem(params,4),32) < 0 )
else if ( cclib_parsehash(MUSIG->msg,jitem(params,4),32) < 0 )
return(cclib_error(result,"error parsing msg"));
Myprivkey(privkey);
GetRandBytes(session,32);
@@ -497,13 +476,13 @@ UniValue musig_commit(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
if ( params != 0 && (n= cJSON_GetArraySize(params)) == 3 )
{
if ( musig_parsehash(pkhash,jitem(params,0),32) < 0 )
if ( cclib_parsehash(pkhash,jitem(params,0),32) < 0 )
return(cclib_error(result,"error parsing pkhash"));
else if ( memcmp(MUSIG->pkhash,pkhash,32) != 0 )
return(cclib_error(result,"pkhash doesnt match session pkhash"));
else if ( (ind= juint(jitem(params,1),0)) < 0 || ind >= MUSIG->num )
return(cclib_error(result,"illegal ind for session"));
else if ( musig_parsehash(&MUSIG->nonce_commitments[ind*32],jitem(params,2),32) < 0 )
else if ( cclib_parsehash(&MUSIG->nonce_commitments[ind*32],jitem(params,2),32) < 0 )
return(cclib_error(result,"error parsing commitment"));
/** Gets the signer's public nonce given a list of all signers' data with commitments
*
@@ -550,13 +529,13 @@ UniValue musig_nonce(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
if ( params != 0 && (n= cJSON_GetArraySize(params)) == 3 )
{
if ( musig_parsehash(pkhash,jitem(params,0),32) < 0 )
if ( cclib_parsehash(pkhash,jitem(params,0),32) < 0 )
return(cclib_error(result,"error parsing pkhash"));
else if ( memcmp(MUSIG->pkhash,pkhash,32) != 0 )
return(cclib_error(result,"pkhash doesnt match session pkhash"));
else if ( (ind= juint(jitem(params,1),0)) < 0 || ind >= MUSIG->num )
return(cclib_error(result,"illegal ind for session"));
else if ( musig_parsepubkey(ctx,MUSIG->nonces[ind],jitem(params,2)) < 0 )
else if ( cclib_parsepubkey(ctx,MUSIG->nonces[ind],jitem(params,2)) < 0 )
return(cclib_error(result,"error parsing nonce"));
result.push_back(Pair("added_index",ind));
/** Checks a signer's public nonce against a commitment to said nonce, and update
@@ -620,13 +599,13 @@ UniValue musig_partialsig(uint64_t txfee,struct CCcontract_info *cp,cJSON *param
ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
if ( params != 0 && (n= cJSON_GetArraySize(params)) == 3 )
{
if ( musig_parsehash(pkhash,jitem(params,0),32) < 0 )
if ( cclib_parsehash(pkhash,jitem(params,0),32) < 0 )
return(cclib_error(result,"error parsing pkhash"));
else if ( memcmp(MUSIG->pkhash,pkhash,32) != 0 )
return(cclib_error(result,"pkhash doesnt match session pkhash"));
else if ( (ind= juint(jitem(params,1),0)) < 0 || ind >= MUSIG->num )
return(cclib_error(result,"illegal ind for session"));
else if ( musig_parsehash(psig,jitem(params,2),32) < 0 )
else if ( cclib_parsehash(psig,jitem(params,2),32) < 0 )
return(cclib_error(result,"error parsing psig"));
else if ( secp256k1_musig_partial_signature_parse(ctx,&MUSIG->partial_sig[ind],psig) == 0 )
return(cclib_error(result,"error parsing partialsig"));
@@ -669,11 +648,11 @@ UniValue musig_verify(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
if ( params != 0 && (n= cJSON_GetArraySize(params)) == 3 )
{
if ( musig_parsehash(msg,jitem(params,0),32) < 0 )
if ( cclib_parsehash(msg,jitem(params,0),32) < 0 )
return(cclib_error(result,"error parsing pkhash"));
else if ( musig_parsepubkey(ctx,combined_pk,jitem(params,1)) < 0 )
else if ( cclib_parsepubkey(ctx,combined_pk,jitem(params,1)) < 0 )
return(cclib_error(result,"error parsing combined_pk"));
else if ( musig_parsehash(musig64,jitem(params,2),64) < 0 )
else if ( cclib_parsehash(musig64,jitem(params,2),64) < 0 )
return(cclib_error(result,"error parsing musig64"));
for (i=0; i<32; i++)
sprintf(&str[i*2],"%02x",msg[i]);