From 5f4061aec36082c3c263497b8397639dd7035407 Mon Sep 17 00:00:00 2001 From: lifegpc Date: Mon, 12 May 2025 18:18:32 +0800 Subject: [PATCH] add HMAC support --- hash_lib.h | 64 ++++++++++++++++++++++++++++++++++++++++++ test/hash_lib_test.cpp | 9 ++++++ 2 files changed, 73 insertions(+) diff --git a/hash_lib.h b/hash_lib.h index 1f15e7f..f42d93d 100644 --- a/hash_lib.h +++ b/hash_lib.h @@ -127,6 +127,70 @@ namespace hash_lib { size_t hashBlocks(const uint8_t* m, size_t pos, size_t len); }; template + class HMAC: public Hash { + public: + HMAC(const uint8_t* key, size_t len) { + int blockSize = _outer.blockSize(); + std::vector pad(blockSize); + if (len > blockSize) { + _inner.update(key, len)->finish(pad)->clean(); + } else { + memcpy(pad.data(), key, len); + } + _pad = std::move(pad); + reset(); + } + HMAC(const std::string& key) : HMAC((const uint8_t*)key.c_str(), key.size()) {} + HMAC(const std::vector& key) : HMAC(key.data(), key.size()) {} + template + HMAC(const uint8_t (&key)[T]) : HMAC(key, T) {} + Hash* reset() override { + _inner.clean(); + _outer.clean(); + int blockSize = _outer.blockSize(); + auto pad(_pad); + for (int i = 0; i < blockSize; i++) { + pad[i] ^= 0x36; + } + _inner.update(pad); + for (int i = 0; i < blockSize; i++) { + pad[i] ^= 0x36 ^ 0x5c; + } + _outer.update(pad); + _finished = false; + return this; + } + int digestLength() override { + return _outer.digestLength(); + } + int blockSize() override { + return _outer.blockSize(); + } + Hash* update(const uint8_t* data, size_t len) override { + _inner.update(data, len); + return this; + } + using Hash::update; + Hash* finish(uint8_t* data, size_t len) override { + if (_finished) { + _outer.finish(data, len); + return this; + } + _outer.update(_inner.digest())->finish(data, len); + _finished = true; + return this; + } + using Hash::finish; + void clean() override { + reset(); + } + private: + H _inner; + H _outer; + std::vector _pad; + bool _finished = false; + }; + template std::vector hash(const uint8_t* data, size_t len) { H h; h.update(data, len); diff --git a/test/hash_lib_test.cpp b/test/hash_lib_test.cpp index d9e92a1..f8748cb 100644 --- a/test/hash_lib_test.cpp +++ b/test/hash_lib_test.cpp @@ -48,3 +48,12 @@ TEST(HashLibTest, SHA1Test) { GTEST_ASSERT_EQ(hashHex("Hello, World!"), "0a0a9f2a6772942557ab5355d76af442f8f65e01"); GTEST_ASSERT_EQ(hashHex("随便来一些中文。测试超过一百二十八字节时的状况。用于测试是否存在问题。还是不够长呢。啊啊啊。"), "21c05e3532d593ec382b8e361d43a17e8fb8774a"); } + +TEST(HashLibTest, HMACClassTest) { + HMAC hmac("key"); + hmac.update("Hello, World!"); + GTEST_ASSERT_EQ(hmac.hexDigest(), "7b735ac190ebd1432d56f95ae2aea5a04a23128f4c228e299b7a49fb7561de8cc8f4fdf4486dc743dfd07827d617273aab42b3bf819d243ded322fac167419f1"); + hmac.clean(); + hmac.update("Hello, World!"); + GTEST_ASSERT_EQ(hmac.hexDigest(), "7b735ac190ebd1432d56f95ae2aea5a04a23128f4c228e299b7a49fb7561de8cc8f4fdf4486dc743dfd07827d617273aab42b3bf819d243ded322fac167419f1"); +}