From a94f4a1abec04d5af61954adeb26a3debb1db4a5 Mon Sep 17 00:00:00 2001 From: Dario Date: Mon, 9 Mar 2020 12:37:06 +0100 Subject: [PATCH] fix multiple hash error --- src/cpp/Crypto/mnemonic.cpp | 77 +++++++++++++++++++++++++++++++++++-- src/cpp/Crypto/mnemonic.h | 13 +++++-- src/cpp/ServerConfig.cpp | 1 + 3 files changed, 84 insertions(+), 7 deletions(-) diff --git a/src/cpp/Crypto/mnemonic.cpp b/src/cpp/Crypto/mnemonic.cpp index 8c5cb61fa..16faa3638 100644 --- a/src/cpp/Crypto/mnemonic.cpp +++ b/src/cpp/Crypto/mnemonic.cpp @@ -3,6 +3,7 @@ #include "mnemonic.h" #include #include +#include #include "../dependencies/tinf/src/tinf.h" #include "DRRandom.h" @@ -51,6 +52,11 @@ int Mnemonic::init(void(*fill_words_func)(unsigned char*), unsigned int original //printf("c[Mnemonic::%s] uncompressing success\n", __FUNCTION__); // fill words in array and hashList + + //FILE* f = fopen("uncompressed_buffer", "a"); + //fwrite(uncompressed_buffer, sizeof(char), original_size, f); + //fclose(f); + unsigned short cursor = 0; u32 word_begin = 0, word_end = 0; @@ -58,7 +64,7 @@ int Mnemonic::init(void(*fill_words_func)(unsigned char*), unsigned int original if (cursor >= 2048) { return -3; } - if (uncompressed_buffer[i] == ',') { + if (uncompressed_buffer[i] == ',' || i == original_size - 1) { word_end = i; u32 word_size = word_end - word_begin; @@ -67,12 +73,16 @@ int Mnemonic::init(void(*fill_words_func)(unsigned char*), unsigned int original //printf("%s\n", uncompressed_buffer); continue; } + if (uncompressed_buffer[i] != ',') { + //printf("last char: %c\n", uncompressed_buffer[i]); + word_size++; + } // + 1 for null terminating mWords[cursor] = (char*)malloc(word_size + 1); // fill hash list for fast reverse lookup memset(mWords[cursor], 0, word_size + 1); - if (word_begin + word_size >= original_size) { + if (word_begin + word_size > original_size) { printf("c[Mnemonic::%s] word goes out of array bounds\n", __FUNCTION__); free(uncompressed_buffer); return -4; @@ -80,12 +90,39 @@ int Mnemonic::init(void(*fill_words_func)(unsigned char*), unsigned int original memcpy(mWords[cursor], &uncompressed_buffer[word_begin], word_size); //char bu[256]; memset(bu, 0, 256); - //memcpy(bu, &uncompressed_buffer[word_begin - 1], 10); + //memcpy(bu, &uncompressed_buffer[word_begin - 1], 15); //printf("word (%d): %s\n", cursor, bu); DHASH word_hash = DRMakeStringHash(mWords[cursor]); //mWordHashIndices.addByHash(word_hash, (void*)cursor); - mWordHashIndices.insert(WordHashEntry(word_hash, cursor)); + auto result = mWordHashIndices.insert(WordHashEntry(word_hash, cursor)); + if (!result.second) { + // handle hash collision + auto it_collide = mHashCollisionWords.find(word_hash); + if (it_collide == mHashCollisionWords.end()) { + std::map collidedWordsMap; + collidedWordsMap.insert(HashCollideWordEntry(mWords[result.first->second], result.first->second)); + auto result2 = mHashCollisionWords.insert(std::pair>(word_hash, collidedWordsMap)); + if (!result2.second) { + free(uncompressed_buffer); + printf("c[Mnemonc::%s] error inserting hash collided word map\n", __FUNCTION__); + return -6; + } + it_collide = result2.first; + } + assert(it_collide != mHashCollisionWords.end()); + + auto result3 = it_collide->second.insert(HashCollideWordEntry(mWords[cursor], cursor)); + if (!result3.second) { + free(uncompressed_buffer); + printf("c[Mnemonc::%s] error inserting hash collided word entry\n", __FUNCTION__); + return -7; + } + + //printf("c[Mnemonic::%s] error inserting word, hash collision?\n", __FUNCTION__); + //printf("current word: %s\n", mWords[cursor]); + //printf("existing word: %s\n", mWords[result.first->second]); + } word_begin = i + 1; cursor++; @@ -93,6 +130,12 @@ int Mnemonic::init(void(*fill_words_func)(unsigned char*), unsigned int original } //printf("c[Mnemonic::%s] before freeing uncompressed buffer \n", __FUNCTION__); free(uncompressed_buffer); + + // remove hash colliding entrys from regular map + for (auto it_collide = mHashCollisionWords.begin(); it_collide != mHashCollisionWords.end(); it_collide++) { + mWordHashIndices.erase(it_collide->first); + } + return 0; } //printf("c[Mnemonic::%s] before freeing buffer \n", __FUNCTION__); @@ -100,6 +143,31 @@ int Mnemonic::init(void(*fill_words_func)(unsigned char*), unsigned int original return -5; } +short Mnemonic::getWordIndex(const char* word) const +{ + DHASH word_hash = DRMakeStringHash(word); + auto it = mWordHashIndices.find(word_hash); + if (it != mWordHashIndices.end()) { + return it->second; + } + auto it_collide = mHashCollisionWords.find(word_hash); + if (it_collide != mHashCollisionWords.end()) { + auto it_collided_word = it_collide->second.find(word); + if (it_collided_word != it_collide->second.end()) { + return it_collided_word->second; + } + } + return -1; +} + +/* +bool Mnemonic::isWordExist(const std::string& word) const +{ + return getWordIndex(word.data()) != -1; + //DHASH word_hash = DRMakeStringHash(word.data()); + //return mWordHashIndices.find(word_hash) != mWordHashIndices.end(); +} +*/ void Mnemonic::clear() { @@ -111,6 +179,7 @@ void Mnemonic::clear() } memset(mWords, 0, 2048); mWordHashIndices.clear(); + mHashCollisionWords.clear(); } std::string Mnemonic::getCompleteWordList() diff --git a/src/cpp/Crypto/mnemonic.h b/src/cpp/Crypto/mnemonic.h index 22cf753b3..216e122ee 100644 --- a/src/cpp/Crypto/mnemonic.h +++ b/src/cpp/Crypto/mnemonic.h @@ -30,9 +30,9 @@ public: int init(void(*fill_words_func)(unsigned char*), unsigned int original_size, unsigned int compressed_size); - inline const char* getWord(unsigned int index) const { if (index < 2048 && index >= 0) return mWords[index]; return nullptr; } - inline unsigned short getWordIndex(const char* word) const { DHASH word_hash = DRMakeStringHash(word); return mWordHashIndices.find(word_hash)->second; } - inline bool isWordExist(const std::string& word) const { DHASH word_hash = DRMakeStringHash(word.data()); return mWordHashIndices.find(word_hash) != mWordHashIndices.end(); } + inline const char* getWord(short index) const { if (index < 2048 && index >= 0) return mWords[index]; return nullptr; } + short getWordIndex(const char* word) const; + inline bool isWordExist(const std::string& word) const { return getWordIndex(word.data()) != -1; } // using only for debugging std::string getCompleteWordList(); @@ -44,10 +44,17 @@ protected: void clear(); + struct HashCollisionWords { + DHASH hash; + std::vector words; + }; + char* mWords[2048]; //DRHashList mWordHashIndices; typedef std::pair WordHashEntry; + typedef std::pair HashCollideWordEntry; std::map mWordHashIndices; + std::map> mHashCollisionWords; Poco::Mutex mWorkingMutex; }; diff --git a/src/cpp/ServerConfig.cpp b/src/cpp/ServerConfig.cpp index 48d8b0797..a94f73572 100644 --- a/src/cpp/ServerConfig.cpp +++ b/src/cpp/ServerConfig.cpp @@ -66,6 +66,7 @@ namespace ServerConfig { printf("[%s] error init bip0039 mnemonic set, error nr: %d\n", __FUNCTION__, iResult); return false; } + //g_Mnemonic_WordLists[i].printToFile("en_words.txt"); break; default: printf("[%s] unknown MnemonicType\n", __FUNCTION__); return false; }