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());
|
static_assert(N <= std::numeric_limits<std::uint8_t>::max());
|
||||||
quint8 m_size = 0;
|
quint8 m_size = 0;
|
||||||
public:
|
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(); }
|
quint8 *data() noexcept { return m_data.data(); }
|
||||||
const quint8 *data() const noexcept { return m_data.data(); }
|
const quint8 *data() const noexcept { return m_data.data(); }
|
||||||
qsizetype size() const noexcept { return qsizetype{m_size}; }
|
qsizetype size() const noexcept { return qsizetype{m_size}; }
|
||||||
@ -136,6 +158,11 @@ public:
|
|||||||
Q_ASSERT(n < size());
|
Q_ASSERT(n < size());
|
||||||
return data()[n];
|
return data()[n];
|
||||||
}
|
}
|
||||||
|
const quint8 &operator[](qsizetype n) const
|
||||||
|
{
|
||||||
|
Q_ASSERT(n < size());
|
||||||
|
return data()[n];
|
||||||
|
}
|
||||||
bool isEmpty() const noexcept { return size() == 0; }
|
bool isEmpty() const noexcept { return size() == 0; }
|
||||||
void clear() noexcept { m_size = 0; }
|
void clear() noexcept { m_size = 0; }
|
||||||
void resizeForOverwrite(qsizetype s)
|
void resizeForOverwrite(qsizetype s)
|
||||||
@ -1074,6 +1101,15 @@ constexpr int maxHashBlockSize()
|
|||||||
|
|
||||||
using HashBlock = QSmallByteArray<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
|
class QMessageAuthenticationCodePrivate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -1082,7 +1118,7 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray key;
|
HashBlock key;
|
||||||
HashResult result;
|
HashResult result;
|
||||||
QBasicMutex finalizeMutex;
|
QBasicMutex finalizeMutex;
|
||||||
QCryptographicHashPrivate messageHash;
|
QCryptographicHashPrivate messageHash;
|
||||||
@ -1115,10 +1151,10 @@ void QMessageAuthenticationCodePrivate::setKey(const QByteArray &newKey)
|
|||||||
messageHash.addData(newKey);
|
messageHash.addData(newKey);
|
||||||
messageHash.finalizeUnchecked();
|
messageHash.finalizeUnchecked();
|
||||||
static_assert(maxHashLength() <= maxHashBlockSize());
|
static_assert(maxHashLength() <= maxHashBlockSize());
|
||||||
key = messageHash.resultView().toByteArray();
|
key = messageHash.result;
|
||||||
messageHash.reset();
|
messageHash.reset();
|
||||||
} else {
|
} else {
|
||||||
key = newKey;
|
key.assign(newKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key.size() < blockSize)
|
if (key.size() < blockSize)
|
||||||
@ -1135,15 +1171,7 @@ void QMessageAuthenticationCodePrivate::setKey(const QByteArray &newKey)
|
|||||||
*/
|
*/
|
||||||
void QMessageAuthenticationCodePrivate::initMessageHash()
|
void QMessageAuthenticationCodePrivate::initMessageHash()
|
||||||
{
|
{
|
||||||
const int blockSize = qt_hash_block_size(method);
|
messageHash.addData(xored(key, 0x36));
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -1291,20 +1319,11 @@ void QMessageAuthenticationCodePrivate::finalize()
|
|||||||
|
|
||||||
void QMessageAuthenticationCodePrivate::finalizeUnchecked() noexcept
|
void QMessageAuthenticationCodePrivate::finalizeUnchecked() noexcept
|
||||||
{
|
{
|
||||||
const int blockSize = qt_hash_block_size(method);
|
|
||||||
|
|
||||||
messageHash.finalizeUnchecked();
|
messageHash.finalizeUnchecked();
|
||||||
const HashResult hashedMessage = messageHash.result;
|
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.reset();
|
||||||
messageHash.addData(oKeyPad);
|
messageHash.addData(xored(key, 0x5c));
|
||||||
messageHash.addData(hashedMessage);
|
messageHash.addData(hashedMessage);
|
||||||
messageHash.finalizeUnchecked();
|
messageHash.finalizeUnchecked();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user