Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
TestHash.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7
9#include "arcane/utils/PlatformUtils.h"
10#include "arcane/utils/Array.h"
11#include "arcane/utils/String.h"
12#include "arcane/utils/Convert.h"
13#include "arcane/utils/MD5HashAlgorithm.h"
14#include "arcane/utils/SHA3HashAlgorithm.h"
15#include "arcane/utils/SHA1HashAlgorithm.h"
16#include "arcane/utils/Ref.h"
17
18#include <gtest/gtest.h>
19
20#include <array>
21
22namespace Arcane
23{
24//extern "C++" ARCANE_UTILS_EXPORT void
25//_computeSHA3_256Hash(Span<const std::byte> bytes, SmallSpan<std::byte> result);
26} // namespace Arcane
27
28/*---------------------------------------------------------------------------*/
29/*---------------------------------------------------------------------------*/
30
31using namespace Arcane;
32
34{
35 String data_value;
36 String expected_hash;
37};
38
39/*---------------------------------------------------------------------------*/
40/*---------------------------------------------------------------------------*/
41
42void _testHash(IHashAlgorithm& algo, SmallSpan<TestInfo> values_to_test)
43{
44 ByteUniqueArray output1;
45 ByteUniqueArray output2;
46 ByteUniqueArray output3;
48 UniqueArray<std::byte> output1_incremental;
49
51 bool has_context = false;
52 if (algo.hasCreateContext()) {
53 context = algo.createContext();
54 has_context = true;
55 }
56
57 // TODO: add test or clear() between calls
58 for (const TestInfo& ti : values_to_test) {
59 Span<const Byte> str_bytes(ti.data_value.bytes());
60 {
61 Span<const std::byte> input1(asBytes(str_bytes));
62 output1.clear();
63 algo.computeHash64(input1, output1);
64 if (has_context) {
65 output1_incremental.clear();
66 context->reset();
67 // Make the call in two parts.
68 auto span1 = input1.subspan(0, input1.size() / 2);
69 auto span2 = input1.subspan(input1.size() / 2, input1.size());
70 context->updateHash(span1);
71 context->updateHash(span2);
73 context->computeHashValue(value);
74 output1_incremental = value.bytes();
75 }
76 {
78 algo.computeHash(input1, value);
79 output4 = value.bytes();
80 }
81 }
82 {
83 Span<const Byte> input2(str_bytes);
84 output2.clear();
85 algo.computeHash64(input2, output2);
86 }
87 {
88 ByteConstArrayView input3(str_bytes.constSmallView());
89 output3.clear();
90 algo.computeHash(input3, output3);
91 }
92 String hash1 = Convert::toHexaString(output1);
93 String hash2 = Convert::toHexaString(output2);
94 String hash3 = Convert::toHexaString(output3);
95 String hash4 = Convert::toHexaString(output4);
96 String hash1_incremental = Convert::toHexaString(output1_incremental);
97 String expected_hash = ti.expected_hash.lower();
98 std::cout << "REF=" << expected_hash << "\n";
99 std::cout << "HASH1=" << hash1 << "\n";
100 std::cout << "HASH2=" << hash2 << "\n";
101 std::cout << "HASH3=" << hash3 << "\n";
102 std::cout << "HASH4=" << hash4 << "\n";
103 std::cout << "HASH1_INCREMENTAL=" << hash1_incremental << "\n";
104 ASSERT_EQ(hash1, expected_hash);
105 if (has_context) {
106 ASSERT_EQ(hash1_incremental, expected_hash);
107 }
108 ASSERT_EQ(hash2, expected_hash);
109 ASSERT_EQ(hash3, expected_hash);
110 ASSERT_EQ(hash4, expected_hash);
111 }
112
113 {
114 // Test a large array
115 const Int32 nb_byte = 100000;
116 UniqueArray<std::byte> bytes(nb_byte);
117 for (Int32 i = 0; i < nb_byte; ++i) {
118 bytes[i] = std::byte(i % 127);
119 }
120 // Loop if we want to test performance
121 //(in this case increase the number of iterations)
122 for (int j = 0; j < 2; ++j) {
123 output1.clear();
124 algo.computeHash64(bytes, output1);
125 }
126 String hash_big = Convert::toHexaString(output1);
127 std::cout << "HASH_BIG=" << hash_big << "\n";
128 if (has_context) {
129 context->reset();
130 Int32 to_add = 549;
131 Int32 nb_iter = 0;
132 for (Int32 i = 0; i < nb_byte; i += to_add) {
133 ++nb_iter;
134 to_add += 15;
135 context->updateHash(bytes.span().subspan(i, to_add));
136 }
137 HashAlgorithmValue value;
138 context->computeHashValue(value);
139 output1_incremental = value.bytes();
140 String hash_big_incremental = Convert::toHexaString(output1_incremental);
141 std::cout << "nb_iter=" << nb_iter << "\n";
142 std::cout << "HASH_BIG_INCREMENTAL=" << hash_big_incremental << "\n";
143 ASSERT_EQ(hash_big_incremental, hash_big);
144 }
145 }
146}
147
148/*---------------------------------------------------------------------------*/
149/*---------------------------------------------------------------------------*/
150
151TEST(Hash, SHA3_224)
152{
153 std::cout << "TEST_SHA3-224\n";
154
155 std::array<TestInfo, 8> values_to_test = {
156 { { "", "6B4E03423667DBB73B6E15454F0EB1ABD4597F9A1B078E3F5B5A6BC7" },
157 { "a", "9E86FF69557CA95F405F081269685B38E3A819B309EE942F482B6A8B" },
158 { "abc", "E642824C3F8CF24AD09234EE7D3C766FC9A3A5168D0C94AD73B46FDF" },
159 { "message digest", "18768BB4C48EB7FC88E5DDB17EFCF2964ABD7798A39D86A4B4A1E4C8" },
160 { "abcdefghijklmnopqrstuvwxyz", "5CDECA81E123F87CAD96B9CBA999F16F6D41549608D4E0F4681B8239" },
161 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "A67C289B8250A6F437A20137985D605589A8C163D45261B15419556E" },
162 { "12345678901234567890123456789012345678901234567890123456789012345678901234567890", "0526898E185869F91B3E2A76DD72A15DC6940A67C8164A044CD25CC8" },
163 { "The quick brown fox jumps over the lazy dog", "D15DADCEAA4D5D7BB3B48F446421D542E08AD8887305E28D58335795" } }
164 };
165
167 _testHash(sha3, SmallSpan<TestInfo>(values_to_test));
168}
169
170/*---------------------------------------------------------------------------*/
171/*---------------------------------------------------------------------------*/
172
173TEST(Hash, SHA3_256)
174{
175 std::cout << "TEST_SHA3-256\n";
176
177 std::array<TestInfo, 8> values_to_test = {
178 { { "",
179 "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a" },
180
181 { "a",
182 "80084bf2fba02475726feb2cab2d8215eab14bc6bdd8bfb2c8151257032ecd8b" },
183
184 { "abc",
185 "3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532" },
186
187 { "message digest",
188 "edcdb2069366e75243860c18c3a11465eca34bce6143d30c8665cefcfd32bffd" },
189
190 { "abcdefghijklmnopqrstuvwxyz",
191 "7cab2dc765e21b241dbc1c255ce620b29f527c6d5e7f5f843e56288f0d707521" },
192
193 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
194 "a79d6a9da47f04a3b9a9323ec9991f2105d4c78a7bc7beeb103855a7a11dfb9f" },
195
196 { "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
197 "293e5ce4ce54ee71990ab06e511b7ccd62722b1beb414f5ff65c8274e0f5be1d" },
198
199 { "The quick brown fox jumps over the lazy dog",
200 "69070dda01975c8c120c3aada1b282394e7f032fa9cf32f4cb2259a0897dfc04" } }
201 };
202
204 _testHash(sha3, SmallSpan<TestInfo>(values_to_test));
205}
206
207/*---------------------------------------------------------------------------*/
208/*---------------------------------------------------------------------------*/
209
210TEST(Hash, SHA3_384)
211{
212 std::cout << "TEST_SHA3-384\n";
213
214 std::array<TestInfo, 8> values_to_test = {
215 { { "", "0C63A75B845E4F7D01107D852E4C2485C51A50AAAA94FC61995E71BBEE983A2AC3713831264ADB47FB6BD1E058D5F004" },
216 { "a", "1815F774F320491B48569EFEC794D249EEB59AAE46D22BF77DAFE25C5EDC28D7EA44F93EE1234AA88F61C91912A4CCD9" },
217 { "abc", "EC01498288516FC926459F58E2C6AD8DF9B473CB0FC08C2596DA7CF0E49BE4B298D88CEA927AC7F539F1EDF228376D25" },
218 { "message digest",
219 "D9519709F44AF73E2C8E291109A979DE3D61DC02BF69DEF7FBFFDFFFE662751513F19AD57E17D4B93BA1E484FC1980D5" },
220 { "abcdefghijklmnopqrstuvwxyz",
221 "FED399D2217AAF4C717AD0C5102C15589E1C990CC2B9A5029056A7F7485888D6AB65DB2370077A5CADB53FC9280D278F" },
222 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
223 "D5B972302F5080D0830E0DE7B6B2CF383665A008F4C4F386A61112652C742D20CB45AA51BD4F542FC733E2719E999291" },
224 { "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
225 "3C213A17F514638ACB3BF17F109F3E24C16F9F14F085B52A2F2B81ADC0DB83DF1A58DB2CE013191B8BA72D8FAE7E2A5E" },
226 { "The quick brown fox jumps over the lazy dog",
227 "7063465E08A93BCE31CD89D2E3CA8F602498696E253592ED26F07BF7E703CF328581E1471A7BA7AB119B1A9EBDF8BE41" } }
228 };
229
231 _testHash(sha3, SmallSpan<TestInfo>(values_to_test));
232}
233
234/*---------------------------------------------------------------------------*/
235/*---------------------------------------------------------------------------*/
236
237TEST(Hash, SHA3_512)
238{
239 std::cout << "TEST_SHA3-512\n";
240
241 std::array<TestInfo, 8> values_to_test = {
242 { { "", "A69F73CCA23A9AC5C8B567DC185A756E97C982164FE25859E0D1DCC1475C80A615B2123AF1F5F94C11E3E9402C3AC558F500199D95B6D3E301758586281DCD26" },
243 { "a", "697F2D856172CB8309D6B8B97DAC4DE344B549D4DEE61EDFB4962D8698B7FA803F4F93FF24393586E28B5B957AC3D1D369420CE53332712F997BD336D09AB02A" },
244 { "abc", "B751850B1A57168A5693CD924B6B096E08F621827444F70D884F5D0240D2712E10E116E9192AF3C91A7EC57647E3934057340B4CF408D5A56592F8274EEC53F0" },
245 { "message digest",
246 "3444E155881FA15511F57726C7D7CFE80302A7433067B29D59A71415CA9DD141AC892D310BC4D78128C98FDA839D18D7F0556F2FE7ACB3C0CDA4BFF3A25F5F59" },
247 { "abcdefghijklmnopqrstuvwxyz",
248 "AF328D17FA28753A3C9F5CB72E376B90440B96F0289E5703B729324A975AB384EDA565FC92AADED143669900D761861687ACDC0A5FFA358BD0571AAAD80ACA68" },
249 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
250 "D1DB17B4745B255E5EB159F66593CC9C143850979FC7A3951796ABA80165AAB536B46174CE19E3F707F0E5C6487F5F03084BC0EC9461691EF20113E42AD28163" },
251 { "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
252 "9524B9A5536B91069526B4F6196B7E9475B4DA69E01F0C855797F224CD7335DDB286FD99B9B32FFE33B59AD424CC1744F6EB59137F5FB8601932E8A8AF0AE930" },
253 { "The quick brown fox jumps over the lazy dog",
254 "01DEDD5DE4EF14642445BA5F5B97C15E47B9AD931326E4B0727CD94CEFC44FFF23F07BF543139939B49128CAF436DC1BDEE54FCB24023A08D9403F9B4BF0D450" } }
255 };
256
258 _testHash(sha3, SmallSpan<TestInfo>(values_to_test));
259}
260
261/*---------------------------------------------------------------------------*/
262/*---------------------------------------------------------------------------*/
263
264TEST(Hash, SHA1)
265{
266 std::cout << "TEST_SHA1\n";
267
268 std::array<TestInfo, 3> values_to_test = {
269 { { "", "da39a3ee5e6b4b0d3255bfef95601890afd80709" },
270 { "The quick brown fox jumps over the lazy cog", "de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3" },
271 { "The quick brown fox jumps over the lazy dog", "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12" } }
272 };
273
275 _testHash(sha1, SmallSpan<TestInfo>(values_to_test));
276}
277
278/*---------------------------------------------------------------------------*/
279/*---------------------------------------------------------------------------*/
280
281TEST(Hash, MD5)
282{
283 std::cout << "MD5 TEST\n";
284
285 std::array<TestInfo, 4> values_to_test = {
286 { { "",
287 "d41d8cd98f00b204e9800998ecf8427e" },
288
289 { "a",
290 "0cc175b9c0f1b6a831c399e269772661" },
291
292 { "The quick brown fox jumps over the lazy dog",
293 "9e107d9d372bb6826bd81d3542a419d6" },
294
295 { "The quick brown fox jumps over the lazy dog.",
296 "e4d909c290d0fb1ca068ffaddf22cbd0" } }
297 };
298
300 _testHash(md5, SmallSpan<TestInfo>(values_to_test));
301}
302
303/*---------------------------------------------------------------------------*/
304/*---------------------------------------------------------------------------*/
Arcane configuration file.
void clear()
Removes the elements from the array.
Hash algorithm return value.
Interface of a hashing algorithm.
virtual bool hasCreateContext() const
Indicates if the implementation supports incremental hashing.
virtual void computeHash(Span< const std::byte > input, HashAlgorithmValue &value)
Calculates the hash value for the array input.
virtual void computeHash64(Span< const Byte > input, ByteArray &output)
Calculates the hash value for the array input.
virtual Ref< IHashAlgorithmContext > createContext()
Creates a context to calculate the hash value incrementally.
Calculates the MD5 hashing function of an array.
void reset()
Positions the instance to the null pointer.
Reference to an instance.
Implementation of the SHA-1 algorithm.
Hash for the SHA-3 224 algorithm.
Hash for the SHA-3 256 algorithm.
Hash for the SHA-3 384 algorithm.
Hash for the SHA-3 512 algorithm.
View of an array of elements of type T.
Definition Span.h:805
View of an array of elements of type T.
Definition Span.h:635
String lower() const
Transforms all characters in the string to lowercase.
Definition String.cc:480
1D data vector with value semantics (STL style).
String toHexaString(ByteConstArrayView input)
Converts a byte array to its hexadecimal representation.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
UniqueArray< Byte > ByteUniqueArray
Dynamic 1D array of characters.
Definition UtilsTypes.h:335
Impl::SpanTypeFromSize< conststd::byte, SizeType >::SpanType asBytes(const SpanImpl< DataType, SizeType, Extent > &s)
Converts the view into an array of non-modifiable bytes.
Definition Span.h:1032
ConstArrayView< Byte > ByteConstArrayView
C equivalent of a 1D array of characters.
Definition UtilsTypes.h:476