diff --git a/CMakeLists.txt b/CMakeLists.txt index 7eea482..c02f092 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -361,6 +361,7 @@ target_link_libraries( ecc_test fc ) add_executable( all_tests tests/all_tests.cpp tests/compress/compress.cpp tests/crypto/aes_test.cpp + tests/crypto/base_n_tests.cpp tests/crypto/blind.cpp tests/network/ntp_test.cpp tests/thread/task_cancel.cpp diff --git a/src/crypto/base32.cpp b/src/crypto/base32.cpp index 789a926..bb5354d 100644 --- a/src/crypto/base32.cpp +++ b/src/crypto/base32.cpp @@ -7,16 +7,17 @@ namespace fc { auto len = cyoBase32DecodeGetLength( b32.size() ); std::vector v(len); - cyoBase32Decode( v.data(), b32.c_str(), b32.size() ); + len = cyoBase32Decode( v.data(), b32.c_str(), b32.size() ); + v.resize( len ); return v; } std::string to_base32( const char* data, size_t len ) { - auto s = cyoBase16EncodeGetLength(len); + auto s = cyoBase32EncodeGetLength(len); std::vector b32; b32.resize(s); - cyoBase16Encode( b32.data(), data, len ); + cyoBase32Encode( b32.data(), data, len ); b32.resize( b32.size()-1); // strip the nullterm return std::string(b32.begin(),b32.end()); } diff --git a/src/crypto/base36.cpp b/src/crypto/base36.cpp index 44ce7b4..5a2f157 100644 --- a/src/crypto/base36.cpp +++ b/src/crypto/base36.cpp @@ -19,7 +19,9 @@ namespace fc out[pos] = base36[(value % _36).to_int64()]; } } while (value /= _36); - + while (*data++ == 0) { + out[--pos] = '0'; + } return &out[pos]; //fc::string( &out[pos], out.size() - pos); } @@ -30,21 +32,39 @@ namespace fc std::vector from_base36( const fc::string& b36 ) { + if ( b36.empty() ) { + std::vector empty; + return empty; + } + fc::bigint value; fc::bigint pos = 0; fc::bigint _36(36); - for( auto itr = b36.begin(); itr != b36.end(); ++itr ) + for( auto itr = b36.rbegin(); itr != b36.rend(); ++itr ) { - if( *itr - '0' < 10 ) value = value + _36.exp(pos) * fc::bigint(*itr - '0'); - else if( *itr - 'a' < 26 ) value = value + (_36.exp(pos) * fc::bigint(10+*itr - 'a')); - else if( *itr - 'A' < 26 ) value = value + (_36.exp(pos) * fc::bigint(10+*itr - 'A')); + if( *itr >= '0' && *itr <= '9' ) + value = value + _36.exp(pos) * fc::bigint(*itr - '0'); + else if( *itr >= 'a' && *itr <= 'z' ) + value = value + (_36.exp(pos) * fc::bigint(10+*itr - 'a')); + else if( *itr >= 'A' && *itr <= 'Z' ) + value = value + (_36.exp(pos) * fc::bigint(10+*itr - 'A')); else { wlog("unknown '${char}'", ("char",fc::string(&*itr,1)) ); } ++pos; } - return value; + + std::vector bytes = value; + int leading_zeros = 0, len = bytes.size(); + const char *in = b36.c_str(); + while (*in++ == '0') { leading_zeros++; } + char* first = bytes.data(); + while (*first == 0) { first++; len--; } + std::vector result; + result.resize(leading_zeros + len, 0); + memcpy( result.data() + leading_zeros, first, len ); + return result; } } diff --git a/tests/crypto/base_n_tests.cpp b/tests/crypto/base_n_tests.cpp new file mode 100644 index 0000000..206ced3 --- /dev/null +++ b/tests/crypto/base_n_tests.cpp @@ -0,0 +1,99 @@ +#include + +#include +#include +#include +#include + +#include + +static const std::string TEST1(""); +static const std::string TEST2("\0\00101", 4); +static const std::string TEST3("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + +static void test_32( const std::string& test, const std::string& expected ) +{ + std::vector vec( test.begin(), test.end() ); + fc::string enc1 = fc::to_base32( vec ); + fc::string enc2 = fc::to_base32( test.c_str(), test.size() ); + BOOST_CHECK_EQUAL( enc1, enc2 ); + BOOST_CHECK_EQUAL( expected, enc2 ); + + std::vector dec = fc::from_base32( enc1 ); + BOOST_CHECK_EQUAL( vec.size(), dec.size() ); + BOOST_CHECK( !memcmp( vec.data(), dec.data(), vec.size() ) ); +} + +BOOST_AUTO_TEST_SUITE(fc_crypto) + +BOOST_AUTO_TEST_CASE(base32_test) +{ + test_32( TEST1, "" ); + test_32( TEST2, "AAATAMI=" ); + test_32( TEST3, "IFBEGRCFIZDUQSKKJNGE2TSPKBIVEU2UKVLFOWCZLI======" ); +} + + +static void test_36( const std::string& test, const std::string& expected ) +{ + std::vector vec( test.begin(), test.end() ); + fc::string enc1 = fc::to_base36( vec ); + fc::string enc2 = fc::to_base36( test.c_str(), test.size() ); + BOOST_CHECK_EQUAL( enc1, enc2 ); + BOOST_CHECK_EQUAL( expected, enc2 ); + + std::vector dec = fc::from_base36( enc1 ); + BOOST_CHECK_EQUAL( vec.size(), dec.size() ); + BOOST_CHECK( !memcmp( vec.data(), dec.data(), vec.size() ) ); +} + +BOOST_AUTO_TEST_CASE(base36_test) +{ + test_36( TEST1, "" ); + test_36( TEST2, "01o35" ); + test_36( TEST3, "l4ksdleyi5pnl0un5raue268ptj43dwjwmz15ie2" ); +} + + +static void test_58( const std::string& test, const std::string& expected ) +{ + std::vector vec( test.begin(), test.end() ); + fc::string enc1 = fc::to_base58( vec ); + fc::string enc2 = fc::to_base58( test.c_str(), test.size() ); + BOOST_CHECK_EQUAL( enc1, enc2 ); + BOOST_CHECK_EQUAL( expected, enc2 ); + + std::vector dec = fc::from_base58( enc1 ); + BOOST_CHECK_EQUAL( vec.size(), dec.size() ); + BOOST_CHECK( !memcmp( vec.data(), dec.data(), vec.size() ) ); +} + +BOOST_AUTO_TEST_CASE(base58_test) +{ + test_58( TEST1, "" ); + test_58( TEST2, "1Q9e" ); + test_58( TEST3, "2zuFXTJSTRK6ESktqhM2QDBkCnH1U46CnxaD" ); +} + + +static void test_64( const std::string& test, const std::string& expected ) +{ + fc::string enc1 = fc::base64_encode( test ); + fc::string enc2 = fc::base64_encode( test.c_str(), test.size() ); + BOOST_CHECK_EQUAL( enc1, enc2 ); + BOOST_CHECK_EQUAL( expected, enc2 ); + + std::string dec = fc::base64_decode( enc1 ); + BOOST_CHECK_EQUAL( test.size(), dec.size() ); + BOOST_CHECK_EQUAL( test, dec ); +} + +BOOST_AUTO_TEST_CASE(base64_test) +{ + test_64( TEST1, "" ); + test_64( TEST2, "AAEwMQ==" ); + test_64( TEST3, "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo=" ); +} + + +BOOST_AUTO_TEST_SUITE_END()