From a824aa04a90e4df907e747c4bf2f1908b008e1f2 Mon Sep 17 00:00:00 2001 From: Daniel Larimer Date: Wed, 10 Jun 2015 18:34:19 -0400 Subject: [PATCH] Mapping blinding crypto to fc ecc api --- CMakeLists.txt | 3 + include/fc/crypto/elliptic.hpp | 21 +++--- src/crypto/elliptic_secp256k1.cpp | 105 +++++++++++++++++++++++++++++- tests/blind.cpp | 90 +++++++++++++++++++++++++ 4 files changed, 207 insertions(+), 12 deletions(-) create mode 100644 tests/blind.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index eb4eae6..1f25542 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -289,6 +289,9 @@ ENDIF() add_executable( api tests/api.cpp ) target_link_libraries( api fc ) +#add_executable( blind tests/blind.cpp ) +#target_link_libraries( blind fc ${ECC_LIB} ) + include_directories( vendor/websocketpp ) add_executable( ntp_test ntp_test.cpp ) diff --git a/include/fc/crypto/elliptic.hpp b/include/fc/crypto/elliptic.hpp index 32dcbe5..b747ac9 100644 --- a/include/fc/crypto/elliptic.hpp +++ b/include/fc/crypto/elliptic.hpp @@ -141,34 +141,33 @@ namespace fc { struct range_proof_info { - uint8_t exp; - uint8_t mantissa; + int exp; + int mantissa; uint64_t min_value; uint64_t max_value; - std::vector proof; }; - commitment_type blind( const blind_factor_type& blind, uint64_t value ); - commitment_type blind_sum( const std::vector& blinds, uint32_t non_neg ); + commitment_type blind( const blind_factor_type& blind, uint64_t value ); + blind_factor_type blind_sum( const std::vector& blinds, uint32_t non_neg ); /** verifies taht commnits + neg_commits + excess == 0 */ bool verify_sum( const std::vector& commits, const std::vector& neg_commits, int64_t excess ); - bool verify_range( uint64_t min_val, uint64_t max_val, const commitment_type& commit, const std::vector& proof ); + bool verify_range( uint64_t& min_val, uint64_t& max_val, const commitment_type& commit, const std::vector& proof ); std::vector range_proof_sign( uint64_t min_value, const commitment_type& commit, const blind_factor_type& commit_blind, const blind_factor_type& nonce, - uint8_t base10_exp, + int8_t base10_exp, uint8_t min_bits, uint64_t actual_value ); - bool verify_range_rewind( blind_factor_type& blind_out, + bool verify_range_proof_rewind( blind_factor_type& blind_out, uint64_t& value_out, string& message_out, const blind_factor_type& nonce, - uint64_t min_val, - uint64_t max_val, + uint64_t& min_val, + uint64_t& max_val, commitment_type commit, const std::vector& proof ); range_proof_info range_get_info( const std::vector& proof ); @@ -218,4 +217,4 @@ namespace fc { FC_REFLECT_TYPENAME( fc::ecc::private_key ) FC_REFLECT_TYPENAME( fc::ecc::public_key ) -FC_REFLECT( fc::ecc::range_proof_info, (exp)(mantissa)(min_value)(max_value)(proof) ) +FC_REFLECT( fc::ecc::range_proof_info, (exp)(mantissa)(min_value)(max_value) ) diff --git a/src/crypto/elliptic_secp256k1.cpp b/src/crypto/elliptic_secp256k1.cpp index 0e6484b..1a7826c 100644 --- a/src/crypto/elliptic_secp256k1.cpp +++ b/src/crypto/elliptic_secp256k1.cpp @@ -16,13 +16,14 @@ namespace fc { namespace ecc { namespace detail { const secp256k1_context_t* _get_context() { - static secp256k1_context_t* ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN); + static secp256k1_context_t* ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_RANGEPROOF | SECP256K1_CONTEXT_COMMIT ); return ctx; } void _init_lib() { static const secp256k1_context_t* ctx = _get_context(); static int init_o = init_openssl(); + (void)ctx; } class public_key_impl @@ -149,4 +150,106 @@ namespace fc { namespace ecc { FC_ASSERT( secp256k1_ecdsa_recover_compact( detail::_get_context(), (unsigned char*) digest.data(), (unsigned char*) c.begin() + 1, (unsigned char*) my->_key.begin(), (int*) &pk_len, 1, (*c.begin() - 27) & 3 ) ); FC_ASSERT( pk_len == my->_key.size() ); } + + + + + commitment_type blind( const blind_factor_type& blind, uint64_t value ) + { + commitment_type result; + FC_ASSERT( secp256k1_pedersen_commit( detail::_get_context(), (unsigned char*)&result, (unsigned char*)&blind, value ) ); + return result; + } + + blind_factor_type blind_sum( const std::vector& blinds_in, uint32_t non_neg ) + { + blind_factor_type result; + std::vector blinds(blinds_in.size()); + for( uint32_t i = 0; i < blinds_in.size(); ++i ) blinds[i] = (const unsigned char*)&blinds_in[i]; + FC_ASSERT( secp256k1_pedersen_blind_sum( detail::_get_context(), (unsigned char*)&result, blinds.data(), blinds_in.size(), non_neg ) ); + return result; + } + + /** verifies taht commnits + neg_commits + excess == 0 */ + bool verify_sum( const std::vector& commits_in, const std::vector& neg_commits_in, int64_t excess ) + { + std::vector commits(commits_in.size()); + for( uint32_t i = 0; i < commits_in.size(); ++i ) commits[i] = (const unsigned char*)&commits_in[i]; + std::vector neg_commits(neg_commits_in.size()); + for( uint32_t i = 0; i < neg_commits_in.size(); ++i ) neg_commits[i] = (const unsigned char*)&neg_commits_in[i]; + + return secp256k1_pedersen_verify_tally( detail::_get_context(), commits.data(), commits.size(), neg_commits.data(), neg_commits.size(), excess ); + } + + bool verify_range( uint64_t& min_val, uint64_t& max_val, const commitment_type& commit, const std::vector& proof ) + { + return secp256k1_rangeproof_verify( detail::_get_context(), &min_val, &max_val, (const unsigned char*)&commit, (const unsigned char*)proof.data(), proof.size() ); + } + + std::vector range_proof_sign( uint64_t min_value, + const commitment_type& commit, + const blind_factor_type& commit_blind, + const blind_factor_type& nonce, + int8_t base10_exp, + uint8_t min_bits, + uint64_t actual_value + ) + { + int proof_len = 5134; + std::vector proof(proof_len); + + FC_ASSERT( secp256k1_rangeproof_sign( detail::_get_context(), + (unsigned char*)proof.data(), + &proof_len, min_value, + (const unsigned char*)&commit, + (const unsigned char*)&commit_blind, + (const unsigned char*)&nonce, + base10_exp, min_bits, actual_value ) ); + proof.resize(proof_len); + return proof; + } + + + bool verify_range_proof_rewind( blind_factor_type& blind_out, + uint64_t& value_out, + string& message_out, + const blind_factor_type& nonce, + uint64_t& min_val, + uint64_t& max_val, + commitment_type commit, + const std::vector& proof ) + { + char msg[4096]; + int mlen = 0; + FC_ASSERT( secp256k1_rangeproof_rewind( detail::_get_context(), + (unsigned char*)&blind_out, + &value_out, + (unsigned char*)msg, + &mlen, + (const unsigned char*)&nonce, + &min_val, + &max_val, + (const unsigned char*)&commit, + (const unsigned char*)proof.data(), + proof.size() ) ); + + message_out = std::string( msg, mlen ); + return true; + } + + range_proof_info range_get_info( const std::vector& proof ) + { + range_proof_info result; + FC_ASSERT( secp256k1_rangeproof_info( detail::_get_context(), + (int*)&result.exp, + (int*)&result.mantissa, + (uint64_t*)&result.min_value, + (uint64_t*)&result.max_value, + (const unsigned char*)proof.data(), + (int)proof.size() ) ); + + return result; + } + + } } diff --git a/tests/blind.cpp b/tests/blind.cpp new file mode 100644 index 0000000..91be6a5 --- /dev/null +++ b/tests/blind.cpp @@ -0,0 +1,90 @@ +#include +#include +#include +#include +#include + +extern "C" { +#include +#include +#include +} +//struct secp256k1_scalar_t { uint64_t v[4]; }; +//extern "C" { void secp256k1_scalar_get_b32(unsigned char *bin, const struct secp256k1_scalar_t* a); } + +int main( int argc, char** argv ) +{ + try { + auto InB1 = fc::sha256::hash("InB1"); + auto InB2 = fc::sha256::hash("InB2"); + auto OutB1 = fc::sha256::hash("OutB1"); + + + auto InC1 = fc::ecc::blind(InB1,25); + auto InC2 = fc::ecc::blind(InB2,75); + + auto OutC1 = fc::ecc::blind(OutB1,40); + + auto OutB2 = fc::ecc::blind_sum( {InB1,InB2,OutB1}, 2 ); + auto OutC2 = fc::ecc::blind( OutB2, 60 ); + + FC_ASSERT( fc::ecc::verify_sum( {InC1,InC2}, {OutC1,OutC2}, 0 ) ); + auto nonce = fc::sha256::hash("nonce"); + + auto proof = fc::ecc::range_proof_sign( 0, OutC1, OutB1, nonce, 0, 0, 40 ); + wdump( (proof.size())); + + auto result = fc::ecc::range_get_info( proof ); + wdump((result)); + FC_ASSERT( result.max_value >= 60 ); + FC_ASSERT( result.min_value >= 0 ); + + + auto B1 = fc::sha256::hash("B1"); + auto B2 = fc::sha256::hash("B2"); + auto b3 = fc::sha256::hash("b3"); + auto C1 = fc::ecc::blind( B1, 1 ); + auto C2 = fc::ecc::blind( B2, 2 ); + auto c3 = fc::ecc::blind( b3, 3 ); + + auto B3 = fc::ecc::blind_sum( {B1,B2}, 2 ); + auto C3 = fc::ecc::blind( B3, 3 ); + + + auto B2m1 = fc::ecc::blind_sum( {B2,B1}, 1 ); + auto C2m1 = fc::ecc::blind( B2m1, 1 ); + + FC_ASSERT( fc::ecc::verify_sum( {C1,C2}, {C3}, 0 ) ); + FC_ASSERT( fc::ecc::verify_sum( {C3}, {C1,C2}, 0 ) ); + + + { + auto B1 = fc::sha256::hash("B1"); + auto B2 = fc::sha256::hash("B2"); + auto B3 = fc::sha256::hash("B3"); + + //secp256k1_scalar_get_b32((unsigned char*)&B1, (const secp256k1_scalar_t*)&B2); + //B1 = fc::variant("b2e5da56ef9f2a34d3e22fd12634bc99261e95c87b9960bf94ed3d27b30").as(); + + auto C1 = fc::ecc::blind( B1, INT64_MAX ); + auto C2 = fc::ecc::blind( B1, 0 ); + auto C3 = fc::ecc::blind( B1, 1 ); + + FC_ASSERT( fc::ecc::verify_sum( {C2}, {C3}, -1 ) ); + FC_ASSERT( fc::ecc::verify_sum( {C1}, {C1}, 0 ) ); + FC_ASSERT( fc::ecc::verify_sum( {C2}, {C2}, 0 ) ); + FC_ASSERT( fc::ecc::verify_sum( {C3}, {C2}, 1 ) ); + FC_ASSERT( fc::ecc::verify_sum( {C1}, {C2}, INT64_MAX ) ); + FC_ASSERT( fc::ecc::verify_sum( {C2}, {C1}, -INT64_MAX ) ); + + + } + + + } + catch ( const fc::exception& e ) + { + edump((e.to_detail_string())); + } + return 0; +}