From 28c2830d7599a5fbeee237533ad5a066c43bd4a5 Mon Sep 17 00:00:00 2001 From: Dario Date: Sun, 7 Jun 2020 18:32:47 +0200 Subject: [PATCH] adding some profiling code sha 512 --- src/cpp/Crypto/KeyPair.cpp | 12 +- src/cpp/Crypto/KeyPairEd25519.cpp | 13 +- src/cpp/Crypto/Passphrase.cpp | 43 ++++++- src/cpp/Crypto/Passphrase.h | 21 ++- src/cpp/test/crypto/TestKeyPairEd25519.cpp | 7 + src/cpp/test/crypto/TestPassphrase.cpp | 142 +++++++++++++++++++-- src/cpp/test/crypto/TestPassphrase.h | 12 +- 7 files changed, 226 insertions(+), 24 deletions(-) diff --git a/src/cpp/Crypto/KeyPair.cpp b/src/cpp/Crypto/KeyPair.cpp index c474a76c6..064b6e74d 100644 --- a/src/cpp/Crypto/KeyPair.cpp +++ b/src/cpp/Crypto/KeyPair.cpp @@ -11,6 +11,7 @@ #include "Passphrase.h" #include "../ServerConfig.h" +#include "../lib/Profiler.h" using namespace Poco::Data::Keywords; @@ -71,10 +72,16 @@ bool KeyPair::generateFromPassphrase(const char* passphrase, const Mnemonic* wor if (!word_indices) { return false; } + printf("word indices: "); + const Poco::UInt64* word_data = (const Poco::UInt64*)word_indices->data(); + for (int i = 0; i < PHRASE_WORD_COUNT; i++) { + printf("%d ", word_data[i]); + } + printf("\n"); std::string clearPassphrase = createClearPassphraseFromWordIndices(word_indices, &ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_BIP0039_SORTED_ORDER]); - + printf("clear passphrase: %s\n", clearPassphrase.data()); sha_context state; unsigned char hash[SHA_512_SIZE]; @@ -82,7 +89,10 @@ bool KeyPair::generateFromPassphrase(const char* passphrase, const Mnemonic* wor size_t word_index_size = sizeof(word_indices); //crypto_auth_hmacsha512_init(&state, (unsigned char*)word_indices, sizeof(word_indices)); sha512_init(&state); + + Profiler timeUsed; sha512_update(&state, *word_indices, word_indices->size()); + printf("time used in one step: %s\n", timeUsed.string().data()); sha512_update(&state, (unsigned char*)clearPassphrase.data(), clearPassphrase.size()); //crypto_auth_hmacsha512_update(&state, (unsigned char*)passphrase, pass_phrase_size); sha512_final(&state, hash); diff --git a/src/cpp/Crypto/KeyPairEd25519.cpp b/src/cpp/Crypto/KeyPairEd25519.cpp index 7439bdfa6..7b4325dd6 100644 --- a/src/cpp/Crypto/KeyPairEd25519.cpp +++ b/src/cpp/Crypto/KeyPairEd25519.cpp @@ -5,6 +5,7 @@ #include "../SingletonManager/ErrorManager.h" #include "../lib/DataTypeConverter.h" +#include "../lib/Profiler.h" #include "Passphrase.h" @@ -56,7 +57,17 @@ KeyPairEd25519* KeyPairEd25519::create(const Passphrase* passphrase) size_t word_index_size = sizeof(word_indices); //crypto_auth_hmacsha512_init(&state, (unsigned char*)word_indices, sizeof(word_indices)); crypto_hash_sha512_init(&state); - crypto_hash_sha512_update(&state, (const unsigned char*)word_indices, PHRASE_WORD_COUNT * sizeof(Poco::UInt16)); + Profiler timeUsed; + //Poco::UInt64 valueBuffer[PHRASE_WORD_COUNT]; + auto value_buffer = mm->getFreeMemory(PHRASE_WORD_COUNT * sizeof(Poco::UInt64)); + Poco::UInt64* value_buffer_p = (Poco::UInt64*)value_buffer->data(); + for (int i = 0; i < PHRASE_WORD_COUNT; i++) { + value_buffer_p[i] = word_indices[i]; + } + auto betweenTime = timeUsed.string(); + crypto_hash_sha512_update(&state, *value_buffer, sizeof(Poco::UInt64) * PHRASE_WORD_COUNT); + printf("time used in for loop: %s (between: %s)\n", timeUsed.string().data(), betweenTime.data()); + //crypto_hash_sha512_update(&state, (const unsigned char*)word_indices, PHRASE_WORD_COUNT * sizeof(Poco::UInt16)); crypto_hash_sha512_update(&state, (unsigned char*)clear_passphrase.data(), clear_passphrase.size()); //crypto_auth_hmacsha512_update(&state, (unsigned char*)passphrase, pass_phrase_size); crypto_hash_sha512_final(&state, hash); diff --git a/src/cpp/Crypto/Passphrase.cpp b/src/cpp/Crypto/Passphrase.cpp index 9b8311ec6..743747bbc 100644 --- a/src/cpp/Crypto/Passphrase.cpp +++ b/src/cpp/Crypto/Passphrase.cpp @@ -5,6 +5,8 @@ #include "../SingletonManager/ErrorManager.h" +#include "KeyPairEd25519.h" + #include "../ServerConfig.h" #define STR_BUFFER_SIZE 25 @@ -114,10 +116,11 @@ Poco::AutoPtr Passphrase::transform(const Mnemonic* targetWordSource return createClearPassphraseFromWordIndices(word_indices, targetWordSource);*/ // Poco::SharedPtr transformedPassphrase = new Passphrase() - if (!targetWordSource || mWordSource) { + if (!targetWordSource || !mWordSource) { return nullptr; } if (targetWordSource == mWordSource) { + duplicate(); return this; } if (createWordIndices()) { @@ -136,6 +139,21 @@ Poco::AutoPtr Passphrase::create(const MemoryBin* wordIndices, const return create(word_indices_p, wordSource); } +std::string Passphrase::createClearPassphrase() const +{ + auto word_indices = getWordIndices(); + std::string clear_passphrase; + auto word_source = &ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_BIP0039_SORTED_ORDER]; + for (int i = 0; i < PHRASE_WORD_COUNT; i++) { + auto word = word_source->getWord(word_indices[i]); + if (word) { + clear_passphrase += word; + clear_passphrase += " "; + } + } + return clear_passphrase; +} + Poco::AutoPtr Passphrase::create(const Poco::UInt16 wordIndices[PHRASE_WORD_COUNT], const Mnemonic* wordSource) { std::string clearPassphrase; @@ -216,6 +234,11 @@ const Poco::UInt16* Passphrase::getWordIndices() return mWordIndices; } +const Poco::UInt16* Passphrase::getWordIndices() const +{ + return mWordIndices; +} + bool Passphrase::checkIfValid() { std::istringstream iss(mPassphraseString); @@ -231,7 +254,7 @@ bool Passphrase::checkIfValid() } return true; } -const Mnemonic* Passphrase::detectMnemonic(const std::string& passphrase, const MemoryBin* publicKey /* = nullptr*/) +const Mnemonic* Passphrase::detectMnemonic(const std::string& passphrase, const KeyPairEd25519* keyPair /* = nullptr*/) { std::istringstream iss(passphrase); std::vector results(std::istream_iterator{iss}, @@ -249,8 +272,20 @@ const Mnemonic* Passphrase::detectMnemonic(const std::string& passphrase, const } } if (existAll) { - if (publicKey) { - + if (keyPair) { + auto test_passphrase = new Passphrase(passphrase, &m); + test_passphrase->createWordIndices(); + auto key_pair = KeyPairEd25519::create(test_passphrase); + delete test_passphrase; + if (key_pair) { + if (*key_pair != *keyPair) { + delete key_pair; + continue; + } + else { + delete key_pair; + } + } } return &ServerConfig::g_Mnemonic_WordLists[i]; } diff --git a/src/cpp/Crypto/Passphrase.h b/src/cpp/Crypto/Passphrase.h index de57ba859..6d9a31965 100644 --- a/src/cpp/Crypto/Passphrase.h +++ b/src/cpp/Crypto/Passphrase.h @@ -4,11 +4,11 @@ //#include #include "mnemonic.h" #include "../SingletonManager/MemoryManager.h" - - #include "../lib/AutoPtrContainer.h" #include "Poco/AutoPtr.h" +class KeyPairEd25519; + class Passphrase : public AutoPtrContainer { public: @@ -16,11 +16,18 @@ public: static Poco::AutoPtr create(const Poco::UInt16 wordIndices[PHRASE_WORD_COUNT], const Mnemonic* wordSource); static Poco::AutoPtr create(const MemoryBin* wordIndices, const Mnemonic* wordSource); - static const Mnemonic* detectMnemonic(const std::string& passphrase, const MemoryBin* publicKey = nullptr); + static const Mnemonic* detectMnemonic(const std::string& passphrase, const KeyPairEd25519* keyPair = nullptr); //! \brief transform passphrase into another language/mnemonic source + //! \return this if targetWordSource is the same as mWordSource Poco::AutoPtr transform(const Mnemonic* targetWordSource); + //! \brief create clear passphrase from word indices from bitcoin word list (bip0039) + //! + //! Used by hashing function to get really the same string, + //! even user has typed in some not filtered character + std::string createClearPassphrase() const; + //! \brief replace utf8 characters with html special character encoding //! //! TODO: add more utf8 chars for other languages as they needed @@ -29,10 +36,16 @@ public: bool checkIfValid(); const Poco::UInt16* getWordIndices(); + const Poco::UInt16* getWordIndices() const; -protected: //! \return true if ok bool createWordIndices(); + + //! \brief please handle with care! should be only seen by user and admin + const std::string& getString() const { return mPassphraseString; } + +protected: + std::string mPassphraseString; const Mnemonic* mWordSource; diff --git a/src/cpp/test/crypto/TestKeyPairEd25519.cpp b/src/cpp/test/crypto/TestKeyPairEd25519.cpp index 436756a18..16eb669a6 100644 --- a/src/cpp/test/crypto/TestKeyPairEd25519.cpp +++ b/src/cpp/test/crypto/TestKeyPairEd25519.cpp @@ -13,8 +13,15 @@ TEST_F(PassphraseTest, TestEd25519KeyPair) { auto word_indices = tr->getWordIndices(); + printf("word indices test: "); + for (int i = 0; i < PHRASE_WORD_COUNT; i++) { + printf("%d ", word_indices[i]); + } + printf("\n"); + auto key_pair_ed25519 = KeyPairEd25519::create(tr); KeyPair key_pair; + key_pair.generateFromPassphrase(test_data_set.passphrases[test_data_set.mnemonicType].data(), mnemonic); EXPECT_EQ(key_pair.getPubkeyHex(), test_data_set.pubkeyHex); diff --git a/src/cpp/test/crypto/TestPassphrase.cpp b/src/cpp/test/crypto/TestPassphrase.cpp index 008504a65..6228e859d 100644 --- a/src/cpp/test/crypto/TestPassphrase.cpp +++ b/src/cpp/test/crypto/TestPassphrase.cpp @@ -7,6 +7,11 @@ #include "gtest/gtest.h" +#include "../../lib/DataTypeConverter.h" + +#include "../../Crypto/KeyPairEd25519.h" +#include "../../Crypto/KeyPair.h" + TestPassphrase::TestPassphrase() @@ -32,20 +37,51 @@ int TestPassphrase::test() void PassphraseTest::SetUp() { + Poco::UInt16 wordIndices1[] = { + 157, 1629, 1619, 1100, 2032, 1185, 1767, 1787, 1325, 963, 1906, 680, 1127, 252, 1547, 853, 414, 1569, 1767, 990, 755, 1593, 431, 722 + }; + std::string passphrases1[] = { + "Fichte Heuschrecke Botschafter Göttingen Leasing losfliegen simpel enorm erkämpft Werk Wolke vorhanden jene Slums stagnieren Verifizieren insgesamt Hanau simpel Inspiration delegieren umtauschen ablegen suggerieren", + "ankommt gesamt gestorben müde Argument stolz diskutiert Kette Leonardo riesig Igor berauben prüfen bislang Villa Fortschritt moralisch unfä hig diskutiert erwidern Hanau Plage Fossilien ethnisch", + "beauty slight skill maze wrap neither table term pizza journey unusual fence mind buzz scrap height critic service table knock fury shrimp curious fog" + }; mPassphrasesForTesting.push_back(PassphraseDataSet( - "beauty slight skill maze wrap neither table term pizza journey unusual fence mind buzz scrap height critic service table knock fury shrimp curious fog", + passphrases1, ServerConfig::MNEMONIC_BIP0039_SORTED_ORDER, - "6fa7180b132e1248c649fc7b2e422ad57663299f85bd88b8b8031dce28b501a8" + "6fa7180b132e1248c649fc7b2e422ad57663299f85bd88b8b8031dce28b501a8", + wordIndices1 )); - mPassphrasesForTesting.push_back(PassphraseDataSet( + + + Poco::UInt16 wordIndices2[] = { + 742, 837, 269, 1067, 310, 1169, 1272, 365, 44, 619, 719, 108, 1750, 464, 1607, 663, 815, 343, 1784, 85, 510, 1809, 66, 1559 + }; + std::string passphrases2[] = { "oftmals bist bietet spalten Datenbank Masse sträflich hervor Derartig Hallo christlich Brief iPhone einpendeln telefonieren musizieren gigantisch Orchester zirkulieren essen gilt Erich Dollar money", - ServerConfig::MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER, - "8943813a623863dd7c5e5b248e408ac8a8851ef758275b6043a06e9b5832c36c" - )); + "Angst ausbeuten besser bekannt Bedürfnisse Neidisch virtuell Pension geprägt inmitten Abfall Absatzmarkt Umkehrschluss Fidel jeder Heinrich Engagement leihen gezogen Disziplin zufolge raffen Iris Jäger", + "fresh hamster canvas lyrics chat mutual pair color airport estate fly assault suspect deliver similar fancy grass cliff tenant apple divert timber analyst seed" + }; mPassphrasesForTesting.push_back(PassphraseDataSet( - "tief Acker Abgaben jenseits Revolution verdeckt Entdeckung Sanktion sammeln Umdrehung regulieren murmeln Erkenntnis hart zwar zuspitzen indem fegen bomber zwölf Mobbing divers Inspiration Krieg", + passphrases2, ServerConfig::MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER, - "d62f14173ae5d66b06753cc9d69d5471913ffc6053feedac2acf901eef3582a9" + "8943813a623863dd7c5e5b248e408ac8a8851ef758275b6043a06e9b5832c36c", + wordIndices2 + )); + + + Poco::UInt16 wordIndices3[] = { + 1412, 777, 1270, 905, 673, 670, 1780, 143, 546, 452, 505, 977, 1616, 916, 1635, 1318, 364, 1229, 1078, 1850, 514, 361, 990, 632 + }; + std::string passphrases3[] = { + "tief Acker Abgaben jenseits Revolution verdeckt Entdeckung Sanktion sammeln Umdrehung regulieren murmeln Erkenntnis hart zwar zuspitzen indem fegen bomber zwölf Mobbing divers Inspiration Krieg", + "aushalten absolut signifikant Bezahlung zukunftsfähig Wurzel spalten unausweichlich dunkel halb Nagel nehmen Begabung bezwingen wehren Fohlen keiner Krankheit leiblich Rü cken Finnland sehen erwidern Absätze", + "rack gentle paddle illness feature fatigue teach ball dust decade dish kick skate income small pill collect often man trap doctor coffee knock excuse" + }; + mPassphrasesForTesting.push_back(PassphraseDataSet( + passphrases3, + ServerConfig::MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER, + "d62f14173ae5d66b06753cc9d69d5471913ffc6053feedac2acf901eef3582a9", + wordIndices3 )); ServerConfig::loadMnemonicWordLists(); @@ -54,9 +90,15 @@ void PassphraseTest::SetUp() TEST_F(PassphraseTest, detectMnemonic) { for (auto it = mPassphrasesForTesting.begin(); it != mPassphrasesForTesting.end(); it++) { auto testDataSet = *it; - EXPECT_EQ(Passphrase::detectMnemonic(testDataSet.passphrase), &ServerConfig::g_Mnemonic_WordLists[testDataSet.mnemonicType]); + for (int i = 0; i < ServerConfig::MNEMONIC_MAX; i++) { + ServerConfig::Mnemonic_Types type = (ServerConfig::Mnemonic_Types)i; + // currently not easy to differentiate from MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER + if (ServerConfig::MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER_FIXED_CASES == type) continue; + EXPECT_EQ(Passphrase::detectMnemonic(testDataSet.passphrases[type]), &ServerConfig::g_Mnemonic_WordLists[type]); + } + } - EXPECT_FALSE(Passphrase::detectMnemonic("Dies ist eine ungültige Passphrase")); + EXPECT_FALSE(Passphrase::detectMnemonic("Dies ist eine ungültige Passphrase")); } TEST_F(PassphraseTest, detectMnemonicWithPubkey) { @@ -66,8 +108,86 @@ TEST_F(PassphraseTest, detectMnemonicWithPubkey) { auto testDataSet = *it; //testDataSet.pubkeyHex ASSERT_FALSE(pubkeyBin->convertFromHex(testDataSet.pubkeyHex)); - EXPECT_EQ(Passphrase::detectMnemonic(testDataSet.passphrase, pubkeyBin), &ServerConfig::g_Mnemonic_WordLists[testDataSet.mnemonicType]); + auto key_pair = new KeyPairEd25519(*pubkeyBin); + for (int i = 0; i < ServerConfig::MNEMONIC_MAX; i++) { + ServerConfig::Mnemonic_Types type = (ServerConfig::Mnemonic_Types)i; + EXPECT_EQ(Passphrase::detectMnemonic(testDataSet.passphrases[type], key_pair), &ServerConfig::g_Mnemonic_WordLists[type]); + } } mm->releaseMemory(pubkeyBin); } +TEST_F(PassphraseTest, filter) { + std::string unfilteredPassphrases[] = { + "oftmals bist bietet spalten Datenbank Masse sträflich hervor Derartig Hallo christlich Brief iPhone einpendeln telefonieren musizieren gigantisch Orchester zirkulieren essen gilt Erich Dollar money", + "Höh, maß, xDäöas" + }; + std::string filteredPassphrases[] = { + "oftmals bist bietet spalten Datenbank Masse sträflich hervor Derartig Hallo christlich Brief iPhone einpendeln telefonieren musizieren gigantisch Orchester zirkulieren essen gilt Erich Dollar money", + "Höh maß xDäöas" + }; + + for (int i = 0; i < 2; i++) { + EXPECT_EQ(Passphrase::filter(unfilteredPassphrases[i]), filteredPassphrases[i]); + } +} + +TEST_F(PassphraseTest, constructAndValid) { + for (auto it = mPassphrasesForTesting.begin(); it != mPassphrasesForTesting.end(); it++) { + auto testDataSet = *it; + for (int i = 0; i < ServerConfig::MNEMONIC_MAX; i++) { + ServerConfig::Mnemonic_Types type = (ServerConfig::Mnemonic_Types)i; + Passphrase passphrase(testDataSet.passphrases[type], &ServerConfig::g_Mnemonic_WordLists[type]); + EXPECT_TRUE(passphrase.checkIfValid()); + } + } + Passphrase passphrase("Höh, maß, xDäöas", &ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER]); + EXPECT_FALSE(passphrase.checkIfValid()); +} + +TEST_F(PassphraseTest, wordIndices) { + for (auto it = mPassphrasesForTesting.begin(); it != mPassphrasesForTesting.end(); it++) { + auto testDataSet = *it; + for (int i = 0; i < ServerConfig::MNEMONIC_MAX; i++) { + ServerConfig::Mnemonic_Types type = (ServerConfig::Mnemonic_Types)i; + Passphrase passphrase(testDataSet.passphrases[type], &ServerConfig::g_Mnemonic_WordLists[type]); + ASSERT_TRUE(passphrase.checkIfValid()); + auto wordIndices = passphrase.getWordIndices(); + EXPECT_EQ(memcmp(wordIndices, testDataSet.wordIndices, PHRASE_WORD_COUNT * sizeof(Poco::UInt16)), 0); + } + } +} + +TEST_F(PassphraseTest, createAndTransform) { + for (auto it = mPassphrasesForTesting.begin(); it != mPassphrasesForTesting.end(); it++) { + auto test_data_set = *it; + auto mnemonic = &ServerConfig::g_Mnemonic_WordLists[test_data_set.mnemonicType]; + auto tr = Passphrase::create(test_data_set.wordIndices, mnemonic); + + auto word_indices = tr->getWordIndices(); + + for (int i = 0; i < PHRASE_WORD_COUNT; i++) { + EXPECT_EQ(word_indices[i], test_data_set.wordIndices[i]); + } + auto key_pair_ed25519 = KeyPairEd25519::create(tr); + KeyPair key_pair; + key_pair.generateFromPassphrase(test_data_set.passphrases[test_data_set.mnemonicType].data(), mnemonic); + //EXPECT_EQ(DataTypeConverter::pubkeyToHex(key_pair_ed25519->getPublicKey()), test_data_set.pubkeyHex); + EXPECT_EQ(key_pair.getPubkeyHex(), test_data_set.pubkeyHex); + + //auto key_pair_old + delete key_pair_ed25519; + ASSERT_FALSE(tr.isNull()); + EXPECT_TRUE(tr->checkIfValid()); + auto tr_english = tr->transform(&ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_BIP0039_SORTED_ORDER]); + ASSERT_FALSE(tr_english.isNull()); + printf("english: %s\n", tr_english->getString().data()); + auto tr_german1 = tr->transform(&ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER]); + ASSERT_FALSE(tr_german1.isNull()); + printf("german 1: %s\n", tr_german1->getString().data()); + auto tr_german2 = tr->transform(&ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER_FIXED_CASES]); + ASSERT_FALSE(tr_german2.isNull()); + printf("german 2: %s\n\n", tr_german2->getString().data()); + } +} + diff --git a/src/cpp/test/crypto/TestPassphrase.h b/src/cpp/test/crypto/TestPassphrase.h index fd68dde5c..42dc4613f 100644 --- a/src/cpp/test/crypto/TestPassphrase.h +++ b/src/cpp/test/crypto/TestPassphrase.h @@ -28,12 +28,18 @@ protected: struct PassphraseDataSet { - PassphraseDataSet(std::string _passphrase, ServerConfig::Mnemonic_Types _type, std::string _pubkeyHex) - : passphrase(_passphrase), mnemonicType(_type), pubkeyHex(_pubkeyHex) {} + PassphraseDataSet(std::string _passphrases[ServerConfig::MNEMONIC_MAX], ServerConfig::Mnemonic_Types _type, std::string _pubkeyHex, Poco::UInt16 _wordIndices[PHRASE_WORD_COUNT]) + : mnemonicType(_type), pubkeyHex(_pubkeyHex) { + memcpy(wordIndices, _wordIndices, PHRASE_WORD_COUNT * sizeof(Poco::UInt16)); + for (int i = 0; i < ServerConfig::MNEMONIC_MAX; i++) { + passphrases[i] = _passphrases[i]; + } + } - std::string passphrase; + std::string passphrases[ServerConfig::MNEMONIC_MAX]; ServerConfig::Mnemonic_Types mnemonicType; std::string pubkeyHex; + Poco::UInt16 wordIndices[PHRASE_WORD_COUNT]; }; std::vector mPassphrasesForTesting;