32 #include <gtest/gtest.h>
54 using namespace scc::encode;
55 using namespace scc::util;
58 using CharVec = std::vector<char>;
60 static string hash_test =
"This is a test sentence to test both hashes and digests. It is a bit longer than the key!";
61 static string hash_test1 =
"This is a test sentence to test both hashes and digests. ";
62 static string hash_test2 =
"It is a bit longer than the key!";
63 static string hash_key =
"This is a keyphrase";
64 static string hmac_sha256 =
"dbe8548042b534bd99ddf26b5fc4c2cdfeaf07d8df5427f5794a4445a0c425b2";
66 struct Hash_digest :
public testing::Test
68 map<Hash::Algorithm, Hash> m_digest;
69 map<Hash::Algorithm, string> m_name;
70 map<Hash::Algorithm, string> m_init;
71 map<Hash::Algorithm, string> m_hash;
72 map<Hash::Algorithm, int> m_size;
76 if (Hash::supported(Hash::md5_type))
78 m_digest.insert(std::make_pair(Hash::md5_type,
Hash(Hash::md5_type)));
79 m_name[Hash::md5_type] =
"md5";
80 m_init[Hash::md5_type] =
"d41d8cd98f00b204e9800998ecf8427e";
81 m_hash[Hash::md5_type] =
"6630d84e20c4f20a87fcf7e069a2d34e";
82 m_size[Hash::md5_type] = 16;
84 if (Hash::supported(Hash::sha1_type))
86 m_digest.insert(std::make_pair(Hash::sha1_type,
Hash(Hash::sha1_type)));
87 m_name[Hash::sha1_type] =
"sha1";
88 m_init[Hash::sha1_type] =
"da39a3ee5e6b4b0d3255bfef95601890afd80709";
89 m_hash[Hash::sha1_type] =
"3acf7561f5bd97534e575ba2565c6400b9128412";
90 m_size[Hash::sha1_type] = 20;
92 if (Hash::supported(Hash::sha224_type))
94 m_digest.insert(std::make_pair(Hash::sha224_type,
Hash(Hash::sha224_type)));
95 m_name[Hash::sha224_type] =
"sha224";
96 m_init[Hash::sha224_type] =
"d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f";
97 m_hash[Hash::sha224_type] =
"317746d2199f50c2bf450bf3412d9ff74645aab7c3b747f7779a7b28";
98 m_size[Hash::sha224_type] = 28;
100 if (Hash::supported(Hash::sha256_type))
102 m_digest.insert(std::make_pair(Hash::sha256_type,
Hash(Hash::sha256_type)));
103 m_name[Hash::sha256_type] =
"sha256";
104 m_init[Hash::sha256_type] =
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
105 m_hash[Hash::sha256_type] =
"382dfbf0cd153aec516de602ee6609ee73d97259cc78d74ea0caa9d5b02afab9";
106 m_size[Hash::sha256_type] = 32;
108 if (Hash::supported(Hash::sha384_type))
110 m_digest.insert(std::make_pair(Hash::sha384_type,
Hash(Hash::sha384_type)));
111 m_name[Hash::sha384_type] =
"sha384";
112 m_init[Hash::sha384_type] =
"38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b";
113 m_hash[Hash::sha384_type] =
"3e7d844e6b9be37e4e8011dd258682c651ea151bf63897503e2ecffbcdfed3492d513028489be69ac3c3f9fb1649fc19";
114 m_size[Hash::sha384_type] = 48;
116 if (Hash::supported(Hash::sha512_type))
118 m_digest.insert(std::make_pair(Hash::sha512_type,
Hash(Hash::sha512_type)));
119 m_name[Hash::sha512_type] =
"sha512";
120 m_init[Hash::sha512_type] =
"cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e";
121 m_hash[Hash::sha512_type] =
"a99f27da164286aea7f2c2928966dda6ce270b851536a6b8c4242f7e20131aa8260dd2239082cc02cc0f9fd0415e3bbe096868bbba7a59afb8a84188b2ce9cf5";
122 m_size[Hash::sha512_type] = 64;
124 if (Hash::supported(Hash::sha512_224_type))
126 m_digest.insert(std::make_pair(Hash::sha512_224_type,
Hash(Hash::sha512_224_type)));
127 m_name[Hash::sha512_224_type] =
"sha512/224";
128 m_init[Hash::sha512_224_type] =
"6ed0dd02806fa89e25de060c19d3ac86cabb87d6a0ddd05c333b84f4";
129 m_hash[Hash::sha512_224_type] =
"2ecce2ef45e929a959b3dd1ea8dbcc19ca644742d74a6d34ec654ac3";
130 m_size[Hash::sha512_224_type] = 28;
132 if (Hash::supported(Hash::sha512_256_type))
134 m_digest.insert(std::make_pair(Hash::sha512_256_type,
Hash(Hash::sha512_256_type)));
135 m_name[Hash::sha512_256_type] =
"sha512/256";
136 m_init[Hash::sha512_256_type] =
"c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a";
137 m_hash[Hash::sha512_256_type] =
"2730a349582f660c6d0660bf7a09b4aa6a8b4a11bb1ab8306950ee93d7d9f258";
138 m_size[Hash::sha512_256_type] = 32;
140 if (Hash::supported(Hash::sm3_type))
142 m_digest.insert(std::make_pair(Hash::sm3_type,
Hash(Hash::sm3_type)));
143 m_name[Hash::sm3_type] =
"sm3";
144 m_init[Hash::sm3_type] =
"1ab21d8355cfa17f8e61194831e81a8f22bec8c728fefb747ed035eb5082aa2b";
145 m_hash[Hash::sm3_type] =
"a4d3f1d0bb8d34696688a434606b5eb3d78e8bcd98ae12621ab36dd0d6a8d9e7";
146 m_size[Hash::sm3_type] = 32;
149 virtual ~Hash_digest() {}
151 string final(
Hash& h)
155 return Hex::bin_to_hex(v.data(), v.size());
159 TEST_F(Hash_digest, Lengths)
161 for (
auto& d : m_digest)
163 cout <<
"Length " << m_name[d.first] <<
": " << d.second.size() << endl;
164 ASSERT_EQ(d.second.size(), m_size[d.first]);
168 TEST_F(Hash_digest, Init)
170 for (
auto& d : m_digest)
172 string hex =
final(d.second);
173 cout <<
"Final " << m_name[d.first] <<
": " << hex << endl;
174 ASSERT_EQ(hex, m_init[d.first]);
178 TEST_F(Hash_digest, Copy_final)
180 for (
auto& d : m_digest)
182 d.second.update(hash_test);
183 char bin[m_size[d.first]];
184 d.second.final(bin, d.second.size());
185 string hex = Hex::bin_to_hex(CharVec(&bin[0], &bin[m_size[d.first]]));
186 cout <<
"Init " << m_name[d.first] <<
": " << hex << endl;
187 ASSERT_EQ(hex, m_hash[d.first]);
191 TEST_F(Hash_digest, Test_one_part)
193 for (
auto& d : m_digest)
195 d.second.update(hash_test);
196 string hex =
final(d.second);
197 ASSERT_EQ(hex, m_hash[d.first]);
201 TEST_F(Hash_digest, Get_tag)
203 for (
auto& d : m_digest)
205 d.second.update(hash_test);
213 ASSERT_EQ(h.get_tag(t), m_size[d.first]);
215 for (
int i = 1; i <= m_size[d.first]; i++)
219 ASSERT_EQ(h.get_tag(t, i), i);
225 TEST_F(Hash_digest, Test_two_parts)
227 for (
auto& d : m_digest)
229 d.second.update(hash_test1);
230 d.second.update(hash_test2);
231 string hex =
final(d.second);
232 ASSERT_EQ(hex, m_hash[d.first]);
236 TEST_F(Hash_digest, Reset_val)
238 for (
auto& d : m_digest)
240 d.second.update(hash_test);
241 string hex =
final(d.second);
242 ASSERT_EQ(hex, m_hash[d.first]);
244 d.second.update(hash_test);
245 hex =
final(d.second);
246 ASSERT_EQ(hex, m_hash[d.first]);
251 TEST_F(Hash_digest, Reset_cmd)
253 for (
auto& d : m_digest)
255 d.second.update(
"bad data");
257 d.second.update(hash_test);
258 string hex =
final(d.second);
259 ASSERT_EQ(hex, m_hash[d.first]);
263 TEST_F(Hash_digest, Streams)
265 for (
auto& d : m_digest)
276 string hex =
final(d.second);
277 ASSERT_EQ(hex, m_hash[d.first]);
280 ASSERT_TRUE(std::getline(ios, s));
281 ASSERT_EQ(s, hash_test);
283 hex =
final(d.second);
284 ASSERT_EQ(hex, m_hash[d.first]);
288 TEST_F(Hash_digest, Hmac_lengths)
290 for (
auto& d : m_digest)
292 cout <<
"HMAC length " << m_name[d.first] <<
": " << d.second.size() << endl;
293 Hmac h(hash_key, d.first);
294 ASSERT_EQ(h.size(), m_size[d.first]);
298 TEST_F(Hash_digest, Hmac_compare) {
299 for (
auto& d : m_digest)
301 Hmac h1(hash_key, d.first);
302 h1.update(hash_test);
303 char h1buf[h1.size()];
304 ASSERT_EQ(h1.final(h1buf, h1.size()), h1.size());
305 Hmac h2(hash_key, d.first);
306 h2.update(hash_test1);
307 h2.update(hash_test2);
308 char h2buf[h2.size()];
309 ASSERT_EQ(h2.final(h2buf, h2.size()), h2.size());
310 ASSERT_EQ(h1.size(), h2.size());
311 ASSERT_EQ(memcmp(h1buf, h2buf, h1.size()), 0);
315 TEST(hmac_test, Hmac_sanity)
317 Hmac h(hash_key, Hash::sha256_type);
318 h.update(hash_test1);
319 h.update(hash_test2);
321 ASSERT_EQ(h.final(hbuf, h.size()), h.size());
322 string hex1 = Hex::bin_to_hex(CharVec(&hbuf[0], &hbuf[h.size()]));
323 ASSERT_EQ(hex1, hmac_sha256);
326 ASSERT_EQ(h.final(hbuf, h.size()), h.size());
327 string hex2 = Hex::bin_to_hex(CharVec(&hbuf[0], &hbuf[h.size()]));
328 ASSERT_EQ(hex2, hmac_sha256);
331 TEST(hmac_test, Hmac_sanity_move)
333 Hmac h(hash_key, Hash::sha256_type);
335 Hmac h2 = std::move(h);
336 char hbuf[h2.
size()];
338 string hex1 = Hex::bin_to_hex(CharVec(&hbuf[0], &hbuf[h2.
size()]));
339 ASSERT_EQ(hex1, hmac_sha256);
340 ASSERT_THROW(h.final(hbuf, h.size()), std::runtime_error);
343 TEST_F(Hash_digest, Hmac_reset)
345 for (
auto& d : m_digest)
347 Hmac h(hash_key, d.first);
350 ASSERT_EQ(h.final(hbuf, h.size()), h.size());
351 string hex1 = Hex::bin_to_hex(CharVec(&hbuf[0], &hbuf[h.size()]));
353 h.update(hash_test1);
354 h.update(hash_test2);
355 ASSERT_EQ(h.final(hbuf, h.size()), h.size());
356 string hex2 = Hex::bin_to_hex(CharVec(&hbuf[0], &hbuf[h.size()]));
357 ASSERT_EQ(hex1, hex2);
361 TEST_F(Hash_digest, hash_vector_validate)
363 CharVec test(hash_test.begin(), hash_test.end());
364 CharVec test1(hash_test1.begin(), hash_test1.end());
365 CharVec test2(hash_test2.begin(), hash_test2.end());
368 for (
auto& d : m_digest)
370 d.second.update(test);
372 string hex = Hex::bin_to_hex(fin);
373 ASSERT_EQ(hex, m_hash[d.first]);
376 d.second.update(test1);
377 d.second.update(test2);
379 hex = Hex::bin_to_hex(fin);
380 ASSERT_EQ(hex, m_hash[d.first]);
384 TEST_F(Hash_digest, hmac_vector_validate)
386 CharVec key(hash_key.begin(), hash_key.end());
387 CharVec test(hash_test.begin(), hash_test.end());
388 CharVec test1(hash_test1.begin(), hash_test1.end());
389 CharVec test2(hash_test2.begin(), hash_test2.end());
392 for (
auto& d : m_digest)
394 Hmac h(key, d.first);
396 ASSERT_EQ(h.final(fin), h.size());
397 string hex1 = Hex::bin_to_hex(fin);
401 ASSERT_EQ(h.final(fin), h.size());
402 string hex2 = Hex::bin_to_hex(fin);
403 ASSERT_EQ(hex1, hex2);
407 TEST_F(Hash_digest, hash_tag)
409 using charv = vector<char>;
412 ifstream f(
"/dev/urandom");
414 f.read(d1.data(), 1024);
416 f.read(d2.data(), 1024);
418 d1d2.insert(d1d2.end(), d2.begin(), d2.end());
420 for (
auto& d : m_hash)
440 ASSERT_EQ(d1h, d1tag);
445 ASSERT_EQ(d1d2h, d1d2tag);
449 ASSERT_EQ(d1d2h, ver);
453 ASSERT_EQ(inittag, inith);
Helper class to hash an incoming stream.
Helper class to hash an outgoing stream.
General one-way hashing algorithms.
Hmac, aka hash-based message authentication code.
int final(void *, int)
Calculate the final hmac value.
int size() const
Hmac size.
Input/output stream wrapper for reader/writer.
Loopback read/write stream buffer.
One-way hashing and message digests.
Binary to hex string converter.
Base input/output stream classes.
Loopback read/write buffer.
TEST(inet_example, client_server_stream_test)
[Inet client server]