1 /**
2  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3  * SPDX-License-Identifier: Apache-2.0.
4  */
5 
6 #include <aws/external/gtest.h>
7 
8 #include <aws/core/utils/HashingUtils.h>
9 #include <aws/core/utils/memory/stl/AWSStringStream.h>
10 
11 
12 using namespace Aws::Utils;
13 
TEST(HashingUtilsTest,TestBase64Encoding)14 TEST(HashingUtilsTest, TestBase64Encoding)
15 {
16     //these are the standard testing vectors from RFC 4648
17     Aws::String test1 = HashingUtils::Base64Encode(ByteBuffer((unsigned char*)"", 0));
18     ASSERT_STREQ("", test1.c_str());
19 
20     Aws::String test2 = HashingUtils::Base64Encode(ByteBuffer((unsigned char*) "f", 1));
21     ASSERT_STREQ("Zg==", test2.c_str());
22 
23     Aws::String test3 = HashingUtils::Base64Encode(ByteBuffer((unsigned char*) "fo", 2));
24     ASSERT_STREQ("Zm8=", test3.c_str());
25 
26     Aws::String test4 = HashingUtils::Base64Encode(ByteBuffer((unsigned char*) "foo", 3));
27     ASSERT_STREQ("Zm9v", test4.c_str());
28 
29     Aws::String test5 = HashingUtils::Base64Encode(ByteBuffer((unsigned char*) "foob", 4));
30     ASSERT_STREQ("Zm9vYg==", test5.c_str());
31 
32     Aws::String test6 = HashingUtils::Base64Encode(ByteBuffer((unsigned char*) "fooba", 5));
33     ASSERT_STREQ("Zm9vYmE=", test6.c_str());
34 
35     Aws::String test7 = HashingUtils::Base64Encode(ByteBuffer((unsigned char*) "foobar", 6));
36     ASSERT_STREQ("Zm9vYmFy", test7.c_str());
37 }
38 
TEST(HashingUtilsTest,TestBase64Decoding)39 TEST(HashingUtilsTest, TestBase64Decoding)
40 {
41     //these are the standard testing vectors from RFC 4648
42     ByteBuffer test0 = HashingUtils::Base64Decode("");
43     ASSERT_EQ(ByteBuffer((unsigned char*)"", 0), test0);
44 
45     ByteBuffer test1 = HashingUtils::Base64Decode("X");
46     ASSERT_EQ(ByteBuffer((unsigned char*)"", 0), test1);
47 
48     ByteBuffer test2 = HashingUtils::Base64Decode("Zg==");
49     ASSERT_EQ(ByteBuffer((unsigned char*)"f", 1), test2);
50 
51     ByteBuffer test3 = HashingUtils::Base64Decode("Zm8=");
52     ASSERT_EQ(ByteBuffer((unsigned char*) "fo", 2), test3);
53 
54     ByteBuffer test4 = HashingUtils::Base64Decode("Zm9v");
55     ASSERT_EQ(ByteBuffer((unsigned char*) "foo", 3), test4);
56 
57     ByteBuffer test5 = HashingUtils::Base64Decode("Zm9vYg==");
58     ASSERT_EQ(ByteBuffer((unsigned char*) "foob", 4), test5);
59 
60     ByteBuffer test6 = HashingUtils::Base64Decode("Zm9vYmE=");
61     ASSERT_EQ(ByteBuffer((unsigned char*) "fooba", 5), test6);
62 
63     ByteBuffer test7 = HashingUtils::Base64Decode("Zm9vYmFy");
64     ASSERT_EQ(ByteBuffer((unsigned char*) "foobar", 6), test7);
65 }
66 
TEST(HashingUtilsTest,TestHexEncodingDecoding)67 TEST(HashingUtilsTest, TestHexEncodingDecoding)
68 {
69     unsigned char beforeHexEncoding[32] =
70     { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
71             0x0D, 0x0E, 0x0F, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x78, 0x69,
72             0x5A, 0x4B, 0x3C, 0x2D, 0x1E, 0x0F, 0x10, 0x00 };
73 
74     Aws::String hexEncodedValue = HashingUtils::HexEncode(ByteBuffer(beforeHexEncoding, 32));
75 
76     const char* afterEncoding =
77             "0102030405060708090a0b0c0d0e0f1122334455667778695a4b3c2d1e0f1000";
78     ASSERT_STREQ(afterEncoding, hexEncodedValue.c_str());
79 
80     ByteBuffer hexBuffer(beforeHexEncoding, 32);
81     ASSERT_EQ(hexBuffer, HashingUtils::HexDecode(afterEncoding));
82 }
83 
TEST(HashingUtilsTest,TestSHA256HMAC)84 TEST(HashingUtilsTest, TestSHA256HMAC)
85 {
86     const char* toHash = "TestHash";
87     const char* secret = "TestSecret";
88 
89     ByteBuffer digest = HashingUtils::CalculateSHA256HMAC(
90             ByteBuffer((unsigned char*) toHash, 8), ByteBuffer((unsigned char*) secret, 10));
91 
92     Aws::String computedHashAsHex = HashingUtils::HexEncode(digest);
93 
94     ASSERT_EQ(32uL, digest.GetLength());
95     EXPECT_STREQ("43cf04fa24b873a456670d34ef9af2cb7870483327b5767509336fa66fb7986c", computedHashAsHex.c_str());
96 }
97 
TEST(HashingUtilsTest,TestSHA256FromString)98 TEST(HashingUtilsTest, TestSHA256FromString)
99 {
100     Aws::String toHash = "TestToHash";
101 
102     ByteBuffer digest = HashingUtils::CalculateSHA256(toHash);
103     ASSERT_EQ(32uL, digest.GetLength());
104 
105     Aws::String base64Hash = HashingUtils::Base64Encode(digest);
106     EXPECT_STREQ("No9GqyFhBA5QWj9+YUchjN83IByaCH5Lqji0McSOKyg=", base64Hash.c_str());
107 
108     // SHA256 results come from https://www.di-mgt.com.au/sha_testvectors.html
109     EXPECT_STREQ(HashingUtils::HexEncode(HashingUtils::CalculateSHA256("")).c_str(),
110             "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
111 
112     EXPECT_STREQ(HashingUtils::HexEncode(HashingUtils::CalculateSHA256("abc")).c_str(),
113             "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad");
114 
115     EXPECT_STREQ(HashingUtils::HexEncode(HashingUtils::CalculateSHA256(
116             "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")).c_str(),
117             "cf5b16a778af8380036ce59e7b0492370b249b11e8f07a51afac45037afee9d1");
118 }
119 
TEST(HashingUtilsTest,TestSHA1FromString)120 TEST(HashingUtilsTest, TestSHA1FromString)
121 {
122     Aws::String toHash = "TestToHash";
123 
124     ByteBuffer digest = HashingUtils::CalculateSHA1(toHash);
125     ASSERT_EQ(20uL, digest.GetLength());
126 
127     // SHA1 results come from https://www.di-mgt.com.au/sha_testvectors.html
128     EXPECT_STREQ(HashingUtils::HexEncode(HashingUtils::CalculateSHA1("")).c_str(),
129                  "da39a3ee5e6b4b0d3255bfef95601890afd80709");
130 
131     EXPECT_STREQ(HashingUtils::HexEncode(HashingUtils::CalculateSHA1("abc")).c_str(),
132                  "a9993e364706816aba3e25717850c26c9cd0d89d");
133 
134     EXPECT_STREQ(HashingUtils::HexEncode(HashingUtils::CalculateSHA1(
135             "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")).c_str(),
136                  "a49b2446a02c645bf419f995b67091253a04a259");
137 }
138 
TEST(HashingUtilsTest,TestSHA1FromStream)139 TEST(HashingUtilsTest, TestSHA1FromStream)
140 {
141     Aws::StringStream toHash;
142     toHash << "TestToHash";
143 
144     ByteBuffer digest = HashingUtils::CalculateSHA1(toHash);
145     ASSERT_EQ(20uL, digest.GetLength());
146 
147     // SHA1 results come from https://www.di-mgt.com.au/sha_testvectors.html
148     toHash.str("");
149     toHash.clear();
150     toHash << "";
151     EXPECT_STREQ(HashingUtils::HexEncode(HashingUtils::CalculateSHA1(toHash)).c_str(),
152             "da39a3ee5e6b4b0d3255bfef95601890afd80709");
153 
154     toHash.str("");
155     toHash.clear();
156     toHash << "abc";
157     EXPECT_STREQ(HashingUtils::HexEncode(HashingUtils::CalculateSHA1(toHash)).c_str(),
158             "a9993e364706816aba3e25717850c26c9cd0d89d");
159 
160     toHash.str("");
161     toHash.clear();
162     toHash << "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu";
163     EXPECT_STREQ(HashingUtils::HexEncode(HashingUtils::CalculateSHA1(toHash)).c_str(),
164             "a49b2446a02c645bf419f995b67091253a04a259");
165 }
166 
TEST(HashingUtilsTest,TestSHA256FromStream)167 TEST(HashingUtilsTest, TestSHA256FromStream)
168 {
169     Aws::StringStream toHash;
170     toHash << "TestToHash";
171 
172     ByteBuffer digest = HashingUtils::CalculateSHA256(toHash);
173     ASSERT_EQ(32uL, digest.GetLength());
174 
175     Aws::String base64Hash = HashingUtils::Base64Encode(digest);
176     EXPECT_STREQ("No9GqyFhBA5QWj9+YUchjN83IByaCH5Lqji0McSOKyg=", base64Hash.c_str());
177 
178     // SHA256 results come from https://www.di-mgt.com.au/sha_testvectors.html
179     toHash.str("");
180     toHash.clear();
181     EXPECT_STREQ(HashingUtils::HexEncode(HashingUtils::CalculateSHA256(toHash)).c_str(),
182             "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
183 
184     toHash.str("");
185     toHash.clear();
186     toHash << "abc";
187     EXPECT_STREQ(HashingUtils::HexEncode(HashingUtils::CalculateSHA256(toHash)).c_str(),
188             "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad");
189 
190     toHash.str("");
191     toHash.clear();
192     toHash << "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu";
193     EXPECT_STREQ(HashingUtils::HexEncode(HashingUtils::CalculateSHA256(toHash)).c_str(),
194             "cf5b16a778af8380036ce59e7b0492370b249b11e8f07a51afac45037afee9d1");
195 }
196 
TEST(HashingUtilsTest,TestSHA256TreeHashEqualsSHA256FromStringWhenSizeLessEqualThanOneMB)197 TEST(HashingUtilsTest, TestSHA256TreeHashEqualsSHA256FromStringWhenSizeLessEqualThanOneMB)
198 {
199     Aws::Vector<Aws::String> strVec;
200     strVec.push_back("");
201     strVec.push_back("abc");
202     strVec.push_back("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu");
203     strVec.push_back("TestToHash");
204     strVec.push_back(Aws::String(1024 * 1024 - 1, 'A'));
205     strVec.push_back(Aws::String(1024 * 1024, 'A'));
206     for (size_t i = 0; i < strVec.size(); i++)
207     {
208         ByteBuffer sha256Digest = HashingUtils::CalculateSHA256(strVec[i]);
209         ByteBuffer sha256TreeHashDigest = HashingUtils::CalculateSHA256TreeHash(strVec[i]);
210         ASSERT_EQ(32uL, sha256Digest.GetLength());
211         ASSERT_EQ(32uL, sha256TreeHashDigest.GetLength());
212 
213         Aws::String base64Hash = HashingUtils::Base64Encode(sha256Digest);
214         Aws::String base64TreeHash = HashingUtils::Base64Encode(sha256TreeHashDigest);
215 
216         EXPECT_STREQ(base64Hash.c_str(), base64TreeHash.c_str());
217     }
218 }
219 
TEST(HashingUtilsTest,TestSHA256TreeHashFromStringWhenSizeMoreThanOneMB)220 TEST(HashingUtilsTest, TestSHA256TreeHashFromStringWhenSizeMoreThanOneMB)
221 {
222     // All cases are generated by java example code supplied at:
223     // http://docs.aws.amazon.com/amazonglacier/latest/dev/checksum-calculations.html#checksum-calculations-examples
224     // 2MB buffer filled with char '0'
225     Aws::String TwoMBStr(1024 * 1024 * 2, '0');
226     EXPECT_STREQ("489117033ee4cf06991b60ce56830ac409862a6ec8afdfb3b510e8fad3b80d24", HashingUtils::HexEncode(HashingUtils::CalculateSHA256TreeHash(TwoMBStr)).c_str());
227     // 3MB
228     Aws::String ThreeMBStr(1024 * 1024 * 3, '0');
229     EXPECT_STREQ("940257b3e0d13f92c98dc3fc32182e3acd07a81fe82f2b2dcd1802e1eedc5a3c", HashingUtils::HexEncode(HashingUtils::CalculateSHA256TreeHash(ThreeMBStr)).c_str());
230     // 4MB
231     Aws::String FourMBStr(1024 * 1024 * 4, '0');
232     EXPECT_STREQ("0c2c286faeadbb8ef7aab5e1198af77b1c00d6ff634a739f0e4d55ea3a40ad2d", HashingUtils::HexEncode(HashingUtils::CalculateSHA256TreeHash(FourMBStr)).c_str());
233     // 5.5MB
234     Aws::String FivePointFiveMBStr(5767168, '0');
235     EXPECT_STREQ("154e26c78fd74d0c2c9b3cc4644191619dc4f2cd539ae2a74d5fd07957a3ee6a", HashingUtils::HexEncode(HashingUtils::CalculateSHA256TreeHash(FivePointFiveMBStr)).c_str());
236     // 8MB
237     Aws::String EightMBStr(1024 * 1024 * 8, '0');
238     EXPECT_STREQ("ff9ea39186cb33cd5ade7aca078e297a1622f8c1abdd4cc47bcbf66dc5877e1f", HashingUtils::HexEncode(HashingUtils::CalculateSHA256TreeHash(EightMBStr)).c_str());
239 }
240 
TEST(HashingUtilsTest,TestSHA256TreeHashEqualsSHA256FromStreamWhenSizeLessEqualThanOneMB)241 TEST(HashingUtilsTest, TestSHA256TreeHashEqualsSHA256FromStreamWhenSizeLessEqualThanOneMB)
242 {
243     Aws::Vector<Aws::StringStream> streamVec(6);
244     streamVec[0] << "";
245     streamVec[1] << "abc";
246     streamVec[2] << "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu";
247     streamVec[3] << "TestToHash";
248     streamVec[4] << Aws::String(1024 * 1024 - 1, 'A');
249     streamVec[5] << Aws::String(1024 * 1024, 'A');
250     for (size_t i = 0; i < streamVec.size(); i++)
251     {
252         ByteBuffer sha256Digest = HashingUtils::CalculateSHA256(streamVec[i]);
253         ByteBuffer sha256TreeHashDigest = HashingUtils::CalculateSHA256TreeHash(streamVec[i]);
254         ASSERT_EQ(32uL, sha256Digest.GetLength());
255         ASSERT_EQ(32uL, sha256TreeHashDigest.GetLength());
256 
257         Aws::String base64Hash = HashingUtils::Base64Encode(sha256Digest);
258         Aws::String base64TreeHash = HashingUtils::Base64Encode(sha256TreeHashDigest);
259 
260         EXPECT_STREQ(base64Hash.c_str(), base64TreeHash.c_str());
261     }
262 }
263 
TEST(HashingUtilsTest,TestSHA256TreeHashFromStreamWhenSizeMoreThanOneMB)264 TEST(HashingUtilsTest, TestSHA256TreeHashFromStreamWhenSizeMoreThanOneMB)
265 {
266     // All cases are generated by java example code supplied at:
267     // http://docs.aws.amazon.com/amazonglacier/latest/dev/checksum-calculations.html#checksum-calculations-examples
268     // 2MB buffer filled with char '0'
269     Aws::StringStream TwoMBStream;
270     TwoMBStream << Aws::String(1024 * 1024 * 2, '0');
271     EXPECT_STREQ("489117033ee4cf06991b60ce56830ac409862a6ec8afdfb3b510e8fad3b80d24", HashingUtils::HexEncode(HashingUtils::CalculateSHA256TreeHash(TwoMBStream)).c_str());
272     // 3MB
273     Aws::StringStream ThreeMBStream;
274     ThreeMBStream << Aws::String(1024 * 1024 * 3, '0');
275     EXPECT_STREQ("940257b3e0d13f92c98dc3fc32182e3acd07a81fe82f2b2dcd1802e1eedc5a3c", HashingUtils::HexEncode(HashingUtils::CalculateSHA256TreeHash(ThreeMBStream)).c_str());
276     // 4MB
277     Aws::StringStream FourMBStream;
278     FourMBStream << Aws::String(1024 * 1024 * 4, '0');
279     EXPECT_STREQ("0c2c286faeadbb8ef7aab5e1198af77b1c00d6ff634a739f0e4d55ea3a40ad2d", HashingUtils::HexEncode(HashingUtils::CalculateSHA256TreeHash(FourMBStream)).c_str());
280     // 5.5MB
281     Aws::StringStream FivePointFiveMBStream;
282     FivePointFiveMBStream << Aws::String(5767168, '0');
283     EXPECT_STREQ("154e26c78fd74d0c2c9b3cc4644191619dc4f2cd539ae2a74d5fd07957a3ee6a", HashingUtils::HexEncode(HashingUtils::CalculateSHA256TreeHash(FivePointFiveMBStream)).c_str());
284     // 8MB
285     Aws::StringStream EightMBStream;
286     EightMBStream << Aws::String(1024 * 1024 * 8, '0');
287     EXPECT_STREQ("ff9ea39186cb33cd5ade7aca078e297a1622f8c1abdd4cc47bcbf66dc5877e1f", HashingUtils::HexEncode(HashingUtils::CalculateSHA256TreeHash(EightMBStream)).c_str());
288 }
289 
TestMD5FromString(const char * value,const char * expectedBase64Hash)290 static void TestMD5FromString(const char* value, const char* expectedBase64Hash)
291 {
292     Aws::String source(value);
293 
294     ByteBuffer digest = HashingUtils::CalculateMD5(source);
295     ASSERT_EQ(16uL, digest.GetLength());
296 
297     Aws::String base64Hash = HashingUtils::Base64Encode(digest);
298     ASSERT_STREQ(expectedBase64Hash, base64Hash.c_str());
299 }
300 
TEST(HashingUtilsTest,TestMD5FromString)301 TEST(HashingUtilsTest, TestMD5FromString)
302 {
303     // "" -> d41d8cd98f00b204e9800998ecf8427e -> 1B2M2Y8AsgTpgAmY7PhCfg== (base 64)
304     TestMD5FromString( "", "1B2M2Y8AsgTpgAmY7PhCfg==" );
305 
306     // "a" -> 0cc175b9c0f1b6a831c399e269772661 -> DMF1ucDxtqgxw5niaXcmYQ== (base 64)
307     TestMD5FromString( "a", "DMF1ucDxtqgxw5niaXcmYQ==" );
308 
309     // "abc" -> 900150983cd24fb0d6963f7d28e17f72 -> kAFQmDzST7DWlj99KOF/cg== (base 64)
310     TestMD5FromString( "abc", "kAFQmDzST7DWlj99KOF/cg==" );
311 
312     // "message digest" -> f96b697d7cb7938d525a2f31aaf161d0 -> +WtpfXy3k41SWi8xqvFh0A== (base 64)
313     TestMD5FromString( "message digest", "+WtpfXy3k41SWi8xqvFh0A==" );
314 
315     // "abcdefghijklmnopqrstuvwxyz" -> c3fcd3d76192e4007dfb496cca67e13b -> w/zT12GS5AB9+0lsymfhOw== (base 64)
316     TestMD5FromString( "abcdefghijklmnopqrstuvwxyz", "w/zT12GS5AB9+0lsymfhOw==" );
317 
318     // "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" -> d174ab98d277d9f5a5611c2c9f419d9f -> 0XSrmNJ32fWlYRwsn0Gdnw== (base 64)
319     TestMD5FromString( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "0XSrmNJ32fWlYRwsn0Gdnw==" );
320 
321     // "12345678901234567890123456789012345678901234567890123456789012345678901234567890" -> 57edf4a22be3c955ac49da2e2107b67a -> V+30oivjyVWsSdouIQe2eg== (base 64)
322     TestMD5FromString( "12345678901234567890123456789012345678901234567890123456789012345678901234567890", "V+30oivjyVWsSdouIQe2eg==" );
323 }
324 
TestMD5FromStream(const char * value,const char * expectedBase64Hash)325 static void TestMD5FromStream(const char* value, const char* expectedBase64Hash)
326 {
327     Aws::StringStream stream;
328 
329     stream.str(value);
330     ByteBuffer digest = HashingUtils::CalculateMD5(stream);
331     ASSERT_EQ(16uL, digest.GetLength());
332 
333     Aws::String base64Hash = HashingUtils::Base64Encode(digest);
334     ASSERT_STREQ(expectedBase64Hash, base64Hash.c_str());
335 }
336 
TEST(HashingUtilsTest,TestMD5FromStream)337 TEST(HashingUtilsTest, TestMD5FromStream)
338 {
339     // "" -> d41d8cd98f00b204e9800998ecf8427e -> 1B2M2Y8AsgTpgAmY7PhCfg== (base 64)
340     TestMD5FromStream( "", "1B2M2Y8AsgTpgAmY7PhCfg==" );
341 
342     // "a" -> 0cc175b9c0f1b6a831c399e269772661 -> DMF1ucDxtqgxw5niaXcmYQ== (base 64)
343     TestMD5FromStream( "a", "DMF1ucDxtqgxw5niaXcmYQ==" );
344 
345     // "abc" -> 900150983cd24fb0d6963f7d28e17f72 -> kAFQmDzST7DWlj99KOF/cg== (base 64)
346     TestMD5FromStream( "abc", "kAFQmDzST7DWlj99KOF/cg==" );
347 
348     // "message digest" -> f96b697d7cb7938d525a2f31aaf161d0 -> +WtpfXy3k41SWi8xqvFh0A== (base 64)
349     TestMD5FromStream( "message digest", "+WtpfXy3k41SWi8xqvFh0A==" );
350 
351     // "abcdefghijklmnopqrstuvwxyz" -> c3fcd3d76192e4007dfb496cca67e13b -> w/zT12GS5AB9+0lsymfhOw== (base 64)
352     TestMD5FromStream( "abcdefghijklmnopqrstuvwxyz", "w/zT12GS5AB9+0lsymfhOw==" );
353 
354     // "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" -> d174ab98d277d9f5a5611c2c9f419d9f -> 0XSrmNJ32fWlYRwsn0Gdnw== (base 64)
355     TestMD5FromStream( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "0XSrmNJ32fWlYRwsn0Gdnw==" );
356 
357     // "12345678901234567890123456789012345678901234567890123456789012345678901234567890" -> 57edf4a22be3c955ac49da2e2107b67a -> V+30oivjyVWsSdouIQe2eg== (base 64)
358     TestMD5FromStream( "12345678901234567890123456789012345678901234567890123456789012345678901234567890", "V+30oivjyVWsSdouIQe2eg==" );
359 }
360 
361