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