• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2011 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "crypto/hmac.h"
6 
7 #include <stddef.h>
8 #include <string.h>
9 
10 #include <string>
11 
12 #include "testing/gtest/include/gtest/gtest.h"
13 
14 static const size_t kSHA1DigestSize = 20;
15 static const size_t kSHA256DigestSize = 32;
16 
17 static const char* kSimpleKey =
18     "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
19     "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
20     "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
21     "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
22     "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA";
23 static const size_t kSimpleKeyLength = 80;
24 
25 static const struct {
26   const char *data;
27   const int data_len;
28   const char *digest;
29 } kSimpleHmacCases[] = {
30   { "Test Using Larger Than Block-Size Key - Hash Key First", 54,
31     "\xAA\x4A\xE5\xE1\x52\x72\xD0\x0E\x95\x70\x56\x37\xCE\x8A\x3B\x55"
32         "\xED\x40\x21\x12" },
33   { "Test Using Larger Than Block-Size Key and Larger "
34         "Than One Block-Size Data", 73,
35     "\xE8\xE9\x9D\x0F\x45\x23\x7D\x78\x6D\x6B\xBA\xA7\x96\x5C\x78\x08"
36         "\xBB\xFF\x1A\x91" }
37 };
38 
TEST(HMACTest,HmacSafeBrowsingResponseTest)39 TEST(HMACTest, HmacSafeBrowsingResponseTest) {
40   const int kKeySize = 16;
41 
42   // Client key.
43   const unsigned char kClientKey[kKeySize] =
44       { 0xbf, 0xf6, 0x83, 0x4b, 0x3e, 0xa3, 0x23, 0xdd,
45         0x96, 0x78, 0x70, 0x8e, 0xa1, 0x9d, 0x3b, 0x40 };
46 
47   // Expected HMAC result using kMessage and kClientKey.
48   const unsigned char kReceivedHmac[kSHA1DigestSize] =
49       { 0xb9, 0x3c, 0xd6, 0xf0, 0x49, 0x47, 0xe2, 0x52,
50         0x59, 0x7a, 0xbd, 0x1f, 0x2b, 0x4c, 0x83, 0xad,
51         0x86, 0xd2, 0x48, 0x85 };
52 
53   const char kMessage[] =
54 "n:1896\ni:goog-malware-shavar\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shav"
55 "ar_s_445-450\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_439-444\nu:s"
56 ".ytimg.com/safebrowsing/rd/goog-malware-shavar_s_437\nu:s.ytimg.com/safebrowsi"
57 "ng/rd/goog-malware-shavar_s_436\nu:s.ytimg.com/safebrowsing/rd/goog-malware-sh"
58 "avar_s_433-435\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_431\nu:s.y"
59 "timg.com/safebrowsing/rd/goog-malware-shavar_s_430\nu:s.ytimg.com/safebrowsing"
60 "/rd/goog-malware-shavar_s_429\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shav"
61 "ar_s_428\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_426\nu:s.ytimg.c"
62 "om/safebrowsing/rd/goog-malware-shavar_s_424\nu:s.ytimg.com/safebrowsing/rd/go"
63 "og-malware-shavar_s_423\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_4"
64 "22\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_420\nu:s.ytimg.com/saf"
65 "ebrowsing/rd/goog-malware-shavar_s_419\nu:s.ytimg.com/safebrowsing/rd/goog-mal"
66 "ware-shavar_s_414\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_409-411"
67 "\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_405\nu:s.ytimg.com/safeb"
68 "rowsing/rd/goog-malware-shavar_s_404\nu:s.ytimg.com/safebrowsing/rd/goog-malwa"
69 "re-shavar_s_402\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_401\nu:s."
70 "ytimg.com/safebrowsing/rd/goog-malware-shavar_a_973-978\nu:s.ytimg.com/safebro"
71 "wsing/rd/goog-malware-shavar_a_937-972\nu:s.ytimg.com/safebrowsing/rd/goog-mal"
72 "ware-shavar_a_931-936\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_a_925"
73 "-930\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_a_919-924\ni:goog-phis"
74 "h-shavar\nu:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_2633\nu:s.ytimg.co"
75 "m/safebrowsing/rd/goog-phish-shavar_a_2632\nu:s.ytimg.com/safebrowsing/rd/goog"
76 "-phish-shavar_a_2629-2631\nu:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_2"
77 "626-2628\nu:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_2625\n";
78 
79   std::string message_data(kMessage);
80 
81   crypto::HMAC hmac(crypto::HMAC::SHA1);
82   ASSERT_TRUE(hmac.Init(kClientKey, kKeySize));
83   unsigned char calculated_hmac[kSHA1DigestSize];
84 
85   EXPECT_TRUE(hmac.Sign(message_data, calculated_hmac, kSHA1DigestSize));
86   EXPECT_EQ(0, memcmp(kReceivedHmac, calculated_hmac, kSHA1DigestSize));
87 }
88 
89 // Test cases from RFC 2202 section 3
TEST(HMACTest,RFC2202TestCases)90 TEST(HMACTest, RFC2202TestCases) {
91   const struct {
92     const char *key;
93     const int key_len;
94     const char *data;
95     const int data_len;
96     const char *digest;
97   } cases[] = {
98     { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B"
99           "\x0B\x0B\x0B\x0B", 20,
100       "Hi There", 8,
101       "\xB6\x17\x31\x86\x55\x05\x72\x64\xE2\x8B\xC0\xB6\xFB\x37\x8C\x8E"
102           "\xF1\x46\xBE\x00" },
103     { "Jefe", 4,
104       "what do ya want for nothing?", 28,
105       "\xEF\xFC\xDF\x6A\xE5\xEB\x2F\xA2\xD2\x74\x16\xD5\xF1\x84\xDF\x9C"
106           "\x25\x9A\x7C\x79" },
107     { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
108           "\xAA\xAA\xAA\xAA", 20,
109       "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
110           "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
111           "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
112           "\xDD\xDD", 50,
113       "\x12\x5D\x73\x42\xB9\xAC\x11\xCD\x91\xA3\x9A\xF4\x8A\xA1\x7B\x4F"
114           "\x63\xF1\x75\xD3" },
115     { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
116           "\x11\x12\x13\x14\x15\x16\x17\x18\x19", 25,
117       "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
118           "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
119           "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
120           "\xCD\xCD", 50,
121       "\x4C\x90\x07\xF4\x02\x62\x50\xC6\xBC\x84\x14\xF9\xBF\x50\xC8\x6C"
122           "\x2D\x72\x35\xDA" },
123     { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C"
124           "\x0C\x0C\x0C\x0C", 20,
125       "Test With Truncation", 20,
126       "\x4C\x1A\x03\x42\x4B\x55\xE0\x7F\xE7\xF2\x7B\xE1\xD5\x8B\xB9\x32"
127           "\x4A\x9A\x5A\x04" },
128     { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
129           "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
130           "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
131           "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
132           "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA",
133       80,
134       "Test Using Larger Than Block-Size Key - Hash Key First", 54,
135       "\xAA\x4A\xE5\xE1\x52\x72\xD0\x0E\x95\x70\x56\x37\xCE\x8A\x3B\x55"
136           "\xED\x40\x21\x12" },
137     { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
138           "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
139           "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
140           "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
141           "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA",
142       80,
143       "Test Using Larger Than Block-Size Key and Larger "
144           "Than One Block-Size Data", 73,
145       "\xE8\xE9\x9D\x0F\x45\x23\x7D\x78\x6D\x6B\xBA\xA7\x96\x5C\x78\x08"
146           "\xBB\xFF\x1A\x91" }
147   };
148 
149   for (size_t i = 0; i < std::size(cases); ++i) {
150     crypto::HMAC hmac(crypto::HMAC::SHA1);
151     ASSERT_TRUE(hmac.Init(reinterpret_cast<const unsigned char*>(cases[i].key),
152                           cases[i].key_len));
153     std::string data_string(cases[i].data, cases[i].data_len);
154     unsigned char digest[kSHA1DigestSize];
155     EXPECT_TRUE(hmac.Sign(data_string, digest, kSHA1DigestSize));
156     EXPECT_EQ(0, memcmp(cases[i].digest, digest, kSHA1DigestSize));
157   }
158 }
159 
160 // TODO(wtc): add other test vectors from RFC 4231.
TEST(HMACTest,RFC4231TestCase6)161 TEST(HMACTest, RFC4231TestCase6) {
162   unsigned char key[131];
163   for (size_t i = 0; i < sizeof(key); ++i)
164     key[i] = 0xaa;
165 
166   std::string data = "Test Using Larger Than Block-Size Key - Hash Key First";
167   ASSERT_EQ(54U, data.size());
168 
169   static unsigned char kKnownHMACSHA256[] = {
170     0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f,
171     0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5, 0xb7, 0x7f,
172     0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14,
173     0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54
174   };
175 
176   crypto::HMAC hmac(crypto::HMAC::SHA256);
177   ASSERT_TRUE(hmac.Init(key, sizeof(key)));
178   unsigned char calculated_hmac[kSHA256DigestSize];
179 
180   EXPECT_EQ(kSHA256DigestSize, hmac.DigestLength());
181   EXPECT_TRUE(hmac.Sign(data, calculated_hmac, kSHA256DigestSize));
182   EXPECT_EQ(0, memcmp(kKnownHMACSHA256, calculated_hmac, kSHA256DigestSize));
183 }
184 
185 // Based on NSS's FIPS HMAC power-up self-test.
TEST(HMACTest,NSSFIPSPowerUpSelfTest)186 TEST(HMACTest, NSSFIPSPowerUpSelfTest) {
187   static const char kKnownMessage[] =
188       "The test message for the MD2, MD5, and SHA-1 hashing algorithms.";
189 
190   static const unsigned char kKnownSecretKey[] = {
191     0x46, 0x69, 0x72, 0x65, 0x66, 0x6f, 0x78, 0x20,
192     0x61, 0x6e, 0x64, 0x20, 0x54, 0x68, 0x75, 0x6e,
193     0x64, 0x65, 0x72, 0x42, 0x69, 0x72, 0x64, 0x20,
194     0x61, 0x72, 0x65, 0x20, 0x61, 0x77, 0x65, 0x73,
195     0x6f, 0x6d, 0x65, 0x21, 0x00
196   };
197 
198   static const size_t kKnownSecretKeySize = sizeof(kKnownSecretKey);
199 
200   // HMAC-SHA-1 known answer (20 bytes).
201   static const unsigned char kKnownHMACSHA1[] = {
202     0xd5, 0x85, 0xf6, 0x5b, 0x39, 0xfa, 0xb9, 0x05,
203     0x3b, 0x57, 0x1d, 0x61, 0xe7, 0xb8, 0x84, 0x1e,
204     0x5d, 0x0e, 0x1e, 0x11
205   };
206 
207   // HMAC-SHA-256 known answer (32 bytes).
208   static const unsigned char kKnownHMACSHA256[] = {
209     0x05, 0x75, 0x9a, 0x9e, 0x70, 0x5e, 0xe7, 0x44,
210     0xe2, 0x46, 0x4b, 0x92, 0x22, 0x14, 0x22, 0xe0,
211     0x1b, 0x92, 0x8a, 0x0c, 0xfe, 0xf5, 0x49, 0xe9,
212     0xa7, 0x1b, 0x56, 0x7d, 0x1d, 0x29, 0x40, 0x48
213   };
214 
215   std::string message_data(kKnownMessage);
216 
217   crypto::HMAC hmac(crypto::HMAC::SHA1);
218   ASSERT_TRUE(hmac.Init(kKnownSecretKey, kKnownSecretKeySize));
219   unsigned char calculated_hmac[kSHA1DigestSize];
220 
221   EXPECT_EQ(kSHA1DigestSize, hmac.DigestLength());
222   EXPECT_TRUE(hmac.Sign(message_data, calculated_hmac, kSHA1DigestSize));
223   EXPECT_EQ(0, memcmp(kKnownHMACSHA1, calculated_hmac, kSHA1DigestSize));
224   EXPECT_TRUE(hmac.Verify(
225       message_data,
226       base::StringPiece(reinterpret_cast<const char*>(kKnownHMACSHA1),
227                         kSHA1DigestSize)));
228   EXPECT_TRUE(hmac.VerifyTruncated(
229       message_data,
230       base::StringPiece(reinterpret_cast<const char*>(kKnownHMACSHA1),
231                         kSHA1DigestSize / 2)));
232 
233   crypto::HMAC hmac2(crypto::HMAC::SHA256);
234   ASSERT_TRUE(hmac2.Init(kKnownSecretKey, kKnownSecretKeySize));
235   unsigned char calculated_hmac2[kSHA256DigestSize];
236 
237   EXPECT_TRUE(hmac2.Sign(message_data, calculated_hmac2, kSHA256DigestSize));
238   EXPECT_EQ(0, memcmp(kKnownHMACSHA256, calculated_hmac2, kSHA256DigestSize));
239 }
240 
TEST(HMACTest,HMACObjectReuse)241 TEST(HMACTest, HMACObjectReuse) {
242   crypto::HMAC hmac(crypto::HMAC::SHA1);
243   ASSERT_TRUE(
244       hmac.Init(reinterpret_cast<const unsigned char*>(kSimpleKey),
245                 kSimpleKeyLength));
246   for (size_t i = 0; i < std::size(kSimpleHmacCases); ++i) {
247     std::string data_string(kSimpleHmacCases[i].data,
248                             kSimpleHmacCases[i].data_len);
249     unsigned char digest[kSHA1DigestSize];
250     EXPECT_TRUE(hmac.Sign(data_string, digest, kSHA1DigestSize));
251     EXPECT_EQ(0, memcmp(kSimpleHmacCases[i].digest, digest, kSHA1DigestSize));
252   }
253 }
254 
TEST(HMACTest,Verify)255 TEST(HMACTest, Verify) {
256   crypto::HMAC hmac(crypto::HMAC::SHA1);
257   ASSERT_TRUE(
258       hmac.Init(reinterpret_cast<const unsigned char*>(kSimpleKey),
259                 kSimpleKeyLength));
260   const char empty_digest[kSHA1DigestSize] = { 0 };
261   for (size_t i = 0; i < std::size(kSimpleHmacCases); ++i) {
262     // Expected results
263     EXPECT_TRUE(hmac.Verify(
264         base::StringPiece(kSimpleHmacCases[i].data,
265                           kSimpleHmacCases[i].data_len),
266         base::StringPiece(kSimpleHmacCases[i].digest,
267                           kSHA1DigestSize)));
268     // Mismatched size
269     EXPECT_FALSE(hmac.Verify(
270         base::StringPiece(kSimpleHmacCases[i].data,
271                           kSimpleHmacCases[i].data_len),
272         base::StringPiece(kSimpleHmacCases[i].data,
273                           kSimpleHmacCases[i].data_len)));
274 
275     // Expected size, mismatched data
276     EXPECT_FALSE(hmac.Verify(
277         base::StringPiece(kSimpleHmacCases[i].data,
278                           kSimpleHmacCases[i].data_len),
279         base::StringPiece(empty_digest, kSHA1DigestSize)));
280   }
281 }
282 
TEST(HMACTest,EmptyKey)283 TEST(HMACTest, EmptyKey) {
284   // Test vector from https://en.wikipedia.org/wiki/HMAC
285   const char* kExpectedDigest =
286       "\xFB\xDB\x1D\x1B\x18\xAA\x6C\x08\x32\x4B\x7D\x64\xB7\x1F\xB7\x63"
287       "\x70\x69\x0E\x1D";
288   base::StringPiece data("");
289 
290   crypto::HMAC hmac(crypto::HMAC::SHA1);
291   ASSERT_TRUE(hmac.Init(nullptr, 0));
292 
293   unsigned char digest[kSHA1DigestSize];
294   EXPECT_TRUE(hmac.Sign(data, digest, kSHA1DigestSize));
295   EXPECT_EQ(0, memcmp(kExpectedDigest, digest, kSHA1DigestSize));
296 
297   EXPECT_TRUE(hmac.Verify(
298       data, base::StringPiece(kExpectedDigest, kSHA1DigestSize)));
299 }
300 
TEST(HMACTest,TooLong)301 TEST(HMACTest, TooLong) {
302   // See RFC4231, section 4.7.
303   unsigned char key[131];
304   for (size_t i = 0; i < sizeof(key); ++i)
305     key[i] = 0xaa;
306 
307   std::string data = "Test Using Larger Than Block-Size Key - Hash Key First";
308   static uint8_t kKnownHMACSHA256[] = {
309       0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f, 0x0d, 0x8a, 0x26,
310       0xaa, 0xcb, 0xf5, 0xb7, 0x7f, 0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28,
311       0xc5, 0x14, 0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54};
312 
313   crypto::HMAC hmac(crypto::HMAC::SHA256);
314   ASSERT_TRUE(hmac.Init(key, sizeof(key)));
315 
316   // Attempting to write too large of an HMAC is an error.
317   uint8_t calculated_hmac[kSHA256DigestSize + 1];
318   EXPECT_FALSE(hmac.Sign(data, calculated_hmac, sizeof(calculated_hmac)));
319 
320   // Attempting to verify too large of an HMAC is an error.
321   memcpy(calculated_hmac, kKnownHMACSHA256, kSHA256DigestSize);
322   calculated_hmac[kSHA256DigestSize] = 0;
323   EXPECT_FALSE(hmac.VerifyTruncated(
324       data,
325       std::string(calculated_hmac, calculated_hmac + sizeof(calculated_hmac))));
326 }
327 
TEST(HMACTest,Bytes)328 TEST(HMACTest, Bytes) {
329   // See RFC4231, section 4.7.
330   std::vector<uint8_t> key(131, 0xaa);
331   std::string data_str =
332       "Test Using Larger Than Block-Size Key - Hash Key First";
333   std::vector<uint8_t> data(data_str.begin(), data_str.end());
334   static uint8_t kKnownHMACSHA256[] = {
335       0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f, 0x0d, 0x8a, 0x26,
336       0xaa, 0xcb, 0xf5, 0xb7, 0x7f, 0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28,
337       0xc5, 0x14, 0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54};
338 
339   crypto::HMAC hmac(crypto::HMAC::SHA256);
340   ASSERT_TRUE(hmac.Init(key));
341 
342   uint8_t calculated_hmac[kSHA256DigestSize];
343   ASSERT_TRUE(hmac.Sign(data, calculated_hmac));
344   EXPECT_EQ(0, memcmp(kKnownHMACSHA256, calculated_hmac, kSHA256DigestSize));
345 
346   EXPECT_TRUE(hmac.Verify(data, calculated_hmac));
347   EXPECT_TRUE(hmac.VerifyTruncated(
348       data, base::make_span(calculated_hmac, kSHA256DigestSize / 2)));
349 
350   data[0]++;
351   EXPECT_FALSE(hmac.Verify(data, calculated_hmac));
352   EXPECT_FALSE(hmac.VerifyTruncated(
353       data, base::make_span(calculated_hmac, kSHA256DigestSize / 2)));
354 }
355