Merge branch 'github_master'
This commit is contained in:
commit
f9e3f0c4e6
11 changed files with 1158 additions and 10 deletions
|
|
@ -305,7 +305,10 @@ target_include_directories(fc
|
|||
)
|
||||
|
||||
#target_link_libraries( fc PUBLIC udt ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES} ${PLATFORM_SPECIFIC_LIBS} ${RPCRT4} ${CMAKE_DL_LIBS} ${rt_library} ${ECC_LIB} )
|
||||
target_link_libraries( fc PUBLIC -L/usr/local/lib udt ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES} ${PLATFORM_SPECIFIC_LIBS} ${RPCRT4} ${CMAKE_DL_LIBS} ${rt_library} ${readline_libraries} ${ECC_LIB} )
|
||||
IF(NOT WIN32)
|
||||
set(LINK_USR_LOCAL_LIB -L/usr/local/lib)
|
||||
ENDIF()
|
||||
target_link_libraries( fc PUBLIC ${LINK_USR_LOCAL_LIB} udt ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES} ${PLATFORM_SPECIFIC_LIBS} ${RPCRT4} ${CMAKE_DL_LIBS} ${rt_library} ${readline_libraries} ${ECC_LIB} )
|
||||
|
||||
if(MSVC)
|
||||
set_source_files_properties( src/network/http/websocket.cpp PROPERTIES COMPILE_FLAGS "/bigobj" )
|
||||
|
|
@ -343,6 +346,12 @@ target_link_libraries( bloom_test fc )
|
|||
add_executable( real128_test tests/all_tests.cpp tests/real128_test.cpp )
|
||||
target_link_libraries( real128_test fc )
|
||||
|
||||
add_executable( hmac_test tests/hmac_test.cpp )
|
||||
target_link_libraries( hmac_test fc )
|
||||
|
||||
add_executable( blinding_test tests/blinding_test.cpp )
|
||||
target_link_libraries( blinding_test fc )
|
||||
|
||||
|
||||
add_executable( udt_server tests/udts.cpp )
|
||||
target_link_libraries( udt_server fc udt )
|
||||
|
|
|
|||
|
|
@ -24,6 +24,9 @@ namespace fc {
|
|||
typedef fc::array<char,72> signature;
|
||||
typedef fc::array<unsigned char,65> compact_signature;
|
||||
typedef std::vector<char> range_proof_type;
|
||||
typedef fc::array<char,78> extended_key_data;
|
||||
typedef fc::sha256 blinded_hash;
|
||||
typedef fc::sha256 blind_signature;
|
||||
|
||||
/**
|
||||
* @class public_key
|
||||
|
|
@ -73,6 +76,8 @@ namespace fc {
|
|||
static std::string to_base58( const public_key_data &key );
|
||||
static public_key from_base58( const std::string& b58 );
|
||||
|
||||
unsigned int fingerprint() const;
|
||||
|
||||
private:
|
||||
friend class private_key;
|
||||
static public_key from_key_data( const public_key_data& v );
|
||||
|
|
@ -136,13 +141,80 @@ namespace fc {
|
|||
return a.get_secret() < b.get_secret();
|
||||
}
|
||||
|
||||
unsigned int fingerprint() const { return get_public_key().fingerprint(); }
|
||||
|
||||
private:
|
||||
private_key( EC_KEY* k );
|
||||
static fc::sha256 get_secret( const EC_KEY * const k );
|
||||
fc::fwd<detail::private_key_impl,32> my;
|
||||
};
|
||||
|
||||
class extended_public_key : public public_key
|
||||
{
|
||||
public:
|
||||
extended_public_key( const public_key& k, const sha256& c,
|
||||
int child = 0, int parent_fp = 0, uint8_t depth = 0 );
|
||||
|
||||
extended_public_key derive_child( int i ) const;
|
||||
extended_public_key derive_normal_child( int i ) const;
|
||||
|
||||
extended_key_data serialize_extended() const;
|
||||
static extended_public_key deserialize( const extended_key_data& data );
|
||||
fc::string str() const;
|
||||
fc::string to_base58() const { return str(); }
|
||||
static extended_public_key from_base58( const fc::string& base58 );
|
||||
|
||||
public_key generate_p( int i ) const;
|
||||
public_key generate_q( int i ) const;
|
||||
private:
|
||||
sha256 c;
|
||||
int child_num, parent_fp;
|
||||
uint8_t depth;
|
||||
};
|
||||
|
||||
class extended_private_key : public private_key
|
||||
{
|
||||
public:
|
||||
extended_private_key( const private_key& k, const sha256& c,
|
||||
int child = 0, int parent_fp = 0, uint8_t depth = 0 );
|
||||
|
||||
extended_public_key get_extended_public_key()const;
|
||||
|
||||
extended_private_key derive_child( int i ) const;
|
||||
extended_private_key derive_normal_child( int i ) const;
|
||||
extended_private_key derive_hardened_child( int i ) const;
|
||||
|
||||
extended_key_data serialize_extended() const;
|
||||
static extended_private_key deserialize( const extended_key_data& data );
|
||||
fc::string str() const;
|
||||
fc::string to_base58() const { return str(); }
|
||||
static extended_private_key from_base58( const fc::string& base58 );
|
||||
static extended_private_key generate_master( const fc::string& seed );
|
||||
static extended_private_key generate_master( const char* seed, uint32_t seed_len );
|
||||
|
||||
// Oleg Andreev's blind signature scheme,
|
||||
// see http://blog.oleganza.com/post/77474860538/blind-signatures
|
||||
public_key blind_public_key( const extended_public_key& bob, int i ) const;
|
||||
blinded_hash blind_hash( const fc::sha256& hash, int i ) const;
|
||||
blind_signature blind_sign( const blinded_hash& hash, int i ) const;
|
||||
// WARNING! This may produce non-canonical signatures!
|
||||
compact_signature unblind_signature( const extended_public_key& bob,
|
||||
const blind_signature& sig,
|
||||
const fc::sha256& hash, int i ) const;
|
||||
|
||||
private:
|
||||
extended_private_key private_derive_rest( const fc::sha512& hash,
|
||||
int num ) const;
|
||||
private_key generate_a( int i ) const;
|
||||
private_key generate_b( int i ) const;
|
||||
private_key generate_c( int i ) const;
|
||||
private_key generate_d( int i ) const;
|
||||
private_key_secret compute_p( int i ) const;
|
||||
private_key_secret compute_q( int i, const private_key_secret& p ) const;
|
||||
sha256 c;
|
||||
int child_num, parent_fp;
|
||||
uint8_t depth;
|
||||
};
|
||||
|
||||
struct range_proof_info
|
||||
{
|
||||
|
|
@ -158,9 +230,9 @@ namespace fc {
|
|||
bool verify_sum( const std::vector<commitment_type>& commits, const std::vector<commitment_type>& neg_commits, int64_t excess );
|
||||
bool verify_range( uint64_t& min_val, uint64_t& max_val, const commitment_type& commit, const range_proof_type& proof );
|
||||
|
||||
range_proof_type range_proof_sign( uint64_t min_value,
|
||||
const commitment_type& commit,
|
||||
const blind_factor_type& commit_blind,
|
||||
range_proof_type 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,
|
||||
|
|
@ -169,15 +241,15 @@ namespace fc {
|
|||
|
||||
bool verify_range_proof_rewind( blind_factor_type& blind_out,
|
||||
uint64_t& value_out,
|
||||
string& message_out,
|
||||
string& message_out,
|
||||
const blind_factor_type& nonce,
|
||||
uint64_t& min_val,
|
||||
uint64_t& max_val,
|
||||
commitment_type commit,
|
||||
uint64_t& min_val,
|
||||
uint64_t& max_val,
|
||||
commitment_type commit,
|
||||
const range_proof_type& proof );
|
||||
range_proof_info range_get_info( const range_proof_type& proof );
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace ecc
|
||||
void to_variant( const ecc::private_key& var, variant& vo );
|
||||
|
|
|
|||
63
include/fc/crypto/hmac.hpp
Normal file
63
include/fc/crypto/hmac.hpp
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* File: hmac.hpp
|
||||
* Author: Peter Conrad
|
||||
*
|
||||
* Created on 1. Juli 2015, 21:48
|
||||
*/
|
||||
|
||||
#ifndef HMAC_HPP
|
||||
#define HMAC_HPP
|
||||
|
||||
#include <fc/crypto/sha224.hpp>
|
||||
#include <fc/crypto/sha256.hpp>
|
||||
#include <fc/crypto/sha512.hpp>
|
||||
|
||||
namespace fc {
|
||||
|
||||
template<typename H>
|
||||
class hmac
|
||||
{
|
||||
public:
|
||||
hmac() {}
|
||||
|
||||
H digest( const char* c, uint32_t c_len, const char* d, uint32_t d_len )
|
||||
{
|
||||
encoder.reset();
|
||||
add_key(c, c_len, 0x36);
|
||||
encoder.write( d, d_len );
|
||||
H intermediate = encoder.result();
|
||||
|
||||
encoder.reset();
|
||||
add_key(c, c_len, 0x5c);
|
||||
encoder.write( intermediate.data(), intermediate.data_size() );
|
||||
return encoder.result();
|
||||
}
|
||||
|
||||
private:
|
||||
void add_key( const char* c, const uint32_t c_len, char pad )
|
||||
{
|
||||
if ( c_len > internal_block_size() )
|
||||
{
|
||||
H hash = H::hash( c, c_len );
|
||||
add_key( hash.data(), hash.data_size(), pad );
|
||||
}
|
||||
else
|
||||
for (unsigned int i = 0; i < internal_block_size(); i++ )
|
||||
{
|
||||
encoder.put( pad ^ ((i < c_len) ? *c++ : 0) );
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int internal_block_size() const;
|
||||
|
||||
H dummy;
|
||||
typename H::encoder encoder;
|
||||
};
|
||||
|
||||
typedef hmac<fc::sha224> hmac_sha224;
|
||||
typedef hmac<fc::sha256> hmac_sha256;
|
||||
typedef hmac<fc::sha512> hmac_sha512;
|
||||
}
|
||||
|
||||
#endif /* HMAC_HPP */
|
||||
|
||||
|
|
@ -1,11 +1,121 @@
|
|||
#include <fc/crypto/base58.hpp>
|
||||
#include <fc/crypto/elliptic.hpp>
|
||||
#include <fc/io/raw.hpp>
|
||||
#include <fc/crypto/hmac.hpp>
|
||||
#include <fc/crypto/openssl.hpp>
|
||||
#include <fc/crypto/ripemd160.hpp>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# include <malloc.h>
|
||||
#else
|
||||
# include <alloca.h>
|
||||
#endif
|
||||
|
||||
/* stuff common to all ecc implementations */
|
||||
|
||||
#define BTC_EXT_PUB_MAGIC (0x0488B21E)
|
||||
#define BTC_EXT_PRIV_MAGIC (0x0488ADE4)
|
||||
|
||||
namespace fc { namespace ecc {
|
||||
|
||||
namespace detail {
|
||||
typedef fc::array<char,37> chr37;
|
||||
|
||||
fc::sha256 _left( const fc::sha512& v )
|
||||
{
|
||||
fc::sha256 result;
|
||||
memcpy( result.data(), v.data(), 32 );
|
||||
return result;
|
||||
}
|
||||
|
||||
fc::sha256 _right( const fc::sha512& v )
|
||||
{
|
||||
fc::sha256 result;
|
||||
memcpy( result.data(), v.data() + 32, 32 );
|
||||
return result;
|
||||
}
|
||||
|
||||
static void _put( unsigned char** dest, unsigned int i)
|
||||
{
|
||||
*(*dest)++ = (i >> 24) & 0xff;
|
||||
*(*dest)++ = (i >> 16) & 0xff;
|
||||
*(*dest)++ = (i >> 8) & 0xff;
|
||||
*(*dest)++ = i & 0xff;
|
||||
}
|
||||
|
||||
static unsigned int _get( unsigned char** src )
|
||||
{
|
||||
unsigned int result = *(*src)++ << 24;
|
||||
result |= *(*src)++ << 16;
|
||||
result |= *(*src)++ << 8;
|
||||
result |= *(*src)++;
|
||||
return result;
|
||||
}
|
||||
|
||||
static chr37 _derive_message( char first, const char* key32, int i )
|
||||
{
|
||||
chr37 result;
|
||||
unsigned char* dest = (unsigned char*) result.begin();
|
||||
*dest++ = first;
|
||||
memcpy( dest, key32, 32 ); dest += 32;
|
||||
_put( &dest, i );
|
||||
return result;
|
||||
}
|
||||
|
||||
chr37 _derive_message( const public_key_data& key, int i )
|
||||
{
|
||||
return _derive_message( *key.begin(), key.begin() + 1, i );
|
||||
}
|
||||
|
||||
static chr37 _derive_message( const private_key_secret& key, int i )
|
||||
{
|
||||
return _derive_message( 0, key.data(), i );
|
||||
}
|
||||
|
||||
const ec_group& get_curve()
|
||||
{
|
||||
static const ec_group secp256k1( EC_GROUP_new_by_curve_name( NID_secp256k1 ) );
|
||||
return secp256k1;
|
||||
}
|
||||
|
||||
static private_key_secret _get_curve_order()
|
||||
{
|
||||
const ec_group& group = get_curve();
|
||||
bn_ctx ctx(BN_CTX_new());
|
||||
ssl_bignum order;
|
||||
FC_ASSERT( EC_GROUP_get_order( group, order, ctx ) );
|
||||
private_key_secret bin;
|
||||
FC_ASSERT( BN_num_bytes( order ) == bin.data_size() );
|
||||
FC_ASSERT( BN_bn2bin( order, (unsigned char*) bin.data() ) == bin.data_size() );
|
||||
return bin;
|
||||
}
|
||||
|
||||
const private_key_secret& get_curve_order()
|
||||
{
|
||||
static private_key_secret order = _get_curve_order();
|
||||
return order;
|
||||
}
|
||||
|
||||
static private_key_secret _get_half_curve_order()
|
||||
{
|
||||
const ec_group& group = get_curve();
|
||||
bn_ctx ctx(BN_CTX_new());
|
||||
ssl_bignum order;
|
||||
FC_ASSERT( EC_GROUP_get_order( group, order, ctx ) );
|
||||
BN_rshift1( order, order );
|
||||
private_key_secret bin;
|
||||
FC_ASSERT( BN_num_bytes( order ) == bin.data_size() );
|
||||
FC_ASSERT( BN_bn2bin( order, (unsigned char*) bin.data() ) == bin.data_size() );
|
||||
return bin;
|
||||
}
|
||||
|
||||
const private_key_secret& get_half_curve_order()
|
||||
{
|
||||
static private_key_secret half_order = _get_half_curve_order();
|
||||
return half_order;
|
||||
}
|
||||
}
|
||||
|
||||
public_key public_key::from_key_data( const public_key_data &data ) {
|
||||
return public_key(data);
|
||||
}
|
||||
|
|
@ -50,6 +160,14 @@ namespace fc { namespace ecc {
|
|||
return from_key_data(key);
|
||||
}
|
||||
|
||||
unsigned int public_key::fingerprint() const
|
||||
{
|
||||
public_key_data key = serialize();
|
||||
ripemd160 hash = ripemd160::hash( sha256::hash( key.begin(), key.size() ) );
|
||||
unsigned char* fp = (unsigned char*) hash._hash;
|
||||
return (fp[0] << 24) | (fp[1] << 16) | (fp[2] << 8) | fp[3];
|
||||
}
|
||||
|
||||
bool public_key::is_canonical( const compact_signature& c ) {
|
||||
return !(c.data[1] & 0x80)
|
||||
&& !(c.data[1] == 0 && !(c.data[2] & 0x80))
|
||||
|
|
@ -111,6 +229,153 @@ namespace fc { namespace ecc {
|
|||
return private_key( k );
|
||||
}
|
||||
|
||||
static fc::string _to_base58( const extended_key_data& key )
|
||||
{
|
||||
char *buffer = (char*)alloca(key.size() + 4);
|
||||
memcpy( buffer, key.begin(), key.size() );
|
||||
fc::sha256 double_hash = fc::sha256::hash( fc::sha256::hash( key.begin(), key.size() ));
|
||||
memcpy( buffer + key.size(), double_hash.data(), 4 );
|
||||
return fc::to_base58( buffer, sizeof(buffer) );
|
||||
}
|
||||
|
||||
static void _parse_extended_data( unsigned char* buffer, fc::string base58 )
|
||||
{
|
||||
memset( buffer, 0, 78 );
|
||||
std::vector<char> decoded = fc::from_base58( base58 );
|
||||
unsigned int i = 0;
|
||||
for ( char c : decoded )
|
||||
{
|
||||
if ( i >= 78 || i > decoded.size() - 4 ) { break; }
|
||||
buffer[i++] = c;
|
||||
}
|
||||
}
|
||||
|
||||
extended_public_key extended_public_key::derive_child(int i) const
|
||||
{
|
||||
FC_ASSERT( !(i&0x80000000), "Can't derive hardened public key!" );
|
||||
return derive_normal_child(i);
|
||||
}
|
||||
|
||||
extended_key_data extended_public_key::serialize_extended() const
|
||||
{
|
||||
extended_key_data result;
|
||||
unsigned char* dest = (unsigned char*) result.begin();
|
||||
detail::_put( &dest, BTC_EXT_PUB_MAGIC );
|
||||
*dest++ = depth;
|
||||
detail::_put( &dest, parent_fp );
|
||||
detail::_put( &dest, child_num );
|
||||
memcpy( dest, c.data(), c.data_size() ); dest += 32;
|
||||
public_key_data key = serialize();
|
||||
memcpy( dest, key.begin(), key.size() );
|
||||
return result;
|
||||
}
|
||||
|
||||
fc::string extended_public_key::str() const
|
||||
{
|
||||
return _to_base58( serialize_extended() );
|
||||
}
|
||||
|
||||
extended_public_key extended_public_key::from_base58( const fc::string& base58 )
|
||||
{
|
||||
unsigned char buffer[78];
|
||||
unsigned char* ptr = buffer;
|
||||
_parse_extended_data( buffer, base58 );
|
||||
FC_ASSERT( detail::_get( &ptr ) == BTC_EXT_PUB_MAGIC, "Invalid extended private key" );
|
||||
uint8_t d = *ptr++;
|
||||
int fp = detail::_get( &ptr );
|
||||
int cn = detail::_get( &ptr );
|
||||
fc::sha256 chain;
|
||||
memcpy( chain.data(), ptr, chain.data_size() ); ptr += chain.data_size();
|
||||
public_key_data key;
|
||||
memcpy( key.begin(), ptr, key.size() );
|
||||
return extended_public_key( key, chain, cn, fp, d );
|
||||
}
|
||||
|
||||
extended_public_key extended_private_key::get_extended_public_key() const
|
||||
{
|
||||
return extended_public_key( get_public_key(), c, child_num, parent_fp, depth );
|
||||
}
|
||||
|
||||
public_key extended_public_key::generate_p(int i) const { return derive_normal_child(2*i + 0); }
|
||||
public_key extended_public_key::generate_q(int i) const { return derive_normal_child(2*i + 1); }
|
||||
|
||||
extended_private_key extended_private_key::derive_child(int i) const
|
||||
{
|
||||
return i < 0 ? derive_hardened_child(i) : derive_normal_child(i);
|
||||
}
|
||||
|
||||
extended_private_key extended_private_key::derive_normal_child(int i) const
|
||||
{
|
||||
const detail::chr37 data = detail::_derive_message( get_public_key().serialize(), i );
|
||||
hmac_sha512 mac;
|
||||
fc::sha512 l = mac.digest( c.data(), c.data_size(), data.begin(), data.size() );
|
||||
return private_derive_rest( l, i );
|
||||
}
|
||||
|
||||
extended_private_key extended_private_key::derive_hardened_child(int i) const
|
||||
{
|
||||
hmac_sha512 mac;
|
||||
private_key_secret key = get_secret();
|
||||
const detail::chr37 data = detail::_derive_message( key, i );
|
||||
fc::sha512 l = mac.digest( c.data(), c.data_size(), data.begin(), data.size() );
|
||||
return private_derive_rest( l, i );
|
||||
}
|
||||
|
||||
extended_key_data extended_private_key::serialize_extended() const
|
||||
{
|
||||
extended_key_data result;
|
||||
unsigned char* dest = (unsigned char*) result.begin();
|
||||
detail::_put( &dest, BTC_EXT_PRIV_MAGIC );
|
||||
*dest++ = depth;
|
||||
detail::_put( &dest, parent_fp );
|
||||
detail::_put( &dest, child_num );
|
||||
memcpy( dest, c.data(), c.data_size() ); dest += 32;
|
||||
*dest++ = 0;
|
||||
private_key_secret key = get_secret();
|
||||
memcpy( dest, key.data(), key.data_size() );
|
||||
return result;
|
||||
}
|
||||
|
||||
private_key extended_private_key::generate_a(int i) const { return derive_hardened_child(4*i + 0); }
|
||||
private_key extended_private_key::generate_b(int i) const { return derive_hardened_child(4*i + 1); }
|
||||
private_key extended_private_key::generate_c(int i) const { return derive_hardened_child(4*i + 2); }
|
||||
private_key extended_private_key::generate_d(int i) const { return derive_hardened_child(4*i + 3); }
|
||||
|
||||
fc::string extended_private_key::str() const
|
||||
{
|
||||
return _to_base58( serialize_extended() );
|
||||
}
|
||||
|
||||
extended_private_key extended_private_key::from_base58( const fc::string& base58 )
|
||||
{
|
||||
unsigned char buffer[78];
|
||||
unsigned char* ptr = buffer;
|
||||
_parse_extended_data( buffer, base58 );
|
||||
FC_ASSERT( detail::_get( &ptr ) == BTC_EXT_PRIV_MAGIC, "Invalid extended private key" );
|
||||
uint8_t d = *ptr++;
|
||||
int fp = detail::_get( &ptr );
|
||||
int cn = detail::_get( &ptr );
|
||||
fc::sha256 chain;
|
||||
memcpy( chain.data(), ptr, chain.data_size() ); ptr += chain.data_size();
|
||||
ptr++;
|
||||
private_key_secret key;
|
||||
memcpy( key.data(), ptr, key.data_size() );
|
||||
return extended_private_key( private_key::regenerate(key), chain, cn, fp, d );
|
||||
}
|
||||
|
||||
extended_private_key extended_private_key::generate_master( const fc::string& seed )
|
||||
{
|
||||
return generate_master( seed.c_str(), seed.size() );
|
||||
}
|
||||
|
||||
extended_private_key extended_private_key::generate_master( const char* seed, uint32_t seed_len )
|
||||
{
|
||||
hmac_sha512 mac;
|
||||
fc::sha512 hash = mac.digest( "Bitcoin seed", 12, seed, seed_len );
|
||||
extended_private_key result( private_key::regenerate( detail::_left(hash) ),
|
||||
detail::_right(hash) );
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
void to_variant( const ecc::private_key& var, variant& vo )
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
#include <fc/crypto/elliptic.hpp>
|
||||
|
||||
#include <fc/crypto/base58.hpp>
|
||||
#include <fc/crypto/hmac.hpp>
|
||||
#include <fc/crypto/openssl.hpp>
|
||||
#include <fc/crypto/sha512.hpp>
|
||||
|
||||
#include <fc/fwd_impl.hpp>
|
||||
#include <fc/exception/exception.hpp>
|
||||
|
|
@ -10,6 +12,12 @@
|
|||
#include <assert.h>
|
||||
#include <secp256k1.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# include <malloc.h>
|
||||
#else
|
||||
# include <alloca.h>
|
||||
#endif
|
||||
|
||||
#include "_elliptic_impl_priv.hpp"
|
||||
|
||||
namespace fc { namespace ecc {
|
||||
|
|
@ -42,6 +50,14 @@ namespace fc { namespace ecc {
|
|||
|
||||
public_key_data _key;
|
||||
};
|
||||
|
||||
typedef fc::array<char,37> chr37;
|
||||
chr37 _derive_message( const public_key_data& key, int i );
|
||||
fc::sha256 _left( const fc::sha512& v );
|
||||
fc::sha256 _right( const fc::sha512& v );
|
||||
const ec_group& get_curve();
|
||||
const private_key_secret& get_curve_order();
|
||||
const private_key_secret& get_half_curve_order();
|
||||
}
|
||||
|
||||
static const public_key_data empty_pub;
|
||||
|
|
@ -151,8 +167,292 @@ namespace fc { namespace ecc {
|
|||
FC_ASSERT( pk_len == my->_key.size() );
|
||||
}
|
||||
|
||||
extended_public_key::extended_public_key( const public_key& k, const fc::sha256& c,
|
||||
int child, int parent, uint8_t depth )
|
||||
: public_key(k), c(c), child_num(child), parent_fp(parent), depth(depth) { }
|
||||
|
||||
extended_public_key extended_public_key::derive_normal_child(int i) const
|
||||
{
|
||||
hmac_sha512 mac;
|
||||
public_key_data key = serialize();
|
||||
const detail::chr37 data = detail::_derive_message( key, i );
|
||||
fc::sha512 l = mac.digest( c.data(), c.data_size(), data.begin(), data.size() );
|
||||
fc::sha256 left = detail::_left(l);
|
||||
FC_ASSERT( left < detail::get_curve_order() );
|
||||
FC_ASSERT( secp256k1_ec_pubkey_tweak_add( detail::_get_context(), (unsigned char*) key.begin(), key.size(), (unsigned char*) left.data() ) > 0 );
|
||||
// FIXME: check validity - if left + key == infinity then invalid
|
||||
extended_public_key result( key, detail::_right(l), i, fingerprint(), depth + 1 );
|
||||
return result;
|
||||
}
|
||||
|
||||
static void to_bignum( const unsigned char* in, ssl_bignum& out, unsigned int len )
|
||||
{
|
||||
if ( *in & 0x80 )
|
||||
{
|
||||
unsigned char *buffer = (unsigned char*)alloca(len + 1);
|
||||
*buffer = 0;
|
||||
memcpy( buffer + 1, in, len );
|
||||
BN_bin2bn( buffer, sizeof(buffer), out );
|
||||
}
|
||||
else
|
||||
{
|
||||
BN_bin2bn( in, len, out );
|
||||
}
|
||||
}
|
||||
|
||||
static void to_bignum( const private_key_secret& in, ssl_bignum& out )
|
||||
{
|
||||
to_bignum( (unsigned char*) in.data(), out, in.data_size() );
|
||||
}
|
||||
|
||||
static void from_bignum( const ssl_bignum& in, unsigned char* out, unsigned int len )
|
||||
{
|
||||
unsigned int l = BN_num_bytes( in );
|
||||
if ( l > len )
|
||||
{
|
||||
unsigned char *buffer = (unsigned char*)alloca(l);
|
||||
BN_bn2bin( in, buffer );
|
||||
memcpy( out, buffer + l - len, len );
|
||||
}
|
||||
else
|
||||
{
|
||||
memset( out, 0, len - l );
|
||||
BN_bn2bin( in, out + len - l );
|
||||
}
|
||||
}
|
||||
|
||||
static void from_bignum( const ssl_bignum& in, private_key_secret& out )
|
||||
{
|
||||
from_bignum( in, (unsigned char*) out.data(), out.data_size() );
|
||||
}
|
||||
|
||||
static void invert( const private_key_secret& in, private_key_secret& out )
|
||||
{
|
||||
ssl_bignum bn_in;
|
||||
to_bignum( in, bn_in );
|
||||
ssl_bignum bn_n;
|
||||
to_bignum( detail::get_curve_order(), bn_n );
|
||||
ssl_bignum bn_inv;
|
||||
bn_ctx ctx( BN_CTX_new() );
|
||||
FC_ASSERT( BN_mod_inverse( bn_inv, bn_in, bn_n, ctx ) );
|
||||
from_bignum( bn_inv, out );
|
||||
}
|
||||
|
||||
static void to_point( const public_key_data& in, ec_point& out )
|
||||
{
|
||||
bn_ctx ctx( BN_CTX_new() );
|
||||
const ec_group& curve = detail::get_curve();
|
||||
private_key_secret x;
|
||||
memcpy( x.data(), in.begin() + 1, x.data_size() );
|
||||
ssl_bignum bn_x;
|
||||
to_bignum( x, bn_x );
|
||||
FC_ASSERT( EC_POINT_set_compressed_coordinates_GFp( curve, out, bn_x, *in.begin() & 1, ctx ) > 0 );
|
||||
}
|
||||
|
||||
static void from_point( const ec_point& in, public_key_data& out )
|
||||
{
|
||||
bn_ctx ctx( BN_CTX_new() );
|
||||
const ec_group& curve = detail::get_curve();
|
||||
ssl_bignum bn_x;
|
||||
ssl_bignum bn_y;
|
||||
FC_ASSERT( EC_POINT_get_affine_coordinates_GFp( curve, in, bn_x, bn_y, ctx ) > 0 );
|
||||
private_key_secret x;
|
||||
from_bignum( bn_x, x );
|
||||
memcpy( out.begin() + 1, x.data(), out.size() - 1 );
|
||||
*out.begin() = BN_is_bit_set( bn_y, 0 ) ? 3 : 2;
|
||||
}
|
||||
|
||||
// static void print(const unsigned char* data) {
|
||||
// for (int i = 0; i < 32; i++) {
|
||||
// printf("%02x", *data++);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// static void print(private_key_secret key) {
|
||||
// print((unsigned char*) key.data());
|
||||
// }
|
||||
//
|
||||
// static void print(public_key_data key) {
|
||||
// print((unsigned char*) key.begin() + 1);
|
||||
// }
|
||||
|
||||
static void canonicalize( unsigned char *int256 )
|
||||
{
|
||||
fc::sha256 biggi( (char*) int256, 32 );
|
||||
if ( detail::get_half_curve_order() >= biggi )
|
||||
{
|
||||
return; // nothing to do
|
||||
}
|
||||
ssl_bignum bn_k;
|
||||
to_bignum( int256, bn_k, 32 );
|
||||
ssl_bignum bn_n;
|
||||
to_bignum( detail::get_curve_order(), bn_n );
|
||||
FC_ASSERT( BN_sub( bn_k, bn_n, bn_k ) );
|
||||
from_bignum( bn_k, int256, 32 );
|
||||
}
|
||||
|
||||
static public_key compute_k( const private_key_secret& a, const private_key_secret& c,
|
||||
const public_key& p )
|
||||
{
|
||||
private_key_secret prod = a;
|
||||
FC_ASSERT( secp256k1_ec_privkey_tweak_mul( detail::_get_context(), (unsigned char*) prod.data(), (unsigned char*) c.data() ) > 0 );
|
||||
invert( prod, prod );
|
||||
public_key_data P = p.serialize();
|
||||
FC_ASSERT( secp256k1_ec_pubkey_tweak_mul( detail::_get_context(), (unsigned char*) P.begin(), P.size(), (unsigned char*) prod.data() ) );
|
||||
// printf("K: "); print(P); printf("\n");
|
||||
return public_key( P );
|
||||
}
|
||||
|
||||
static public_key compute_t( const private_key_secret& a, const private_key_secret& b,
|
||||
const private_key_secret& c, const private_key_secret& d,
|
||||
const public_key_data& p, const public_key_data& q )
|
||||
{
|
||||
private_key_secret prod;
|
||||
invert( c, prod ); // prod == c^-1
|
||||
FC_ASSERT( secp256k1_ec_privkey_tweak_mul( detail::_get_context(), (unsigned char*) prod.data(), (unsigned char*) d.data() ) > 0 );
|
||||
// prod == c^-1 * d
|
||||
|
||||
public_key_data accu = p;
|
||||
FC_ASSERT( secp256k1_ec_pubkey_tweak_mul( detail::_get_context(), (unsigned char*) accu.begin(), accu.size(), (unsigned char*) prod.data() ) );
|
||||
// accu == prod * P == c^-1 * d * P
|
||||
|
||||
ec_point point_accu( EC_POINT_new( detail::get_curve() ) );
|
||||
to_point( accu, point_accu );
|
||||
ec_point point_q( EC_POINT_new( detail::get_curve() ) );
|
||||
to_point( q, point_q );
|
||||
bn_ctx ctx(BN_CTX_new());
|
||||
FC_ASSERT( EC_POINT_add( detail::get_curve(), point_accu, point_accu, point_q, ctx ) > 0 );
|
||||
from_point( point_accu, accu );
|
||||
// accu == c^-1 * a * P + Q
|
||||
|
||||
FC_ASSERT( secp256k1_ec_pubkey_tweak_add( detail::_get_context(), (unsigned char*) accu.begin(), accu.size(), (unsigned char*) b.data() ) );
|
||||
// accu == c^-1 * a * P + Q + b*G
|
||||
|
||||
public_key_data k = compute_k( a, c, p ).serialize();
|
||||
memcpy( prod.data(), k.begin() + 1, prod.data_size() );
|
||||
// prod == Kx
|
||||
FC_ASSERT( secp256k1_ec_privkey_tweak_mul( detail::_get_context(), (unsigned char*) prod.data(), (unsigned char*) a.data() ) > 0 );
|
||||
// prod == Kx * a
|
||||
invert( prod, prod );
|
||||
// prod == (Kx * a)^-1
|
||||
|
||||
FC_ASSERT( secp256k1_ec_pubkey_tweak_mul( detail::_get_context(), (unsigned char*) accu.begin(), accu.size(), (unsigned char*) prod.data() ) );
|
||||
// accu == (c^-1 * a * P + Q + b*G) * (Kx * a)^-1
|
||||
|
||||
// printf("T: "); print(accu); printf("\n");
|
||||
return public_key( accu );
|
||||
}
|
||||
|
||||
extended_private_key::extended_private_key( const private_key& k, const sha256& c,
|
||||
int child, int parent, uint8_t depth )
|
||||
: private_key(k), c(c), child_num(child), parent_fp(parent), depth(depth) { }
|
||||
|
||||
extended_private_key extended_private_key::private_derive_rest( const fc::sha512& hash,
|
||||
int i) const
|
||||
{
|
||||
fc::sha256 left = detail::_left(hash);
|
||||
FC_ASSERT( left < detail::get_curve_order() );
|
||||
FC_ASSERT( secp256k1_ec_privkey_tweak_add( detail::_get_context(), (unsigned char*) left.data(), (unsigned char*) get_secret().data() ) > 0 );
|
||||
extended_private_key result( private_key::regenerate( left ), detail::_right(hash),
|
||||
i, fingerprint(), depth + 1 );
|
||||
return result;
|
||||
}
|
||||
|
||||
public_key extended_private_key::blind_public_key( const extended_public_key& bob, int i ) const
|
||||
{
|
||||
private_key_secret a = generate_a(i).get_secret();
|
||||
private_key_secret b = generate_b(i).get_secret();
|
||||
private_key_secret c = generate_c(i).get_secret();
|
||||
private_key_secret d = generate_d(i).get_secret();
|
||||
public_key_data p = bob.generate_p(i).serialize();
|
||||
public_key_data q = bob.generate_q(i).serialize();
|
||||
// printf("a: "); print(a); printf("\n");
|
||||
// printf("b: "); print(b); printf("\n");
|
||||
// printf("c: "); print(c); printf("\n");
|
||||
// printf("d: "); print(d); printf("\n");
|
||||
// printf("P: "); print(p); printf("\n");
|
||||
// printf("Q: "); print(q); printf("\n");
|
||||
return compute_t( a, b, c, d, p, q );
|
||||
}
|
||||
|
||||
blinded_hash extended_private_key::blind_hash( const fc::sha256& hash, int i ) const
|
||||
{
|
||||
private_key_secret a = generate_a(i).get_secret();
|
||||
private_key_secret b = generate_b(i).get_secret();
|
||||
FC_ASSERT( secp256k1_ec_privkey_tweak_mul( detail::_get_context(), (unsigned char*) a.data(), (unsigned char*) hash.data() ) > 0 );
|
||||
FC_ASSERT( secp256k1_ec_privkey_tweak_add( detail::_get_context(), (unsigned char*) a.data(), (unsigned char*) b.data() ) > 0 );
|
||||
// printf("hash: "); print(hash); printf("\n");
|
||||
// printf("blinded: "); print(a); printf("\n");
|
||||
return a;
|
||||
}
|
||||
|
||||
private_key_secret extended_private_key::compute_p( int i ) const
|
||||
{
|
||||
private_key_secret p_inv = derive_normal_child( 2*i ).get_secret();
|
||||
invert( p_inv, p_inv );
|
||||
// printf("p: "); print(p_inv); printf("\n");
|
||||
return p_inv;
|
||||
}
|
||||
|
||||
private_key_secret extended_private_key::compute_q( int i, const private_key_secret& p ) const
|
||||
{
|
||||
private_key_secret q = derive_normal_child( 2*i + 1 ).get_secret();
|
||||
FC_ASSERT( secp256k1_ec_privkey_tweak_mul( detail::_get_context(), (unsigned char*) q.data(), (unsigned char*) p.data() ) > 0 );
|
||||
// printf("q: "); print(q); printf("\n");
|
||||
return q;
|
||||
}
|
||||
|
||||
blind_signature extended_private_key::blind_sign( const blinded_hash& hash, int i ) const
|
||||
{
|
||||
private_key_secret p = compute_p( i );
|
||||
private_key_secret q = compute_q( i, p );
|
||||
FC_ASSERT( secp256k1_ec_privkey_tweak_mul( detail::_get_context(), (unsigned char*) p.data(), (unsigned char*) hash.data() ) > 0 );
|
||||
FC_ASSERT( secp256k1_ec_privkey_tweak_add( detail::_get_context(), (unsigned char*) p.data(), (unsigned char*) q.data() ) > 0 );
|
||||
// printf("blind_sig: "); print(p); printf("\n");
|
||||
return p;
|
||||
}
|
||||
|
||||
compact_signature extended_private_key::unblind_signature( const extended_public_key& bob,
|
||||
const blind_signature& sig,
|
||||
const fc::sha256& hash,
|
||||
int i ) const
|
||||
{
|
||||
private_key_secret a = generate_a(i).get_secret();
|
||||
private_key_secret b = generate_b(i).get_secret();
|
||||
private_key_secret c = generate_c(i).get_secret();
|
||||
private_key_secret d = generate_d(i).get_secret();
|
||||
public_key p = bob.generate_p(i);
|
||||
public_key q = bob.generate_q(i);
|
||||
public_key_data k = compute_k( a, c, p );
|
||||
public_key_data t = compute_t( a, b, c, d, p, q ).serialize();
|
||||
|
||||
FC_ASSERT( secp256k1_ec_privkey_tweak_mul( detail::_get_context(), (unsigned char*) c.data(), (unsigned char*) sig.data() ) > 0 );
|
||||
FC_ASSERT( secp256k1_ec_privkey_tweak_add( detail::_get_context(), (unsigned char*) c.data(), (unsigned char*) d.data() ) > 0 );
|
||||
|
||||
compact_signature result;
|
||||
memcpy( result.begin() + 1, k.begin() + 1, 32 );
|
||||
memcpy( result.begin() + 33, c.data(), 32 );
|
||||
canonicalize( result.begin() + 33 );
|
||||
// printf("unblinded: "); print(result.begin() + 33); printf("\n");
|
||||
for ( int i = 0; i < 4; i++ )
|
||||
{
|
||||
unsigned char pubkey[33];
|
||||
int pklen = 33;
|
||||
if ( secp256k1_ecdsa_recover_compact( detail::_get_context(), (unsigned char*) hash.data(),
|
||||
(unsigned char*) result.begin() + 1,
|
||||
pubkey, &pklen, 1, i ) )
|
||||
{
|
||||
if ( !memcmp( t.begin(), pubkey, sizeof(pubkey) ) )
|
||||
{
|
||||
*result.begin() = 27 + 4 + i;
|
||||
return result;
|
||||
// } else {
|
||||
// printf("Candidate: "); print( pubkey ); printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
FC_ASSERT( 0, "Failed to unblind - use different i" );
|
||||
}
|
||||
|
||||
commitment_type blind( const blind_factor_type& blind, uint64_t value )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include <fc/crypto/hex.hpp>
|
||||
#include <fc/crypto/hmac.hpp>
|
||||
#include <fc/fwd_impl.hpp>
|
||||
#include <openssl/sha.h>
|
||||
#include <string.h>
|
||||
|
|
@ -92,4 +93,7 @@ namespace fc {
|
|||
else
|
||||
memset( &bi, char(0), sizeof(bi) );
|
||||
}
|
||||
|
||||
template<>
|
||||
unsigned int hmac<sha224>::internal_block_size() const { return 64; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include <fc/crypto/hex.hpp>
|
||||
#include <fc/crypto/hmac.hpp>
|
||||
#include <fc/fwd_impl.hpp>
|
||||
#include <openssl/sha.h>
|
||||
#include <string.h>
|
||||
|
|
@ -113,4 +114,6 @@ namespace fc {
|
|||
return sha_value._hash[0];
|
||||
}
|
||||
|
||||
template<>
|
||||
unsigned int hmac<sha256>::internal_block_size() const { return 64; }
|
||||
} //end namespace fc
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include <fc/crypto/hex.hpp>
|
||||
#include <fc/crypto/hmac.hpp>
|
||||
#include <fc/fwd_impl.hpp>
|
||||
#include <openssl/sha.h>
|
||||
#include <string.h>
|
||||
|
|
@ -98,4 +99,7 @@ namespace fc {
|
|||
else
|
||||
memset( &bi, char(0), sizeof(bi) );
|
||||
}
|
||||
|
||||
template<>
|
||||
unsigned int hmac<sha512>::internal_block_size() const { return 128; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -665,6 +665,9 @@ namespace fc {
|
|||
if( tp <= (time_point::now()+fc::microseconds(10000)) )
|
||||
return;
|
||||
|
||||
FC_ASSERT(std::current_exception() == std::exception_ptr(),
|
||||
"Attempting to yield while processing an exception");
|
||||
|
||||
if( !current )
|
||||
current = new fc::context(&fc::thread::current());
|
||||
|
||||
|
|
@ -698,6 +701,9 @@ namespace fc {
|
|||
if( p->ready() )
|
||||
return;
|
||||
|
||||
FC_ASSERT(std::current_exception() == std::exception_ptr(),
|
||||
"Attempting to yield while processing an exception");
|
||||
|
||||
if( timeout < time_point::now() )
|
||||
FC_THROW_EXCEPTION( timeout_exception, "" );
|
||||
|
||||
|
|
|
|||
304
tests/blinding_test.cpp
Normal file
304
tests/blinding_test.cpp
Normal file
|
|
@ -0,0 +1,304 @@
|
|||
#define BOOST_TEST_MODULE BlindingTest
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <fc/array.hpp>
|
||||
#include <fc/crypto/base58.hpp>
|
||||
#include <fc/crypto/hex.hpp>
|
||||
#include <fc/crypto/elliptic.hpp>
|
||||
#include <fc/crypto/openssl.hpp>
|
||||
#include <fc/exception/exception.hpp>
|
||||
|
||||
// See https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#Test_Vectors
|
||||
|
||||
static fc::string TEST1_SEED = "000102030405060708090a0b0c0d0e0f";
|
||||
static fc::string TEST1_M_PUB = "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8";
|
||||
static fc::string TEST1_M_PRIV = "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi";
|
||||
static fc::string TEST1_M_0H_PUB = "xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw";
|
||||
static fc::string TEST1_M_0H_PRIV = "xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7";
|
||||
static fc::string TEST1_M_0H_1_PUB = "xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ";
|
||||
static fc::string TEST1_M_0H_1_PRIV = "xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs";
|
||||
static fc::string TEST1_M_0H_1_2H_PUB = "xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5";
|
||||
static fc::string TEST1_M_0H_1_2H_PRIV = "xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM";
|
||||
static fc::string TEST1_M_0H_1_2H_2_PUB = "xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV";
|
||||
static fc::string TEST1_M_0H_1_2H_2_PRIV = "xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334";
|
||||
static fc::string TEST1_M_0H_1_2H_2_1g_PUB = "xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy";
|
||||
static fc::string TEST1_M_0H_1_2H_2_1g_PRIV = "xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76";
|
||||
|
||||
static fc::string TEST2_SEED = "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542";
|
||||
static fc::string TEST2_M_PUB = "xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB";
|
||||
static fc::string TEST2_M_PRIV = "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U";
|
||||
static fc::string TEST2_M_0_PUB = "xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH";
|
||||
static fc::string TEST2_M_0_PRIV = "xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt";
|
||||
static fc::string TEST2_M_0_m1_PUB = "xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a";
|
||||
static fc::string TEST2_M_0_m1_PRIV = "xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9";
|
||||
static fc::string TEST2_M_0_m1_1_PUB = "xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon";
|
||||
static fc::string TEST2_M_0_m1_1_PRIV = "xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef";
|
||||
static fc::string TEST2_M_0_m1_1_m2_PUB = "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL";
|
||||
static fc::string TEST2_M_0_m1_1_m2_PRIV = "xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc";
|
||||
static fc::string TEST2_M_0_m1_1_m2_2_PUB = "xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt";
|
||||
static fc::string TEST2_M_0_m1_1_m2_2_PRIV = "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j";
|
||||
|
||||
static fc::string BLIND_K_X = "08be5c5076f8cbd1283cf98e74bff873032b9bc79a0769962bf3900f33c2df6e";
|
||||
static fc::string BLIND_T_X = "80deff382af8a8e4a5f297588e44d5bf858f30a524f74b13efcefeb54f4b3f47";
|
||||
static fc::string BLINDED_HASH = "7196e80cdafdfdfb7496323ad24bf47dda8447febd7426e444facc04940c7309";
|
||||
static fc::string BLIND_SIG = "40d6a477d849cc860df8ad159481f2ffc5b4dc3131b86a799d7d10460824dd53";
|
||||
static fc::string UNBLINDED = "700092a72a05e33509f9b068aa1d7c5336d8b5692b4157da199d7ec1e10fd7c0";
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_extended_keys_1)
|
||||
{
|
||||
char seed[16];
|
||||
fc::from_hex( TEST1_SEED, seed, sizeof(seed) );
|
||||
fc::ecc::extended_private_key master = fc::ecc::extended_private_key::generate_master( seed, sizeof(seed) );
|
||||
BOOST_CHECK_EQUAL( master.str(), TEST1_M_PRIV );
|
||||
BOOST_CHECK_EQUAL( master.get_extended_public_key().str(), TEST1_M_PUB );
|
||||
|
||||
BOOST_CHECK_EQUAL( fc::ecc::extended_private_key::from_base58(TEST1_M_PRIV).str(), TEST1_M_PRIV );
|
||||
BOOST_CHECK_EQUAL( fc::ecc::extended_public_key::from_base58(TEST1_M_PUB).str(), TEST1_M_PUB );
|
||||
BOOST_CHECK_EQUAL( fc::ecc::extended_private_key::from_base58(TEST1_M_0H_PRIV).str(), TEST1_M_0H_PRIV );
|
||||
BOOST_CHECK_EQUAL( fc::ecc::extended_public_key::from_base58(TEST1_M_0H_PUB).str(), TEST1_M_0H_PUB );
|
||||
|
||||
fc::ecc::extended_private_key m_0 = master.derive_child(0x80000000);
|
||||
BOOST_CHECK_EQUAL( m_0.str(), TEST1_M_0H_PRIV );
|
||||
BOOST_CHECK_EQUAL( m_0.get_extended_public_key().str(), TEST1_M_0H_PUB );
|
||||
|
||||
fc::ecc::extended_private_key m_0_1 = m_0.derive_child(1);
|
||||
BOOST_CHECK_EQUAL( m_0_1.str(), TEST1_M_0H_1_PRIV );
|
||||
BOOST_CHECK_EQUAL( m_0_1.get_extended_public_key().str(), TEST1_M_0H_1_PUB );
|
||||
BOOST_CHECK_EQUAL( m_0.get_extended_public_key().derive_child(1).str(), TEST1_M_0H_1_PUB );
|
||||
|
||||
fc::ecc::extended_private_key m_0_1_2 = m_0_1.derive_child(0x80000002);
|
||||
BOOST_CHECK_EQUAL( m_0_1_2.str(), TEST1_M_0H_1_2H_PRIV );
|
||||
BOOST_CHECK_EQUAL( m_0_1_2.get_extended_public_key().str(), TEST1_M_0H_1_2H_PUB );
|
||||
|
||||
fc::ecc::extended_private_key m_0_1_2_2 = m_0_1_2.derive_child(2);
|
||||
BOOST_CHECK_EQUAL( m_0_1_2_2.str(), TEST1_M_0H_1_2H_2_PRIV );
|
||||
BOOST_CHECK_EQUAL( m_0_1_2_2.get_extended_public_key().str(), TEST1_M_0H_1_2H_2_PUB );
|
||||
BOOST_CHECK_EQUAL( m_0_1_2.get_extended_public_key().derive_child(2).str(), TEST1_M_0H_1_2H_2_PUB );
|
||||
|
||||
fc::ecc::extended_private_key m_0_1_2_2_1g = m_0_1_2_2.derive_child(1000000000);
|
||||
BOOST_CHECK_EQUAL( m_0_1_2_2_1g.str(), TEST1_M_0H_1_2H_2_1g_PRIV );
|
||||
BOOST_CHECK_EQUAL( m_0_1_2_2_1g.get_extended_public_key().str(), TEST1_M_0H_1_2H_2_1g_PUB );
|
||||
BOOST_CHECK_EQUAL( m_0_1_2_2.get_extended_public_key().derive_child(1000000000).str(), TEST1_M_0H_1_2H_2_1g_PUB );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_extended_keys_2)
|
||||
{
|
||||
char seed[64];
|
||||
fc::from_hex( TEST2_SEED, seed, sizeof(seed) );
|
||||
fc::ecc::extended_private_key master = fc::ecc::extended_private_key::generate_master( seed, sizeof(seed) );
|
||||
BOOST_CHECK_EQUAL( master.str(), TEST2_M_PRIV );
|
||||
BOOST_CHECK_EQUAL( master.get_extended_public_key().str(), TEST2_M_PUB );
|
||||
|
||||
fc::ecc::extended_private_key m_0 = master.derive_child(0);
|
||||
BOOST_CHECK_EQUAL( m_0.str(), TEST2_M_0_PRIV );
|
||||
BOOST_CHECK_EQUAL( m_0.get_extended_public_key().str(), TEST2_M_0_PUB );
|
||||
BOOST_CHECK_EQUAL( master.get_extended_public_key().derive_child(0).str(), TEST2_M_0_PUB );
|
||||
|
||||
fc::ecc::extended_private_key m_0_m1 = m_0.derive_child(-1);
|
||||
BOOST_CHECK_EQUAL( m_0_m1.str(), TEST2_M_0_m1_PRIV );
|
||||
BOOST_CHECK_EQUAL( m_0_m1.get_extended_public_key().str(), TEST2_M_0_m1_PUB );
|
||||
|
||||
fc::ecc::extended_private_key m_0_m1_1 = m_0_m1.derive_child(1);
|
||||
BOOST_CHECK_EQUAL( m_0_m1_1.str(), TEST2_M_0_m1_1_PRIV );
|
||||
BOOST_CHECK_EQUAL( m_0_m1_1.get_extended_public_key().str(), TEST2_M_0_m1_1_PUB );
|
||||
BOOST_CHECK_EQUAL( m_0_m1.get_extended_public_key().derive_child(1).str(), TEST2_M_0_m1_1_PUB );
|
||||
|
||||
fc::ecc::extended_private_key m_0_m1_1_m2 = m_0_m1_1.derive_child(-2);
|
||||
BOOST_CHECK_EQUAL( m_0_m1_1_m2.str(), TEST2_M_0_m1_1_m2_PRIV );
|
||||
BOOST_CHECK_EQUAL( m_0_m1_1_m2.get_extended_public_key().str(), TEST2_M_0_m1_1_m2_PUB );
|
||||
|
||||
fc::ecc::extended_private_key m_0_m1_1_m2_2 = m_0_m1_1_m2.derive_child(2);
|
||||
BOOST_CHECK_EQUAL( m_0_m1_1_m2_2.str(), TEST2_M_0_m1_1_m2_2_PRIV );
|
||||
BOOST_CHECK_EQUAL( m_0_m1_1_m2_2.get_extended_public_key().str(), TEST2_M_0_m1_1_m2_2_PUB );
|
||||
BOOST_CHECK_EQUAL( m_0_m1_1_m2.get_extended_public_key().derive_child(2).str(), TEST2_M_0_m1_1_m2_2_PUB );
|
||||
}
|
||||
|
||||
//static void print(const unsigned char* data, int len) {
|
||||
// for (int i = 0; i < len; i++) {
|
||||
// printf("%02x", *data++);
|
||||
// }
|
||||
//}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_blinding_1)
|
||||
{
|
||||
char buffer[7] = "test_";
|
||||
fc::ecc::extended_private_key alice = fc::ecc::extended_private_key::generate_master( "master" );
|
||||
fc::ecc::extended_private_key bob = fc::ecc::extended_private_key::generate_master( "puppet" );
|
||||
|
||||
for ( int i = 0; i < 30; i++ )
|
||||
{
|
||||
buffer[5] = '0' + i;
|
||||
fc::ecc::extended_public_key bob_pub = bob.get_extended_public_key();
|
||||
fc::sha256 hash = fc::sha256::hash( buffer, sizeof(buffer) );
|
||||
fc::ecc::public_key t = alice.blind_public_key( bob_pub, i );
|
||||
fc::ecc::blinded_hash blinded = alice.blind_hash( hash, i );
|
||||
fc::ecc::blind_signature blind_sig = bob.blind_sign( blinded, i );
|
||||
try {
|
||||
fc::ecc::compact_signature sig = alice.unblind_signature( bob_pub, blind_sig, hash, i );
|
||||
fc::ecc::public_key validate( sig, hash );
|
||||
// printf("Validated: "); print((unsigned char*) validate.serialize().begin(), 33);
|
||||
// printf("\nT: "); print((unsigned char*) t.serialize().begin(), 33); printf("\n");
|
||||
BOOST_CHECK( validate.serialize() == t.serialize() );
|
||||
} catch (const fc::exception& e) {
|
||||
printf( "Test %d: %s\n", i, e.to_string().c_str() );
|
||||
}
|
||||
alice = alice.derive_child( i );
|
||||
bob = bob.derive_child( i | 0x80000000 );
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_blinding_2)
|
||||
{
|
||||
char message[7] = "test_0";
|
||||
fc::ecc::extended_private_key alice = fc::ecc::extended_private_key::generate_master( "master" );
|
||||
fc::ecc::extended_private_key bob = fc::ecc::extended_private_key::generate_master( "puppet" );
|
||||
fc::ecc::extended_public_key bob_pub = bob.get_extended_public_key();
|
||||
fc::sha256 hash = fc::sha256::hash( message, sizeof(message) );
|
||||
|
||||
fc::ecc::public_key t = alice.blind_public_key( bob_pub, 0 );
|
||||
fc::ecc::public_key_data pub = t.serialize();
|
||||
char buffer[32];
|
||||
fc::from_hex( BLIND_T_X, buffer, sizeof(buffer) );
|
||||
BOOST_CHECK( !memcmp( pub.begin() + 1, buffer, sizeof(buffer) ) );
|
||||
|
||||
fc::ecc::blinded_hash blinded = alice.blind_hash( hash, 0 );
|
||||
fc::from_hex( BLINDED_HASH, buffer, sizeof(buffer) );
|
||||
BOOST_CHECK( !memcmp( blinded.data(), buffer, sizeof(buffer) ) );
|
||||
|
||||
fc::ecc::blind_signature blind_sig = bob.blind_sign( blinded, 0 );
|
||||
fc::from_hex( BLIND_SIG, buffer, sizeof(buffer) );
|
||||
BOOST_CHECK( !memcmp( blind_sig.data(), buffer, sizeof(buffer) ) );
|
||||
|
||||
fc::ecc::compact_signature sig = alice.unblind_signature( bob_pub, blind_sig, hash, 0 );
|
||||
fc::from_hex( BLIND_K_X, buffer, sizeof(buffer) );
|
||||
BOOST_CHECK( !memcmp( sig.begin() + 1, buffer, sizeof(buffer) ) );
|
||||
fc::from_hex( UNBLINDED, buffer, sizeof(buffer) );
|
||||
BOOST_CHECK( !memcmp( sig.begin() + 33, buffer, sizeof(buffer) ) );
|
||||
}
|
||||
|
||||
static void to_bignum(const char* data32, fc::ssl_bignum& out) {
|
||||
unsigned char dummy[33]; dummy[0] = 0;
|
||||
memcpy(dummy, data32, 32);
|
||||
BN_bin2bn((unsigned char*) data32, 32, out);
|
||||
}
|
||||
|
||||
//static void print(const fc::sha256 hash) {
|
||||
// print((unsigned char*) hash.data(), hash.data_size());
|
||||
//}
|
||||
//
|
||||
//static void print(const BIGNUM* bn) {
|
||||
// unsigned char buffer[64];
|
||||
// int len = BN_num_bytes(bn);
|
||||
// if (len > sizeof(buffer)) {
|
||||
// printf("BN too long - %d bytes?!", len);
|
||||
// return;
|
||||
// }
|
||||
// BN_bn2bin(bn, buffer);
|
||||
// print(buffer, len);
|
||||
//}
|
||||
//
|
||||
//static void print(const fc::ec_group& curve, const fc::ec_point& p, fc::bn_ctx& ctx) {
|
||||
// fc::ssl_bignum x;
|
||||
// fc::ssl_bignum y;
|
||||
// EC_POINT_get_affine_coordinates_GFp(curve, p, x, y, ctx);
|
||||
// printf("(");
|
||||
// print(x);
|
||||
// printf(", ");
|
||||
// print(y);
|
||||
// printf(")");
|
||||
//}
|
||||
|
||||
namespace fc {
|
||||
SSL_TYPE(ec_key, EC_KEY, EC_KEY_free)
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(openssl_blinding)
|
||||
{
|
||||
// Needed this "test" for producing data for debugging my libsecp256k1 implementation
|
||||
|
||||
char buffer[7] = "test_0";
|
||||
fc::ecc::extended_private_key alice = fc::ecc::extended_private_key::generate_master( "master" );
|
||||
fc::ecc::extended_private_key bob = fc::ecc::extended_private_key::generate_master( "puppet" );
|
||||
fc::ec_group curve(EC_GROUP_new_by_curve_name(NID_secp256k1));
|
||||
fc::bn_ctx ctx(BN_CTX_new());
|
||||
fc::ssl_bignum n;
|
||||
EC_GROUP_get_order(curve, n, ctx);
|
||||
fc::ssl_bignum n_half;
|
||||
BN_rshift1(n_half, n);
|
||||
fc::ssl_bignum zero; BN_zero(zero);
|
||||
|
||||
fc::sha256 hash_ = fc::sha256::hash( buffer, sizeof(buffer) );
|
||||
fc::ssl_bignum hash; to_bignum(hash_.data(), hash);
|
||||
fc::ssl_bignum a; to_bignum(alice.derive_hardened_child(0).get_secret().data(), a);
|
||||
fc::ssl_bignum b; to_bignum(alice.derive_hardened_child(1).get_secret().data(), b);
|
||||
fc::ssl_bignum c; to_bignum(alice.derive_hardened_child(2).get_secret().data(), c);
|
||||
fc::ssl_bignum d; to_bignum(alice.derive_hardened_child(3).get_secret().data(), d);
|
||||
|
||||
fc::ec_point P(EC_POINT_new(curve));
|
||||
fc::ecc::public_key_data Pd = bob.get_extended_public_key().derive_child(0).serialize();
|
||||
fc::ssl_bignum Px; to_bignum(Pd.begin() + 1, Px);
|
||||
EC_POINT_set_compressed_coordinates_GFp(curve, P, Px, (*Pd.begin()) & 1, ctx);
|
||||
|
||||
fc::ec_point Q(EC_POINT_new(curve));
|
||||
fc::ecc::public_key_data Qd = bob.get_extended_public_key().derive_child(1).serialize();
|
||||
fc::ssl_bignum Qx; to_bignum(Qd.begin() + 1, Qx);
|
||||
EC_POINT_set_compressed_coordinates_GFp(curve, Q, Qx, (*Qd.begin()) & 1, ctx);
|
||||
|
||||
// Alice computes K = (c·a)^-1·P and public key T = (a·Kx)^-1·(b·G + Q + d·c^-1·P).
|
||||
fc::ec_point K(EC_POINT_new(curve));
|
||||
fc::ssl_bignum tmp;
|
||||
BN_mod_mul(tmp, a, c, n, ctx);
|
||||
BN_mod_inverse(tmp, tmp, n, ctx);
|
||||
EC_POINT_mul(curve, K, zero, P, tmp, ctx);
|
||||
|
||||
fc::ec_point T(EC_POINT_new(curve));
|
||||
BN_mod_inverse(tmp, c, n, ctx);
|
||||
BN_mod_mul(tmp, d, tmp, n, ctx);
|
||||
EC_POINT_mul(curve, T, b, P, tmp, ctx);
|
||||
EC_POINT_add(curve, T, T, Q, ctx);
|
||||
fc::ssl_bignum Kx;
|
||||
fc::ssl_bignum Ky;
|
||||
EC_POINT_get_affine_coordinates_GFp(curve, K, Kx, Ky, ctx);
|
||||
BN_mod_mul(tmp, a, Kx, n, ctx);
|
||||
BN_mod_inverse(tmp, tmp, n, ctx);
|
||||
EC_POINT_mul(curve, T, zero, T, tmp, ctx);
|
||||
|
||||
fc::ssl_bignum blinded;
|
||||
BN_mod_mul(blinded, a, hash, n, ctx);
|
||||
BN_mod_add(blinded, blinded, b, n, ctx);
|
||||
|
||||
fc::ssl_bignum p; to_bignum(bob.derive_normal_child(0).get_secret().data(), p);
|
||||
fc::ssl_bignum q; to_bignum(bob.derive_normal_child(1).get_secret().data(), q);
|
||||
BN_mod_inverse(p, p, n, ctx);
|
||||
BN_mod_mul(q, q, p, n, ctx);
|
||||
fc::ssl_bignum blind_sig;
|
||||
BN_mod_mul(blind_sig, p, blinded, n, ctx);
|
||||
BN_mod_add(blind_sig, blind_sig, q, n, ctx);
|
||||
|
||||
fc::ecdsa_sig sig(ECDSA_SIG_new());
|
||||
BN_copy(sig->r, Kx);
|
||||
BN_mod_mul(sig->s, c, blind_sig, n, ctx);
|
||||
BN_mod_add(sig->s, sig->s, d, n, ctx);
|
||||
|
||||
if (BN_cmp(sig->s, n_half) > 0) {
|
||||
BN_sub(sig->s, n, sig->s);
|
||||
}
|
||||
|
||||
fc::ec_key verify(EC_KEY_new());
|
||||
EC_KEY_set_public_key(verify, T);
|
||||
BOOST_CHECK( ECDSA_do_verify( (unsigned char*) hash_.data(), hash_.data_size(), sig, verify ) );
|
||||
// printf("a: "); print(a);
|
||||
// printf("\nb: "); print(b);
|
||||
// printf("\nc: "); print(c);
|
||||
// printf("\nd: "); print(d);
|
||||
// printf("\nP: "); print(curve, P, ctx);
|
||||
// printf("\nQ: "); print(curve, Q, ctx);
|
||||
// printf("\nK: "); print(curve, K, ctx);
|
||||
// printf("\nT: "); print(curve, T, ctx);
|
||||
// printf("\np: "); print(p);
|
||||
// printf("\nq: "); print(q);
|
||||
// printf("\nhash: "); print(hash_);
|
||||
// printf("\nblinded: "); print(blinded);
|
||||
// printf("\nblind_sig: "); print(blind_sig);
|
||||
// printf("\nunblinded: "); print(sig->s);
|
||||
// printf("\n");
|
||||
}
|
||||
118
tests/hmac_test.cpp
Normal file
118
tests/hmac_test.cpp
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
#define BOOST_TEST_MODULE HmacTest
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <fc/array.hpp>
|
||||
#include <fc/crypto/hex.hpp>
|
||||
#include <fc/crypto/hmac.hpp>
|
||||
#include <fc/crypto/sha224.hpp>
|
||||
#include <fc/crypto/sha256.hpp>
|
||||
#include <fc/crypto/sha512.hpp>
|
||||
|
||||
// See http://tools.ietf.org/html/rfc4231
|
||||
|
||||
static const fc::string TEST1_KEY = "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b";
|
||||
static const fc::string TEST1_DATA = "4869205468657265";
|
||||
static const fc::string TEST1_224 = "896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22";
|
||||
static const fc::string TEST1_256 = "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7";
|
||||
static const fc::string TEST1_512 = "87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cde"
|
||||
"daa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854";
|
||||
|
||||
static const fc::string TEST2_KEY = "4a656665";
|
||||
static const fc::string TEST2_DATA = "7768617420646f2079612077616e7420666f72206e6f7468696e673f";
|
||||
static const fc::string TEST2_224 = "a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44";
|
||||
static const fc::string TEST2_256 = "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843";
|
||||
static const fc::string TEST2_512 = "164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea250554"
|
||||
"9758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737";
|
||||
|
||||
static const fc::string TEST3_KEY = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
|
||||
static const fc::string TEST3_DATA = "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
|
||||
"dddddddddddddddddddddddddddddddddddd";
|
||||
static const fc::string TEST3_224 = "7fb3cb3588c6c1f6ffa9694d7d6ad2649365b0c1f65d69d1ec8333ea";
|
||||
static const fc::string TEST3_256 = "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe";
|
||||
static const fc::string TEST3_512 = "fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39"
|
||||
"bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb";
|
||||
|
||||
static const fc::string TEST4_KEY = "0102030405060708090a0b0c0d0e0f10111213141516171819";
|
||||
static const fc::string TEST4_DATA = "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
|
||||
"cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd";
|
||||
static const fc::string TEST4_224 = "6c11506874013cac6a2abc1bb382627cec6a90d86efc012de7afec5a";
|
||||
static const fc::string TEST4_256 = "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b";
|
||||
static const fc::string TEST4_512 = "b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3db"
|
||||
"a91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd";
|
||||
|
||||
// test 5 skipped - truncated
|
||||
|
||||
static const fc::string TEST6_KEY = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
"aaaaaa";
|
||||
static const fc::string TEST6_DATA = "54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a"
|
||||
"65204b6579202d2048617368204b6579204669727374";
|
||||
static const fc::string TEST6_224 = "95e9a0db962095adaebe9b2d6f0dbce2d499f112f2d2b7273fa6870e";
|
||||
static const fc::string TEST6_256 = "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54";
|
||||
static const fc::string TEST6_512 = "80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f352"
|
||||
"6b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598";
|
||||
|
||||
static const fc::string TEST7_KEY = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
"aaaaaa";
|
||||
static const fc::string TEST7_DATA = "5468697320697320612074657374207573696e672061206c6172676572207468"
|
||||
"616e20626c6f636b2d73697a65206b657920616e642061206c61726765722074"
|
||||
"68616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565"
|
||||
"647320746f20626520686173686564206265666f7265206265696e6720757365"
|
||||
"642062792074686520484d414320616c676f726974686d2e";
|
||||
static const fc::string TEST7_224 = "3a854166ac5d9f023f54d517d0b39dbd946770db9c2b95c9f6f565d1";
|
||||
static const fc::string TEST7_256 = "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2";
|
||||
static const fc::string TEST7_512 = "e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944"
|
||||
"b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58";
|
||||
|
||||
static fc::hmac<fc::sha224> mac_224;
|
||||
static fc::hmac<fc::sha256> mac_256;
|
||||
static fc::hmac<fc::sha512> mac_512;
|
||||
|
||||
template<int N,int M>
|
||||
static void run_test( const fc::string& key, const fc::string& data, const fc::string& expect_224,
|
||||
const fc::string& expect_256, const fc::string& expect_512 )
|
||||
{
|
||||
|
||||
fc::array<char,N> key_arr;
|
||||
BOOST_CHECK_EQUAL( fc::from_hex( key, key_arr.begin(), key_arr.size() ), N );
|
||||
fc::array<char,M> data_arr;
|
||||
BOOST_CHECK_EQUAL( fc::from_hex( data, data_arr.begin(), data_arr.size() ), M );
|
||||
|
||||
BOOST_CHECK_EQUAL( mac_224.digest( key_arr.begin(), N, data_arr.begin(), M ).str(), expect_224 );
|
||||
BOOST_CHECK_EQUAL( mac_256.digest( key_arr.begin(), N, data_arr.begin(), M ).str(), expect_256 );
|
||||
BOOST_CHECK_EQUAL( mac_512.digest( key_arr.begin(), N, data_arr.begin(), M ).str(), expect_512 );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(hmac_test_1)
|
||||
{
|
||||
run_test<20,8>( TEST1_KEY, TEST1_DATA, TEST1_224, TEST1_256, TEST1_512 );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(hmac_test_2)
|
||||
{
|
||||
run_test<4,28>( TEST2_KEY, TEST2_DATA, TEST2_224, TEST2_256, TEST2_512 );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(hmac_test_3)
|
||||
{
|
||||
run_test<20,50>( TEST3_KEY, TEST3_DATA, TEST3_224, TEST3_256, TEST3_512 );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(hmac_test_4)
|
||||
{
|
||||
run_test<25,50>( TEST4_KEY, TEST4_DATA, TEST4_224, TEST4_256, TEST4_512 );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(hmac_test_6)
|
||||
{
|
||||
run_test<131,54>( TEST6_KEY, TEST6_DATA, TEST6_224, TEST6_256, TEST6_512 );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(hmac_test_7)
|
||||
{
|
||||
run_test<131,152>( TEST7_KEY, TEST7_DATA, TEST7_224, TEST7_256, TEST7_512 );
|
||||
}
|
||||
Loading…
Reference in a new issue