summaryrefslogtreecommitdiffstats
path: root/src/corelib/tools/qcryptographichash.cpp
diff options
context:
space:
mode:
authorGiuseppe D'Angelo <giuseppe.dangelo@kdab.com>2017-03-28 20:09:22 +0100
committerGiuseppe D'Angelo <giuseppe.dangelo@kdab.com>2017-03-31 07:58:35 +0000
commit88a8feeacb9bdaff9ee06164424e407eb904cd10 (patch)
tree45bdc0c2d5026b5699f58496f13920531f576ad2 /src/corelib/tools/qcryptographichash.cpp
parentcd9e850f9e9620a8bafec964efad8098443be7f1 (diff)
QCryptographicHash: make SHA3 calculate SHA3, not Keccak
The SHA3 family is a modified version of Keccak. We were incorrectly calculating Keccak (and even *testing* Keccak!), but claiming it was SHA3. To actually calculate SHA3, we need invoke Keccak on the original message followed by the two bits sequence 0b01, cf. §6.1 [1]. [1] http://dx.doi.org/10.6028/NIST.FIPS.202 [ChangeLog][QtCore][QCryptographicHash] QCryptographicHash now properly calculates SHA3 message digests. Before, when asked to calculate a SHA3 digest, it calculated a Keccak digest instead. Task-number: QTBUG-59770 Change-Id: Iae694d1a1668aa676922e3e00a292cddc30d3e0d Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/tools/qcryptographichash.cpp')
-rw-r--r--src/corelib/tools/qcryptographichash.cpp52
1 files changed, 40 insertions, 12 deletions
diff --git a/src/corelib/tools/qcryptographichash.cpp b/src/corelib/tools/qcryptographichash.cpp
index cdd7f6f4f6..963a91b9a9 100644
--- a/src/corelib/tools/qcryptographichash.cpp
+++ b/src/corelib/tools/qcryptographichash.cpp
@@ -180,9 +180,45 @@ public:
SHA3Context sha3Context;
#endif
};
+#ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1
+ void sha3Finish(int bitCount);
+#endif
QByteArray result;
};
+#ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1
+void QCryptographicHashPrivate::sha3Finish(int bitCount)
+{
+ /*
+ FIPS 202 §6.1 defines SHA-3 in terms of calculating the Keccak function
+ over the original message with the two-bit suffix "01" appended to it.
+ This variable stores that suffix (and it's fed into the calculations
+ when the hash is returned to users).
+
+ Only 2 bits of this variable are actually used (see the call to sha3Update
+ below). The Keccak implementation we're using will actually use the
+ *leftmost* 2 bits, and interpret them right-to-left. In other words, the
+ bits must appear in order of *increasing* significance; and as the two most
+ significant bits of the byte -- the rightmost 6 are ignored. (Yes, this
+ seems self-contradictory, but it's the way it is...)
+
+ Overall, this means:
+ * the leftmost two bits must be "10" (not "01"!);
+ * we don't care what the other six bits are set to (they can be set to
+ any value), but we arbitrarily set them to 0;
+
+ and for an unsigned char this gives us 0b10'00'00'00, or 0x80.
+ */
+ static const unsigned char sha3FinalSuffix = 0x80;
+
+ result.resize(bitCount / 8);
+
+ SHA3Context copy = sha3Context;
+ sha3Update(&copy, reinterpret_cast<const BitSequence *>(&sha3FinalSuffix), 2);
+ sha3Final(&copy, reinterpret_cast<BitSequence *>(result.data()));
+}
+#endif
+
/*!
\class QCryptographicHash
\inmodule QtCore
@@ -427,27 +463,19 @@ QByteArray QCryptographicHash::result() const
break;
}
case Sha3_224: {
- SHA3Context copy = d->sha3Context;
- d->result.resize(224/8);
- sha3Final(&copy, reinterpret_cast<BitSequence *>(d->result.data()));
+ d->sha3Finish(224);
break;
}
case Sha3_256: {
- SHA3Context copy = d->sha3Context;
- d->result.resize(256/8);
- sha3Final(&copy, reinterpret_cast<BitSequence *>(d->result.data()));
+ d->sha3Finish(256);
break;
}
case Sha3_384: {
- SHA3Context copy = d->sha3Context;
- d->result.resize(384/8);
- sha3Final(&copy, reinterpret_cast<BitSequence *>(d->result.data()));
+ d->sha3Finish(384);
break;
}
case Sha3_512: {
- SHA3Context copy = d->sha3Context;
- d->result.resize(512/8);
- sha3Final(&copy, reinterpret_cast<BitSequence *>(d->result.data()));
+ d->sha3Finish(512);
break;
}
#endif