1 ///////////////////////////////////////////////////////////////////////////////
2 // MuldeR's Utilities for Qt
3 // Copyright (C) 2004-2016 LoRd_MuldeR <MuldeR2@GMX.de>
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Lesser General Public License for more details.
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 // http://www.gnu.org/licenses/lgpl-2.1.txt
20 //////////////////////////////////////////////////////////////////////////////////
22 /***************************************************************************
24 ** QKeccakHash, an API wrapper bringing the optimized implementation of **
25 ** Keccak (http://keccak.noekeon.org/) to Qt. **
26 ** Copyright (C) 2013 Emanuel Eichhammer **
28 ** This program is free software: you can redistribute it and/or modify **
29 ** it under the terms of the GNU General Public License as published by **
30 ** the Free Software Foundation, either version 3 of the License, or **
31 ** (at your option) any later version. **
33 ** This program is distributed in the hope that it will be useful, **
34 ** but WITHOUT ANY WARRANTY; without even the implied warranty of **
35 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the **
36 ** GNU General Public License for more details. **
38 ** You should have received a copy of the GNU General Public License **
39 ** along with this program. If not, see http://www.gnu.org/licenses/. **
41 ****************************************************************************
42 ** Author: Emanuel Eichhammer **
43 ** Website/Contact: http://www.WorksLikeClockwork.com/ **
45 ****************************************************************************/
47 #include "Hash_Keccak.h"
50 #include <MUtils/Exception.h>
56 #include "3rd_party/keccak/include/keccak_impl.h"
58 MUtils::Hash::Keccak::Keccak()
60 m_initialized
= false;
61 m_state
= (MUtils::Hash::Internal::KeccakImpl::hashState
*) _aligned_malloc(sizeof(MUtils::Hash::Internal::KeccakImpl::hashState
), 32);
64 MUTILS_THROW("_aligned_malloc() has failed, probably out of heap space!");
66 memset(m_state
, 0, sizeof(MUtils::Hash::Internal::KeccakImpl::hashState
));
69 MUtils::Hash::Keccak::~Keccak()
73 _aligned_free(m_state
);
78 bool MUtils::Hash::Keccak::init(const HashBits hashBits
)
82 qWarning("MUtils::KeccakHash has already been initialized!");
86 memset(m_state
, 0, sizeof(MUtils::Hash::Internal::KeccakImpl::hashState
));
87 int hashBitLength
= 0;
91 case hb224
: hashBitLength
= 224; break;
92 case hb256
: hashBitLength
= 256; break;
93 case hb384
: hashBitLength
= 384; break;
94 case hb512
: hashBitLength
= 512; break;
95 default: throw "Invalid hash length!!";
98 if(MUtils::Hash::Internal::KeccakImpl::Init(m_state
, hashBitLength
) != MUtils::Hash::Internal::KeccakImpl::SUCCESS
)
100 qWarning("KeccakImpl::Init() has failed unexpectedly!");
104 m_initialized
= true;
109 bool MUtils::Hash::Keccak::process(const quint8
*const data
, const quint32 len
)
113 qWarning("MUtils::KeccakHash has not been initialized yet!");
117 if(MUtils::Hash::Internal::KeccakImpl::Update(m_state
, (MUtils::Hash::Internal::KeccakImpl::BitSequence
*)data
, len
*8U) != MUtils::Hash::Internal::KeccakImpl::SUCCESS
)
119 qWarning("KeccakImpl::Update() has failed unexpectedly!");
120 m_initialized
= false;
127 QByteArray
MUtils::Hash::Keccak::finalize(void)
131 qWarning("MUtils::KeccakHash has not been initialized yet!");
135 Q_ASSERT(m_state
->fixedOutputLength
> 0);
136 Q_ASSERT((m_state
->fixedOutputLength
% 8) == 0);
138 QByteArray
hashResult(m_state
->fixedOutputLength
/ 8, '\0');
139 if(MUtils::Hash::Internal::KeccakImpl::Final(m_state
, (MUtils::Hash::Internal::KeccakImpl::BitSequence
*)hashResult
.data()) != MUtils::Hash::Internal::KeccakImpl::SUCCESS
)
141 qWarning("KeccakImpl::Final() has failed unexpectedly!");
145 m_initialized
= false;
149 MUtils::Hash::Keccak
*MUtils::Hash::Keccak::create(const HashBits hashBit
, const char *const key
)
151 Keccak
*const keccak
= new Keccak();
152 if (!keccak
->init(hashBit
))
154 MUTILS_THROW("Keccak initialization has failed!");
158 keccak
->update(((const uint8_t*)key
), strlen(key
));
163 bool MUtils::Hash::Keccak::selfTest(void)
166 const QByteArray
input("The quick brown fox jumps over the lazy dog");
167 bool passed
[4] = {false, false, false, false};
170 if(hash
.init(MUtils::Hash::Keccak::hb224
))
172 if(hash
.update(input
))
174 QByteArray result
= hash
.finalize();
175 if(!result
.isEmpty())
177 passed
[0] = (_stricmp(result
.toHex().constData(), "310aee6b30c47350576ac2873fa89fd190cdc488442f3ef654cf23fe") == 0);
178 if(!passed
[0]) qWarning("MUtils::KeccakHash self-test: Test #1 failed !!!");
183 if(hash
.init(MUtils::Hash::Keccak::hb256
))
185 if(hash
.update(input
))
187 QByteArray result
= hash
.finalize();
188 if(!result
.isEmpty())
190 passed
[1] = (_stricmp(result
.toHex().constData(), "4d741b6f1eb29cb2a9b9911c82f56fa8d73b04959d3d9d222895df6c0b28aa15") == 0);
191 if(!passed
[1]) qWarning("MUtils::KeccakHash self-test: Test #2 failed !!!");
196 if(hash
.init(MUtils::Hash::Keccak::hb384
))
198 if(hash
.update(input
))
200 QByteArray result
= hash
.finalize();
201 if(!result
.isEmpty())
203 passed
[2] = (_stricmp(result
.toHex().constData(), "283990fa9d5fb731d786c5bbee94ea4db4910f18c62c03d173fc0a5e494422e8a0b3da7574dae7fa0baf005e504063b3") == 0);
204 if(!passed
[2]) qWarning("MUtils::KeccakHash self-test: Test #3 failed !!!");
209 if(hash
.init(MUtils::Hash::Keccak::hb512
))
211 if(hash
.update(input
))
213 QByteArray result
= hash
.finalize();
214 if(!result
.isEmpty())
216 passed
[3] = (_stricmp(result
.toHex().constData(), "d135bb84d0439dbac432247ee573a23ea7d3c9deb2a968eb31d47c4fb45f1ef4422d6c531b5b9bd6f449ebcc449ea94d0a8f05f62130fda612da53c79659f609") == 0);
217 if(!passed
[3]) qWarning("MUtils::KeccakHash self-test: Test #4 failed !!!");
222 return (passed
[0] && passed
[1] && passed
[2] && passed
[3]);