diff --git a/src/corelib/tools/qcryptographichash.cpp b/src/corelib/tools/qcryptographichash.cpp index 8c02ea21f9..9f98475dc0 100644 --- a/src/corelib/tools/qcryptographichash.cpp +++ b/src/corelib/tools/qcryptographichash.cpp @@ -164,6 +164,9 @@ static inline int SHA384_512AddLength(SHA512Context *context, unsigned int lengt QT_PREPEND_NAMESPACE(quint64) addTemp; return SHA384_512AddLengthM(context, length); } + +#include "../../3rdparty/blake2/src/blake2b-ref.c" +#include "../../3rdparty/blake2/src/blake2s-ref.c" #endif // QT_CRYPTOGRAPHICHASH_ONLY_SHA1 QT_BEGIN_NAMESPACE @@ -182,6 +185,8 @@ public: SHA384Context sha384Context; SHA512Context sha512Context; SHA3Context sha3Context; + blake2b_state blake2bContext; + blake2s_state blake2sContext; #endif }; #ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1 @@ -277,6 +282,14 @@ void QCryptographicHashPrivate::sha3Finish(int bitCount, Sha3Variant sha3Variant \value Keccak_256 Generate a Keccak-256 hash sum. Introduced in Qt 5.9.2 \value Keccak_384 Generate a Keccak-384 hash sum. Introduced in Qt 5.9.2 \value Keccak_512 Generate a Keccak-512 hash sum. Introduced in Qt 5.9.2 + \value Blake2b_160 Generate a BLAKE2b-160 hash sum. Introduced in Qt 6.0 + \value Blake2b_256 Generate a BLAKE2b-256 hash sum. Introduced in Qt 6.0 + \value Blake2b_384 Generate a BLAKE2b-384 hash sum. Introduced in Qt 6.0 + \value Blake2b_512 Generate a BLAKE2b-512 hash sum. Introduced in Qt 6.0 + \value Blake2s_128 Generate a BLAKE2s-128 hash sum. Introduced in Qt 6.0 + \value Blake2s_160 Generate a BLAKE2s-160 hash sum. Introduced in Qt 6.0 + \value Blake2s_224 Generate a BLAKE2s-224 hash sum. Introduced in Qt 6.0 + \value Blake2s_256 Generate a BLAKE2s-256 hash sum. Introduced in Qt 6.0 \omitvalue RealSha3_224 \omitvalue RealSha3_256 \omitvalue RealSha3_384 @@ -352,6 +365,20 @@ void QCryptographicHash::reset() new (&d->sha3Context) SHA3Context; sha3Init(&d->sha3Context, hashLength(d->method) * 8); break; + case Blake2b_160: + case Blake2b_256: + case Blake2b_384: + case Blake2b_512: + new (&d->blake2bContext) blake2b_state; + blake2b_init(&d->blake2bContext, hashLength(d->method)); + break; + case Blake2s_128: + case Blake2s_160: + case Blake2s_224: + case Blake2s_256: + new (&d->blake2sContext) blake2s_state; + blake2s_init(&d->blake2sContext, hashLength(d->method)); + break; #endif } d->result.clear(); @@ -420,6 +447,18 @@ void QCryptographicHash::addData(const char *data, qsizetype length) case Keccak_512: sha3Update(&d->sha3Context, reinterpret_cast(data), quint64(length) * 8); break; + case Blake2b_160: + case Blake2b_256: + case Blake2b_384: + case Blake2b_512: + blake2b_update(&d->blake2bContext, reinterpret_cast(data), length); + break; + case Blake2s_128: + case Blake2s_160: + case Blake2s_224: + case Blake2s_256: + blake2s_update(&d->blake2sContext, reinterpret_cast(data), length); + break; #endif } } @@ -549,6 +588,26 @@ QByteArray QCryptographicHash::result() const d->sha3Finish(512, QCryptographicHashPrivate::Sha3Variant::Keccak); break; } + case Blake2b_160: + case Blake2b_256: + case Blake2b_384: + case Blake2b_512: { + const auto length = hashLength(d->method); + blake2b_state copy = d->blake2bContext; + d->result.resize(length); + blake2b_final(©, reinterpret_cast(d->result.data()), length); + break; + } + case Blake2s_128: + case Blake2s_160: + case Blake2s_224: + case Blake2s_256: { + const auto length = hashLength(d->method); + blake2s_state copy = d->blake2sContext; + d->result.resize(length); + blake2s_final(©, reinterpret_cast(d->result.data()), length); + break; + } #endif } return d->result; @@ -587,17 +646,27 @@ int QCryptographicHash::hashLength(QCryptographicHash::Algorithm method) return SHA384HashSize; case QCryptographicHash::Sha512: return SHA512HashSize; + case QCryptographicHash::Blake2s_128: + return 128 / 8; + case QCryptographicHash::Blake2b_160: + case QCryptographicHash::Blake2s_160: + return 160 / 8; case QCryptographicHash::RealSha3_224: case QCryptographicHash::Keccak_224: + case QCryptographicHash::Blake2s_224: return 224 / 8; case QCryptographicHash::RealSha3_256: case QCryptographicHash::Keccak_256: + case QCryptographicHash::Blake2b_256: + case QCryptographicHash::Blake2s_256: return 256 / 8; case QCryptographicHash::RealSha3_384: case QCryptographicHash::Keccak_384: + case QCryptographicHash::Blake2b_384: return 384 / 8; case QCryptographicHash::RealSha3_512: case QCryptographicHash::Keccak_512: + case QCryptographicHash::Blake2b_512: return 512 / 8; #endif } diff --git a/src/corelib/tools/qcryptographichash.h b/src/corelib/tools/qcryptographichash.h index f76fe2d013..bef0c4dbe1 100644 --- a/src/corelib/tools/qcryptographichash.h +++ b/src/corelib/tools/qcryptographichash.h @@ -78,13 +78,22 @@ public: Sha3_224 = RealSha3_224, Sha3_256 = RealSha3_256, Sha3_384 = RealSha3_384, - Sha3_512 = RealSha3_512 + Sha3_512 = RealSha3_512, # else Sha3_224 = Keccak_224, Sha3_256 = Keccak_256, Sha3_384 = Keccak_384, - Sha3_512 = Keccak_512 + Sha3_512 = Keccak_512, # endif + + Blake2b_160 = 15, + Blake2b_256, + Blake2b_384, + Blake2b_512, + Blake2s_128, + Blake2s_160, + Blake2s_224, + Blake2s_256, #endif }; Q_ENUM(Algorithm) diff --git a/src/corelib/tools/qmessageauthenticationcode.cpp b/src/corelib/tools/qmessageauthenticationcode.cpp index 40a1193622..d84b1b0b6c 100644 --- a/src/corelib/tools/qmessageauthenticationcode.cpp +++ b/src/corelib/tools/qmessageauthenticationcode.cpp @@ -75,6 +75,8 @@ // sha1.h - commented out '#include ' on line 74 #include "../../3rdparty/rfc6234/sha.h" +#include "../../3rdparty/blake2/src/blake2.h" + #undef uint64_t #undef uint32_t #undef uint68_t @@ -111,6 +113,16 @@ static int qt_hash_block_size(QCryptographicHash::Algorithm method) case QCryptographicHash::RealSha3_512: case QCryptographicHash::Keccak_512: return 72; + case QCryptographicHash::Blake2b_160: + case QCryptographicHash::Blake2b_256: + case QCryptographicHash::Blake2b_384: + case QCryptographicHash::Blake2b_512: + return BLAKE2B_BLOCKBYTES; + case QCryptographicHash::Blake2s_128: + case QCryptographicHash::Blake2s_160: + case QCryptographicHash::Blake2s_224: + case QCryptographicHash::Blake2s_256: + return BLAKE2S_BLOCKBYTES; } return 0; } diff --git a/tests/auto/corelib/tools/qcryptographichash/tst_qcryptographichash.cpp b/tests/auto/corelib/tools/qcryptographichash/tst_qcryptographichash.cpp index 3eef7631c8..436734f05a 100644 --- a/tests/auto/corelib/tools/qcryptographichash/tst_qcryptographichash.cpp +++ b/tests/auto/corelib/tools/qcryptographichash/tst_qcryptographichash.cpp @@ -44,6 +44,8 @@ private slots: void sha1(); void sha3_data(); void sha3(); + void blake2_data(); + void blake2(); void files_data(); void files(); void hashLength(); @@ -264,6 +266,110 @@ void tst_QCryptographicHash::sha3() QCOMPARE(result, expectedResult); } +void tst_QCryptographicHash::blake2_data() +{ + QTest::addColumn("algorithm"); + QTest::addColumn("data"); + QTest::addColumn("expectedResult"); + +#define ROW(Tag, Algorithm, Input, Result) \ + QTest::newRow(Tag) << Algorithm << QByteArrayLiteral(Input) << QByteArray::fromHex(Result) + + // BLAKE2b + ROW("blake2b_160_pangram", + QCryptographicHash::Blake2b_160, + "The quick brown fox jumps over the lazy dog", + "3c523ed102ab45a37d54f5610d5a983162fde84f"); + + ROW("blake2b_160_pangram_dot", + QCryptographicHash::Blake2b_160, + "The quick brown fox jumps over the lazy dog.", + "d0c8bb0bdd830296d1d4f4348176699ccccc16bb"); + + ROW("blake2b_256_pangram", + QCryptographicHash::Blake2b_256, + "The quick brown fox jumps over the lazy dog", + "01718cec35cd3d796dd00020e0bfecb473ad23457d063b75eff29c0ffa2e58a9"); + + ROW("blake2b_256_pangram_dot", + QCryptographicHash::Blake2b_256, + "The quick brown fox jumps over the lazy dog.", + "69d7d3b0afba81826d27024c17f7f183659ed0812cf27b382eaef9fdc29b5712"); + + ROW("blake2b_384_pangram", + QCryptographicHash::Blake2b_384, + "The quick brown fox jumps over the lazy dog", + "b7c81b228b6bd912930e8f0b5387989691c1cee1e65aade4da3b86a3c9f678fc8018f6ed9e2906720c8d2a3aeda9c03d"); + + ROW("blake2b_384_pangram_dot", + QCryptographicHash::Blake2b_384, + "The quick brown fox jumps over the lazy dog.", + "16d65de1a3caf1c26247234c39af636284c7e19ca448c0de788272081410778852c94d9cef6b939968d4f872c7f78337"); + + ROW("blake2b_512_pangram", + QCryptographicHash::Blake2b_512, + "The quick brown fox jumps over the lazy dog", + "a8add4bdddfd93e4877d2746e62817b116364a1fa7bc148d95090bc7333b3673f82401cf7aa2e4cb1ecd90296e3f14cb5413f8ed77be73045b13914cdcd6a918"); + + ROW("blake2b_512_pangram_dot", + QCryptographicHash::Blake2b_512, + "The quick brown fox jumps over the lazy dog.", + "87af9dc4afe5651b7aa89124b905fd214bf17c79af58610db86a0fb1e0194622a4e9d8e395b352223a8183b0d421c0994b98286cbf8c68a495902e0fe6e2bda2"); + + // BLAKE2s + ROW("blake2s_128_pangram", + QCryptographicHash::Blake2s_128, + "The quick brown fox jumps over the lazy dog", + "96fd07258925748a0d2fb1c8a1167a73"); + + ROW("blake2s_128_pangram_dot", + QCryptographicHash::Blake2s_128, + "The quick brown fox jumps over the lazy dog.", + "1f298f2e1f9c2490e506c2308f64e7c0"); + + ROW("blake2s_160_pangram", + QCryptographicHash::Blake2s_160, + "The quick brown fox jumps over the lazy dog", + "5a604fec9713c369e84b0ed68daed7d7504ef240"); + + ROW("blake2s_160_pangram_dot", + QCryptographicHash::Blake2s_160, + "The quick brown fox jumps over the lazy dog.", + "cd4a863226463aac852662d16275d399966e3ffe"); + + ROW("blake2s_224_pangram", + QCryptographicHash::Blake2s_224, + "The quick brown fox jumps over the lazy dog", + "e4e5cb6c7cae41982b397bf7b7d2d9d1949823ae78435326e8db4912"); + + ROW("blake2s_224_pangram_dot", + QCryptographicHash::Blake2s_224, + "The quick brown fox jumps over the lazy dog.", + "fd1557500ef49f308882969507acd18a13e155c26f8fcd82f9bf2ff7"); + + ROW("blake2s_256_pangram", + QCryptographicHash::Blake2s_256, + "The quick brown fox jumps over the lazy dog", + "606beeec743ccbeff6cbcdf5d5302aa855c256c29b88c8ed331ea1a6bf3c8812"); + + ROW("blake2s_256_pangram_dot", + QCryptographicHash::Blake2s_256, + "The quick brown fox jumps over the lazy dog.", + "95bca6e1b761dca1323505cc629949a0e03edf11633cc7935bd8b56f393afcf2"); + +#undef ROW +} + +void tst_QCryptographicHash::blake2() +{ + QFETCH(QCryptographicHash::Algorithm, algorithm); + QFETCH(QByteArray, data); + QFETCH(QByteArray, expectedResult); + + const auto result = QCryptographicHash::hash(data, algorithm); + QCOMPARE(result, expectedResult); +} + void tst_QCryptographicHash::files_data() { QTest::addColumn("filename"); QTest::addColumn("algorithm");