Make Hmac rekey-initializable (like Arc4Gen)

This commit is contained in:
hashlag
2025-08-26 00:37:13 +03:00
parent 30e7740eae
commit 8843589950
2 changed files with 49 additions and 3 deletions

View File

@@ -6,6 +6,7 @@
#include <type_traits> #include <type_traits>
#include "Hash/Hasher.hpp" #include "Hash/Hasher.hpp"
#include "Service/ChaosException.hpp"
namespace Chaos::Mac::Hmac namespace Chaos::Mac::Hmac
{ {
@@ -15,23 +16,33 @@ template<typename HasherImpl,
class Hmac class Hmac
{ {
public: public:
Hmac()
: IsInitialized_(false)
{ }
template<typename InputIt> template<typename InputIt>
Hmac(InputIt keyBegin, InputIt keyEnd) Hmac(InputIt keyBegin, InputIt keyEnd)
{ {
Key_ = GenerateKey(keyBegin, keyEnd); RekeyImpl(keyBegin, keyEnd);
}
KeyType ipaddedKey = PadKey<IPAD_BYTE>(Key_); template<typename InputIt>
Hasher_.Update(ipaddedKey.begin(), ipaddedKey.end()); void Rekey(InputIt keyBegin, InputIt keyEnd)
{
RekeyImpl(keyBegin, keyEnd);
} }
template<typename InputIt> template<typename InputIt>
void Update(InputIt begin, InputIt end) void Update(InputIt begin, InputIt end)
{ {
EnsureInitialized();
Hasher_.Update(begin, end); Hasher_.Update(begin, end);
} }
typename HasherImpl::HashType Finish() typename HasherImpl::HashType Finish()
{ {
EnsureInitialized();
auto innerDigest = Hasher_.Finish().GetRawDigest(); auto innerDigest = Hasher_.Finish().GetRawDigest();
Hasher_.Reset(); Hasher_.Reset();
@@ -49,9 +60,19 @@ private:
static constexpr uint8_t OPAD_BYTE = 0x5c; static constexpr uint8_t OPAD_BYTE = 0x5c;
static constexpr uint8_t IPAD_BYTE = 0x36; static constexpr uint8_t IPAD_BYTE = 0x36;
bool IsInitialized_;
KeyType Key_; KeyType Key_;
HasherImpl Hasher_; HasherImpl Hasher_;
void EnsureInitialized() const
{
if (!IsInitialized_)
{
throw Service::ChaosException("Hmac: not initialized");
}
}
template<typename InputIt> template<typename InputIt>
static KeyType GenerateKey(InputIt keyBegin, InputIt keyEnd) static KeyType GenerateKey(InputIt keyBegin, InputIt keyEnd)
{ {
@@ -108,6 +129,18 @@ private:
return paddedKey; return paddedKey;
} }
template<typename InputIt>
void RekeyImpl(InputIt keyBegin, InputIt keyEnd)
{
Key_ = GenerateKey(keyBegin, keyEnd);
Hasher_.Reset();
KeyType ipaddedKey = PadKey<IPAD_BYTE>(Key_);
Hasher_.Update(ipaddedKey.begin(), ipaddedKey.end());
IsInitialized_ = true;
}
}; };
} // namespace Chaos::Mac::Hmac } // namespace Chaos::Mac::Hmac

View File

@@ -72,3 +72,16 @@ TEST(HmacTests, LongKeyTest)
ASSERT_EQ("99459b85e800f3e5eab24e1c945794f8", hmacMd5(key, data)); ASSERT_EQ("99459b85e800f3e5eab24e1c945794f8", hmacMd5(key, data));
} }
} }
TEST(HmacTests, UninitializedHmacTest)
{
std::array<uint8_t, 10> in;
in.fill(0);
{
Hmac<Md5Hasher> hmac;
ASSERT_THROW(hmac.Update(in.begin(), in.end()), Chaos::Service::ChaosException);
ASSERT_THROW(hmac.Finish(), Chaos::Service::ChaosException);
}
}