diff --git a/MUtilities_VS2015.vcxproj b/MUtilities_VS2015.vcxproj index 45e2e58..d2eb433 100644 --- a/MUtilities_VS2015.vcxproj +++ b/MUtilities_VS2015.vcxproj @@ -26,6 +26,7 @@ + @@ -47,10 +48,9 @@ - + - diff --git a/MUtilities_VS2015.vcxproj.filters b/MUtilities_VS2015.vcxproj.filters index 33c5c99..9f18a2b 100644 --- a/MUtilities_VS2015.vcxproj.filters +++ b/MUtilities_VS2015.vcxproj.filters @@ -102,6 +102,9 @@ Source Files + + Source Files + @@ -161,12 +164,6 @@ Public Headers - - Public Headers - - - Public Headers - Header Files\3rd Party @@ -176,6 +173,9 @@ Header Files + + Public Headers + diff --git a/include/MUtils/Hash.h b/include/MUtils/Hash.h new file mode 100644 index 0000000..313d827 --- /dev/null +++ b/include/MUtils/Hash.h @@ -0,0 +1,60 @@ +/////////////////////////////////////////////////////////////////////////////// +// MuldeR's Utilities for Qt +// Copyright (C) 2004-2016 LoRd_MuldeR +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// http://www.gnu.org/licenses/lgpl-2.1.txt +////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +//MUtils +#include + +//Qt +#include +#include + +namespace MUtils +{ + namespace Hash + { + static const quint16 HASH_BLAKE2_512 = 0x0000U; + static const quint16 HASH_KECCAK_224 = 0x0100U; + static const quint16 HASH_KECCAK_256 = 0x0101U; + static const quint16 HASH_KECCAK_384 = 0x0102U; + static const quint16 HASH_KECCAK_512 = 0x0103U; + + class MUTILS_API Hash + { + public: + Hash(const char* key = NULL) {}; + virtual ~Hash(void) {}; + + bool update(const quint8 *const data, const quint32 len) { return process(data, len); } + bool update(const QByteArray &data) { return process(((const quint8*)data.constData()), ((quint32)data.length())); } + bool update(QFile &file); + + QByteArray digest(const bool bAsHex = true) { return bAsHex ? finalize().toHex() : finalize(); } + + protected: + virtual bool process(const quint8 *const data, const quint32 len) = 0; + virtual QByteArray finalize(void) = 0; + }; + + Hash *create(const quint16 &hashId, const char *const key = NULL); + } +} diff --git a/src/Hash.cpp b/src/Hash.cpp new file mode 100644 index 0000000..6989ea2 --- /dev/null +++ b/src/Hash.cpp @@ -0,0 +1,68 @@ +/////////////////////////////////////////////////////////////////////////////// +// Simple x264 Launcher +// Copyright (C) 2004-2016 LoRd_MuldeR +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// http://www.gnu.org/licenses/gpl-2.0.txt +/////////////////////////////////////////////////////////////////////////////// + +//MUtils +#include +#include + +//Hash Functions +#include "Hash_Keccak.h" +#include "Hash_Blake2.h" + +// ========================================================================== +// Abstract Hash Class +// ========================================================================== + +bool MUtils::Hash::Hash::update(QFile &file) +{ + while (!file.atEnd()) + { + const QByteArray data = file.read(4194304i64); + if (data.isEmpty() || (!update(data))) + { + return false; + } + } + return true; +} + +// ========================================================================== +// Hash Factory +// ========================================================================== + +MUtils::Hash::Hash *MUtils::Hash::create(const quint16 &hashId, const char *const key) +{ + switch (hashId) + { + case HASH_KECCAK_224: + return Keccak::create(Keccak::hb224, key); + case HASH_KECCAK_256: + return Keccak::create(Keccak::hb256, key); + case HASH_KECCAK_384: + return Keccak::create(Keccak::hb384, key); + case HASH_KECCAK_512: + return Keccak::create(Keccak::hb512, key); + case HASH_BLAKE2_512: + return new Blake2(key); + default: + MUTILS_THROW_FMT("Hash algorithm 0x%02X is unknown!", quint32(hashId)); + } +} diff --git a/src/Hash_Blake2.cpp b/src/Hash_Blake2.cpp index 388bc8f..0c85c47 100644 --- a/src/Hash_Blake2.cpp +++ b/src/Hash_Blake2.cpp @@ -32,8 +32,9 @@ this software. If not, see . */ +#include "Hash_Blake2.h" + //MUtils -#include #include //Internal @@ -51,7 +52,7 @@ class MUtils::Hash::Blake2_Context Blake2_Context(void) { - if(!(state = (MUtils::Hash::Internal::Blake2Impl::blake2b_state*) _aligned_malloc(sizeof(MUtils::Hash::Internal::Blake2Impl::blake2b_state), 64))) + if(!(state = (MUtils::Hash::Internal::Blake2Impl::blake2b_state*) _aligned_malloc(sizeof(MUtils::Hash::Internal::Blake2Impl::blake2b_state), HASH_SIZE))) { MUTILS_THROW("Aligend malloc has failed!"); } @@ -68,9 +69,8 @@ private: MUtils::Hash::Internal::Blake2Impl::blake2b_state *state; }; -MUtils::Hash::Blake2::Blake2(const char* key) +MUtils::Hash::Blake2::Blake2(const char *const key) : - m_hash(HASH_SIZE, '\0'), m_context(new Blake2_Context()), m_finalized(false) { @@ -89,55 +89,31 @@ MUtils::Hash::Blake2::~Blake2(void) delete m_context; } -void MUtils::Hash::Blake2::update(const QByteArray &data) +bool MUtils::Hash::Blake2::process(const quint8 *const data, const quint32 len) { if(m_finalized) { MUTILS_THROW("BLAKE2 was already finalized!"); } - if(data.size() > 0) + if(data && (len > 0)) { - if(blake2b_update(m_context->state, (const uint8_t*) data.constData(), data.size()) != 0) + if(blake2b_update(m_context->state, data, len) != 0) { MUTILS_THROW("BLAKE2 internal error!"); } } + + return true; } -void MUtils::Hash::Blake2::update(QFile &file) +QByteArray MUtils::Hash::Blake2::finalize(void) { - bool okay = false; - - for(;;) + QByteArray result(HASH_SIZE, '\0'); + if(blake2b_final(m_context->state, (uint8_t*) result.data(), result.size()) != 0) { - QByteArray data = file.read(16384); - if(data.size() > 0) - { - okay = true; - update(data); - continue; - } - break; - } - - if(!okay) - { - qWarning("[QBlake2Checksum] Could not ready any data from file!"); + MUTILS_THROW("BLAKE2 internal error!"); } -} - -QByteArray MUtils::Hash::Blake2::finalize(const bool bAsHex) -{ - if(!m_finalized) - { - if(blake2b_final(m_context->state, (uint8_t*) m_hash.data(), m_hash.size()) != 0) - { - MUTILS_THROW("BLAKE2 internal error!"); - } - - m_finalized = true; - } - - return bAsHex ? m_hash.toHex() : m_hash; + m_finalized = true; + return result; } diff --git a/include/MUtils/Hash_Blake2.h b/src/Hash_Blake2.h similarity index 88% rename from include/MUtils/Hash_Blake2.h rename to src/Hash_Blake2.h index 1d99b9d..293a085 100644 --- a/include/MUtils/Hash_Blake2.h +++ b/src/Hash_Blake2.h @@ -36,6 +36,7 @@ //MUtils #include +#include //Qt #include @@ -47,20 +48,18 @@ namespace MUtils { class MUTILS_API Blake2_Context; - class MUTILS_API Blake2 + class MUTILS_API Blake2 : public Hash { public: - Blake2(const char* key = NULL); - ~Blake2(void); - - void update(const QByteArray &data); - void update(QFile &file); - QByteArray finalize(const bool bAsHex = true); + Blake2(const char *const key = NULL); + virtual ~Blake2(void); private: - QByteArray m_hash; Blake2_Context *const m_context; bool m_finalized; + + virtual bool process(const quint8 *const data, const quint32 len); + virtual QByteArray finalize(void); }; } diff --git a/src/Hash_Keccak.cpp b/src/Hash_Keccak.cpp index a15e75b..c08f2c1 100644 --- a/src/Hash_Keccak.cpp +++ b/src/Hash_Keccak.cpp @@ -44,9 +44,15 @@ ** Date: 12.01.12 ** ****************************************************************************/ -#include +#include "Hash_Keccak.h" + +//MUtils +#include + +//Qt #include +//Implementation #include "3rd_party/keccak/include/keccak_impl.h" MUtils::Hash::Keccak::Keccak() @@ -55,16 +61,13 @@ MUtils::Hash::Keccak::Keccak() m_state = (MUtils::Hash::Internal::KeccakImpl::hashState*) _aligned_malloc(sizeof(MUtils::Hash::Internal::KeccakImpl::hashState), 32); if(!m_state) { - throw "[MUtils::KeccakHash] Error: _aligned_malloc() has failed, probably out of heap space!"; + MUTILS_THROW("_aligned_malloc() has failed, probably out of heap space!"); } memset(m_state, 0, sizeof(MUtils::Hash::Internal::KeccakImpl::hashState)); - m_hashResult.clear(); } MUtils::Hash::Keccak::~Keccak() { - m_hashResult.clear(); - if(m_state) { _aligned_free(m_state); @@ -72,7 +75,7 @@ MUtils::Hash::Keccak::~Keccak() } } -bool MUtils::Hash::Keccak::init(HashBits hashBits) +bool MUtils::Hash::Keccak::init(const HashBits hashBits) { if(m_initialized) { @@ -80,7 +83,6 @@ bool MUtils::Hash::Keccak::init(HashBits hashBits) return false; } - m_hashResult.clear(); memset(m_state, 0, sizeof(MUtils::Hash::Internal::KeccakImpl::hashState)); int hashBitLength = 0; @@ -99,18 +101,12 @@ bool MUtils::Hash::Keccak::init(HashBits hashBits) return false; } - m_hashResult.fill(char(0), hashBitLength/8); m_initialized = true; - return true; } -bool MUtils::Hash::Keccak::addData(const QByteArray &data) -{ - return addData(data.constData(), data.size()); -} -bool MUtils::Hash::Keccak::addData(const char *data, int size) +bool MUtils::Hash::Keccak::process(const quint8 *const data, const quint32 len) { if(!m_initialized) { @@ -118,10 +114,9 @@ bool MUtils::Hash::Keccak::addData(const char *data, int size) return false; } - if(MUtils::Hash::Internal::KeccakImpl::Update(m_state, (MUtils::Hash::Internal::KeccakImpl::BitSequence*)data, size*8) != MUtils::Hash::Internal::KeccakImpl::SUCCESS) + if(MUtils::Hash::Internal::KeccakImpl::Update(m_state, (MUtils::Hash::Internal::KeccakImpl::BitSequence*)data, len*8U) != MUtils::Hash::Internal::KeccakImpl::SUCCESS) { qWarning("KeccakImpl::Update() has failed unexpectedly!"); - m_hashResult.clear(); m_initialized = false; return false; } @@ -129,34 +124,52 @@ bool MUtils::Hash::Keccak::addData(const char *data, int size) return true; } -const QByteArray &MUtils::Hash::Keccak::finalize() +QByteArray MUtils::Hash::Keccak::finalize(void) { if(!m_initialized) { qWarning("MUtils::KeccakHash has not been initialized yet!"); - m_hashResult.clear(); - return m_hashResult; + return QByteArray(); } - if(MUtils::Hash::Internal::KeccakImpl::Final(m_state, (MUtils::Hash::Internal::KeccakImpl::BitSequence*)m_hashResult.data()) != MUtils::Hash::Internal::KeccakImpl::SUCCESS) + Q_ASSERT(m_state->fixedOutputLength > 0); + Q_ASSERT((m_state->fixedOutputLength % 8) == 0); + + QByteArray hashResult(m_state->fixedOutputLength / 8, '\0'); + if(MUtils::Hash::Internal::KeccakImpl::Final(m_state, (MUtils::Hash::Internal::KeccakImpl::BitSequence*)hashResult.data()) != MUtils::Hash::Internal::KeccakImpl::SUCCESS) { qWarning("KeccakImpl::Final() has failed unexpectedly!"); - m_hashResult.clear(); + hashResult.clear(); } m_initialized = false; - return m_hashResult; + return hashResult; +} + +MUtils::Hash::Keccak *MUtils::Hash::Keccak::create(const HashBits hashBit, const char *const key) +{ + Keccak *const keccak = new Keccak(); + if (!keccak->init(hashBit)) + { + MUTILS_THROW("Keccak initialization has failed!"); + } + if (key) + { + keccak->update(((const uint8_t*)key), strlen(key)); + } + return keccak; } bool MUtils::Hash::Keccak::selfTest(void) { - MUtils::Hash::Keccak hash; + Keccak hash; const QByteArray input("The quick brown fox jumps over the lazy dog"); bool passed[4] = {false, false, false, false}; + if(hash.init(MUtils::Hash::Keccak::hb224)) { - if(hash.addData(input)) + if(hash.update(input)) { QByteArray result = hash.finalize(); if(!result.isEmpty()) @@ -169,7 +182,7 @@ bool MUtils::Hash::Keccak::selfTest(void) if(hash.init(MUtils::Hash::Keccak::hb256)) { - if(hash.addData(input)) + if(hash.update(input)) { QByteArray result = hash.finalize(); if(!result.isEmpty()) @@ -182,7 +195,7 @@ bool MUtils::Hash::Keccak::selfTest(void) if(hash.init(MUtils::Hash::Keccak::hb384)) { - if(hash.addData(input)) + if(hash.update(input)) { QByteArray result = hash.finalize(); if(!result.isEmpty()) @@ -195,7 +208,7 @@ bool MUtils::Hash::Keccak::selfTest(void) if(hash.init(MUtils::Hash::Keccak::hb512)) { - if(hash.addData(input)) + if(hash.update(input)) { QByteArray result = hash.finalize(); if(!result.isEmpty()) diff --git a/include/MUtils/Hash_Keccak.h b/src/Hash_Keccak.h similarity index 92% rename from include/MUtils/Hash_Keccak.h rename to src/Hash_Keccak.h index 1cc01b9..e971b67 100644 --- a/include/MUtils/Hash_Keccak.h +++ b/src/Hash_Keccak.h @@ -48,6 +48,7 @@ //MUtils #include +#include //Qt #include @@ -95,25 +96,25 @@ namespace MUtils // End Section from KeccakSponge.h } - class MUTILS_API Keccak + class MUTILS_API Keccak : public Hash { public: enum HashBits {hb224, hb256, hb384, hb512}; Keccak(); - ~Keccak(); + virtual ~Keccak(); - static bool selfTest(void); + bool init(const HashBits hashBits=hb256); - bool init(HashBits hashBits=hb256); - bool addData(const QByteArray &data); - bool addData(const char *data, int size); - const QByteArray &finalize(); + static Keccak *create(const HashBits hashBits = hb256, const char *const key = NULL); + static bool selfTest(void); protected: bool m_initialized; Internal::KeccakImpl::hashState *m_state; - QByteArray m_hashResult; + + virtual bool process(const quint8 *const data, const quint32 len); + virtual QByteArray finalize(void); }; } };