mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-06-08 05:27:14 +09:00
LibCrypto: Refactor HMAC
implementations with OpenSSL
This commit is contained in:
parent
c5d0af54d0
commit
80fe259dab
Notes:
github-actions[bot]
2025-03-02 14:12:54 +00:00
Author: https://github.com/devgianlu
Commit: 80fe259dab
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3749
Reviewed-by: https://github.com/konradekk
7 changed files with 153 additions and 123 deletions
69
Libraries/LibCrypto/Authentication/HMAC.cpp
Normal file
69
Libraries/LibCrypto/Authentication/HMAC.cpp
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright (c) 2025, Altomani Gianluca <altomanigianluca@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibCrypto/Authentication/HMAC.h>
|
||||
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/evp.h>
|
||||
|
||||
namespace Crypto::Authentication {
|
||||
|
||||
HMAC::HMAC(Hash::HashKind hash_kind, ReadonlyBytes key)
|
||||
: m_hash_kind(hash_kind)
|
||||
, m_key(key)
|
||||
, m_mac(EVP_MAC_fetch(nullptr, "HMAC", nullptr))
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
HMAC::~HMAC()
|
||||
{
|
||||
EVP_MAC_free(m_mac);
|
||||
EVP_MAC_CTX_free(m_ctx);
|
||||
}
|
||||
|
||||
size_t HMAC::digest_size() const
|
||||
{
|
||||
return EVP_MAC_CTX_get_mac_size(m_ctx);
|
||||
}
|
||||
|
||||
void HMAC::update(u8 const* message, size_t length)
|
||||
{
|
||||
if (EVP_MAC_update(m_ctx, message, length) != 1) {
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
ByteBuffer HMAC::digest()
|
||||
{
|
||||
auto buf = MUST(ByteBuffer::create_uninitialized(digest_size()));
|
||||
|
||||
auto size = digest_size();
|
||||
if (EVP_MAC_final(m_ctx, buf.data(), &size, size) != 1) {
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
return MUST(buf.slice(0, size));
|
||||
}
|
||||
|
||||
void HMAC::reset()
|
||||
{
|
||||
EVP_MAC_CTX_free(m_ctx);
|
||||
m_ctx = EVP_MAC_CTX_new(m_mac);
|
||||
|
||||
auto hash_name = MUST(hash_kind_to_openssl_digest_name(m_hash_kind));
|
||||
|
||||
OSSL_PARAM params[] = {
|
||||
OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_DIGEST, const_cast<char*>(hash_name.characters_without_null_termination()), hash_name.length()),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
|
||||
if (EVP_MAC_init(m_ctx, m_key.data(), m_key.size(), params) != 1) {
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2020, Ali Mohammad Pur <mpfard@serenityos.org>
|
||||
* Copyright (c) 2025, Altomani Gianluca <altomanigianluca@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -8,110 +9,51 @@
|
|||
|
||||
#include <AK/ByteBuffer.h>
|
||||
#include <AK/ByteString.h>
|
||||
#include <AK/StringBuilder.h>
|
||||
#include <AK/StringView.h>
|
||||
#include <AK/Types.h>
|
||||
#include <AK/Vector.h>
|
||||
|
||||
constexpr static auto IPAD = 0x36;
|
||||
constexpr static auto OPAD = 0x5c;
|
||||
#include <LibCrypto/Hash/HashManager.h>
|
||||
#include <LibCrypto/OpenSSL.h>
|
||||
#include <LibCrypto/OpenSSLForward.h>
|
||||
|
||||
namespace Crypto::Authentication {
|
||||
|
||||
template<typename HashT>
|
||||
class HMAC {
|
||||
public:
|
||||
using HashType = HashT;
|
||||
using TagType = typename HashType::DigestType;
|
||||
explicit HMAC(Hash::HashKind hash, ReadonlyBytes key);
|
||||
~HMAC();
|
||||
|
||||
size_t digest_size() const { return m_inner_hasher->digest_size(); }
|
||||
size_t digest_size() const;
|
||||
|
||||
template<typename KeyBufferType, typename... Args>
|
||||
HMAC(KeyBufferType key, Args... args)
|
||||
: m_inner_hasher(move(HashT::create(args...)))
|
||||
, m_outer_hasher(move(HashT::create(args...)))
|
||||
{
|
||||
derive_key(key);
|
||||
reset();
|
||||
}
|
||||
void update(u8 const* message, size_t length);
|
||||
void update(ReadonlyBytes span) { return update(span.data(), span.size()); }
|
||||
void update(StringView string) { return update((u8 const*)string.characters_without_null_termination(), string.length()); }
|
||||
|
||||
TagType process(u8 const* message, size_t length)
|
||||
ByteBuffer process(u8 const* message, size_t length)
|
||||
{
|
||||
reset();
|
||||
update(message, length);
|
||||
return digest();
|
||||
}
|
||||
ByteBuffer process(ReadonlyBytes span) { return process(span.data(), span.size()); }
|
||||
ByteBuffer process(StringView string) { return process((u8 const*)string.characters_without_null_termination(), string.length()); }
|
||||
|
||||
void update(u8 const* message, size_t length)
|
||||
{
|
||||
m_inner_hasher->update(message, length);
|
||||
}
|
||||
ByteBuffer digest();
|
||||
|
||||
TagType process(ReadonlyBytes span) { return process(span.data(), span.size()); }
|
||||
TagType process(StringView string) { return process((u8 const*)string.characters_without_null_termination(), string.length()); }
|
||||
|
||||
void update(ReadonlyBytes span) { return update(span.data(), span.size()); }
|
||||
void update(StringView string) { return update((u8 const*)string.characters_without_null_termination(), string.length()); }
|
||||
|
||||
TagType digest()
|
||||
{
|
||||
m_outer_hasher->update(m_inner_hasher->digest().immutable_data(), m_inner_hasher->digest_size());
|
||||
auto result = m_outer_hasher->digest();
|
||||
reset();
|
||||
return result;
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
m_inner_hasher->reset();
|
||||
m_outer_hasher->reset();
|
||||
m_inner_hasher->update(m_key_data, m_inner_hasher->block_size());
|
||||
m_outer_hasher->update(m_key_data + m_inner_hasher->block_size(), m_outer_hasher->block_size());
|
||||
}
|
||||
void reset();
|
||||
|
||||
ByteString class_name() const
|
||||
{
|
||||
auto hash_name = MUST(hash_kind_to_openssl_digest_name(m_hash_kind));
|
||||
|
||||
StringBuilder builder;
|
||||
builder.append("HMAC-"sv);
|
||||
builder.append(m_inner_hasher->class_name());
|
||||
builder.append(hash_name);
|
||||
return builder.to_byte_string();
|
||||
}
|
||||
|
||||
private:
|
||||
void derive_key(u8 const* key, size_t length)
|
||||
{
|
||||
auto block_size = m_inner_hasher->block_size();
|
||||
// Note: The block size of all the current hash functions is 512 bits.
|
||||
Vector<u8, 64> v_key;
|
||||
v_key.resize(block_size);
|
||||
auto key_buffer = v_key.span();
|
||||
// m_key_data is zero'd, so copying the data in
|
||||
// the first few bytes leaves the rest zero, which
|
||||
// is exactly what we want (zero padding)
|
||||
if (length > block_size) {
|
||||
m_inner_hasher->update(key, length);
|
||||
auto digest = m_inner_hasher->digest();
|
||||
// FIXME: should we check if the hash function creates more data than its block size?
|
||||
key_buffer.overwrite(0, digest.immutable_data(), m_inner_hasher->digest_size());
|
||||
} else if (length > 0) {
|
||||
key_buffer.overwrite(0, key, length);
|
||||
}
|
||||
|
||||
// fill out the inner and outer padded keys
|
||||
auto* i_key = m_key_data;
|
||||
auto* o_key = m_key_data + block_size;
|
||||
for (size_t i = 0; i < block_size; ++i) {
|
||||
auto key_byte = key_buffer[i];
|
||||
i_key[i] = key_byte ^ IPAD;
|
||||
o_key[i] = key_byte ^ OPAD;
|
||||
}
|
||||
}
|
||||
|
||||
void derive_key(ReadonlyBytes key) { derive_key(key.data(), key.size()); }
|
||||
void derive_key(StringView key) { derive_key(key.bytes()); }
|
||||
|
||||
NonnullOwnPtr<HashType> m_inner_hasher, m_outer_hasher;
|
||||
u8 m_key_data[2048];
|
||||
Hash::HashKind m_hash_kind;
|
||||
ReadonlyBytes m_key;
|
||||
EVP_MAC* m_mac { nullptr };
|
||||
EVP_MAC_CTX* m_ctx { nullptr };
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ set(SOURCES
|
|||
ASN1/DER.cpp
|
||||
ASN1/PEM.cpp
|
||||
Authentication/GHash.cpp
|
||||
Authentication/HMAC.cpp
|
||||
BigFraction/BigFraction.cpp
|
||||
BigInt/Algorithms/BitwiseOperations.cpp
|
||||
BigInt/Algorithms/Division.cpp
|
||||
|
|
|
@ -47,6 +47,8 @@ ErrorOr<UnsignedBigInteger> openssl_bignum_to_unsigned_big_integer(OpenSSL_BN co
|
|||
ErrorOr<StringView> hash_kind_to_openssl_digest_name(Hash::HashKind hash)
|
||||
{
|
||||
switch (hash) {
|
||||
case Hash::HashKind::MD5:
|
||||
return "MD5"sv;
|
||||
case Hash::HashKind::SHA1:
|
||||
return "SHA1"sv;
|
||||
case Hash::HashKind::SHA256:
|
||||
|
|
|
@ -15,6 +15,8 @@ typedef struct evp_pkey_st EVP_PKEY;
|
|||
typedef struct evp_pkey_ctx_st EVP_PKEY_CTX;
|
||||
typedef struct evp_kdf_st EVP_KDF;
|
||||
typedef struct evp_kdf_ctx_st EVP_KDF_CTX;
|
||||
typedef struct evp_mac_st EVP_MAC;
|
||||
typedef struct evp_mac_ctx_st EVP_MAC_CTX;
|
||||
|
||||
void ERR_print_errors_cb(int (*cb)(char const* str, size_t len, void* u), void* u);
|
||||
|
||||
|
|
|
@ -7781,21 +7781,21 @@ WebIDL::ExceptionOr<GC::Ref<CryptoKey>> X448::import_key(
|
|||
|
||||
static WebIDL::ExceptionOr<ByteBuffer> hmac_calculate_message_digest(JS::Realm& realm, GC::Ptr<KeyAlgorithm> hash, ReadonlyBytes key, ReadonlyBytes message)
|
||||
{
|
||||
auto calculate_digest = [&]<typename T>() -> ByteBuffer {
|
||||
::Crypto::Authentication::HMAC<T> hmac(key);
|
||||
auto digest = hmac.process(message);
|
||||
return MUST(ByteBuffer::copy(digest.bytes()));
|
||||
};
|
||||
auto hash_name = hash->name();
|
||||
if (hash_name == "SHA-1")
|
||||
return calculate_digest.operator()<::Crypto::Hash::SHA1>();
|
||||
if (hash_name == "SHA-256")
|
||||
return calculate_digest.operator()<::Crypto::Hash::SHA256>();
|
||||
if (hash_name == "SHA-384")
|
||||
return calculate_digest.operator()<::Crypto::Hash::SHA384>();
|
||||
if (hash_name == "SHA-512")
|
||||
return calculate_digest.operator()<::Crypto::Hash::SHA512>();
|
||||
return WebIDL::NotSupportedError::create(realm, "Invalid algorithm"_string);
|
||||
auto hash_kind = TRY([&] -> WebIDL::ExceptionOr<::Crypto::Hash::HashKind> {
|
||||
if (hash_name == "SHA-1")
|
||||
return ::Crypto::Hash::HashKind::SHA1;
|
||||
if (hash_name == "SHA-256")
|
||||
return ::Crypto::Hash::HashKind::SHA256;
|
||||
if (hash_name == "SHA-384")
|
||||
return ::Crypto::Hash::HashKind::SHA384;
|
||||
if (hash_name == "SHA-512")
|
||||
return ::Crypto::Hash::HashKind::SHA512;
|
||||
return WebIDL::NotSupportedError::create(realm, MUST(String::formatted("Invalid hash function '{}'", hash_name)));
|
||||
}());
|
||||
|
||||
::Crypto::Authentication::HMAC hmac(hash_kind, key);
|
||||
return hmac.process(message);
|
||||
}
|
||||
|
||||
static WebIDL::ExceptionOr<WebIDL::UnsignedLong> hmac_hash_block_size(JS::Realm& realm, HashAlgorithmIdentifier hash)
|
||||
|
|
|
@ -1,52 +1,58 @@
|
|||
/*
|
||||
* Copyright (c) 2021, [your name here] <[your email here]>
|
||||
* Copyright (c) 2021, the Ladybird developers.
|
||||
* Copyright (c) 2025, Altomani Gianluca <altomanigianluca@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibCrypto/Authentication/HMAC.h>
|
||||
#include <LibCrypto/Hash/MD5.h>
|
||||
#include <LibCrypto/Hash/SHA1.h>
|
||||
#include <LibCrypto/Hash/SHA2.h>
|
||||
#include <LibTest/TestCase.h>
|
||||
#include <cstring>
|
||||
|
||||
static ByteBuffer operator""_b(char const* string, size_t length)
|
||||
{
|
||||
return MUST(ByteBuffer::copy(string, length));
|
||||
}
|
||||
|
||||
TEST_CASE(test_hmac_md5_name)
|
||||
{
|
||||
Crypto::Authentication::HMAC<Crypto::Hash::MD5> hmac("Well Hello Friends"sv);
|
||||
auto key = "Well Hello Friends"_b;
|
||||
Crypto::Authentication::HMAC hmac(Crypto::Hash::HashKind::MD5, key);
|
||||
EXPECT_EQ(hmac.class_name(), "HMAC-MD5"sv);
|
||||
}
|
||||
|
||||
TEST_CASE(test_hmac_md5_process)
|
||||
{
|
||||
Crypto::Authentication::HMAC<Crypto::Hash::MD5> hmac("Well Hello Friends"sv);
|
||||
auto key = "Well Hello Friends"_b;
|
||||
Crypto::Authentication::HMAC hmac(Crypto::Hash::HashKind::MD5, key);
|
||||
u8 result[] {
|
||||
0x3b, 0x5b, 0xde, 0x30, 0x3a, 0x54, 0x7b, 0xbb, 0x09, 0xfe, 0x78, 0x89, 0xbc, 0x9f, 0x22, 0xa3
|
||||
};
|
||||
auto mac = hmac.process("Some bogus data"sv);
|
||||
EXPECT(memcmp(result, mac.data, hmac.digest_size()) == 0);
|
||||
EXPECT(memcmp(result, mac.data(), hmac.digest_size()) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE(test_hmac_md5_process_reuse)
|
||||
{
|
||||
Crypto::Authentication::HMAC<Crypto::Hash::MD5> hmac("Well Hello Friends"sv);
|
||||
auto key = "Well Hello Friends"_b;
|
||||
Crypto::Authentication::HMAC hmac(Crypto::Hash::HashKind::MD5, key);
|
||||
|
||||
auto mac_0 = hmac.process("Some bogus data"sv);
|
||||
auto mac_1 = hmac.process("Some bogus data"sv);
|
||||
|
||||
EXPECT(memcmp(mac_0.data, mac_1.data, hmac.digest_size()) == 0);
|
||||
EXPECT(memcmp(mac_0.data(), mac_1.data(), hmac.digest_size()) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE(test_hmac_sha1_name)
|
||||
{
|
||||
Crypto::Authentication::HMAC<Crypto::Hash::SHA1> hmac("Well Hello Friends"sv);
|
||||
auto key = "Well Hello Friends"_b;
|
||||
Crypto::Authentication::HMAC hmac(Crypto::Hash::HashKind::SHA1, key);
|
||||
EXPECT_EQ(hmac.class_name(), "HMAC-SHA1"sv);
|
||||
}
|
||||
|
||||
TEST_CASE(test_hmac_sha1_process)
|
||||
{
|
||||
u8 key[] { 0xc8, 0x52, 0xe5, 0x4a, 0x2c, 0x03, 0x2b, 0xc9, 0x63, 0xd3, 0xc2, 0x79, 0x0f, 0x76, 0x43, 0xef, 0x36, 0xc3, 0x7a, 0xca };
|
||||
Crypto::Authentication::HMAC<Crypto::Hash::SHA1> hmac(ReadonlyBytes { key, sizeof(key) });
|
||||
Crypto::Authentication::HMAC hmac(Crypto::Hash::HashKind::SHA1, ReadonlyBytes { key, sizeof(key) });
|
||||
u8 result[] {
|
||||
0x2c, 0x57, 0x32, 0x61, 0x3b, 0xa7, 0x84, 0x87, 0x0e, 0x4f, 0x42, 0x07, 0x2f, 0xf0, 0xe7, 0x41, 0xd7, 0x15, 0xf4, 0x56
|
||||
};
|
||||
|
@ -54,13 +60,13 @@ TEST_CASE(test_hmac_sha1_process)
|
|||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x03, 0x03, 0x00, 0x10, 0x14, 0x00, 0x00, 0x0c, 0xa1, 0x91, 0x1a, 0x20, 0x59, 0xb5, 0x45, 0xa9, 0xb4, 0xad, 0x75, 0x3e
|
||||
};
|
||||
auto mac = hmac.process(value, 29);
|
||||
EXPECT(memcmp(result, mac.data, hmac.digest_size()) == 0);
|
||||
EXPECT(memcmp(result, mac.data(), hmac.digest_size()) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE(test_hmac_sha1_process_reuse)
|
||||
{
|
||||
u8 key[] { 0xc8, 0x52, 0xe5, 0x4a, 0x2c, 0x03, 0x2b, 0xc9, 0x63, 0xd3, 0xc2, 0x79, 0x0f, 0x76, 0x43, 0xef, 0x36, 0xc3, 0x7a, 0xca };
|
||||
Crypto::Authentication::HMAC<Crypto::Hash::SHA1> hmac(ReadonlyBytes { key, sizeof(key) });
|
||||
Crypto::Authentication::HMAC hmac(Crypto::Hash::HashKind::SHA1, ReadonlyBytes { key, sizeof(key) });
|
||||
u8 result[] {
|
||||
0x2c, 0x57, 0x32, 0x61, 0x3b, 0xa7, 0x84, 0x87, 0x0e, 0x4f, 0x42, 0x07, 0x2f, 0xf0, 0xe7, 0x41, 0xd7, 0x15, 0xf4, 0x56
|
||||
};
|
||||
|
@ -71,77 +77,85 @@ TEST_CASE(test_hmac_sha1_process_reuse)
|
|||
hmac.update(value + 8, 5);
|
||||
hmac.update(value + 13, 16);
|
||||
auto mac = hmac.digest();
|
||||
EXPECT(memcmp(result, mac.data, hmac.digest_size()) == 0);
|
||||
EXPECT(memcmp(result, mac.data(), hmac.digest_size()) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE(test_hmac_sha256_name)
|
||||
{
|
||||
Crypto::Authentication::HMAC<Crypto::Hash::SHA256> hmac("Well Hello Friends"sv);
|
||||
auto key = "Well Hello Friends"_b;
|
||||
Crypto::Authentication::HMAC hmac(Crypto::Hash::HashKind::SHA256, key);
|
||||
EXPECT_EQ(hmac.class_name(), "HMAC-SHA256"sv);
|
||||
}
|
||||
|
||||
TEST_CASE(test_hmac_sha256_process)
|
||||
{
|
||||
Crypto::Authentication::HMAC<Crypto::Hash::SHA256> hmac("Well Hello Friends"sv);
|
||||
auto key = "Well Hello Friends"_b;
|
||||
Crypto::Authentication::HMAC hmac(Crypto::Hash::HashKind::SHA256, key);
|
||||
u8 result[] {
|
||||
0x1a, 0xf2, 0x20, 0x62, 0xde, 0x3b, 0x84, 0x65, 0xc1, 0x25, 0x23, 0x99, 0x76, 0x15, 0x1b, 0xec, 0x15, 0x21, 0x82, 0x1f, 0x23, 0xca, 0x11, 0x66, 0xdd, 0x8c, 0x6e, 0xf1, 0x81, 0x3b, 0x7f, 0x1b
|
||||
};
|
||||
auto mac = hmac.process("Some bogus data"sv);
|
||||
EXPECT(memcmp(result, mac.data, hmac.digest_size()) == 0);
|
||||
EXPECT(memcmp(result, mac.data(), hmac.digest_size()) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE(test_hmac_sha256_reuse)
|
||||
{
|
||||
Crypto::Authentication::HMAC<Crypto::Hash::SHA256> hmac("Well Hello Friends"sv);
|
||||
auto key = "Well Hello Friends"_b;
|
||||
Crypto::Authentication::HMAC hmac(Crypto::Hash::HashKind::SHA256, key);
|
||||
|
||||
auto mac_0 = hmac.process("Some bogus data"sv);
|
||||
auto mac_1 = hmac.process("Some bogus data"sv);
|
||||
|
||||
EXPECT(memcmp(mac_0.data, mac_1.data, hmac.digest_size()) == 0);
|
||||
EXPECT(memcmp(mac_0.data(), mac_1.data(), hmac.digest_size()) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE(test_hmac_sha256_data_is_same_size_as_block)
|
||||
{
|
||||
Crypto::Authentication::HMAC<Crypto::Hash::SHA256> hmac("Well Hello Friends"sv);
|
||||
auto key = "Well Hello Friends"_b;
|
||||
Crypto::Authentication::HMAC hmac(Crypto::Hash::HashKind::SHA256, key);
|
||||
u8 result[] = {
|
||||
0x1d, 0x90, 0xce, 0x68, 0x45, 0x0b, 0xba, 0xd6, 0xbe, 0x1c, 0xb2, 0x3a, 0xea, 0x7f, 0xac, 0x4b, 0x68, 0x08, 0xa4, 0x77, 0x81, 0x2a, 0xad, 0x5d, 0x05, 0xe2, 0x15, 0xe8, 0xf4, 0xcb, 0x06, 0xaf
|
||||
};
|
||||
auto mac = hmac.process("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"sv);
|
||||
EXPECT(memcmp(result, mac.data, hmac.digest_size()) == 0);
|
||||
EXPECT(memcmp(result, mac.data(), hmac.digest_size()) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE(test_hmac_sha256_data_is_bigger_size_as_block)
|
||||
{
|
||||
Crypto::Authentication::HMAC<Crypto::Hash::SHA256> hmac("Well Hello Friends"sv);
|
||||
auto key = "Well Hello Friends"_b;
|
||||
Crypto::Authentication::HMAC hmac(Crypto::Hash::HashKind::SHA256, key);
|
||||
u8 result[] = {
|
||||
0x9b, 0xa3, 0x9e, 0xf3, 0xb4, 0x30, 0x5f, 0x6f, 0x67, 0xd0, 0xa8, 0xb0, 0xf0, 0xcb, 0x12, 0xf5, 0x85, 0xe2, 0x19, 0xba, 0x0c, 0x8b, 0xe5, 0x43, 0xf0, 0x93, 0x39, 0xa8, 0xa3, 0x07, 0xf1, 0x95
|
||||
};
|
||||
auto mac = hmac.process("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"sv);
|
||||
EXPECT(memcmp(result, mac.data, hmac.digest_size()) == 0);
|
||||
EXPECT(memcmp(result, mac.data(), hmac.digest_size()) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE(test_hmac_sha512_name)
|
||||
{
|
||||
Crypto::Authentication::HMAC<Crypto::Hash::SHA512> hmac("Well Hello Friends"sv);
|
||||
auto key = "Well Hello Friends"_b;
|
||||
Crypto::Authentication::HMAC hmac(Crypto::Hash::HashKind::SHA512, key);
|
||||
EXPECT_EQ(hmac.class_name(), "HMAC-SHA512");
|
||||
}
|
||||
|
||||
TEST_CASE(test_hmac_sha512_process)
|
||||
{
|
||||
Crypto::Authentication::HMAC<Crypto::Hash::SHA512> hmac("Well Hello Friends"sv);
|
||||
auto key = "Well Hello Friends"_b;
|
||||
Crypto::Authentication::HMAC hmac(Crypto::Hash::HashKind::SHA512, key);
|
||||
u8 result[] {
|
||||
0xeb, 0xa8, 0x34, 0x11, 0xfd, 0x5b, 0x46, 0x5b, 0xef, 0xbb, 0x67, 0x5e, 0x7d, 0xc2, 0x7c, 0x2c, 0x6b, 0xe1, 0xcf, 0xe6, 0xc7, 0xe4, 0x7d, 0xeb, 0xca, 0x97, 0xb7, 0x4c, 0xd3, 0x4d, 0x6f, 0x08, 0x9f, 0x0d, 0x3a, 0xf1, 0xcb, 0x00, 0x79, 0x78, 0x2f, 0x05, 0x8e, 0xeb, 0x94, 0x48, 0x0d, 0x50, 0x64, 0x3b, 0xca, 0x70, 0xe2, 0x69, 0x38, 0x4f, 0xe4, 0xb0, 0x49, 0x0f, 0xc5, 0x4c, 0x7a, 0xa7
|
||||
};
|
||||
auto mac = hmac.process("Some bogus data"sv);
|
||||
EXPECT(memcmp(result, mac.data, hmac.digest_size()) == 0);
|
||||
EXPECT(memcmp(result, mac.data(), hmac.digest_size()) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE(test_hmac_sha512_reuse)
|
||||
{
|
||||
Crypto::Authentication::HMAC<Crypto::Hash::SHA512> hmac("Well Hello Friends"sv);
|
||||
auto key = "Well Hello Friends"_b;
|
||||
Crypto::Authentication::HMAC hmac(Crypto::Hash::HashKind::SHA512, key);
|
||||
|
||||
auto mac_0 = hmac.process("Some bogus data"sv);
|
||||
auto mac_1 = hmac.process("Some bogus data"sv);
|
||||
|
||||
EXPECT(memcmp(mac_0.data, mac_1.data, hmac.digest_size()) == 0);
|
||||
EXPECT(memcmp(mac_0.data(), mac_1.data(), hmac.digest_size()) == 0);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue