Absolute File Name: | /home/qt/qt5_coco/qt5/qtbase/src/corelib/tools/qmessageauthenticationcode.cpp |
Source code | Switch to Preprocessed file |
Line | Source | Count | ||||||
---|---|---|---|---|---|---|---|---|
1 | /**************************************************************************** | - | ||||||
2 | ** | - | ||||||
3 | ** Copyright (C) 2013 Ruslan Nigmatullin <euroelessar@yandex.ru> | - | ||||||
4 | ** Contact: https://www.qt.io/licensing/ | - | ||||||
5 | ** | - | ||||||
6 | ** This file is part of the QtCore module of the Qt Toolkit. | - | ||||||
7 | ** | - | ||||||
8 | ** $QT_BEGIN_LICENSE:LGPL$ | - | ||||||
9 | ** Commercial License Usage | - | ||||||
10 | ** Licensees holding valid commercial Qt licenses may use this file in | - | ||||||
11 | ** accordance with the commercial license agreement provided with the | - | ||||||
12 | ** Software or, alternatively, in accordance with the terms contained in | - | ||||||
13 | ** a written agreement between you and The Qt Company. For licensing terms | - | ||||||
14 | ** and conditions see https://www.qt.io/terms-conditions. For further | - | ||||||
15 | ** information use the contact form at https://www.qt.io/contact-us. | - | ||||||
16 | ** | - | ||||||
17 | ** GNU Lesser General Public License Usage | - | ||||||
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | - | ||||||
19 | ** General Public License version 3 as published by the Free Software | - | ||||||
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the | - | ||||||
21 | ** packaging of this file. Please review the following information to | - | ||||||
22 | ** ensure the GNU Lesser General Public License version 3 requirements | - | ||||||
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. | - | ||||||
24 | ** | - | ||||||
25 | ** GNU General Public License Usage | - | ||||||
26 | ** Alternatively, this file may be used under the terms of the GNU | - | ||||||
27 | ** General Public License version 2.0 or (at your option) the GNU General | - | ||||||
28 | ** Public license version 3 or any later version approved by the KDE Free | - | ||||||
29 | ** Qt Foundation. The licenses are as published by the Free Software | - | ||||||
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 | - | ||||||
31 | ** included in the packaging of this file. Please review the following | - | ||||||
32 | ** information to ensure the GNU General Public License requirements will | - | ||||||
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and | - | ||||||
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. | - | ||||||
35 | ** | - | ||||||
36 | ** $QT_END_LICENSE$ | - | ||||||
37 | ** | - | ||||||
38 | ****************************************************************************/ | - | ||||||
39 | - | |||||||
40 | #include "qmessageauthenticationcode.h" | - | ||||||
41 | #include "qvarlengtharray.h" | - | ||||||
42 | - | |||||||
43 | /* | - | ||||||
44 | These #defines replace the typedefs needed by the RFC6234 code. Normally | - | ||||||
45 | the typedefs would come from from stdint.h, but since this header is not | - | ||||||
46 | available on all platforms (MSVC 2008, for example), we #define them to the | - | ||||||
47 | Qt equivalents. | - | ||||||
48 | */ | - | ||||||
49 | - | |||||||
50 | #ifdef uint64_t | - | ||||||
51 | #undef uint64_t | - | ||||||
52 | #endif | - | ||||||
53 | - | |||||||
54 | #define uint64_t QT_PREPEND_NAMESPACE(quint64) | - | ||||||
55 | - | |||||||
56 | #ifdef uint32_t | - | ||||||
57 | #undef uint32_t | - | ||||||
58 | #endif | - | ||||||
59 | - | |||||||
60 | #define uint32_t QT_PREPEND_NAMESPACE(quint32) | - | ||||||
61 | - | |||||||
62 | #ifdef uint8_t | - | ||||||
63 | #undef uint8_t | - | ||||||
64 | #endif | - | ||||||
65 | - | |||||||
66 | #define uint8_t QT_PREPEND_NAMESPACE(quint8) | - | ||||||
67 | - | |||||||
68 | #ifdef int_least16_t | - | ||||||
69 | #undef int_least16_t | - | ||||||
70 | #endif | - | ||||||
71 | - | |||||||
72 | #define int_least16_t QT_PREPEND_NAMESPACE(qint16) | - | ||||||
73 | - | |||||||
74 | // Header from rfc6234 with 1 modification: | - | ||||||
75 | // sha1.h - commented out '#include <stdint.h>' on line 74 | - | ||||||
76 | #include "../../3rdparty/rfc6234/sha.h" | - | ||||||
77 | - | |||||||
78 | #undef uint64_t | - | ||||||
79 | #undef uint32_t | - | ||||||
80 | #undef uint68_t | - | ||||||
81 | #undef int_least16_t | - | ||||||
82 | - | |||||||
83 | QT_BEGIN_NAMESPACE | - | ||||||
84 | - | |||||||
85 | static int qt_hash_block_size(QCryptographicHash::Algorithm method) | - | ||||||
86 | { | - | ||||||
87 | switch (method) { | - | ||||||
88 | case QCryptographicHash::Md4: never executed: case QCryptographicHash::Md4: | 0 | ||||||
89 | return 64; never executed: return 64; | 0 | ||||||
90 | case QCryptographicHash::Md5: executed 20 times by 1 test: case QCryptographicHash::Md5: Executed by:
| 20 | ||||||
91 | return 64; executed 20 times by 1 test: return 64; Executed by:
| 20 | ||||||
92 | case QCryptographicHash::Sha1: executed 8 times by 1 test: case QCryptographicHash::Sha1: Executed by:
| 8 | ||||||
93 | return SHA1_Message_Block_Size; executed 8 times by 1 test: return SHA1_Message_Block_Size; Executed by:
| 8 | ||||||
94 | case QCryptographicHash::Sha224: never executed: case QCryptographicHash::Sha224: | 0 | ||||||
95 | return SHA224_Message_Block_Size; never executed: return SHA224_Message_Block_Size; | 0 | ||||||
96 | case QCryptographicHash::Sha256: executed 8 times by 1 test: case QCryptographicHash::Sha256: Executed by:
| 8 | ||||||
97 | return SHA256_Message_Block_Size; executed 8 times by 1 test: return SHA256_Message_Block_Size; Executed by:
| 8 | ||||||
98 | case QCryptographicHash::Sha384: never executed: case QCryptographicHash::Sha384: | 0 | ||||||
99 | return SHA384_Message_Block_Size; never executed: return SHA384_Message_Block_Size; | 0 | ||||||
100 | case QCryptographicHash::Sha512: never executed: case QCryptographicHash::Sha512: | 0 | ||||||
101 | return SHA512_Message_Block_Size; never executed: return SHA512_Message_Block_Size; | 0 | ||||||
102 | case QCryptographicHash::Sha3_224: never executed: case QCryptographicHash::Sha3_224: | 0 | ||||||
103 | return 144; never executed: return 144; | 0 | ||||||
104 | case QCryptographicHash::Sha3_256: never executed: case QCryptographicHash::Sha3_256: | 0 | ||||||
105 | return 136; never executed: return 136; | 0 | ||||||
106 | case QCryptographicHash::Sha3_384: never executed: case QCryptographicHash::Sha3_384: | 0 | ||||||
107 | return 104; never executed: return 104; | 0 | ||||||
108 | case QCryptographicHash::Sha3_512: never executed: case QCryptographicHash::Sha3_512: | 0 | ||||||
109 | return 72; never executed: return 72; | 0 | ||||||
110 | } | - | ||||||
111 | return 0; never executed: return 0; | 0 | ||||||
112 | } | - | ||||||
113 | - | |||||||
114 | class QMessageAuthenticationCodePrivate | - | ||||||
115 | { | - | ||||||
116 | public: | - | ||||||
117 | QMessageAuthenticationCodePrivate(QCryptographicHash::Algorithm m) | - | ||||||
118 | : messageHash(m), method(m), messageHashInited(false) | - | ||||||
119 | { | - | ||||||
120 | } executed 18 times by 1 test: end of block Executed by:
| 18 | ||||||
121 | - | |||||||
122 | QByteArray key; | - | ||||||
123 | QByteArray result; | - | ||||||
124 | QCryptographicHash messageHash; | - | ||||||
125 | QCryptographicHash::Algorithm method; | - | ||||||
126 | bool messageHashInited; | - | ||||||
127 | - | |||||||
128 | void initMessageHash(); | - | ||||||
129 | }; | - | ||||||
130 | - | |||||||
131 | void QMessageAuthenticationCodePrivate::initMessageHash() | - | ||||||
132 | { | - | ||||||
133 | if (messageHashInited)
| 18-27 | ||||||
134 | return; executed 27 times by 1 test: return; Executed by:
| 27 | ||||||
135 | messageHashInited = true; | - | ||||||
136 | - | |||||||
137 | const int blockSize = qt_hash_block_size(method); | - | ||||||
138 | - | |||||||
139 | if (key.size() > blockSize) {
| 0-18 | ||||||
140 | QCryptographicHash hash(method); | - | ||||||
141 | hash.addData(key); | - | ||||||
142 | key = hash.result(); | - | ||||||
143 | hash.reset(); | - | ||||||
144 | } never executed: end of block | 0 | ||||||
145 | - | |||||||
146 | if (key.size() < blockSize) {
| 0-18 | ||||||
147 | const int size = key.size(); | - | ||||||
148 | key.resize(blockSize); | - | ||||||
149 | memset(key.data() + size, 0, blockSize - size); | - | ||||||
150 | } executed 18 times by 1 test: end of block Executed by:
| 18 | ||||||
151 | - | |||||||
152 | QVarLengthArray<char> iKeyPad(blockSize); | - | ||||||
153 | const char * const keyData = key.constData(); | - | ||||||
154 | - | |||||||
155 | for (int i = 0; i < blockSize; ++i)
| 18-1152 | ||||||
156 | iKeyPad[i] = keyData[i] ^ 0x36; executed 1152 times by 1 test: iKeyPad[i] = keyData[i] ^ 0x36; Executed by:
| 1152 | ||||||
157 | - | |||||||
158 | messageHash.addData(iKeyPad.data(), iKeyPad.size()); | - | ||||||
159 | } executed 18 times by 1 test: end of block Executed by:
| 18 | ||||||
160 | - | |||||||
161 | /*! | - | ||||||
162 | \class QMessageAuthenticationCode | - | ||||||
163 | \inmodule QtCore | - | ||||||
164 | - | |||||||
165 | \brief The QMessageAuthenticationCode class provides a way to generate | - | ||||||
166 | hash-based message authentication codes. | - | ||||||
167 | - | |||||||
168 | \since 5.1 | - | ||||||
169 | - | |||||||
170 | \ingroup tools | - | ||||||
171 | \reentrant | - | ||||||
172 | - | |||||||
173 | QMessageAuthenticationCode supports all cryptographic hashes which are supported by | - | ||||||
174 | QCryptographicHash. | - | ||||||
175 | - | |||||||
176 | To generate message authentication code, pass hash algorithm QCryptographicHash::Algorithm | - | ||||||
177 | to constructor, then set key and message by setKey() and addData() functions. Result | - | ||||||
178 | can be acquired by result() function. | - | ||||||
179 | \snippet qmessageauthenticationcode/main.cpp 0 | - | ||||||
180 | \dots | - | ||||||
181 | \snippet qmessageauthenticationcode/main.cpp 1 | - | ||||||
182 | - | |||||||
183 | Alternatively, this effect can be achieved by providing message, | - | ||||||
184 | key and method to hash() method. | - | ||||||
185 | \snippet qmessageauthenticationcode/main.cpp 2 | - | ||||||
186 | - | |||||||
187 | \sa QCryptographicHash | - | ||||||
188 | */ | - | ||||||
189 | - | |||||||
190 | /*! | - | ||||||
191 | Constructs an object that can be used to create a cryptographic hash from data | - | ||||||
192 | using method \a method and key \a key. | - | ||||||
193 | */ | - | ||||||
194 | QMessageAuthenticationCode::QMessageAuthenticationCode(QCryptographicHash::Algorithm method, | - | ||||||
195 | const QByteArray &key) | - | ||||||
196 | : d(new QMessageAuthenticationCodePrivate(method)) | - | ||||||
197 | { | - | ||||||
198 | d->key = key; | - | ||||||
199 | } executed 18 times by 1 test: end of block Executed by:
| 18 | ||||||
200 | - | |||||||
201 | /*! | - | ||||||
202 | Destroys the object. | - | ||||||
203 | */ | - | ||||||
204 | QMessageAuthenticationCode::~QMessageAuthenticationCode() | - | ||||||
205 | { | - | ||||||
206 | delete d; | - | ||||||
207 | } executed 18 times by 1 test: end of block Executed by:
| 18 | ||||||
208 | - | |||||||
209 | /*! | - | ||||||
210 | Resets message data. Calling this method doesn't affect the key. | - | ||||||
211 | */ | - | ||||||
212 | void QMessageAuthenticationCode::reset() | - | ||||||
213 | { | - | ||||||
214 | d->result.clear(); | - | ||||||
215 | d->messageHash.reset(); | - | ||||||
216 | d->messageHashInited = false; | - | ||||||
217 | } executed 18 times by 1 test: end of block Executed by:
| 18 | ||||||
218 | - | |||||||
219 | /*! | - | ||||||
220 | Sets secret \a key. Calling this method automatically resets the object state. | - | ||||||
221 | */ | - | ||||||
222 | void QMessageAuthenticationCode::setKey(const QByteArray &key) | - | ||||||
223 | { | - | ||||||
224 | reset(); | - | ||||||
225 | d->key = key; | - | ||||||
226 | } executed 18 times by 1 test: end of block Executed by:
| 18 | ||||||
227 | - | |||||||
228 | /*! | - | ||||||
229 | Adds the first \a length chars of \a data to the message. | - | ||||||
230 | */ | - | ||||||
231 | void QMessageAuthenticationCode::addData(const char *data, int length) | - | ||||||
232 | { | - | ||||||
233 | d->initMessageHash(); | - | ||||||
234 | d->messageHash.addData(data, length); | - | ||||||
235 | } never executed: end of block | 0 | ||||||
236 | - | |||||||
237 | /*! | - | ||||||
238 | \overload addData() | - | ||||||
239 | */ | - | ||||||
240 | void QMessageAuthenticationCode::addData(const QByteArray &data) | - | ||||||
241 | { | - | ||||||
242 | d->initMessageHash(); | - | ||||||
243 | d->messageHash.addData(data); | - | ||||||
244 | } executed 27 times by 1 test: end of block Executed by:
| 27 | ||||||
245 | - | |||||||
246 | /*! | - | ||||||
247 | Reads the data from the open QIODevice \a device until it ends | - | ||||||
248 | and adds it to message. Returns \c true if reading was successful. | - | ||||||
249 | - | |||||||
250 | \note \a device must be already opened. | - | ||||||
251 | */ | - | ||||||
252 | bool QMessageAuthenticationCode::addData(QIODevice *device) | - | ||||||
253 | { | - | ||||||
254 | d->initMessageHash(); | - | ||||||
255 | return d->messageHash.addData(device); never executed: return d->messageHash.addData(device); | 0 | ||||||
256 | } | - | ||||||
257 | - | |||||||
258 | /*! | - | ||||||
259 | Returns the final authentication code. | - | ||||||
260 | - | |||||||
261 | \sa QByteArray::toHex() | - | ||||||
262 | */ | - | ||||||
263 | QByteArray QMessageAuthenticationCode::result() const | - | ||||||
264 | { | - | ||||||
265 | if (!d->result.isEmpty())
| 0-18 | ||||||
266 | return d->result; never executed: return d->result; | 0 | ||||||
267 | - | |||||||
268 | d->initMessageHash(); | - | ||||||
269 | - | |||||||
270 | const int blockSize = qt_hash_block_size(d->method); | - | ||||||
271 | - | |||||||
272 | QByteArray hashedMessage = d->messageHash.result(); | - | ||||||
273 | - | |||||||
274 | QVarLengthArray<char> oKeyPad(blockSize); | - | ||||||
275 | const char * const keyData = d->key.constData(); | - | ||||||
276 | - | |||||||
277 | for (int i = 0; i < blockSize; ++i)
| 18-1152 | ||||||
278 | oKeyPad[i] = keyData[i] ^ 0x5c; executed 1152 times by 1 test: oKeyPad[i] = keyData[i] ^ 0x5c; Executed by:
| 1152 | ||||||
279 | - | |||||||
280 | QCryptographicHash hash(d->method); | - | ||||||
281 | hash.addData(oKeyPad.data(), oKeyPad.size()); | - | ||||||
282 | hash.addData(hashedMessage); | - | ||||||
283 | - | |||||||
284 | d->result = hash.result(); | - | ||||||
285 | return d->result; executed 18 times by 1 test: return d->result; Executed by:
| 18 | ||||||
286 | } | - | ||||||
287 | - | |||||||
288 | /*! | - | ||||||
289 | Returns the authentication code for the message \a message using | - | ||||||
290 | the key \a key and the method \a method. | - | ||||||
291 | */ | - | ||||||
292 | QByteArray QMessageAuthenticationCode::hash(const QByteArray &message, const QByteArray &key, | - | ||||||
293 | QCryptographicHash::Algorithm method) | - | ||||||
294 | { | - | ||||||
295 | QMessageAuthenticationCode mac(method); | - | ||||||
296 | mac.setKey(key); | - | ||||||
297 | mac.addData(message); | - | ||||||
298 | return mac.result(); never executed: return mac.result(); | 0 | ||||||
299 | } | - | ||||||
300 | - | |||||||
301 | QT_END_NAMESPACE | - | ||||||
Source code | Switch to Preprocessed file |