Make Hmac rekey-initializable (like Arc4Gen)
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user