TrinityCore
HMAC.h
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef TRINITY_HMAC_H
19#define TRINITY_HMAC_H
20
21#include "CryptoConstants.h"
22#include "CryptoHash.h"
23#include "Define.h"
24#include "Errors.h"
25#include <array>
26#include <string>
27#include <string_view>
28
29class BigNumber;
30
31namespace Trinity::Impl
32{
33 template <GenericHashImpl::HashCreator HashCreator, size_t DigestLength>
35 {
36 public:
37 static constexpr size_t DIGEST_LENGTH = DigestLength;
38 using Digest = std::array<uint8, DIGEST_LENGTH>;
39
40 template <typename Container>
41 static Digest GetDigestOf(Container const& seed, uint8 const* data, size_t len)
42 {
43 GenericHMAC hash(seed);
44 hash.UpdateData(data, len);
45 hash.Finalize();
46 return hash.GetDigest();
47 }
48
49 template <typename Container, typename... Ts>
50 static auto GetDigestOf(Container const& seed, Ts&&... pack) -> std::enable_if_t<std::conjunction_v<std::negation<std::is_integral<Ts>>...>, Digest>
51 {
52 GenericHMAC hash(seed);
53 (hash.UpdateData(std::forward<Ts>(pack)), ...);
54 hash.Finalize();
55 return hash.GetDigest();
56 }
57
58 GenericHMAC(uint8 const* seed, size_t len) : _ctx(GenericHashImpl::MakeCTX()), _key(EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, nullptr, seed, len))
59 {
60 int result = EVP_DigestSignInit(_ctx, nullptr, HashCreator(), nullptr, _key);
61 ASSERT(result == 1);
62 }
63 template <typename Container>
64 GenericHMAC(Container const& container) : GenericHMAC(std::data(container), std::size(container)) {}
65
66 GenericHMAC(GenericHMAC const& right) : _ctx(GenericHashImpl::MakeCTX())
67 {
68 *this = right;
69 }
70
71 GenericHMAC(GenericHMAC&& right) noexcept
72 {
73 *this = std::move(right);
74 }
75
77 {
79 _ctx = nullptr;
80 EVP_PKEY_free(_key);
81 _key = nullptr;
82 }
83
85 {
86 if (this == &right)
87 return *this;
88
89 int result = EVP_MD_CTX_copy_ex(_ctx, right._ctx);
90 ASSERT(result == 1);
91 _key = right._key; // EVP_PKEY uses reference counting internally, just copy the pointer
92 EVP_PKEY_up_ref(_key); // Bump reference count for PKEY, as every instance of this class holds two references to PKEY and destructor decrements it twice
93 _digest = right._digest;
94 return *this;
95 }
96
98 {
99 if (this == &right)
100 return *this;
101
102 _ctx = std::exchange(right._ctx, GenericHashImpl::MakeCTX());
103 _key = std::exchange(right._key, EVP_PKEY_new());
104 _digest = std::exchange(right._digest, Digest{});
105 return *this;
106 }
107
108 void UpdateData(uint8 const* data, size_t len)
109 {
110 int result = EVP_DigestSignUpdate(_ctx, data, len);
111 ASSERT(result == 1);
112 }
113 void UpdateData(std::string_view str) { UpdateData(reinterpret_cast<uint8 const*>(str.data()), str.size()); }
114 void UpdateData(std::string const& str) { UpdateData(std::string_view(str)); } /* explicit overload to avoid using the container template */
115 void UpdateData(char const* str) { UpdateData(std::string_view(str)); } /* explicit overload to avoid using the container template */
116 template <typename Container>
117 void UpdateData(Container const& c) { UpdateData(std::data(c), std::size(c)); }
118
119 void Finalize()
120 {
121 size_t length = DIGEST_LENGTH;
122 int result = EVP_DigestSignFinal(_ctx, _digest.data(), &length);
123 ASSERT(result == 1);
124 ASSERT(length == DIGEST_LENGTH);
125 }
126
127 Digest const& GetDigest() const { return _digest; }
128 private:
129 EVP_MD_CTX* _ctx;
130 EVP_PKEY* _key;
132 };
133}
134
135namespace Trinity::Crypto
136{
139}
140#endif
uint8_t uint8
Definition: Define.h:144
#define ASSERT
Definition: Errors.h:68
void UpdateData(std::string const &str)
Definition: HMAC.h:114
void UpdateData(uint8 const *data, size_t len)
Definition: HMAC.h:108
GenericHMAC(GenericHMAC &&right) noexcept
Definition: HMAC.h:71
static auto GetDigestOf(Container const &seed, Ts &&... pack) -> std::enable_if_t< std::conjunction_v< std::negation< std::is_integral< Ts > >... >, Digest >
Definition: HMAC.h:50
void UpdateData(Container const &c)
Definition: HMAC.h:117
static Digest GetDigestOf(Container const &seed, uint8 const *data, size_t len)
Definition: HMAC.h:41
static constexpr size_t DIGEST_LENGTH
Definition: HMAC.h:37
void UpdateData(std::string_view str)
Definition: HMAC.h:113
std::array< uint8, DIGEST_LENGTH > Digest
Definition: HMAC.h:38
Digest const & GetDigest() const
Definition: HMAC.h:127
void UpdateData(char const *str)
Definition: HMAC.h:115
GenericHMAC & operator=(GenericHMAC const &right)
Definition: HMAC.h:84
GenericHMAC(uint8 const *seed, size_t len)
Definition: HMAC.h:58
GenericHMAC & operator=(GenericHMAC &&right) noexcept
Definition: HMAC.h:97
GenericHMAC(GenericHMAC const &right)
Definition: HMAC.h:66
EVP_MD_CTX * _ctx
Definition: HMAC.h:129
GenericHMAC(Container const &container)
Definition: HMAC.h:64
constexpr std::size_t size()
Definition: UpdateField.h:796
STL namespace.
static void DestroyCTX(EVP_MD_CTX *ctx)
Definition: CryptoHash.h:39
static EVP_MD_CTX * MakeCTX() noexcept
Definition: CryptoHash.h:38