1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Copyright (C) 2013 Richard J. Moore <rich@kde.org>. |
5 | ** Contact: https://www.qt.io/licensing/ |
6 | ** |
7 | ** This file is part of the QtCore module of the Qt Toolkit. |
8 | ** |
9 | ** $QT_BEGIN_LICENSE:LGPL$ |
10 | ** Commercial License Usage |
11 | ** Licensees holding valid commercial Qt licenses may use this file in |
12 | ** accordance with the commercial license agreement provided with the |
13 | ** Software or, alternatively, in accordance with the terms contained in |
14 | ** a written agreement between you and The Qt Company. For licensing terms |
15 | ** and conditions see https://www.qt.io/terms-conditions. For further |
16 | ** information use the contact form at https://www.qt.io/contact-us. |
17 | ** |
18 | ** GNU Lesser General Public License Usage |
19 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
20 | ** General Public License version 3 as published by the Free Software |
21 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
22 | ** packaging of this file. Please review the following information to |
23 | ** ensure the GNU Lesser General Public License version 3 requirements |
24 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
25 | ** |
26 | ** GNU General Public License Usage |
27 | ** Alternatively, this file may be used under the terms of the GNU |
28 | ** General Public License version 2.0 or (at your option) the GNU General |
29 | ** Public license version 3 or any later version approved by the KDE Free |
30 | ** Qt Foundation. The licenses are as published by the Free Software |
31 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
32 | ** included in the packaging of this file. Please review the following |
33 | ** information to ensure the GNU General Public License requirements will |
34 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
35 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
36 | ** |
37 | ** $QT_END_LICENSE$ |
38 | ** |
39 | ****************************************************************************/ |
40 | |
41 | #include <qcryptographichash.h> |
42 | #include <qiodevice.h> |
43 | |
44 | #include "../../3rdparty/sha1/sha1.cpp" |
45 | |
46 | #if defined(QT_BOOTSTRAPPED) && !defined(QT_CRYPTOGRAPHICHASH_ONLY_SHA1) |
47 | # error "Are you sure you need the other hashing algorithms besides SHA-1?" |
48 | #endif |
49 | |
50 | #ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1 |
51 | // qdoc and qmake only need SHA-1 |
52 | #include "../../3rdparty/md5/md5.h" |
53 | #include "../../3rdparty/md5/md5.cpp" |
54 | #include "../../3rdparty/md4/md4.h" |
55 | #include "../../3rdparty/md4/md4.cpp" |
56 | |
57 | typedef unsigned char BitSequence; |
58 | typedef unsigned long long DataLength; |
59 | typedef enum { SUCCESS = 0, FAIL = 1, BAD_HASHLEN = 2 } HashReturn; |
60 | |
61 | #ifdef Q_OS_RTEMS |
62 | # undef ALIGN |
63 | #endif |
64 | |
65 | #include "../../3rdparty/sha3/KeccakSponge.c" |
66 | typedef spongeState hashState; |
67 | |
68 | #include "../../3rdparty/sha3/KeccakNISTInterface.c" |
69 | |
70 | /* |
71 | This lets us choose between SHA3 implementations at build time. |
72 | */ |
73 | typedef spongeState SHA3Context; |
74 | typedef HashReturn (SHA3Init)(hashState *state, int hashbitlen); |
75 | typedef HashReturn (SHA3Update)(hashState *state, const BitSequence *data, DataLength databitlen); |
76 | typedef HashReturn (SHA3Final)(hashState *state, BitSequence *hashval); |
77 | |
78 | #if Q_PROCESSOR_WORDSIZE == 8 // 64 bit version |
79 | |
80 | #include "../../3rdparty/sha3/KeccakF-1600-opt64.c" |
81 | |
82 | static SHA3Init * const sha3Init = Init; |
83 | static SHA3Update * const sha3Update = Update; |
84 | static SHA3Final * const sha3Final = Final; |
85 | |
86 | #else // 32 bit optimised fallback |
87 | |
88 | #include "../../3rdparty/sha3/KeccakF-1600-opt32.c" |
89 | |
90 | static SHA3Init * const sha3Init = Init; |
91 | static SHA3Update * const sha3Update = Update; |
92 | static SHA3Final * const sha3Final = Final; |
93 | |
94 | #endif |
95 | |
96 | /* |
97 | These #defines replace the typedefs needed by the RFC6234 code. Normally |
98 | the typedefs would come from from stdint.h, but since this header is not |
99 | available on all platforms (MSVC 2008, for example), we #define them to the |
100 | Qt equivalents. |
101 | */ |
102 | |
103 | #ifdef uint64_t |
104 | #undef uint64_t |
105 | #endif |
106 | |
107 | #define uint64_t QT_PREPEND_NAMESPACE(quint64) |
108 | |
109 | #ifdef uint32_t |
110 | #undef uint32_t |
111 | #endif |
112 | |
113 | #define uint32_t QT_PREPEND_NAMESPACE(quint32) |
114 | |
115 | #ifdef uint8_t |
116 | #undef uint8_t |
117 | #endif |
118 | |
119 | #define uint8_t QT_PREPEND_NAMESPACE(quint8) |
120 | |
121 | #ifdef int_least16_t |
122 | #undef int_least16_t |
123 | #endif |
124 | |
125 | #define int_least16_t QT_PREPEND_NAMESPACE(qint16) |
126 | |
127 | // Header from rfc6234 with 1 modification: |
128 | // sha1.h - commented out '#include <stdint.h>' on line 74 |
129 | #include "../../3rdparty/rfc6234/sha.h" |
130 | |
131 | /* |
132 | These 2 functions replace macros of the same name in sha224-256.c and |
133 | sha384-512.c. Originally, these macros relied on a global static 'addTemp' |
134 | variable. We do not want this for 2 reasons: |
135 | |
136 | 1. since we are including the sources directly, the declaration of the 2 conflict |
137 | |
138 | 2. static variables are not thread-safe, we do not want multiple threads |
139 | computing a hash to corrupt one another |
140 | */ |
141 | static int SHA224_256AddLength(SHA256Context *context, unsigned int length); |
142 | static int SHA384_512AddLength(SHA512Context *context, unsigned int length); |
143 | |
144 | // Sources from rfc6234, with 4 modifications: |
145 | // sha224-256.c - commented out 'static uint32_t addTemp;' on line 68 |
146 | // sha224-256.c - appended 'M' to the SHA224_256AddLength macro on line 70 |
147 | #include "../../3rdparty/rfc6234/sha224-256.c" |
148 | // sha384-512.c - commented out 'static uint64_t addTemp;' on line 302 |
149 | // sha384-512.c - appended 'M' to the SHA224_256AddLength macro on line 304 |
150 | #include "../../3rdparty/rfc6234/sha384-512.c" |
151 | |
152 | #undef uint64_t |
153 | #undef uint32_t |
154 | #undef uint68_t |
155 | #undef int_least16_t |
156 | |
157 | static inline int SHA224_256AddLength(SHA256Context *context, unsigned int length) |
158 | { |
159 | QT_PREPEND_NAMESPACE(quint32) addTemp; |
160 | return SHA224_256AddLengthM(context, length); |
161 | } |
162 | static inline int SHA384_512AddLength(SHA512Context *context, unsigned int length) |
163 | { |
164 | QT_PREPEND_NAMESPACE(quint64) addTemp; |
165 | return SHA384_512AddLengthM(context, length); |
166 | } |
167 | #endif // QT_CRYPTOGRAPHICHASH_ONLY_SHA1 |
168 | |
169 | QT_BEGIN_NAMESPACE |
170 | |
171 | class QCryptographicHashPrivate |
172 | { |
173 | public: |
174 | QCryptographicHash::Algorithm method; |
175 | union { |
176 | Sha1State sha1Context; |
177 | #ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1 |
178 | MD5Context md5Context; |
179 | md4_context md4Context; |
180 | SHA224Context sha224Context; |
181 | SHA256Context sha256Context; |
182 | SHA384Context sha384Context; |
183 | SHA512Context sha512Context; |
184 | SHA3Context sha3Context; |
185 | #endif |
186 | }; |
187 | #ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1 |
188 | enum class Sha3Variant |
189 | { |
190 | Sha3, |
191 | Keccak |
192 | }; |
193 | void sha3Finish(int bitCount, Sha3Variant sha3Variant); |
194 | #endif |
195 | QByteArray result; |
196 | }; |
197 | |
198 | #ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1 |
199 | void QCryptographicHashPrivate::sha3Finish(int bitCount, Sha3Variant sha3Variant) |
200 | { |
201 | /* |
202 | FIPS 202 ยง6.1 defines SHA-3 in terms of calculating the Keccak function |
203 | over the original message with the two-bit suffix "01" appended to it. |
204 | This variable stores that suffix (and it's fed into the calculations |
205 | when the hash is returned to users). |
206 | |
207 | Only 2 bits of this variable are actually used (see the call to sha3Update |
208 | below). The Keccak implementation we're using will actually use the |
209 | *leftmost* 2 bits, and interpret them right-to-left. In other words, the |
210 | bits must appear in order of *increasing* significance; and as the two most |
211 | significant bits of the byte -- the rightmost 6 are ignored. (Yes, this |
212 | seems self-contradictory, but it's the way it is...) |
213 | |
214 | Overall, this means: |
215 | * the leftmost two bits must be "10" (not "01"!); |
216 | * we don't care what the other six bits are set to (they can be set to |
217 | any value), but we arbitrarily set them to 0; |
218 | |
219 | and for an unsigned char this gives us 0b10'00'00'00, or 0x80. |
220 | */ |
221 | static const unsigned char sha3FinalSuffix = 0x80; |
222 | |
223 | result.resize(size: bitCount / 8); |
224 | |
225 | SHA3Context copy = sha3Context; |
226 | |
227 | switch (sha3Variant) { |
228 | case Sha3Variant::Sha3: |
229 | sha3Update(©, reinterpret_cast<const BitSequence *>(&sha3FinalSuffix), 2); |
230 | break; |
231 | case Sha3Variant::Keccak: |
232 | break; |
233 | } |
234 | |
235 | sha3Final(©, reinterpret_cast<BitSequence *>(result.data())); |
236 | } |
237 | #endif |
238 | |
239 | /*! |
240 | \class QCryptographicHash |
241 | \inmodule QtCore |
242 | |
243 | \brief The QCryptographicHash class provides a way to generate cryptographic hashes. |
244 | |
245 | \since 4.3 |
246 | |
247 | \ingroup tools |
248 | \reentrant |
249 | |
250 | QCryptographicHash can be used to generate cryptographic hashes of binary or text data. |
251 | |
252 | Refer to the documentation of the \l QCryptographicHash::Algorithm enum for a |
253 | list of the supported algorithms. |
254 | */ |
255 | |
256 | /*! |
257 | \enum QCryptographicHash::Algorithm |
258 | |
259 | \note In Qt versions before 5.9, when asked to generate a SHA3 hash sum, |
260 | QCryptographicHash actually calculated Keccak. If you need compatibility with |
261 | SHA-3 hashes produced by those versions of Qt, use the \c{Keccak_} |
262 | enumerators. Alternatively, if source compatibility is required, define the |
263 | macro \c QT_SHA3_KECCAK_COMPAT. |
264 | |
265 | \value Md4 Generate an MD4 hash sum |
266 | \value Md5 Generate an MD5 hash sum |
267 | \value Sha1 Generate an SHA-1 hash sum |
268 | \value Sha224 Generate an SHA-224 hash sum (SHA-2). Introduced in Qt 5.0 |
269 | \value Sha256 Generate an SHA-256 hash sum (SHA-2). Introduced in Qt 5.0 |
270 | \value Sha384 Generate an SHA-384 hash sum (SHA-2). Introduced in Qt 5.0 |
271 | \value Sha512 Generate an SHA-512 hash sum (SHA-2). Introduced in Qt 5.0 |
272 | \value Sha3_224 Generate an SHA3-224 hash sum. Introduced in Qt 5.1 |
273 | \value Sha3_256 Generate an SHA3-256 hash sum. Introduced in Qt 5.1 |
274 | \value Sha3_384 Generate an SHA3-384 hash sum. Introduced in Qt 5.1 |
275 | \value Sha3_512 Generate an SHA3-512 hash sum. Introduced in Qt 5.1 |
276 | \value Keccak_224 Generate a Keccak-224 hash sum. Introduced in Qt 5.9.2 |
277 | \value Keccak_256 Generate a Keccak-256 hash sum. Introduced in Qt 5.9.2 |
278 | \value Keccak_384 Generate a Keccak-384 hash sum. Introduced in Qt 5.9.2 |
279 | \value Keccak_512 Generate a Keccak-512 hash sum. Introduced in Qt 5.9.2 |
280 | \omitvalue RealSha3_224 |
281 | \omitvalue RealSha3_256 |
282 | \omitvalue RealSha3_384 |
283 | \omitvalue RealSha3_512 |
284 | */ |
285 | |
286 | /*! |
287 | Constructs an object that can be used to create a cryptographic hash from data using \a method. |
288 | */ |
289 | QCryptographicHash::QCryptographicHash(Algorithm method) |
290 | : d(new QCryptographicHashPrivate) |
291 | { |
292 | d->method = method; |
293 | reset(); |
294 | } |
295 | |
296 | /*! |
297 | Destroys the object. |
298 | */ |
299 | QCryptographicHash::~QCryptographicHash() |
300 | { |
301 | delete d; |
302 | } |
303 | |
304 | /*! |
305 | Resets the object. |
306 | */ |
307 | void QCryptographicHash::reset() |
308 | { |
309 | switch (d->method) { |
310 | case Sha1: |
311 | sha1InitState(state: &d->sha1Context); |
312 | break; |
313 | #ifdef QT_CRYPTOGRAPHICHASH_ONLY_SHA1 |
314 | default: |
315 | Q_ASSERT_X(false, "QCryptographicHash" , "Method not compiled in" ); |
316 | Q_UNREACHABLE(); |
317 | break; |
318 | #else |
319 | case Md4: |
320 | md4_init(ctx: &d->md4Context); |
321 | break; |
322 | case Md5: |
323 | MD5Init(ctx: &d->md5Context); |
324 | break; |
325 | case Sha224: |
326 | SHA224Reset(context: &d->sha224Context); |
327 | break; |
328 | case Sha256: |
329 | SHA256Reset(context: &d->sha256Context); |
330 | break; |
331 | case Sha384: |
332 | SHA384Reset(context: &d->sha384Context); |
333 | break; |
334 | case Sha512: |
335 | SHA512Reset(context: &d->sha512Context); |
336 | break; |
337 | case RealSha3_224: |
338 | case Keccak_224: |
339 | sha3Init(&d->sha3Context, 224); |
340 | break; |
341 | case RealSha3_256: |
342 | case Keccak_256: |
343 | sha3Init(&d->sha3Context, 256); |
344 | break; |
345 | case RealSha3_384: |
346 | case Keccak_384: |
347 | sha3Init(&d->sha3Context, 384); |
348 | break; |
349 | case RealSha3_512: |
350 | case Keccak_512: |
351 | sha3Init(&d->sha3Context, 512); |
352 | break; |
353 | #endif |
354 | } |
355 | d->result.clear(); |
356 | } |
357 | |
358 | /*! |
359 | Adds the first \a length chars of \a data to the cryptographic |
360 | hash. |
361 | */ |
362 | void QCryptographicHash::addData(const char *data, int length) |
363 | { |
364 | switch (d->method) { |
365 | case Sha1: |
366 | sha1Update(state: &d->sha1Context, data: (const unsigned char *)data, len: length); |
367 | break; |
368 | #ifdef QT_CRYPTOGRAPHICHASH_ONLY_SHA1 |
369 | default: |
370 | Q_ASSERT_X(false, "QCryptographicHash" , "Method not compiled in" ); |
371 | Q_UNREACHABLE(); |
372 | break; |
373 | #else |
374 | case Md4: |
375 | md4_update(ctx: &d->md4Context, data: (const unsigned char *)data, size: length); |
376 | break; |
377 | case Md5: |
378 | MD5Update(ctx: &d->md5Context, buf: (const unsigned char *)data, len: length); |
379 | break; |
380 | case Sha224: |
381 | SHA224Input(context: &d->sha224Context, message_array: reinterpret_cast<const unsigned char *>(data), length); |
382 | break; |
383 | case Sha256: |
384 | SHA256Input(context: &d->sha256Context, message_array: reinterpret_cast<const unsigned char *>(data), length); |
385 | break; |
386 | case Sha384: |
387 | SHA384Input(context: &d->sha384Context, message_array: reinterpret_cast<const unsigned char *>(data), length); |
388 | break; |
389 | case Sha512: |
390 | SHA512Input(context: &d->sha512Context, message_array: reinterpret_cast<const unsigned char *>(data), length); |
391 | break; |
392 | case RealSha3_224: |
393 | case Keccak_224: |
394 | sha3Update(&d->sha3Context, reinterpret_cast<const BitSequence *>(data), quint64(length) * 8); |
395 | break; |
396 | case RealSha3_256: |
397 | case Keccak_256: |
398 | sha3Update(&d->sha3Context, reinterpret_cast<const BitSequence *>(data), quint64(length) * 8); |
399 | break; |
400 | case RealSha3_384: |
401 | case Keccak_384: |
402 | sha3Update(&d->sha3Context, reinterpret_cast<const BitSequence *>(data), quint64(length) * 8); |
403 | break; |
404 | case RealSha3_512: |
405 | case Keccak_512: |
406 | sha3Update(&d->sha3Context, reinterpret_cast<const BitSequence *>(data), quint64(length) * 8); |
407 | break; |
408 | #endif |
409 | } |
410 | d->result.clear(); |
411 | } |
412 | |
413 | /*! |
414 | \overload addData() |
415 | */ |
416 | void QCryptographicHash::addData(const QByteArray &data) |
417 | { |
418 | addData(data: data.constData(), length: data.length()); |
419 | } |
420 | |
421 | /*! |
422 | Reads the data from the open QIODevice \a device until it ends |
423 | and hashes it. Returns \c true if reading was successful. |
424 | \since 5.0 |
425 | */ |
426 | bool QCryptographicHash::addData(QIODevice* device) |
427 | { |
428 | if (!device->isReadable()) |
429 | return false; |
430 | |
431 | if (!device->isOpen()) |
432 | return false; |
433 | |
434 | char buffer[1024]; |
435 | int length; |
436 | |
437 | while ((length = device->read(data: buffer,maxlen: sizeof(buffer))) > 0) |
438 | addData(data: buffer,length); |
439 | |
440 | return device->atEnd(); |
441 | } |
442 | |
443 | |
444 | /*! |
445 | Returns the final hash value. |
446 | |
447 | \sa QByteArray::toHex() |
448 | */ |
449 | QByteArray QCryptographicHash::result() const |
450 | { |
451 | if (!d->result.isEmpty()) |
452 | return d->result; |
453 | |
454 | switch (d->method) { |
455 | case Sha1: { |
456 | Sha1State copy = d->sha1Context; |
457 | d->result.resize(size: 20); |
458 | sha1FinalizeState(state: ©); |
459 | sha1ToHash(state: ©, buffer: (unsigned char *)d->result.data()); |
460 | break; |
461 | } |
462 | #ifdef QT_CRYPTOGRAPHICHASH_ONLY_SHA1 |
463 | default: |
464 | Q_ASSERT_X(false, "QCryptographicHash" , "Method not compiled in" ); |
465 | Q_UNREACHABLE(); |
466 | break; |
467 | #else |
468 | case Md4: { |
469 | md4_context copy = d->md4Context; |
470 | d->result.resize(MD4_RESULTLEN); |
471 | md4_final(ctx: ©, result: (unsigned char *)d->result.data()); |
472 | break; |
473 | } |
474 | case Md5: { |
475 | MD5Context copy = d->md5Context; |
476 | d->result.resize(size: 16); |
477 | MD5Final(ctx: ©, digest: (unsigned char *)d->result.data()); |
478 | break; |
479 | } |
480 | case Sha224: { |
481 | SHA224Context copy = d->sha224Context; |
482 | d->result.resize(size: SHA224HashSize); |
483 | SHA224Result(context: ©, Message_Digest: reinterpret_cast<unsigned char *>(d->result.data())); |
484 | break; |
485 | } |
486 | case Sha256:{ |
487 | SHA256Context copy = d->sha256Context; |
488 | d->result.resize(size: SHA256HashSize); |
489 | SHA256Result(context: ©, Message_Digest: reinterpret_cast<unsigned char *>(d->result.data())); |
490 | break; |
491 | } |
492 | case Sha384:{ |
493 | SHA384Context copy = d->sha384Context; |
494 | d->result.resize(size: SHA384HashSize); |
495 | SHA384Result(context: ©, Message_Digest: reinterpret_cast<unsigned char *>(d->result.data())); |
496 | break; |
497 | } |
498 | case Sha512:{ |
499 | SHA512Context copy = d->sha512Context; |
500 | d->result.resize(size: SHA512HashSize); |
501 | SHA512Result(context: ©, Message_Digest: reinterpret_cast<unsigned char *>(d->result.data())); |
502 | break; |
503 | } |
504 | case RealSha3_224: { |
505 | d->sha3Finish(bitCount: 224, sha3Variant: QCryptographicHashPrivate::Sha3Variant::Sha3); |
506 | break; |
507 | } |
508 | case RealSha3_256: { |
509 | d->sha3Finish(bitCount: 256, sha3Variant: QCryptographicHashPrivate::Sha3Variant::Sha3); |
510 | break; |
511 | } |
512 | case RealSha3_384: { |
513 | d->sha3Finish(bitCount: 384, sha3Variant: QCryptographicHashPrivate::Sha3Variant::Sha3); |
514 | break; |
515 | } |
516 | case RealSha3_512: { |
517 | d->sha3Finish(bitCount: 512, sha3Variant: QCryptographicHashPrivate::Sha3Variant::Sha3); |
518 | break; |
519 | } |
520 | case Keccak_224: { |
521 | d->sha3Finish(bitCount: 224, sha3Variant: QCryptographicHashPrivate::Sha3Variant::Keccak); |
522 | break; |
523 | } |
524 | case Keccak_256: { |
525 | d->sha3Finish(bitCount: 256, sha3Variant: QCryptographicHashPrivate::Sha3Variant::Keccak); |
526 | break; |
527 | } |
528 | case Keccak_384: { |
529 | d->sha3Finish(bitCount: 384, sha3Variant: QCryptographicHashPrivate::Sha3Variant::Keccak); |
530 | break; |
531 | } |
532 | case Keccak_512: { |
533 | d->sha3Finish(bitCount: 512, sha3Variant: QCryptographicHashPrivate::Sha3Variant::Keccak); |
534 | break; |
535 | } |
536 | #endif |
537 | } |
538 | return d->result; |
539 | } |
540 | |
541 | /*! |
542 | Returns the hash of \a data using \a method. |
543 | */ |
544 | QByteArray QCryptographicHash::hash(const QByteArray &data, Algorithm method) |
545 | { |
546 | QCryptographicHash hash(method); |
547 | hash.addData(data); |
548 | return hash.result(); |
549 | } |
550 | |
551 | /*! |
552 | Returns the size of the output of the selected hash \a method in bytes. |
553 | |
554 | \since 5.12 |
555 | */ |
556 | int QCryptographicHash::hashLength(QCryptographicHash::Algorithm method) |
557 | { |
558 | switch (method) { |
559 | case QCryptographicHash::Sha1: |
560 | return 20; |
561 | #ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1 |
562 | case QCryptographicHash::Md4: |
563 | return 16; |
564 | case QCryptographicHash::Md5: |
565 | return 16; |
566 | case QCryptographicHash::Sha224: |
567 | return SHA224HashSize; |
568 | case QCryptographicHash::Sha256: |
569 | return SHA256HashSize; |
570 | case QCryptographicHash::Sha384: |
571 | return SHA384HashSize; |
572 | case QCryptographicHash::Sha512: |
573 | return SHA512HashSize; |
574 | case QCryptographicHash::RealSha3_224: |
575 | case QCryptographicHash::Keccak_224: |
576 | return 224 / 8; |
577 | case QCryptographicHash::RealSha3_256: |
578 | case QCryptographicHash::Keccak_256: |
579 | return 256 / 8; |
580 | case QCryptographicHash::RealSha3_384: |
581 | case QCryptographicHash::Keccak_384: |
582 | return 384 / 8; |
583 | case QCryptographicHash::RealSha3_512: |
584 | case QCryptographicHash::Keccak_512: |
585 | return 512 / 8; |
586 | #endif |
587 | } |
588 | return 0; |
589 | } |
590 | |
591 | QT_END_NAMESPACE |
592 | |
593 | #ifndef QT_NO_QOBJECT |
594 | #include "moc_qcryptographichash.cpp" |
595 | #endif |
596 | |