QMessageAuthenticationCode: use QSmallByteArray for the key
Add more API to QSmallByteArray: - const op[] overload - copy construction and -assignment from QSmallByteArrays with smaller N (for implicitly converting a HashResult into a HashBlock, incl. a static assertion that it always fits - STL-style assign() This allows us to use HashBlock for the key, instead of a QByteArray. To make-it-cool®, add a method that xor's all bytes in a QSmallByteArray with a given value and returns the result. We use that algorithm twice in the implementation, and the code simplification at the call sites is amazing. Pick-to: 6.5 Change-Id: I7fbc11538544b4a8d1771dc8ad025be154d446df Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
parent
18aa3309a4
commit
1fb0dca140
@ -127,7 +127,29 @@ class QSmallByteArray
|
||||
static_assert(N <= std::numeric_limits<std::uint8_t>::max());
|
||||
quint8 m_size = 0;
|
||||
public:
|
||||
// all SMFs are ok!
|
||||
QSmallByteArray() = default;
|
||||
// all compiler-generated SMFs are ok!
|
||||
template <std::size_t M, std::enable_if_t<M < N, bool> = true> // M == N is for copy ctor!
|
||||
QSmallByteArray(const QSmallByteArray<M> &other) noexcept
|
||||
{
|
||||
assign(other);
|
||||
}
|
||||
template <std::size_t M, std::enable_if_t<M < N, bool> = true> // M == N is for copy-assignment op!
|
||||
QSmallByteArray &operator=(const QSmallByteArray<M> &other) noexcept
|
||||
{
|
||||
assign(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Container> // ### underconstrained
|
||||
void assign(const Container &c)
|
||||
{
|
||||
const size_t otherSize = size_t(std::size(c));
|
||||
Q_ASSERT(otherSize < N);
|
||||
memcpy(data(), std::data(c), otherSize);
|
||||
m_size = quint8(otherSize);
|
||||
}
|
||||
|
||||
quint8 *data() noexcept { return m_data.data(); }
|
||||
const quint8 *data() const noexcept { return m_data.data(); }
|
||||
qsizetype size() const noexcept { return qsizetype{m_size}; }
|
||||
@ -136,6 +158,11 @@ public:
|
||||
Q_ASSERT(n < size());
|
||||
return data()[n];
|
||||
}
|
||||
const quint8 &operator[](qsizetype n) const
|
||||
{
|
||||
Q_ASSERT(n < size());
|
||||
return data()[n];
|
||||
}
|
||||
bool isEmpty() const noexcept { return size() == 0; }
|
||||
void clear() noexcept { m_size = 0; }
|
||||
void resizeForOverwrite(qsizetype s)
|
||||
@ -1074,6 +1101,15 @@ constexpr int maxHashBlockSize()
|
||||
|
||||
using HashBlock = QSmallByteArray<maxHashBlockSize()>;
|
||||
|
||||
static HashBlock xored(const HashBlock &block, quint8 val) noexcept
|
||||
{
|
||||
HashBlock result;
|
||||
result.resizeForOverwrite(block.size());
|
||||
for (qsizetype i = 0; i < block.size(); ++i)
|
||||
result[i] = block[i] ^ val;
|
||||
return result;
|
||||
}
|
||||
|
||||
class QMessageAuthenticationCodePrivate
|
||||
{
|
||||
public:
|
||||
@ -1082,7 +1118,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
QByteArray key;
|
||||
HashBlock key;
|
||||
HashResult result;
|
||||
QBasicMutex finalizeMutex;
|
||||
QCryptographicHashPrivate messageHash;
|
||||
@ -1115,10 +1151,10 @@ void QMessageAuthenticationCodePrivate::setKey(const QByteArray &newKey)
|
||||
messageHash.addData(newKey);
|
||||
messageHash.finalizeUnchecked();
|
||||
static_assert(maxHashLength() <= maxHashBlockSize());
|
||||
key = messageHash.resultView().toByteArray();
|
||||
key = messageHash.result;
|
||||
messageHash.reset();
|
||||
} else {
|
||||
key = newKey;
|
||||
key.assign(newKey);
|
||||
}
|
||||
|
||||
if (key.size() < blockSize)
|
||||
@ -1135,15 +1171,7 @@ void QMessageAuthenticationCodePrivate::setKey(const QByteArray &newKey)
|
||||
*/
|
||||
void QMessageAuthenticationCodePrivate::initMessageHash()
|
||||
{
|
||||
const int blockSize = qt_hash_block_size(method);
|
||||
|
||||
QVarLengthArray<char> iKeyPad(blockSize);
|
||||
const char * const keyData = key.constData();
|
||||
|
||||
for (int i = 0; i < blockSize; ++i)
|
||||
iKeyPad[i] = keyData[i] ^ 0x36;
|
||||
|
||||
messageHash.addData(iKeyPad);
|
||||
messageHash.addData(xored(key, 0x36));
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -1291,20 +1319,11 @@ void QMessageAuthenticationCodePrivate::finalize()
|
||||
|
||||
void QMessageAuthenticationCodePrivate::finalizeUnchecked() noexcept
|
||||
{
|
||||
const int blockSize = qt_hash_block_size(method);
|
||||
|
||||
messageHash.finalizeUnchecked();
|
||||
const HashResult hashedMessage = messageHash.result;
|
||||
|
||||
HashBlock oKeyPad;
|
||||
oKeyPad.resizeForOverwrite(blockSize);
|
||||
const char * const keyData = key.constData();
|
||||
|
||||
for (int i = 0; i < blockSize; ++i)
|
||||
oKeyPad[i] = keyData[i] ^ 0x5c;
|
||||
|
||||
messageHash.reset();
|
||||
messageHash.addData(oKeyPad);
|
||||
messageHash.addData(xored(key, 0x5c));
|
||||
messageHash.addData(hashedMessage);
|
||||
messageHash.finalizeUnchecked();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user