diff --git a/CMakeLists.txt b/CMakeLists.txt index e269e91..d56f86d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ PROJECT( fc ) CMAKE_MINIMUM_REQUIRED( VERSION 2.8.0 ) -SET( CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMakeModules;${CMAKE_MODULE_PATH}" ) +SET( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules;${CMAKE_MODULE_PATH}" ) INCLUDE( VersionMacros ) INCLUDE( SetupTargetMacros ) @@ -40,7 +40,7 @@ endif() option( UNITY_BUILD OFF ) FIND_PACKAGE( OpenSSL ) -#FIND_PACKAGE( ZLIB ) +FIND_PACKAGE( ZLIB ) include_directories( vendor/zlib-1.2.7/) include_directories( vendor/libssh2-1.4.2/include ) @@ -83,6 +83,7 @@ set( sources src/thread.cpp src/hex.cpp src/sha1.cpp + src/sha256.cpp src/filesystem.cpp src/ip.cpp src/bigint.cpp diff --git a/include/fc/sha256.hpp b/include/fc/sha256.hpp new file mode 100644 index 0000000..1b04db5 --- /dev/null +++ b/include/fc/sha256.hpp @@ -0,0 +1,69 @@ +#pragma once +#include +#include +#include + +namespace fc { + class path; + + class sha256 { + public: + sha256(); + explicit sha256( const fc::string& hex_str ); + + fc::string str()const; + + operator fc::string()const; + + char* data()const; + + static sha256 hash( const char* d, uint32_t dlen ); + static sha256 hash( const fc::string& ); + static sha256 hash( const fc::path& ); + + template + static sha256 hash( const T& t ) { sha256::encoder e; e << t; return e.result(); } + + class encoder { + public: + encoder(); + ~encoder(); + + void write( const char* d, uint32_t dlen ); + void put( char c ) { write( &c, 1 ); } + void reset(); + sha256 result(); + + private: + struct impl; + fwd my; + }; + + template + inline friend T& operator<<( T& ds, const sha256& ep ) { + ds.write( ep.data(), sizeof(ep) ); + return ds; + } + + template + inline friend T& operator>>( T& ds, sha256& ep ) { + ds.read( ep.data(), sizeof(ep) ); + return ds; + } + friend sha256 operator << ( const sha256& h1, uint32_t i ); + friend bool operator == ( const sha256& h1, const sha256& h2 ); + friend bool operator != ( const sha256& h1, const sha256& h2 ); + friend sha256 operator ^ ( const sha256& h1, const sha256& h2 ); + friend bool operator >= ( const sha256& h1, const sha256& h2 ); + friend bool operator > ( const sha256& h1, const sha256& h2 ); + friend bool operator < ( const sha256& h1, const sha256& h2 ); + + uint64_t _hash[4]; + }; + + class value; + void pack( fc::value& , const fc::sha256& ); + void unpack( const fc::value& , fc::sha256& ); +} + + diff --git a/src/sha256.cpp b/src/sha256.cpp new file mode 100644 index 0000000..7473839 --- /dev/null +++ b/src/sha256.cpp @@ -0,0 +1,105 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace fc { + + sha256::sha256() { memset( _hash, 0, sizeof(_hash) ); } + sha256::sha256( const fc::string& hex_str ) { + fc::from_hex( hex_str, (char*)_hash, sizeof(_hash) ); + } + + fc::string sha256::str()const { + return to_hex( (char*)_hash, sizeof(_hash) ); + } + sha256::operator fc::string()const { return str(); } + + char* sha256::data()const { return (char*)&_hash[0]; } + + + struct sha256::encoder::impl { + SHA_CTX ctx; + }; + + sha256::encoder::~encoder() {} + sha256::encoder::encoder() { + reset(); + } + + sha256 sha256::hash( const char* d, uint32_t dlen ) { + encoder e; + e.write(d,dlen); + return e.result(); + } + sha256 sha256::hash( const fc::string& s ) { + return hash( s.c_str(), s.size() ); + } + sha256 sha256::hash( const fc::path& s ) { + file_mapping fmap( s.string().c_str(), read_only ); + size_t fsize = file_size(s); + mapped_region mr( fmap, fc::read_only, 0, fsize ); + + const char* pos = reinterpret_cast(mr.get_address()); + return hash( pos, fsize ); + } + + void sha256::encoder::write( const char* d, uint32_t dlen ) { + SHA1_Update( &my->ctx, d, dlen); + } + sha256 sha256::encoder::result() { + sha256 h; + SHA1_Final((uint8_t*)h.data(), &my->ctx ); + return h; + } + void sha256::encoder::reset() { + SHA1_Init( &my->ctx); + } + + fc::sha256 operator << ( const fc::sha256& h1, uint32_t i ) { + fc::sha256 result; + uint8_t* r = (uint8_t*)result._hash; + uint8_t* s = (uint8_t*)h1._hash; + for( uint32_t p = 0; p < sizeof(h1._hash)-1; ++p ) + r[p] = s[p] << i | (s[p+1]>>(8-i)); + r[31] = s[31] << i; + return result; + } + fc::sha256 operator ^ ( const fc::sha256& h1, const fc::sha256& h2 ) { + fc::sha256 result; + result._hash[0] = h1._hash[0] ^ h2._hash[0]; + result._hash[1] = h1._hash[1] ^ h2._hash[1]; + result._hash[2] = h1._hash[2] ^ h2._hash[2]; + result._hash[3] = h1._hash[3] ^ h2._hash[3]; + return result; + } + bool operator >= ( const fc::sha256& h1, const fc::sha256& h2 ) { + return memcmp( h1._hash, h2._hash, sizeof(h1._hash) ) >= 0; + } + bool operator > ( const fc::sha256& h1, const fc::sha256& h2 ) { + return memcmp( h1._hash, h2._hash, sizeof(h1._hash) ) > 0; + } + bool operator < ( const fc::sha256& h1, const fc::sha256& h2 ) { + return memcmp( h1._hash, h2._hash, sizeof(h1._hash) ) < 0; + } + bool operator != ( const fc::sha256& h1, const fc::sha256& h2 ) { + return memcmp( h1._hash, h2._hash, sizeof(h1._hash) ) != 0; + } + bool operator == ( const fc::sha256& h1, const fc::sha256& h2 ) { + return memcmp( h1._hash, h2._hash, sizeof(h1._hash) ) == 0; + } + + void pack( fc::value& v, const fc::sha256& s ) { + v = fc::string(s); + } + void unpack( const fc::value& v, fc::sha256& s ) { + s = sha256(fc::value_cast(v)); + } + +} // namespace fc +