From ecf11a5db21ae49f64d7f9d23da883ba0d7395f9 Mon Sep 17 00:00:00 2001 From: Alex Zolotarev Date: Sun, 13 Mar 2011 20:26:36 +0000 Subject: [PATCH] Added coding/sha2.hpp and coding/base64.hpp Unique user ID now calculated as sha224 + base64 --- 3party/tomcrypt/tomcrypt.pro | 4 +- coding/base64.cpp | 25 ++++++++ coding/base64.hpp | 9 +++ coding/coding.pro | 8 ++- coding/coding_tests/base64_test.cpp | 24 ++++++++ coding/coding_tests/coding_tests.pro | 4 +- coding/coding_tests/sha2_test.cpp | 40 ++++++++++++ coding/hex.hpp | 4 +- coding/sha2.cpp | 72 ++++++++++++++++++++++ coding/sha2.hpp | 30 +++++++++ iphone/Maps/Maps.xcodeproj/project.pbxproj | 20 ++++++ iphone/Maps/Platform/IPhoneDownload.mm | 20 +++--- platform/platform.pro | 4 +- platform/qt_download.cpp | 18 ++---- 14 files changed, 249 insertions(+), 33 deletions(-) create mode 100644 coding/base64.cpp create mode 100644 coding/base64.hpp create mode 100644 coding/coding_tests/base64_test.cpp create mode 100644 coding/coding_tests/sha2_test.cpp create mode 100644 coding/sha2.cpp create mode 100644 coding/sha2.hpp diff --git a/3party/tomcrypt/tomcrypt.pro b/3party/tomcrypt/tomcrypt.pro index eee3c3c9cb..5b8764978a 100644 --- a/3party/tomcrypt/tomcrypt.pro +++ b/3party/tomcrypt/tomcrypt.pro @@ -10,8 +10,10 @@ CONFIG += staticlib DEFINES += LTC_NO_ROLC SOURCES += \ + src/hashes/sha2/sha224.c \ src/hashes/sha2/sha256.c \ - src/hashes/sha1.c \ + src/hashes/sha2/sha384.c \ + src/hashes/sha2/sha512.c \ HEADERS += \ src/headers/tomcrypt.h \ diff --git a/coding/base64.cpp b/coding/base64.cpp new file mode 100644 index 0000000000..86b2346c93 --- /dev/null +++ b/coding/base64.cpp @@ -0,0 +1,25 @@ +#include "base64.hpp" + +#include +#include +#include + +using namespace boost::archive::iterators; +typedef base64_from_binary > base64_t; +typedef transform_width, 8, 6 > binary_t; + +namespace base64 +{ + string encode(string const & rawBytes) + { + return string(base64_t(rawBytes.begin()), base64_t(rawBytes.end())); + } + + string decode(string const & base64Chars) + { + if (base64Chars.empty()) + return string(); + // minus 1 needed to avoid finishing zero in a string + return string(binary_t(base64Chars.begin()), binary_t(base64Chars.begin() + base64Chars.size() - 1)); + } +} diff --git a/coding/base64.hpp b/coding/base64.hpp new file mode 100644 index 0000000000..35003b12e0 --- /dev/null +++ b/coding/base64.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include "../std/string.hpp" + +namespace base64 +{ + string encode(string const & rawBytes); + string decode(string const & base64Chars); +} diff --git a/coding/coding.pro b/coding/coding.pro index ed831031be..71f257ffba 100644 --- a/coding/coding.pro +++ b/coding/coding.pro @@ -4,10 +4,12 @@ TEMPLATE = lib CONFIG += staticlib ROOT_DIR = .. -DEPENDENCIES = bzip2 zlib base +DEPENDENCIES = base bzip2 zlib tomcrypt include($$ROOT_DIR/common.pri) +INCLUDEPATH += ../3party/tomcrypt/src/headers + SOURCES += \ hex.cpp \ file_reader.cpp \ @@ -17,6 +19,8 @@ SOURCES += \ bzip2_compressor.cpp \ gzip_compressor.cpp \ timsort/timsort.cpp \ + base64.cpp \ + sha2.cpp \ HEADERS += \ internal/xmlparser.h \ @@ -70,3 +74,5 @@ HEADERS += \ gzip_compressor.hpp \ timsort/timsort.hpp \ bit_shift.hpp \ + base64.hpp \ + sha2.hpp \ diff --git a/coding/coding_tests/base64_test.cpp b/coding/coding_tests/base64_test.cpp new file mode 100644 index 0000000000..a2ccb1bff3 --- /dev/null +++ b/coding/coding_tests/base64_test.cpp @@ -0,0 +1,24 @@ +#include "../../base/SRC_FIRST.hpp" +#include "../../testing/testing.hpp" + +#include "../base64.hpp" + +UNIT_TEST(Base64_Encode) +{ + TEST_EQUAL(base64::encode("Hello, world!"), "SGVsbG8sIHdvcmxkIQ", ()); + TEST_EQUAL(base64::encode(""), "", ()); + TEST_EQUAL(base64::encode("$"), "JA", ()); + TEST_EQUAL(base64::encode("MapsWithMe is an offline maps application for any device in the world."), + "TWFwc1dpdGhNZSBpcyBhbiBvZmZsaW5lIG1hcHMgYXBwbGljYXRpb24gZm9yIGFueSBkZXZpY2Ug" + "aW4gdGhlIHdvcmxkLg", ()); +} + +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.", ()); +} diff --git a/coding/coding_tests/coding_tests.pro b/coding/coding_tests/coding_tests.pro index 14a2d24573..ea22eaab3c 100644 --- a/coding/coding_tests/coding_tests.pro +++ b/coding/coding_tests/coding_tests.pro @@ -5,7 +5,7 @@ CONFIG -= app_bundle TEMPLATE = app ROOT_DIR = ../.. -DEPENDENCIES = coding base bzip2 zlib +DEPENDENCIES = coding base bzip2 zlib tomcrypt include($$ROOT_DIR/common.pri) @@ -32,6 +32,8 @@ SOURCES += ../../testing/testingmain.cpp \ gzip_test.cpp \ coder_util_test.cpp \ bit_shift_test.cpp \ + base64_test.cpp \ + sha2_test.cpp HEADERS += \ reader_test.hpp \ diff --git a/coding/coding_tests/sha2_test.cpp b/coding/coding_tests/sha2_test.cpp new file mode 100644 index 0000000000..a208d98d45 --- /dev/null +++ b/coding/coding_tests/sha2_test.cpp @@ -0,0 +1,40 @@ +#include "../../base/SRC_FIRST.hpp" +#include "../../testing/testing.hpp" + +#include "../sha2.hpp" + +UNIT_TEST(Sha2_224) +{ + TEST_EQUAL(sha2::digest224("Hello, world!"), + "8552D8B7A7DC5476CB9E25DEE69A8091290764B7F2A64FE6E78E9568", ()); + TEST_EQUAL(sha2::digest224(""), + "D14A028C2A3A2BC9476102BB288234C415A2B01F828EA62AC5B3E42F", ()); +} + +UNIT_TEST(Sha2_256) +{ + TEST_EQUAL(sha2::digest256("Hello, world!"), + "315F5BDB76D078C43B8AC0064E4A0164612B1FCE77C869345BFC94C75894EDD3", ()); + TEST_EQUAL(sha2::digest256(""), + "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855", ()); +} + +UNIT_TEST(Sha2_384) +{ + TEST_EQUAL(sha2::digest384("Hello, world!"), + "55BC556B0D2FE0FCE582BA5FE07BAAFFF035653638C7AC0D5494C2A64C0BEA1CC" + "57331C7C12A45CDBCA7F4C34A089EEB", ()); + TEST_EQUAL(sha2::digest384(""), + "38B060A751AC96384CD9327EB1B1E36A21FDB71114BE07434C0CC7BF63F6E1DA2" + "74EDEBFE76F65FBD51AD2F14898B95B", ()); +} + +UNIT_TEST(Sha2_512) +{ + TEST_EQUAL(sha2::digest512(""), + "CF83E1357EEFB8BDF1542850D66D8007D620E4050B5715DC83F4A921D36CE9CE" + "47D0D13C5D85F2B0FF8318D2877EEC2F63B931BD47417A81A538327AF927DA3E", ()); + TEST_EQUAL(sha2::digest512("Hello, world!"), + "C1527CD893C124773D811911970C8FE6E857D6DF5DC9226BD8A160614C0CD963" + "A4DDEA2B94BB7D36021EF9D865D5CEA294A82DD49A0BB269F51F6E7A57F79421", ()); +} diff --git a/coding/hex.hpp b/coding/hex.hpp index aa559498f5..f20eea3f9b 100644 --- a/coding/hex.hpp +++ b/coding/hex.hpp @@ -1,9 +1,9 @@ #pragma once #include "../base/base.hpp" -#include "../std/string.hpp" +#include "../base/assert.hpp" -#include "../base/start_mem_debug.hpp" +#include "../std/string.hpp" #include diff --git a/coding/sha2.cpp b/coding/sha2.cpp new file mode 100644 index 0000000000..d71dd6667c --- /dev/null +++ b/coding/sha2.cpp @@ -0,0 +1,72 @@ +#include "sha2.hpp" +#include "hex.hpp" + +#include + +namespace sha2 +{ + string digest224(char const * data, size_t dataSize, bool returnAsHexString) + { + hash_state md; + unsigned char out[MAXBLOCKSIZE + 1] = { 0 }; + if (CRYPT_OK == sha224_init(&md) + && CRYPT_OK == sha224_process(&md, reinterpret_cast(data), dataSize) + && CRYPT_OK == sha224_done(&md, out)) + { + if (returnAsHexString) + return ToHex(string(reinterpret_cast(out))); + else + return string(reinterpret_cast(out)); + } + return string(); + } + + string digest256(char const * data, size_t dataSize, bool returnAsHexString) + { + hash_state md; + unsigned char out[MAXBLOCKSIZE + 1] = { 0 }; + if (CRYPT_OK == sha256_init(&md) + && CRYPT_OK == sha256_process(&md, reinterpret_cast(data), dataSize) + && CRYPT_OK == sha256_done(&md, out)) + { + if (returnAsHexString) + return ToHex(string(reinterpret_cast(out))); + else + return string(reinterpret_cast(out)); + } + return string(); + } + + string digest384(char const * data, size_t dataSize, bool returnAsHexString) + { + hash_state md; + unsigned char out[MAXBLOCKSIZE + 1] = { 0 }; + if (CRYPT_OK == sha384_init(&md) + && CRYPT_OK == sha384_process(&md, reinterpret_cast(data), dataSize) + && CRYPT_OK == sha384_done(&md, out)) + { + if (returnAsHexString) + return ToHex(string(reinterpret_cast(out))); + else + return string(reinterpret_cast(out)); + } + return string(); + } + + string digest512(char const * data, size_t dataSize, bool returnAsHexString) + { + hash_state md; + unsigned char out[MAXBLOCKSIZE + 1] = { 0 }; + if (CRYPT_OK == sha512_init(&md) + && CRYPT_OK == sha512_process(&md, reinterpret_cast(data), dataSize) + && CRYPT_OK == sha512_done(&md, out)) + { + if (returnAsHexString) + return ToHex(string(reinterpret_cast(out))); + else + return string(reinterpret_cast(out)); + } + return string(); + } +} + diff --git a/coding/sha2.hpp b/coding/sha2.hpp new file mode 100644 index 0000000000..a0661b7dff --- /dev/null +++ b/coding/sha2.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include "../std/string.hpp" + +namespace sha2 +{ + string digest224(char const * data, size_t dataSize, bool returnAsHexString); + inline string digest224(string const & data, bool returnAsHexString = true) + { + return digest224(data.c_str(), data.size(), returnAsHexString); + } + + string digest256(char const * data, size_t dataSize, bool returnAsHexString); + inline string digest256(string const & data, bool returnAsHexString = true) + { + return digest256(data.c_str(), data.size(), returnAsHexString); + } + + string digest384(char const * data, size_t dataSize, bool returnAsHexString); + inline string digest384(string const & data, bool returnAsHexString = true) + { + return digest384(data.c_str(), data.size(), returnAsHexString); + } + + string digest512(char const * data, size_t dataSize, bool returnAsHexString); + inline string digest512(string const & data, bool returnAsHexString = true) + { + return digest512(data.c_str(), data.size(), returnAsHexString); + } +} diff --git a/iphone/Maps/Maps.xcodeproj/project.pbxproj b/iphone/Maps/Maps.xcodeproj/project.pbxproj index a6d973654b..bb27a0d812 100644 --- a/iphone/Maps/Maps.xcodeproj/project.pbxproj +++ b/iphone/Maps/Maps.xcodeproj/project.pbxproj @@ -75,6 +75,7 @@ FA500588128907F0002961F0 /* visibility.txt in Resources */ = {isa = PBXBuildFile; fileRef = FA500587128907F0002961F0 /* visibility.txt */; }; FA57ADF412F338FB002BFB9D /* countries_poly.txt in Resources */ = {isa = PBXBuildFile; fileRef = FA57ADF312F338FB002BFB9D /* countries_poly.txt */; }; FA87151B12B1518F00592DAF /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA87151A12B1518F00592DAF /* SystemConfiguration.framework */; }; + FA8F8938132D5DB00048E3FE /* libtomcrypt.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FA8F8937132D5DB00048E3FE /* libtomcrypt.a */; }; FAF37EFF126DCE6F005EA154 /* IPhoneDownload.mm in Sources */ = {isa = PBXBuildFile; fileRef = FAF37EFA126DCE6F005EA154 /* IPhoneDownload.mm */; }; FAF37F00126DCE6F005EA154 /* IPhoneDownloadManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = FAF37EFB126DCE6F005EA154 /* IPhoneDownloadManager.mm */; }; FAF37F01126DCE6F005EA154 /* IPhonePlatform.mm in Sources */ = {isa = PBXBuildFile; fileRef = FAF37EFD126DCE6F005EA154 /* IPhonePlatform.mm */; }; @@ -162,6 +163,7 @@ FA500587128907F0002961F0 /* visibility.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = visibility.txt; path = ../../data/visibility.txt; sourceTree = SOURCE_ROOT; }; FA57ADF312F338FB002BFB9D /* countries_poly.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = countries_poly.txt; path = ../../data/countries_poly.txt; sourceTree = SOURCE_ROOT; }; FA87151A12B1518F00592DAF /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; + FA8F8937132D5DB00048E3FE /* libtomcrypt.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libtomcrypt.a; path = libtomcrypt.a; sourceTree = SOURCE_ROOT; }; FAF37EFA126DCE6F005EA154 /* IPhoneDownload.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = IPhoneDownload.mm; path = Platform/IPhoneDownload.mm; sourceTree = SOURCE_ROOT; }; FAF37EFB126DCE6F005EA154 /* IPhoneDownloadManager.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = IPhoneDownloadManager.mm; path = Platform/IPhoneDownloadManager.mm; sourceTree = SOURCE_ROOT; }; FAF37EFD126DCE6F005EA154 /* IPhonePlatform.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = IPhonePlatform.mm; path = Platform/IPhonePlatform.mm; sourceTree = SOURCE_ROOT; }; @@ -191,6 +193,7 @@ FA87151B12B1518F00592DAF /* SystemConfiguration.framework in Frameworks */, FA04373212CAB83F00017494 /* libstorage.a in Frameworks */, EEF5745512DE1AD50082F472 /* libfribidi.a in Frameworks */, + FA8F8938132D5DB00048E3FE /* libtomcrypt.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -332,6 +335,7 @@ FA1DE68411E15D4E00C6D69A /* Static Libraries */ = { isa = PBXGroup; children = ( + FA8F8937132D5DB00048E3FE /* libtomcrypt.a */, EEF5745412DE1AD50082F472 /* libfribidi.a */, FA04373112CAB83F00017494 /* libstorage.a */, EE1201FF11CD464100ABDD5D /* libbase.a */, @@ -495,6 +499,10 @@ 1D6058940D05DD3E006BFB54 /* Simulator Debug */ = { isa = XCBuildConfiguration; buildSettings = { + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(DEVELOPER_DIR)/omim/omim-iphone-build/out/release\"", + ); }; name = "Simulator Debug"; }; @@ -589,6 +597,10 @@ FA1DE83211E2205400C6D69A /* Simulator Release */ = { isa = XCBuildConfiguration; buildSettings = { + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(DEVELOPER_DIR)/omim/omim-iphone-build/out/release\"", + ); }; name = "Simulator Release"; }; @@ -641,6 +653,10 @@ FA1DE85A11E2235D00C6D69A /* Device Debug */ = { isa = XCBuildConfiguration; buildSettings = { + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(DEVELOPER_DIR)/omim/omim-iphone-build/out/release\"", + ); }; name = "Device Debug"; }; @@ -694,6 +710,10 @@ FA1DE85C11E2236200C6D69A /* Device Release */ = { isa = XCBuildConfiguration; buildSettings = { + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(DEVELOPER_DIR)/omim/omim-iphone-build/out/release\"", + ); }; name = "Device Release"; }; diff --git a/iphone/Maps/Platform/IPhoneDownload.mm b/iphone/Maps/Platform/IPhoneDownload.mm index 2f6d9931ba..a8053bfa2c 100644 --- a/iphone/Maps/Platform/IPhoneDownload.mm +++ b/iphone/Maps/Platform/IPhoneDownload.mm @@ -1,9 +1,10 @@ #import "IPhoneDownload.h" -#import - #include "../../platform/download_manager.hpp" +#include "../../coding/base64.hpp" +#include "../../coding/sha2.hpp" + #include #include #include @@ -30,16 +31,11 @@ NSString * GetEncryptedMac() && ((const struct sockaddr_dl *) currentAddr->ifa_addr)->sdl_type == IFT_ETHER) { const struct sockaddr_dl * dlAddr = (const struct sockaddr_dl *) currentAddr->ifa_addr; - const uint8_t * base = (const uint8_t *) &dlAddr->sdl_data[dlAddr->sdl_nlen]; - // generate sha1 hash for mac address - uint8_t outHash[CC_SHA1_DIGEST_LENGTH + 1] = { 0 }; - CC_SHA1(base, dlAddr->sdl_alen, outHash); - - NSMutableString * output = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2]; - - for (int i = 0; i < CC_SHA1_DIGEST_LENGTH; ++i) - [output appendFormat:@"%02x", outHash[i]]; - return output; + const char * base = &dlAddr->sdl_data[dlAddr->sdl_nlen]; + // generate sha2 hash for mac address + string const hash = sha2::digest224(base, dlAddr->sdl_alen, false); + // and use base64 encoding + return [NSString stringWithUTF8String: base64::encode(hash).c_str()]; } currentAddr = currentAddr->ifa_next; } diff --git a/platform/platform.pro b/platform/platform.pro index 775dd21d35..a7d9c5dceb 100644 --- a/platform/platform.pro +++ b/platform/platform.pro @@ -5,12 +5,10 @@ TEMPLATE = lib CONFIG += staticlib ROOT_DIR = .. -DEPENDENCIES = base tomcrypt +DEPENDENCIES = coding base include($$ROOT_DIR/common.pri) -INCLUDEPATH += ../3party/tomcrypt/src/headers - QT *= core network SOURCES += \ diff --git a/platform/qt_download.cpp b/platform/qt_download.cpp index 99a3f6b7f3..9cca18126c 100644 --- a/platform/qt_download.cpp +++ b/platform/qt_download.cpp @@ -4,9 +4,10 @@ #include "../base/logging.hpp" #include "../base/assert.hpp" -#include "../std/target_os.hpp" +#include "../coding/sha2.hpp" +#include "../coding/base64.hpp" -#include +#include "../std/target_os.hpp" #include #include @@ -63,17 +64,8 @@ static QString UniqueClientId() } // calculate one-way hash QByteArray const original = QByteArray::fromHex(result.toLocal8Bit()); - unsigned char out[100] = { 0 }; - hash_state md; - if (CRYPT_OK == sha1_init(&md) - && CRYPT_OK == sha1_process(&md, reinterpret_cast(original.constData()), - original.size()) - && CRYPT_OK == sha1_done(&md, out)) - { - return QByteArray(reinterpret_cast(out)).toHex(); - } - // if encryption failed, do not encrypt data - return result; + string const hash = sha2::digest224(original.constData(), original.size(), false); + return base64::encode(hash).c_str(); } static QString UserAgent()