OSDN Git Service

Simplified QKeccakHash and added self-test function.
[lamexp/LameXP.git] / etc / Prerequisites / keccak / src / qkeccakhash.cpp
1 /***************************************************************************
2 **                                                                        **
3 **  QKeccakHash, an API wrapper bringing the optimized implementation of  **
4 **  Keccak (http://keccak.noekeon.org/) to Qt.                            **
5 **  Copyright (C) 2012 Emanuel Eichhammer                                 **
6 **                                                                        **
7 **  This program is free software: you can redistribute it and/or modify  **
8 **  it under the terms of the GNU General Public License as published by  **
9 **  the Free Software Foundation, either version 3 of the License, or     **
10 **  (at your option) any later version.                                   **
11 **                                                                        **
12 **  This program is distributed in the hope that it will be useful,       **
13 **  but WITHOUT ANY WARRANTY; without even the implied warranty of        **
14 **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         **
15 **  GNU General Public License for more details.                          **
16 **                                                                        **
17 **  You should have received a copy of the GNU General Public License     **
18 **  along with this program.  If not, see http://www.gnu.org/licenses/.   **
19 **                                                                        **
20 ****************************************************************************
21 **           Author: Emanuel Eichhammer                                   **
22 **  Website/Contact: http://www.WorksLikeClockwork.com/                   **
23 **             Date: 12.01.12                                             **
24 ****************************************************************************/
25
26 #include "qkeccakhash.h"
27 #include <QDebug>
28
29 #include "keccakimpl.cpp"
30
31 QKeccakHash::QKeccakHash()
32 {
33         m_initialized = false;
34         m_state = new KeccakImpl::hashState;
35         memset(m_state, 0, sizeof(KeccakImpl::hashState));
36         m_hashResult.clear();
37 }
38
39 QKeccakHash::~QKeccakHash()
40 {
41         m_hashResult.clear();
42
43         if(m_state)
44         {
45                 delete m_state;
46                 m_state = NULL;
47         }
48 }
49
50 bool QKeccakHash::init(HashBits hashBits)
51 {
52         if(m_initialized)
53         {
54                 qWarning("QKeccakHash has already been initialized!");
55                 return false;
56         }
57
58         m_hashResult.clear();
59         memset(m_state, 0, sizeof(KeccakImpl::hashState));
60         int hashBitLength = 0;
61
62         switch (hashBits)
63         {
64                 case hb224: hashBitLength = 224; break;
65                 case hb256: hashBitLength = 256; break;
66                 case hb384: hashBitLength = 384; break;
67                 case hb512: hashBitLength = 512; break;
68                 default: throw "Invalid hash length!!";
69         }
70
71         if(KeccakImpl::Init(m_state, hashBitLength) != KeccakImpl::SUCCESS)
72         {
73                 qWarning("KeccakImpl::Init() has failed unexpectedly!");
74                 return false;
75         }
76         
77         m_hashResult.fill(char(0), hashBitLength/8);
78         m_initialized = true;
79
80         return true;
81 }
82
83 bool QKeccakHash::addData(const QByteArray &data)
84 {
85         return addData(data.constData(), data.size());
86 }
87
88 bool QKeccakHash::addData(const char *data, int size)
89 {
90         if(!m_initialized)
91         {
92                 qWarning("QKeccakHash has not been initialized yet!");
93                 return false;
94         }
95         
96         if(KeccakImpl::Update(m_state, (KeccakImpl::BitSequence*)data, size*8) != KeccakImpl::SUCCESS)
97         {
98                 qWarning("KeccakImpl::Update() has failed unexpectedly!");
99                 m_hashResult.clear();
100                 m_initialized = false;
101                 return false;
102         }
103         
104         return true;
105 }
106
107 const QByteArray &QKeccakHash::finalize()
108 {
109         if(!m_initialized)
110         {
111                 qWarning("QKeccakHash has not been initialized yet!");
112                 m_hashResult.clear();
113                 return m_hashResult;
114         }
115
116         if(KeccakImpl::Final(m_state, (KeccakImpl::BitSequence*)m_hashResult.data()) != KeccakImpl::SUCCESS)
117         {
118                 qWarning("KeccakImpl::Final() has failed unexpectedly!");
119                 m_hashResult.clear();
120         }
121
122         m_initialized = false;
123         return m_hashResult;
124 }
125
126 bool QKeccakHash::selfTest(void)
127 {
128         QKeccakHash hash;
129         const QByteArray input("The quick brown fox jumps over the lazy dog");
130         bool passed[4] = {false, false, false, false};
131
132         if(hash.init(QKeccakHash::hb224))
133         {
134                 if(hash.addData(input))
135                 {
136                         QByteArray result = hash.finalize();
137                         if(!result.isEmpty())
138                         {
139                                 passed[0] = (_stricmp(result.toHex().constData(), "310aee6b30c47350576ac2873fa89fd190cdc488442f3ef654cf23fe") == 0);
140                                 if(!passed[0]) qWarning("QKeccakHash self-test: Test #1 failed !!!");
141                         }
142                 }
143         }
144
145         if(hash.init(QKeccakHash::hb256))
146         {
147                 if(hash.addData(input))
148                 {
149                         QByteArray result = hash.finalize();
150                         if(!result.isEmpty())
151                         {
152                                 passed[1] = (_stricmp(result.toHex().constData(), "4d741b6f1eb29cb2a9b9911c82f56fa8d73b04959d3d9d222895df6c0b28aa15") == 0);
153                                 if(!passed[1]) qWarning("QKeccakHash self-test: Test #2 failed !!!");
154                         }
155                 }
156         }
157         
158         if(hash.init(QKeccakHash::hb384))
159         {
160                 if(hash.addData(input))
161                 {
162                         QByteArray result = hash.finalize();
163                         if(!result.isEmpty())
164                         {
165                                 passed[2] = (_stricmp(result.toHex().constData(), "283990fa9d5fb731d786c5bbee94ea4db4910f18c62c03d173fc0a5e494422e8a0b3da7574dae7fa0baf005e504063b3") == 0);
166                                 if(!passed[2]) qWarning("QKeccakHash self-test: Test #3 failed !!!");
167                         }
168                 }
169         }
170
171         if(hash.init(QKeccakHash::hb512))
172         {
173                 if(hash.addData(input))
174                 {
175                         QByteArray result = hash.finalize();
176                         if(!result.isEmpty())
177                         {
178                                 passed[3] = (_stricmp(result.toHex().constData(), "d135bb84d0439dbac432247ee573a23ea7d3c9deb2a968eb31d47c4fb45f1ef4422d6c531b5b9bd6f449ebcc449ea94d0a8f05f62130fda612da53c79659f609") == 0);
179                                 if(!passed[3]) qWarning("QKeccakHash self-test: Test #4 failed !!!");
180                         }
181                 }
182         }
183
184         return (passed[0] && passed[1] && passed[2] && passed[3]);
185 }