QCryptographicHash: Add BLAKE2b and BLAKE2s hashing algorithms

BLAKE2 does not specify requirements about specific hash sizes and
since QCryptographicHash does not support dynamic hash sizes, only the
most common hash sizes could be covered by this.

The supported hash sizes were chosen to match the ones supported by the
Linux kernel.

The new hashing algorithms for QCryptographicHash are:
 * BLAKE2b (160 bit, 256 bit, 384 bit, 512 bit)
 * BLAKE2s (128 bit, 160 bit, 224 bit, 256 bit)

[ChangeLog][QtCore][QCryptographicHash] Added BLAKE2b and BLAKE2s
hashing algorithms.

Fixes: QTBUG-78198
Change-Id: Id9e0180a974093982fdf1cdd6180988a2e5e9f4f
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Linus Jahn 2019-11-28 19:42:23 +01:00
parent 06f7a24574
commit 5d69aa3ee1
4 changed files with 198 additions and 2 deletions

View File

@ -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<const BitSequence *>(data), quint64(length) * 8);
break;
case Blake2b_160:
case Blake2b_256:
case Blake2b_384:
case Blake2b_512:
blake2b_update(&d->blake2bContext, reinterpret_cast<const uint8_t *>(data), length);
break;
case Blake2s_128:
case Blake2s_160:
case Blake2s_224:
case Blake2s_256:
blake2s_update(&d->blake2sContext, reinterpret_cast<const uint8_t *>(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(&copy, reinterpret_cast<uint8_t *>(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(&copy, reinterpret_cast<uint8_t *>(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
}

View File

@ -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)

View File

@ -75,6 +75,8 @@
// sha1.h - commented out '#include <stdint.h>' 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;
}

View File

@ -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<QCryptographicHash::Algorithm>("algorithm");
QTest::addColumn<QByteArray>("data");
QTest::addColumn<QByteArray>("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<QString>("filename");
QTest::addColumn<QCryptographicHash::Algorithm>("algorithm");