Opens up cryptographic methods in their own API with serialized wrappers for public and private keys.

Tests for serialization of the wrappers added in serialization_tests.
This commit is contained in:
Michael Vandeberg 2016-01-07 11:04:14 -05:00
parent acfbad2cd4
commit 8df58439b1
6 changed files with 290 additions and 43 deletions

View file

@ -89,7 +89,7 @@ namespace graphene { namespace app {
}
else if( api_name == "crypto_api" )
{
_crypto_api = std::make_shared< crypto_api >( std::ref(_app) );
_crypto_api = std::make_shared< crypto_api >();
}
return;
}
@ -416,18 +416,20 @@ namespace graphene { namespace app {
return result;
} FC_CAPTURE_AND_RETHROW( (a)(b)(bucket_seconds)(start)(end) ) }
blind_signature crypto_api::blind_sign( extended_private_key key, const blinded_hash& hash, int i ) const
crypto_api::crypto_api(){};
blind_signature crypto_api::blind_sign( const extended_private_key_type& key, const blinded_hash& hash, int i )
{
return key.blind_sign( hash, i );
return fc::ecc::extended_private_key( key ).blind_sign( hash, i );
}
compact_signature crypto_api::unblind_signature( extended_private_key key,
const extended_public_key& bob,
signature_type crypto_api::unblind_signature( const extended_private_key_type& key,
const extended_public_key_type& bob,
const blind_signature& sig,
const fc::sha256& hash,
int i ) const
int i )
{
return key.unblind_signature( bob, sig, hash, i );
return fc::ecc::extended_private_key( key ).unblind_signature( extended_public_key( bob ), sig, hash, i );
}
commitment_type crypto_api::blind( const blind_factor_type& blind, uint64_t value )
@ -444,12 +446,14 @@ namespace graphene { namespace app {
{
return fc::ecc::verify_sum( commits_in, neg_commits_in, excess );
}
bool crypto_api::verify_range( uint64_t& min_val, uint64_t& max_val, const commitment_type& commit, const std::vector<char>& proof )
verify_range_result crypto_api::verify_range( const commitment_type& commit, const std::vector<char>& proof )
{
return fc::ecc::verify_range( min_val, max_val, commit, proof );
verify_range_result result;
result.success = fc::ecc::verify_range( result.min_val, result.max_val, commit, proof );
return result;
}
std::vector<char> crypto_api::range_proof_sign( uint64_t min_value,
const commitment_type& commit,
const blind_factor_type& commit_blind,
@ -460,20 +464,24 @@ namespace graphene { namespace app {
{
return fc::ecc::range_proof_sign( min_value, commit, commit_blind, nonce, base10_exp, min_bits, actual_value );
}
bool crypto_api::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<char>& proof )
verify_range_proof_rewind_result crypto_api::verify_range_proof_rewind( const blind_factor_type& nonce,
const commitment_type& commit,
const std::vector<char>& proof )
{
return fc::ecc::verify_range_proof_rewind( blind_out, value_out, message_out, nonce, min_val, max_val, commit, proof );
verify_range_proof_rewind_result result;
result.success = fc::ecc::verify_range_proof_rewind( result.blind_out,
result.value_out,
result.message_out,
nonce,
result.min_val,
result.max_val,
const_cast< commitment_type& >( commit ),
proof );
return result;
}
range_proof_info crypto_ap::range_get_info( const std::vector<char>& proof )
range_proof_info crypto_api::range_get_info( const std::vector<char>& proof )
{
return fc::ecc::range_get_info( proof );
}

View file

@ -386,6 +386,7 @@ namespace detail {
wild_access.allowed_apis.push_back( "database_api" );
wild_access.allowed_apis.push_back( "network_broadcast_api" );
wild_access.allowed_apis.push_back( "history_api" );
wild_access.allowed_apis.push_back( "crypto_api" );
_apiaccess.permission_map["*"] = wild_access;
}

View file

@ -23,6 +23,7 @@
#include <graphene/app/database_api.hpp>
#include <graphene/chain/protocol/types.hpp>
#include <graphene/chain/protocol/confidential.hpp>
#include <graphene/market_history/market_history_plugin.hpp>
@ -48,6 +49,22 @@ namespace graphene { namespace app {
class application;
struct verify_range_result
{
bool success;
uint64_t min_val;
uint64_t max_val;
};
struct verify_range_proof_rewind_result
{
bool success;
uint64_t min_val;
uint64_t max_val;
uint64_t value_out;
fc::ecc::blind_factor_type blind_out;
string message_out;
};
/**
* @brief The history_api class implements the RPC API for account history
@ -179,21 +196,23 @@ namespace graphene { namespace app {
class crypto_api
{
public:
blind_signature blind_sign( extended_private_key key, const blinded_hash& hash, int i ) const;
crypto_api();
compact_signature unblind_signature( extended_private_key key,
const extended_public_key& bob,
const blind_signature& sig,
fc::ecc::blind_signature blind_sign( const extended_private_key_type& key, const fc::ecc::blinded_hash& hash, int i );
signature_type unblind_signature( const extended_private_key_type& key,
const extended_public_key_type& bob,
const fc::ecc::blind_signature& sig,
const fc::sha256& hash,
int i ) const;
commitment_type blind( const blind_factor_type& blind, uint64_t value );
int i );
fc::ecc::commitment_type blind( const fc::ecc::blind_factor_type& blind, uint64_t value );
blind_factor_type blind_sum( const std::vector<blind_factor_type>& blinds_in, uint32_t non_neg );
fc::ecc::blind_factor_type blind_sum( const std::vector<blind_factor_type>& blinds_in, uint32_t non_neg );
bool verify_sum( const std::vector<commitment_type>& commits_in, const std::vector<commitment_type>& neg_commits_in, int64_t excess );
bool verify_range( uint64_t& min_val, uint64_t& max_val, const commitment_type& commit, const std::vector<char>& proof );
verify_range_result verify_range( const fc::ecc::commitment_type& commit, const std::vector<char>& proof );
std::vector<char> range_proof_sign( uint64_t min_value,
const commitment_type& commit,
@ -203,14 +222,11 @@ namespace graphene { namespace app {
uint8_t min_bits,
uint64_t actual_value );
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<char>& proof );
verify_range_proof_rewind_result verify_range_proof_rewind( const blind_factor_type& nonce,
const fc::ecc::commitment_type& commit,
const std::vector<char>& proof );
range_proof_info range_get_info( const std::vector<char>& proof );
};
@ -245,7 +261,7 @@ namespace graphene { namespace app {
/// @brief Retrieve the network node API
fc::api<network_node_api> network_node()const;
/// @brief Retrieve the cryptography API
fc::api<crypto_apI> crypto()const;
fc::api<crypto_api> crypto()const;
private:
/// @brief Called to enable an API, not reflected.
@ -256,13 +272,19 @@ namespace graphene { namespace app {
optional< fc::api<network_broadcast_api> > _network_broadcast_api;
optional< fc::api<network_node_api> > _network_node_api;
optional< fc::api<history_api> > _history_api;
optional< fc::api<crypto_api> _crypto_api;
optional< fc::api<crypto_api> > _crypto_api;
};
}} // graphene::app
FC_REFLECT( graphene::app::network_broadcast_api::transaction_confirmation,
(id)(block_num)(trx_num)(trx) )
FC_REFLECT( graphene::app::verify_range_result,
(success)(min_val)(max_val) )
FC_REFLECT( graphene::app::verify_range_proof_rewind_result,
(success)(min_val)(max_val)(value_out)(blind_out)(message_out) )
//FC_REFLECT_TYPENAME( fc::ecc::compact_signature );
//FC_REFLECT_TYPENAME( fc::ecc::commitment_type );
FC_API(graphene::app::history_api,
(get_account_history)
@ -292,7 +314,8 @@ FC_API(graphene::app::crypto_api,
(verify_range)
(range_proof_sign)
(verify_range_proof_rewind)
(range_get_info))
(range_get_info)
)
FC_API(graphene::app::login_api,
(login)
(network_broadcast)

View file

@ -248,16 +248,67 @@ namespace graphene { namespace chain {
bool is_valid_v1( const std::string& base58str );
};
struct extended_public_key_type
{
struct binary_key
{
binary_key() {}
uint32_t check = 0;
fc::ecc::extended_key_data data;
};
fc::ecc::extended_key_data key_data;
extended_public_key_type();
extended_public_key_type( const fc::ecc::extended_key_data& data );
extended_public_key_type( const fc::ecc::extended_public_key& extpubkey );
explicit extended_public_key_type( const std::string& base58str );
operator fc::ecc::extended_public_key() const;
explicit operator std::string() const;
friend bool operator == ( const extended_public_key_type& p1, const fc::ecc::extended_public_key& p2);
friend bool operator == ( const extended_public_key_type& p1, const extended_public_key_type& p2);
friend bool operator != ( const extended_public_key_type& p1, const extended_public_key_type& p2);
};
struct extended_private_key_type
{
struct binary_key
{
binary_key() {}
uint32_t check = 0;
fc::ecc::extended_key_data data;
};
fc::ecc::extended_key_data key_data;
extended_private_key_type();
extended_private_key_type( const fc::ecc::extended_key_data& data );
extended_private_key_type( const fc::ecc::extended_private_key& extprivkey );
explicit extended_private_key_type( const std::string& base58str );
operator fc::ecc::extended_private_key() const;
explicit operator std::string() const;
friend bool operator == ( const extended_private_key_type& p1, const fc::ecc::extended_private_key& p2);
friend bool operator == ( const extended_private_key_type& p1, const extended_private_key_type& p2);
friend bool operator != ( const extended_private_key_type& p1, const extended_private_key_type& p2);
};
} } // graphene::chain
namespace fc
{
void to_variant( const graphene::chain::public_key_type& var, fc::variant& vo );
void from_variant( const fc::variant& var, graphene::chain::public_key_type& vo );
void to_variant( const graphene::chain::extended_public_key_type& var, fc::variant& vo );
void from_variant( const fc::variant& var, graphene::chain::extended_public_key_type& vo );
void to_variant( const graphene::chain::extended_private_key_type& var, fc::variant& vo );
void from_variant( const fc::variant& var, graphene::chain::extended_private_key_type& vo );
}
FC_REFLECT( graphene::chain::public_key_type, (key_data) )
FC_REFLECT( graphene::chain::public_key_type::binary_key, (data)(check) )
FC_REFLECT( graphene::chain::extended_public_key_type, (key_data) )
FC_REFLECT( graphene::chain::extended_public_key_type::binary_key, (check)(data) )
FC_REFLECT( graphene::chain::extended_private_key_type, (key_data) )
FC_REFLECT( graphene::chain::extended_private_key_type::binary_key, (check)(data) )
FC_REFLECT_ENUM( graphene::chain::object_type,
(null_object_type)

View file

@ -108,6 +108,114 @@ namespace graphene { namespace chain {
{
return p1.key_data != p2.key_data;
}
// extended_public_key_type
extended_public_key_type::extended_public_key_type():key_data(){};
extended_public_key_type::extended_public_key_type( const fc::ecc::extended_key_data& data )
:key_data( data ){};
extended_public_key_type::extended_public_key_type( const fc::ecc::extended_public_key& extpubkey )
{
key_data = extpubkey.serialize_extended();
};
extended_public_key_type::extended_public_key_type( const std::string& base58str )
{
std::string prefix( GRAPHENE_ADDRESS_PREFIX );
const size_t prefix_len = prefix.size();
FC_ASSERT( base58str.size() > prefix_len );
FC_ASSERT( base58str.substr( 0, prefix_len ) == prefix , "", ("base58str", base58str) );
auto bin = fc::from_base58( base58str.substr( prefix_len ) );
auto bin_key = fc::raw::unpack<binary_key>(bin);
FC_ASSERT( fc::ripemd160::hash( bin_key.data.data, bin_key.data.size() )._hash[0] == bin_key.check );
key_data = bin_key.data;
}
extended_public_key_type::operator fc::ecc::extended_public_key() const
{
return fc::ecc::extended_public_key::deserialize( key_data );
}
extended_public_key_type::operator std::string() const
{
binary_key k;
k.data = key_data;
k.check = fc::ripemd160::hash( k.data.data, k.data.size() )._hash[0];
auto data = fc::raw::pack( k );
return GRAPHENE_ADDRESS_PREFIX + fc::to_base58( data.data(), data.size() );
}
bool operator == ( const extended_public_key_type& p1, const fc::ecc::extended_public_key& p2)
{
return p1.key_data == p2.serialize_extended();
}
bool operator == ( const extended_public_key_type& p1, const extended_public_key_type& p2)
{
return p1.key_data == p2.key_data;
}
bool operator != ( const extended_public_key_type& p1, const extended_public_key_type& p2)
{
return p1.key_data != p2.key_data;
}
// extended_private_key_type
extended_private_key_type::extended_private_key_type():key_data(){};
extended_private_key_type::extended_private_key_type( const fc::ecc::extended_key_data& data )
:key_data( data ){};
extended_private_key_type::extended_private_key_type( const fc::ecc::extended_private_key& extprivkey )
{
key_data = extprivkey.serialize_extended();
};
extended_private_key_type::extended_private_key_type( const std::string& base58str )
{
std::string prefix( GRAPHENE_ADDRESS_PREFIX );
const size_t prefix_len = prefix.size();
FC_ASSERT( base58str.size() > prefix_len );
FC_ASSERT( base58str.substr( 0, prefix_len ) == prefix , "", ("base58str", base58str) );
auto bin = fc::from_base58( base58str.substr( prefix_len ) );
auto bin_key = fc::raw::unpack<binary_key>(bin);
FC_ASSERT( fc::ripemd160::hash( bin_key.data.data, bin_key.data.size() )._hash[0] == bin_key.check );
key_data = bin_key.data;
}
extended_private_key_type::operator fc::ecc::extended_private_key() const
{
return fc::ecc::extended_private_key::deserialize( key_data );
}
extended_private_key_type::operator std::string() const
{
binary_key k;
k.data = key_data;
k.check = fc::ripemd160::hash( k.data.data, k.data.size() )._hash[0];
auto data = fc::raw::pack( k );
return GRAPHENE_ADDRESS_PREFIX + fc::to_base58( data.data(), data.size() );
}
bool operator == ( const extended_private_key_type& p1, const fc::ecc::extended_public_key& p2)
{
return p1.key_data == p2.serialize_extended();
}
bool operator == ( const extended_private_key_type& p1, const extended_private_key_type& p2)
{
return p1.key_data == p2.key_data;
}
bool operator != ( const extended_private_key_type& p1, const extended_private_key_type& p2)
{
return p1.key_data != p2.key_data;
}
} } // graphene::chain
@ -116,12 +224,31 @@ namespace fc
using namespace std;
void to_variant( const graphene::chain::public_key_type& var, fc::variant& vo )
{
vo = std::string(var);
vo = std::string( var );
}
void from_variant( const fc::variant& var, graphene::chain::public_key_type& vo )
{
vo = graphene::chain::public_key_type( var.as_string() );
}
void to_variant( const graphene::chain::extended_public_key_type& var, fc::variant& vo )
{
vo = std::string( var );
}
void from_variant( const fc::variant& var, graphene::chain::extended_public_key_type& vo )
{
vo = graphene::chain::extended_public_key_type( var.as_string() );
}
void to_variant( const graphene::chain::extended_private_key_type& var, fc::variant& vo )
{
vo = std::string( var );
}
void from_variant( const fc::variant& var, graphene::chain::extended_private_key_type& vo )
{
vo = graphene::chain::extended_private_key_type( var.as_string() );
}
} // fc

View file

@ -25,6 +25,7 @@
#include <fc/crypto/digest.hpp>
#include <fc/crypto/elliptic.hpp>
#include <fc/reflect/variant.hpp>
#include "../common/database_fixture.hpp"
@ -82,4 +83,40 @@ BOOST_AUTO_TEST_CASE( json_tests )
}
}
BOOST_AUTO_TEST_CASE( extended_private_key_type_test )
{
try
{
fc::ecc::extended_private_key key = fc::ecc::extended_private_key( fc::ecc::private_key::generate(),
fc::sha256(),
0, 0, 0 );
extended_private_key_type type = extended_private_key_type( key );
std::string packed = std::string( type );
extended_private_key_type unpacked = extended_private_key_type( packed );
BOOST_CHECK( type == unpacked );
} catch ( const fc::exception& e )
{
edump((e.to_detail_string()));
throw;
}
}
BOOST_AUTO_TEST_CASE( extended_public_key_type_test )
{
try
{
fc::ecc::extended_public_key key = fc::ecc::extended_public_key( fc::ecc::private_key::generate().get_public_key(),
fc::sha256(),
0, 0, 0 );
extended_public_key_type type = extended_public_key_type( key );
std::string packed = std::string( type );
extended_public_key_type unpacked = extended_public_key_type( packed );
BOOST_CHECK( type == unpacked );
} catch ( const fc::exception& e )
{
edump((e.to_detail_string()));
throw;
}
}
BOOST_AUTO_TEST_SUITE_END()