Update to elliptic curve signature verification
This commit is contained in:
parent
e29438461e
commit
a4a90fac05
4 changed files with 85 additions and 57 deletions
|
|
@ -249,6 +249,9 @@ target_link_libraries( udt_client fc udt )
|
||||||
add_executable( lzma_test tests/lzma_test.cpp )
|
add_executable( lzma_test tests/lzma_test.cpp )
|
||||||
target_link_libraries( lzma_test fc )
|
target_link_libraries( lzma_test fc )
|
||||||
|
|
||||||
|
add_executable( ecc_test tests/ecc_test.cpp )
|
||||||
|
target_link_libraries( ecc_test fc )
|
||||||
|
|
||||||
#add_executable( test_compress tests/compress.cpp )
|
#add_executable( test_compress tests/compress.cpp )
|
||||||
#target_link_libraries( test_compress fc )
|
#target_link_libraries( test_compress fc )
|
||||||
#add_executable( test_aes tests/aes_test.cpp )
|
#add_executable( test_aes tests/aes_test.cpp )
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ namespace fc {
|
||||||
|
|
||||||
public_key( const public_key_data& v );
|
public_key( const public_key_data& v );
|
||||||
public_key( const public_key_point_data& v );
|
public_key( const public_key_point_data& v );
|
||||||
public_key( const compact_signature& c, const fc::sha256& digest );
|
public_key( const compact_signature& c, const fc::sha256& digest, bool check_cannonical = true );
|
||||||
|
|
||||||
bool valid()const;
|
bool valid()const;
|
||||||
public_key mult( const fc::sha256& offset );
|
public_key mult( const fc::sha256& offset );
|
||||||
|
|
|
||||||
|
|
@ -481,7 +481,7 @@ namespace fc { namespace ecc {
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public_key::public_key( const compact_signature& c, const fc::sha256& digest )
|
public_key::public_key( const compact_signature& c, const fc::sha256& digest, bool check_cannonical )
|
||||||
{
|
{
|
||||||
int nV = c.data[0];
|
int nV = c.data[0];
|
||||||
if (nV<27 || nV>=35)
|
if (nV<27 || nV>=35)
|
||||||
|
|
@ -491,6 +491,14 @@ namespace fc { namespace ecc {
|
||||||
BN_bin2bn(&c.data[1],32,sig->r);
|
BN_bin2bn(&c.data[1],32,sig->r);
|
||||||
BN_bin2bn(&c.data[33],32,sig->s);
|
BN_bin2bn(&c.data[33],32,sig->s);
|
||||||
|
|
||||||
|
if( check_cannonical )
|
||||||
|
{
|
||||||
|
FC_ASSERT( !(c.data[1] & 0x80), "signature is not cannonical" );
|
||||||
|
FC_ASSERT( !(c.data[1] == 0 && !(c.data[2] & 0x80)), "signature is not cannonical" );
|
||||||
|
FC_ASSERT( !(c.data[33] & 0x80), "signature is not cannonical" );
|
||||||
|
FC_ASSERT( !(c.data[33] == 0 && !(c.data[34] & 0x80)), "signature is not cannonical" );
|
||||||
|
}
|
||||||
|
|
||||||
my->_key = EC_KEY_new_by_curve_name(NID_secp256k1);
|
my->_key = EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||||
|
|
||||||
if (nV >= 31)
|
if (nV >= 31)
|
||||||
|
|
@ -515,59 +523,65 @@ namespace fc { namespace ecc {
|
||||||
FC_ASSERT( my->_key != nullptr );
|
FC_ASSERT( my->_key != nullptr );
|
||||||
auto my_pub_key = get_public_key().serialize(); // just for good measure
|
auto my_pub_key = get_public_key().serialize(); // just for good measure
|
||||||
//ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&digest, sizeof(digest), my->_key);
|
//ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&digest, sizeof(digest), my->_key);
|
||||||
ecdsa_sig sig = ECDSA_do_sign((unsigned char*)&digest, sizeof(digest), my->_key);
|
while( true )
|
||||||
|
|
||||||
if (sig==nullptr)
|
|
||||||
FC_THROW_EXCEPTION( exception, "Unable to sign" );
|
|
||||||
|
|
||||||
compact_signature csig;
|
|
||||||
// memset( csig.data, 0, sizeof(csig) );
|
|
||||||
|
|
||||||
int nBitsR = BN_num_bits(sig->r);
|
|
||||||
int nBitsS = BN_num_bits(sig->s);
|
|
||||||
if (nBitsR <= 256 && nBitsS <= 256)
|
|
||||||
{
|
{
|
||||||
int nRecId = -1;
|
ecdsa_sig sig = ECDSA_do_sign((unsigned char*)&digest, sizeof(digest), my->_key);
|
||||||
for (int i=0; i<4; i++)
|
|
||||||
{
|
|
||||||
public_key keyRec;
|
|
||||||
keyRec.my->_key = EC_KEY_new_by_curve_name( NID_secp256k1 );
|
|
||||||
// keyRec.fSet = true;
|
|
||||||
// if (fCompressedPubKey) keyRec.SetCompressedPubKey();
|
|
||||||
if (ECDSA_SIG_recover_key_GFp(keyRec.my->_key, sig, (unsigned char*)&digest, sizeof(digest), i, 1) == 1)
|
|
||||||
{
|
|
||||||
if (keyRec.serialize() == my_pub_key )
|
|
||||||
{
|
|
||||||
nRecId = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nRecId == -1)
|
if (sig==nullptr)
|
||||||
{
|
FC_THROW_EXCEPTION( exception, "Unable to sign" );
|
||||||
FC_THROW_EXCEPTION( exception, "unable to construct recoverable key");
|
|
||||||
}
|
|
||||||
|
|
||||||
csig.data[0] = nRecId+27+4;//(fCompressedPubKey ? 4 : 0);
|
compact_signature csig;
|
||||||
BN_bn2bin(sig->r,&csig.data[33-(nBitsR+7)/8]);
|
// memset( csig.data, 0, sizeof(csig) );
|
||||||
BN_bn2bin(sig->s,&csig.data[65-(nBitsS+7)/8]);
|
|
||||||
|
|
||||||
/*try {
|
int nBitsR = BN_num_bits(sig->r);
|
||||||
auto pubk = public_key( csig, digest ).serialize();
|
int nBitsS = BN_num_bits(sig->s);
|
||||||
FC_ASSERT( pubk == my_pub_key, "", ("pubk",pubk)("my_pub_key",my_pub_key)("private_key", *this) );
|
if (nBitsR <= 256 && nBitsS <= 256)
|
||||||
} catch ( fc::exception& e)
|
{
|
||||||
{
|
int nRecId = -1;
|
||||||
wlog( "${e}", ("e", e.to_detail_string() ) );
|
for (int i=0; i<4; i++)
|
||||||
csig = sign_compact( digest );
|
{
|
||||||
elog( "it worked the second time!" );
|
public_key keyRec;
|
||||||
exit(1);
|
keyRec.my->_key = EC_KEY_new_by_curve_name( NID_secp256k1 );
|
||||||
}
|
if (ECDSA_SIG_recover_key_GFp(keyRec.my->_key, sig, (unsigned char*)&digest, sizeof(digest), i, 1) == 1)
|
||||||
*/
|
{
|
||||||
}
|
if (keyRec.serialize() == my_pub_key )
|
||||||
// TODO: memory leak if exception thrown!
|
{
|
||||||
//ECDSA_SIG_free(sig);
|
nRecId = i;
|
||||||
return csig;
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nRecId == -1)
|
||||||
|
{
|
||||||
|
FC_THROW_EXCEPTION( exception, "unable to construct recoverable key");
|
||||||
|
}
|
||||||
|
unsigned char* result = nullptr;
|
||||||
|
auto bytes = i2d_ECDSA_SIG( sig, &result );
|
||||||
|
auto lenR = result[3];
|
||||||
|
auto lenS = result[5+lenR];
|
||||||
|
//idump( (result[0])(result[1])(result[2])(result[3])(result[3+lenR])(result[4+lenR])(bytes)(lenR)(lenS) );
|
||||||
|
if( lenR != 32 ) { free(result); continue; }
|
||||||
|
if( lenS != 32 ) { free(result); continue; }
|
||||||
|
//idump( (33-(nBitsR+7)/8) );
|
||||||
|
//idump( (65-(nBitsS+7)/8) );
|
||||||
|
//idump( (sizeof(csig) ) );
|
||||||
|
memcpy( &csig.data[1], &result[4], lenR );
|
||||||
|
memcpy( &csig.data[33], &result[6+lenR], lenS );
|
||||||
|
//idump( (csig.data[33]) );
|
||||||
|
//idump( (csig.data[1]) );
|
||||||
|
free(result);
|
||||||
|
//idump( (nRecId) );
|
||||||
|
csig.data[0] = nRecId+27+4;//(fCompressedPubKey ? 4 : 0);
|
||||||
|
/*
|
||||||
|
idump( (csig) );
|
||||||
|
auto rlen = BN_bn2bin(sig->r,&csig.data[33-(nBitsR+7)/8]);
|
||||||
|
auto slen = BN_bn2bin(sig->s,&csig.data[65-(nBitsS+7)/8]);
|
||||||
|
idump( (rlen)(slen) );
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
return csig;
|
||||||
|
} // while true
|
||||||
} FC_RETHROW_EXCEPTIONS( warn, "sign ${digest}", ("digest", digest)("private_key",*this) );
|
} FC_RETHROW_EXCEPTIONS( warn, "sign ${digest}", ("digest", digest)("private_key",*this) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,34 @@
|
||||||
#include <fc/crypto/elliptic.hpp>
|
#include <fc/crypto/elliptic.hpp>
|
||||||
#include <bts/address.hpp>
|
#include <fc/exception/exception.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
int main( int argc, char** argv )
|
int main( int argc, char** argv )
|
||||||
{
|
{
|
||||||
|
for( uint32_t i = 0; i < 3000; ++ i )
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
FC_ASSERT( argc > 1 );
|
||||||
|
|
||||||
std::string pass(argv[1]);
|
std::string pass(argv[1]);
|
||||||
fc::sha256 h = fc::sha256::hash( pass.c_str(), pass.size() );
|
fc::sha256 h = fc::sha256::hash( pass.c_str(), pass.size() );
|
||||||
fc::ecc::private_key priv = fc::ecc::private_key::generate_from_seed(h);
|
fc::ecc::private_key priv = fc::ecc::private_key::generate_from_seed(h);
|
||||||
fc::ecc::public_key pub = priv.get_public_key();
|
fc::ecc::public_key pub = priv.get_public_key();
|
||||||
std::cerr<<"oroginal master pubkey1: "<<std::string(bts::address(pub))<<"\n";
|
|
||||||
|
|
||||||
pass += "1";
|
pass += "1";
|
||||||
fc::sha256 h2 = fc::sha256::hash( pass.c_str(), pass.size() );
|
fc::sha256 h2 = fc::sha256::hash( pass.c_str(), pass.size() );
|
||||||
fc::ecc::public_key pub1 = pub.mult( h2 );
|
fc::ecc::public_key pub1 = pub.mult( h2 );
|
||||||
fc::ecc::private_key priv1 = fc::ecc::private_key::generate_from_seed(h, h2);
|
fc::ecc::private_key priv1 = fc::ecc::private_key::generate_from_seed(h, h2);
|
||||||
|
|
||||||
std::cerr<<"master pubkey: "<<std::string(bts::address(pub))<<"\n";
|
auto sig = priv.sign_compact( h );
|
||||||
std::cerr<<"derived pubkey1: "<<std::string(bts::address(pub1))<<"\n";
|
auto recover = fc::ecc::public_key( sig, h );
|
||||||
std::cerr<<"actual pubkey1: "<<std::string(bts::address(priv1.get_public_key()))<<"\n";
|
FC_ASSERT( recover == priv.get_public_key() );
|
||||||
|
}
|
||||||
|
catch ( const fc::exception& e )
|
||||||
|
{
|
||||||
|
edump( (e.to_detail_string()) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue