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);
};
}
};