OSDN Git Service

VS2013 build fix.
[mutilities/MUtilities.git] / src / Hash_Keccak.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // MuldeR's Utilities for Qt
3 // Copyright (C) 2004-2017 LoRd_MuldeR <MuldeR2@GMX.de>
4 //
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.
9 //
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.
14 //
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
18 //
19 // http://www.gnu.org/licenses/lgpl-2.1.txt
20 //////////////////////////////////////////////////////////////////////////////////
21
22 /***************************************************************************
23 **                                                                        **
24 **  QKeccakHash, an API wrapper bringing the optimized implementation of  **
25 **  Keccak (http://keccak.noekeon.org/) to Qt.                            **
26 **  Copyright (C) 2013 Emanuel Eichhammer                                 **
27 **                                                                        **
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.                                   **
32 **                                                                        **
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.                          **
37 **                                                                        **
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/.   **
40 **                                                                        **
41 ****************************************************************************
42 **           Author: Emanuel Eichhammer                                   **
43 **  Website/Contact: http://www.WorksLikeClockwork.com/                   **
44 **             Date: 12.01.12                                             **
45 ****************************************************************************/
46
47 #include "Hash_Keccak.h"
48
49 //MUtils
50 #include <MUtils/Exception.h>
51
52 //Qt
53 #include <QDebug>
54
55 //Implementation
56 #include "3rd_party/keccak/include/keccak_impl.h"
57
58 MUtils::Hash::Keccak::Keccak()
59 {
60         m_initialized = false;
61         m_state = (MUtils::Hash::Internal::KeccakImpl::hashState*) _aligned_malloc(sizeof(MUtils::Hash::Internal::KeccakImpl::hashState), 32);
62         if(!m_state)
63         {
64                 MUTILS_THROW("_aligned_malloc() has failed, probably out of heap space!");
65         }
66         memset(m_state, 0, sizeof(MUtils::Hash::Internal::KeccakImpl::hashState));
67 }
68
69 MUtils::Hash::Keccak::~Keccak()
70 {
71         if(m_state)
72         {
73                 _aligned_free(m_state);
74                 m_state = NULL;
75         }
76 }
77
78 bool MUtils::Hash::Keccak::init(const HashBits hashBits)
79 {
80         if(m_initialized)
81         {
82                 qWarning("MUtils::KeccakHash has already been initialized!");
83                 return false;
84         }
85
86         memset(m_state, 0, sizeof(MUtils::Hash::Internal::KeccakImpl::hashState));
87         int hashBitLength = 0;
88
89         switch (hashBits)
90         {
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!!";
96         }
97
98         if(MUtils::Hash::Internal::KeccakImpl::Init(m_state, hashBitLength) != MUtils::Hash::Internal::KeccakImpl::SUCCESS)
99         {
100                 qWarning("KeccakImpl::Init() has failed unexpectedly!");
101                 return false;
102         }
103         
104         m_initialized = true;
105         return true;
106 }
107
108
109 bool MUtils::Hash::Keccak::process(const quint8 *const data, const quint32 len)
110 {
111         if(!m_initialized)
112         {
113                 qWarning("MUtils::KeccakHash has not been initialized yet!");
114                 return false;
115         }
116         
117         if(MUtils::Hash::Internal::KeccakImpl::Update(m_state, (MUtils::Hash::Internal::KeccakImpl::BitSequence*)data, len*8U) != MUtils::Hash::Internal::KeccakImpl::SUCCESS)
118         {
119                 qWarning("KeccakImpl::Update() has failed unexpectedly!");
120                 m_initialized = false;
121                 return false;
122         }
123         
124         return true;
125 }
126
127 QByteArray MUtils::Hash::Keccak::finalize(void)
128 {
129         if(!m_initialized)
130         {
131                 qWarning("MUtils::KeccakHash has not been initialized yet!");
132                 return QByteArray();
133         }
134
135         Q_ASSERT(m_state->fixedOutputLength > 0);
136         Q_ASSERT((m_state->fixedOutputLength % 8) == 0);
137
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)
140         {
141                 qWarning("KeccakImpl::Final() has failed unexpectedly!");
142                 hashResult.clear();
143         }
144
145         m_initialized = false;
146         return hashResult;
147 }
148
149 MUtils::Hash::Keccak *MUtils::Hash::Keccak::create(const HashBits hashBit, const char *const key)
150 {
151         Keccak *const keccak = new Keccak();
152         if (!keccak->init(hashBit))
153         {
154                 MUTILS_THROW("Keccak initialization has failed!");
155         }
156         if (key)
157         {
158                 keccak->update(((const Internal::KeccakImpl::UINT8*)key), strlen(key));
159         }
160         return keccak;
161 }
162
163 bool MUtils::Hash::Keccak::selfTest(void)
164 {
165         Keccak hash;
166         const QByteArray input("The quick brown fox jumps over the lazy dog");
167         bool passed[4] = {false, false, false, false};
168
169
170         if(hash.init(MUtils::Hash::Keccak::hb224))
171         {
172                 if(hash.update(input))
173                 {
174                         QByteArray result = hash.finalize();
175                         if(!result.isEmpty())
176                         {
177                                 passed[0] = (_stricmp(result.toHex().constData(), "310aee6b30c47350576ac2873fa89fd190cdc488442f3ef654cf23fe") == 0);
178                                 if(!passed[0]) qWarning("MUtils::KeccakHash self-test: Test #1 failed !!!");
179                         }
180                 }
181         }
182
183         if(hash.init(MUtils::Hash::Keccak::hb256))
184         {
185                 if(hash.update(input))
186                 {
187                         QByteArray result = hash.finalize();
188                         if(!result.isEmpty())
189                         {
190                                 passed[1] = (_stricmp(result.toHex().constData(), "4d741b6f1eb29cb2a9b9911c82f56fa8d73b04959d3d9d222895df6c0b28aa15") == 0);
191                                 if(!passed[1]) qWarning("MUtils::KeccakHash self-test: Test #2 failed !!!");
192                         }
193                 }
194         }
195         
196         if(hash.init(MUtils::Hash::Keccak::hb384))
197         {
198                 if(hash.update(input))
199                 {
200                         QByteArray result = hash.finalize();
201                         if(!result.isEmpty())
202                         {
203                                 passed[2] = (_stricmp(result.toHex().constData(), "283990fa9d5fb731d786c5bbee94ea4db4910f18c62c03d173fc0a5e494422e8a0b3da7574dae7fa0baf005e504063b3") == 0);
204                                 if(!passed[2]) qWarning("MUtils::KeccakHash self-test: Test #3 failed !!!");
205                         }
206                 }
207         }
208
209         if(hash.init(MUtils::Hash::Keccak::hb512))
210         {
211                 if(hash.update(input))
212                 {
213                         QByteArray result = hash.finalize();
214                         if(!result.isEmpty())
215                         {
216                                 passed[3] = (_stricmp(result.toHex().constData(), "d135bb84d0439dbac432247ee573a23ea7d3c9deb2a968eb31d47c4fb45f1ef4422d6c531b5b9bd6f449ebcc449ea94d0a8f05f62130fda612da53c79659f609") == 0);
217                                 if(!passed[3]) qWarning("MUtils::KeccakHash self-test: Test #4 failed !!!");
218                         }
219                 }
220         }
221
222         return (passed[0] && passed[1] && passed[2] && passed[3]);
223 }