diff --git a/3party/tomcrypt/tomcrypt.pro b/3party/tomcrypt/tomcrypt.pro index 79e3d8f0b5..55f72fad24 100644 --- a/3party/tomcrypt/tomcrypt.pro +++ b/3party/tomcrypt/tomcrypt.pro @@ -11,6 +11,9 @@ DEFINES += LTC_NO_ROLC SOURCES += \ src/hashes/sha2/sha256.c \ + src/misc/base64/base64_decode.c \ + src/misc/base64/base64_encode.c \ HEADERS += \ src/headers/tomcrypt.h \ + src/headers/tomcrypt_misc.h \ diff --git a/coding/base64.cpp b/coding/base64.cpp index f80c483139..6b6681382a 100644 --- a/coding/base64.cpp +++ b/coding/base64.cpp @@ -1,5 +1,9 @@ #include "base64.hpp" +#include "../3party/tomcrypt/src/headers/tomcrypt.h" +#include "../3party/tomcrypt/src/headers/tomcrypt_misc.h" +#include "../base/assert.hpp" + #include #include #include @@ -35,3 +39,44 @@ namespace base64_for_user_ids return string(binary_t(base64Chars.begin()), binary_t(base64Chars.begin() + base64Chars.size() - 1)); } } + +namespace base64 +{ + +string Encode(string const & bytesToEncode) +{ + string result; + long unsigned int resSize = (bytesToEncode.size() + 3) * 4 / 3; + // Raw new/delete because we don't throw exceptions inbetween + unsigned char * buffer = new unsigned char[resSize]; + if (CRYPT_OK == base64_encode(reinterpret_cast(bytesToEncode.data()), + bytesToEncode.size(), + buffer, + &resSize)) + result.assign(reinterpret_cast(buffer), resSize); + else + ASSERT(false, ("It should work!")); + + delete[] buffer; + return result; +} + +string Decode(string const & base64CharsToDecode) +{ + string result; + long unsigned int resSize = base64CharsToDecode.size() * 3 / 4 + 2; + // Raw new/delete because we don't throw exceptions inbetween + unsigned char * buffer = new unsigned char[resSize]; + if (CRYPT_OK == base64_decode(reinterpret_cast(base64CharsToDecode.data()), + base64CharsToDecode.size(), + buffer, + &resSize)) + result.assign(reinterpret_cast(buffer), resSize); + else + ASSERT(false, ("It should work!")); + + delete[] buffer; + return result; +} + +} diff --git a/coding/base64.hpp b/coding/base64.hpp index e9a4081a8e..5ae58c69ed 100644 --- a/coding/base64.hpp +++ b/coding/base64.hpp @@ -1,7 +1,16 @@ #pragma once +#include "../std/vector.hpp" #include "../std/string.hpp" +namespace base64 +{ + +string Encode(string const & bytesToEncode); +string Decode(string const & base64CharsToDecode); + +} + /// This namespace contains historically invalid implementation of base64, /// but it's still needed for production code namespace base64_for_user_ids diff --git a/coding/coding_tests/base64_test.cpp b/coding/coding_tests/base64_test.cpp index f96016b4bc..56bf7a9b2e 100644 --- a/coding/coding_tests/base64_test.cpp +++ b/coding/coding_tests/base64_test.cpp @@ -5,46 +5,27 @@ #include "../base64.hpp" -UNIT_TEST(Base64_Encode) -{ - TEST_EQUAL(base64::encode("Hello, world!"), "SGVsbG8sIHdvcmxkITAw", ()); - TEST_EQUAL(base64::encode(""), "", ()); - TEST_EQUAL(base64::encode("$"), "JDAw", ()); - TEST_EQUAL(base64::encode("MapsWithMe is an offline maps application for any device in the world."), - "TWFwc1dpdGhNZSBpcyBhbiBvZmZsaW5lIG1hcHMgYXBwbGljYXRpb24gZm9yIGFueSBkZXZpY2Ug" - "aW4gdGhlIHdvcmxkLjAw", ()); -} -UNIT_TEST(Base64_Decode) -{ - TEST_EQUAL(base64::decode("SGVsbG8sIHdvcmxkIQ"), "Hello, world!", ()); - TEST_EQUAL(base64::decode(""), "", ()); - TEST_EQUAL(base64::decode("JA"), "$", ()); - TEST_EQUAL(base64::decode("TWFwc1dpdGhNZSBpcyBhbiBvZmZsaW5lIG1hcHMgYXBwbGljYXRpb24gZm9yIGFueSBkZXZpY2Ug" - "aW4gdGhlIHdvcmxkLg"), - "MapsWithMe is an offline maps application for any device in the world.", ()); -} +using namespace base64; -UNIT_TEST(Base64_QualityTest) +UNIT_TEST(Base64_Smoke) { - size_t const NUMBER_OF_TESTS = 10000; - LCG32 generator(NUMBER_OF_TESTS); - for (size_t i = 0; i < NUMBER_OF_TESTS; ++i) + char const * bytes[] = {"H", "He", "Hel", "Hell", "Hello", "Hello,", "Hello, ", "Hello, World!"}; + char const * encoded[] = {"SA==", "SGU=", "SGVs", "SGVsbA==", "SGVsbG8=", "SGVsbG8s", + "SGVsbG8sIA==", "SGVsbG8sIFdvcmxkIQ=="}; + + TEST_EQUAL(ARRAY_SIZE(bytes), ARRAY_SIZE(encoded), ()); + + for (size_t i = 0; i < ARRAY_SIZE(bytes); ++i) { - string randomBytes; - for (size_t j = 0 ; j < 8; ++j) - { - if (j == 4) - { - randomBytes.push_back('\0'); - continue; - } - randomBytes.push_back(static_cast(generator.Generate())); - } - string const result = base64::encode(randomBytes); - TEST_GREATER_OR_EQUAL(result.size(), randomBytes.size(), - (randomBytes, result)); - for (size_t i = 0; i < result.size(); ++i) - TEST_NOT_EQUAL(result[i], 0, ()); + TEST_EQUAL(Encode(bytes[i]), encoded[i], ()); + TEST_EQUAL(Decode(encoded[i]), bytes[i], ()); + TEST_EQUAL(Decode(Encode(bytes[i])), bytes[i], ()); + TEST_EQUAL(Encode(Decode(encoded[i])), encoded[i], ()); } + + char const * str = "MapsWithMe is the offline maps application for any device in the world."; + char const * encStr = "TWFwc1dpdGhNZSBpcyB0aGUgb2ZmbGluZSBtYXBzIGFwcGxpY2F0aW9uIGZvciBhbnkgZGV2aWNlIGluIHRoZSB3b3JsZC4="; + TEST_EQUAL(Encode(str), encStr, ()); + TEST_EQUAL(Decode(encStr), str, ()); } diff --git a/coding/coding_tests/coding_tests.pro b/coding/coding_tests/coding_tests.pro index 226fb3ece2..2eb6cf7ffe 100644 --- a/coding/coding_tests/coding_tests.pro +++ b/coding/coding_tests/coding_tests.pro @@ -32,6 +32,7 @@ SOURCES += ../../testing/testingmain.cpp \ gzip_test.cpp \ coder_util_test.cpp \ bit_shift_test.cpp \ + base64_test.cpp \ base64_for_user_id_test.cpp \ sha2_test.cpp \ value_opt_string_test.cpp \