xrpld
Loading...
Searching...
No Matches
hardened_hash.cpp
1#include <xrpl/basics/hardened_hash.h>
2
3#include <xrpl/beast/hash/hash_append.h>
4
5#include <gtest/gtest.h>
6
7#include <array>
8#include <cstddef>
9#include <cstdint>
10#include <iomanip>
11#include <ios>
12#include <ostream>
13#include <string>
14#include <type_traits>
15#include <unordered_map>
16#include <unordered_set>
17
18namespace xrpl::detail {
19
20template <class T>
22{
23private:
24 T t_;
25
26public:
27 explicit TestUserTypeMember(T const& t = T()) : t_(t)
28 {
29 }
30
31 template <class Hasher>
32 friend void
33 // NOLINTNEXTLINE(readability-identifier-naming)
34 hash_append(Hasher& h, TestUserTypeMember const& a) noexcept
35 {
37 hash_append(h, a.t_);
38 }
39};
40
41template <class T>
43{
44private:
45 T t_;
46
47public:
48 explicit TestUserTypeFree(T const& t = T()) : t_(t)
49 {
50 }
51
52 template <class Hasher>
53 friend void
54 // NOLINTNEXTLINE(readability-identifier-naming)
55 hash_append(Hasher& h, TestUserTypeFree const& a) noexcept
56 {
58 hash_append(h, a.t_);
59 }
60};
61
62} // namespace xrpl::detail
63
64//------------------------------------------------------------------------------
65
66namespace xrpl {
67
68namespace detail {
69
70template <class T>
72
73template <class T>
75
76template <class T>
78
79template <class T>
81
82} // namespace detail
83
84template <std::size_t Bits, class UInt = std::uint64_t>
86{
87private:
88 static_assert(
90 "UInt must be an unsigned integral type");
91
92 static_assert(Bits % (8 * sizeof(UInt)) == 0, "Bits must be a multiple of 8*sizeof(UInt)");
93
94 static_assert(Bits >= (8 * sizeof(UInt)), "Bits must be at least 8*sizeof(UInt)");
95
96 static std::size_t const kSize = Bits / (8 * sizeof(UInt));
97
99
100public:
101 using value_type = UInt;
102
103 static std::size_t const kBits = Bits;
104 static std::size_t const kBytes = kBits / 8;
105
106 template <class Int>
107 static UnsignedInteger
109 {
110 UnsignedInteger result;
111 for (std::size_t i(1); i < kSize; ++i)
112 result.vec_[i] = 0;
113 result.vec_[0] = v;
114 return result;
115 }
116
117 void*
118 data() noexcept
119 {
120 return &vec_[0];
121 }
122
123 [[nodiscard]] void const*
124 data() const noexcept
125 {
126 return &vec_[0];
127 }
128
129 template <class Hasher>
130 friend void
131 hash_append(Hasher& h, UnsignedInteger const& a) noexcept
132 {
133 using beast::hash_append;
134 hash_append(h, a.vec_);
135 }
136
139 {
140 for (std::size_t i(0); i < kSize; ++i)
141 s << std::hex << std::setfill('0') << std::setw(2 * sizeof(UInt)) << v.vec_[i];
142 return s;
143 }
144};
145
147
148#ifndef __INTELLISENSE__
149static_assert(sha256_t::kBits == 256, "sha256_t must have 256 bits");
150#endif
151
152} // namespace xrpl
153
154//------------------------------------------------------------------------------
155
156namespace xrpl {
157
158class HardenedHashTest : public ::testing::Test
159{
160public:
161 template <class T>
162 static void
164 {
165 T t{};
166 HardenedHash<>()(t);
167 SUCCEED();
168 }
169
170 template <template <class T> class U>
171 static void
173 {
174 check<U<bool>>();
175 check<U<char>>();
178 // These cause trouble for boost
179 // check <U <char16_t>> ();
180 // check <U <char32_t>> ();
184 check<U<int>>();
186 check<U<long>>();
193 }
194
195 template <template <class T> class C>
196 static void
198 {
199 {
200 C<detail::TestUserTypeMember<std::string>> const c;
201 }
202
203 SUCCEED();
204
205 {
206 C<detail::TestUserTypeFree<std::string>> const c;
207 }
208
209 SUCCEED();
210 }
211};
212
214{
215 checkUserType<detail::TestUserTypeMember>();
216 checkUserType<detail::TestUserTypeFree>();
217}
218
220{
221 checkContainer<detail::test_hardened_unordered_set>();
222 checkContainer<detail::test_hardened_unordered_map>();
223 checkContainer<detail::test_hardened_unordered_multiset>();
224 checkContainer<detail::test_hardened_unordered_multimap>();
225}
226
227} // namespace xrpl
Seed functor once per construction.
static UnsignedInteger fronumber(Int v)
std::array< std::size_t, kSize > vec_
friend void hash_append(Hasher &h, UnsignedInteger const &a) noexcept
void const * data() const noexcept
friend std::ostream & operator<<(std::ostream &s, UnsignedInteger const &v)
void * data() noexcept
friend void hash_append(Hasher &h, TestUserTypeFree const &a) noexcept
friend void hash_append(Hasher &h, TestUserTypeMember const &a) noexcept
T hex(T... args)
T is_integral_v
T is_unsigned_v
void hash_append(Hasher &h, T const &t) noexcept
Logically concatenate input data to a Hasher.
std::unordered_multiset< T, HardenedHash<> > test_hardened_unordered_multiset
std::unordered_set< T, HardenedHash<> > test_hardened_unordered_set
std::unordered_multimap< T, int, HardenedHash<> > test_hardened_unordered_multimap
std::unordered_map< T, int, HardenedHash<> > test_hardened_unordered_map
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
TEST_F(HardenedHashTest, user_types)
UnsignedInteger< 256, std::size_t > sha256_t
T setfill(T... args)
T setw(T... args)