1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/cdm/json_web_key.h"
7 #include "base/base64.h"
8 #include "base/logging.h"
9 #include "testing/gtest/include/gtest/gtest.h"
13 class JSONWebKeyTest
: public testing::Test
{
18 void ExtractJWKKeysAndExpect(const std::string
& jwk
,
20 size_t expected_number_of_keys
) {
22 KeyIdAndKeyPairs keys
;
23 MediaKeys::SessionType session_type
;
24 EXPECT_EQ(expected_result
,
25 ExtractKeysFromJWKSet(jwk
, &keys
, &session_type
));
26 EXPECT_EQ(expected_number_of_keys
, keys
.size());
29 void ExtractSessionTypeAndExpect(const std::string
& jwk
,
31 MediaKeys::SessionType expected_type
) {
33 KeyIdAndKeyPairs keys
;
34 MediaKeys::SessionType session_type
;
35 EXPECT_EQ(expected_result
,
36 ExtractKeysFromJWKSet(jwk
, &keys
, &session_type
));
37 if (expected_result
) {
38 // Only check if successful.
39 EXPECT_EQ(expected_type
, session_type
);
43 void CreateLicenseAndExpect(const uint8
* key_id
,
45 MediaKeys::SessionType session_type
,
46 const std::string
& expected_result
) {
47 std::vector
<uint8
> result
;
49 key_ids
.push_back(std::vector
<uint8
>(key_id
, key_id
+ key_id_length
));
50 CreateLicenseRequest(key_ids
, session_type
, &result
);
51 std::string
s(result
.begin(), result
.end());
52 EXPECT_EQ(expected_result
, s
);
55 void ExtractKeyFromLicenseAndExpect(const std::string
& license
,
57 const uint8
* expected_key
,
58 int expected_key_length
) {
59 std::vector
<uint8
> license_vector(license
.begin(), license
.end());
60 std::vector
<uint8
> key
;
61 EXPECT_EQ(expected_result
,
62 ExtractFirstKeyIdFromLicenseRequest(license_vector
, &key
));
64 VerifyKeyId(key
, expected_key
, expected_key_length
);
67 void VerifyKeyId(std::vector
<uint8
> key
,
68 const uint8
* expected_key
,
69 int expected_key_length
) {
70 std::vector
<uint8
> key_result(expected_key
,
71 expected_key
+ expected_key_length
);
72 EXPECT_EQ(key_result
, key
);
76 TEST_F(JSONWebKeyTest
, GenerateJWKSet
) {
77 const uint8 data1
[] = { 0x01, 0x02 };
78 const uint8 data2
[] = { 0x01, 0x02, 0x03, 0x04 };
79 const uint8 data3
[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
80 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 };
82 EXPECT_EQ("{\"keys\":[{\"k\":\"AQI\",\"kid\":\"AQI\",\"kty\":\"oct\"}]}",
83 GenerateJWKSet(data1
, arraysize(data1
), data1
, arraysize(data1
)));
85 "{\"keys\":[{\"k\":\"AQIDBA\",\"kid\":\"AQIDBA\",\"kty\":\"oct\"}]}",
86 GenerateJWKSet(data2
, arraysize(data2
), data2
, arraysize(data2
)));
87 EXPECT_EQ("{\"keys\":[{\"k\":\"AQI\",\"kid\":\"AQIDBA\",\"kty\":\"oct\"}]}",
88 GenerateJWKSet(data1
, arraysize(data1
), data2
, arraysize(data2
)));
89 EXPECT_EQ("{\"keys\":[{\"k\":\"AQIDBA\",\"kid\":\"AQI\",\"kty\":\"oct\"}]}",
90 GenerateJWKSet(data2
, arraysize(data2
), data1
, arraysize(data1
)));
92 "{\"keys\":[{\"k\":\"AQIDBAUGBwgJCgsMDQ4PEA\",\"kid\":"
93 "\"AQIDBAUGBwgJCgsMDQ4PEA\",\"kty\":\"oct\"}]}",
94 GenerateJWKSet(data3
, arraysize(data3
), data3
, arraysize(data3
)));
97 TEST_F(JSONWebKeyTest
, ExtractValidJWKKeys
) {
98 // Try an empty 'keys' dictionary.
99 ExtractJWKKeysAndExpect("{ \"keys\": [] }", true, 0);
101 // Try a key list with one entry.
102 const std::string kJwksOneEntry
=
107 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
108 " \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
112 ExtractJWKKeysAndExpect(kJwksOneEntry
, true, 1);
114 // Try a key list with multiple entries.
115 const std::string kJwksMultipleEntries
=
120 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
121 " \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
125 " \"kid\": \"JCUmJygpKissLS4vMA\","
126 " \"k\":\"MTIzNDU2Nzg5Ojs8PT4_QA\""
130 ExtractJWKKeysAndExpect(kJwksMultipleEntries
, true, 2);
132 // Try a key with no spaces and some \n plus additional fields.
133 const std::string kJwksNoSpaces
=
134 "\n\n{\"something\":1,\"keys\":[{\n\n\"kty\":\"oct\","
135 "\"kid\":\"AAECAwQFBgcICQoLDA0ODxAREhM\",\"k\":\"GawgguFyGrWKav7AX4VKUg"
136 "\",\"foo\":\"bar\"}]}\n\n";
137 ExtractJWKKeysAndExpect(kJwksNoSpaces
, true, 1);
139 // Try a list with multiple keys with the same kid.
140 const std::string kJwksDuplicateKids
=
145 " \"kid\": \"JCUmJygpKissLS4vMA\","
146 " \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
150 " \"kid\": \"JCUmJygpKissLS4vMA\","
151 " \"k\":\"MTIzNDU2Nzg5Ojs8PT4_QA\""
155 ExtractJWKKeysAndExpect(kJwksDuplicateKids
, true, 2);
158 TEST_F(JSONWebKeyTest
, ExtractInvalidJWKKeys
) {
159 // Try a simple JWK key (i.e. not in a set)
160 const std::string kJwkSimple
=
163 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
164 " \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
166 ExtractJWKKeysAndExpect(kJwkSimple
, false, 0);
168 // Try some non-ASCII characters.
169 ExtractJWKKeysAndExpect(
170 "This is not ASCII due to \xff\xfe\xfd in it.", false, 0);
172 // Try some non-ASCII characters in an otherwise valid JWK.
173 const std::string kJwksInvalidCharacters
=
174 "\n\n{\"something\":1,\"keys\":[{\n\n\"kty\":\"oct\","
175 "\"kid\":\"AAECAwQFBgcICQoLDA0ODxAREhM\",\"k\":\"\xff\xfe\xfd"
176 "\",\"foo\":\"bar\"}]}\n\n";
177 ExtractJWKKeysAndExpect(kJwksInvalidCharacters
, false, 0);
179 // Try a badly formatted key. Assume that the JSON parser is fully tested,
180 // so we won't try a lot of combinations. However, need a test to ensure
181 // that the code doesn't crash if invalid JSON received.
182 ExtractJWKKeysAndExpect("This is not a JSON key.", false, 0);
184 // Try passing some valid JSON that is not a dictionary at the top level.
185 ExtractJWKKeysAndExpect("40", false, 0);
187 // Try an empty dictionary.
188 ExtractJWKKeysAndExpect("{ }", false, 0);
190 // Try with 'keys' not a dictionary.
191 ExtractJWKKeysAndExpect("{ \"keys\":\"1\" }", false, 0);
193 // Try with 'keys' a list of integers.
194 ExtractJWKKeysAndExpect("{ \"keys\": [ 1, 2, 3 ] }", false, 0);
196 // Try padding(=) at end of 'k' base64 string.
197 const std::string kJwksWithPaddedKey
=
202 " \"kid\": \"AAECAw\","
203 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw==\""
207 ExtractJWKKeysAndExpect(kJwksWithPaddedKey
, false, 0);
209 // Try padding(=) at end of 'kid' base64 string.
210 const std::string kJwksWithPaddedKeyId
=
215 " \"kid\": \"AAECAw==\","
216 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
220 ExtractJWKKeysAndExpect(kJwksWithPaddedKeyId
, false, 0);
222 // Try a key with invalid base64 encoding.
223 const std::string kJwksWithInvalidBase64
=
228 " \"kid\": \"!@#$%^&*()\","
229 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
233 ExtractJWKKeysAndExpect(kJwksWithInvalidBase64
, false, 0);
236 const std::string kJwksWithEmptyKeyId
=
242 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
246 ExtractJWKKeysAndExpect(kJwksWithEmptyKeyId
, false, 0);
249 TEST_F(JSONWebKeyTest
, KeyType
) {
251 const std::string kJwksWithValidKeyType
=
256 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
257 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
261 ExtractJWKKeysAndExpect(kJwksWithValidKeyType
, true, 1);
264 const std::string kJwksWithEmptyKeyType
=
269 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
270 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
274 ExtractJWKKeysAndExpect(kJwksWithEmptyKeyType
, false, 0);
276 // Key type is case sensitive.
277 const std::string kJwksWithUppercaseKeyType
=
282 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
283 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
287 ExtractJWKKeysAndExpect(kJwksWithUppercaseKeyType
, false, 0);
290 const std::string kJwksWithWrongKeyType
=
295 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
296 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
300 ExtractJWKKeysAndExpect(kJwksWithWrongKeyType
, false, 0);
303 TEST_F(JSONWebKeyTest
, Alg
) {
304 // 'alg' is ignored, so verify that anything is allowed.
306 const std::string kJwksWithValidAlg
=
311 " \"alg\": \"A128KW\","
312 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
313 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
317 ExtractJWKKeysAndExpect(kJwksWithValidAlg
, true, 1);
320 const std::string kJwksWithEmptyAlg
=
326 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
327 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
331 ExtractJWKKeysAndExpect(kJwksWithEmptyAlg
, true, 1);
333 // Alg is case sensitive.
334 const std::string kJwksWithLowercaseAlg
=
339 " \"alg\": \"a128kw\","
340 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
341 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
345 ExtractJWKKeysAndExpect(kJwksWithLowercaseAlg
, true, 1);
348 const std::string kJwksWithWrongAlg
=
353 " \"alg\": \"RS256\","
354 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
355 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
359 ExtractJWKKeysAndExpect(kJwksWithWrongAlg
, true, 1);
362 TEST_F(JSONWebKeyTest
, SessionType
) {
363 ExtractSessionTypeAndExpect(
364 "{\"keys\":[{\"k\":\"AQI\",\"kid\":\"AQI\",\"kty\":\"oct\"}]}", true,
365 MediaKeys::TEMPORARY_SESSION
);
366 ExtractSessionTypeAndExpect(
367 "{\"keys\":[{\"k\":\"AQI\",\"kid\":\"AQI\",\"kty\":\"oct\"}],\"type\":"
369 true, MediaKeys::TEMPORARY_SESSION
);
370 ExtractSessionTypeAndExpect(
371 "{\"keys\":[{\"k\":\"AQI\",\"kid\":\"AQI\",\"kty\":\"oct\"}],\"type\":"
372 "\"persistent-license\"}",
373 true, MediaKeys::PERSISTENT_LICENSE_SESSION
);
374 ExtractSessionTypeAndExpect(
375 "{\"keys\":[{\"k\":\"AQI\",\"kid\":\"AQI\",\"kty\":\"oct\"}],\"type\":"
376 "\"persistent-release-message\"}",
377 true, MediaKeys::PERSISTENT_RELEASE_MESSAGE_SESSION
);
378 ExtractSessionTypeAndExpect(
379 "{\"keys\":[{\"k\":\"AQI\",\"kid\":\"AQI\",\"kty\":\"oct\"}],\"type\":"
381 false, MediaKeys::TEMPORARY_SESSION
);
382 ExtractSessionTypeAndExpect(
383 "{\"keys\":[{\"k\":\"AQI\",\"kid\":\"AQI\",\"kty\":\"oct\"}],\"type\":3}",
384 false, MediaKeys::TEMPORARY_SESSION
);
387 TEST_F(JSONWebKeyTest
, CreateLicense
) {
388 const uint8 data1
[] = { 0x01, 0x02 };
389 const uint8 data2
[] = { 0x01, 0x02, 0x03, 0x04 };
390 const uint8 data3
[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
391 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 };
393 CreateLicenseAndExpect(data1
,
395 MediaKeys::TEMPORARY_SESSION
,
396 "{\"kids\":[\"AQI\"],\"type\":\"temporary\"}");
397 CreateLicenseAndExpect(
398 data1
, arraysize(data1
), MediaKeys::PERSISTENT_LICENSE_SESSION
,
399 "{\"kids\":[\"AQI\"],\"type\":\"persistent-license\"}");
400 CreateLicenseAndExpect(
401 data1
, arraysize(data1
), MediaKeys::PERSISTENT_RELEASE_MESSAGE_SESSION
,
402 "{\"kids\":[\"AQI\"],\"type\":\"persistent-release-message\"}");
403 CreateLicenseAndExpect(data2
,
405 MediaKeys::TEMPORARY_SESSION
,
406 "{\"kids\":[\"AQIDBA\"],\"type\":\"temporary\"}");
407 CreateLicenseAndExpect(data3
, arraysize(data3
),
408 MediaKeys::PERSISTENT_LICENSE_SESSION
,
409 "{\"kids\":[\"AQIDBAUGBwgJCgsMDQ4PEA\"],\"type\":"
410 "\"persistent-license\"}");
413 TEST_F(JSONWebKeyTest
, ExtractLicense
) {
414 const uint8 data1
[] = { 0x01, 0x02 };
415 const uint8 data2
[] = { 0x01, 0x02, 0x03, 0x04 };
416 const uint8 data3
[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
417 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 };
419 ExtractKeyFromLicenseAndExpect(
420 "{\"kids\":[\"AQI\"],\"type\":\"temporary\"}",
424 ExtractKeyFromLicenseAndExpect(
425 "{\"kids\":[\"AQIDBA\"],\"type\":\"temporary\"}",
429 ExtractKeyFromLicenseAndExpect(
430 "{\"kids\":[\"AQIDBAUGBwgJCgsMDQ4PEA\"],\"type\":\"persistent\"}",
435 // Try some incorrect JSON.
436 ExtractKeyFromLicenseAndExpect("", false, NULL
, 0);
437 ExtractKeyFromLicenseAndExpect("!@#$%^&*()", false, NULL
, 0);
439 // Valid JSON, but not a dictionary.
440 ExtractKeyFromLicenseAndExpect("6", false, NULL
, 0);
441 ExtractKeyFromLicenseAndExpect("[\"AQI\"]", false, NULL
, 0);
443 // Dictionary, but missing expected tag.
444 ExtractKeyFromLicenseAndExpect("{\"kid\":[\"AQI\"]}", false, NULL
, 0);
446 // Correct tag, but empty list.
447 ExtractKeyFromLicenseAndExpect("{\"kids\":[]}", false, NULL
, 0);
449 // Correct tag, but list doesn't contain a string.
450 ExtractKeyFromLicenseAndExpect("{\"kids\":[[\"AQI\"]]}", false, NULL
, 0);
452 // Correct tag, but invalid base64 encoding.
453 ExtractKeyFromLicenseAndExpect("{\"kids\":[\"!@#$%^&*()\"]}", false, NULL
, 0);
456 TEST_F(JSONWebKeyTest
, Base64UrlEncoding
) {
457 const uint8 data1
[] = { 0xfb, 0xfd, 0xfb, 0xfd, 0xfb, 0xfd, 0xfb };
459 // Verify that |data1| contains invalid base64url characters '+' and '/'
460 // and is padded with = when converted to base64.
461 std::string encoded_text
;
463 std::string(reinterpret_cast<const char*>(&data1
[0]), arraysize(data1
)),
465 EXPECT_EQ(encoded_text
, "+/37/fv9+w==");
466 EXPECT_NE(encoded_text
.find('+'), std::string::npos
);
467 EXPECT_NE(encoded_text
.find('/'), std::string::npos
);
468 EXPECT_NE(encoded_text
.find('='), std::string::npos
);
470 // base64url characters '-' and '_' not in base64 encoding.
471 EXPECT_EQ(encoded_text
.find('-'), std::string::npos
);
472 EXPECT_EQ(encoded_text
.find('_'), std::string::npos
);
474 CreateLicenseAndExpect(data1
, arraysize(data1
), MediaKeys::TEMPORARY_SESSION
,
475 "{\"kids\":[\"-_37_fv9-w\"],\"type\":\"temporary\"}");
477 ExtractKeyFromLicenseAndExpect(
478 "{\"kids\":[\"-_37_fv9-w\"],\"type\":\"temporary\"}", true, data1
,
482 TEST_F(JSONWebKeyTest
, MultipleKeys
) {
483 const uint8 data1
[] = { 0x01, 0x02 };
484 const uint8 data2
[] = { 0x01, 0x02, 0x03, 0x04 };
485 const uint8 data3
[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
486 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 };
488 std::vector
<uint8
> result
;
490 key_ids
.push_back(std::vector
<uint8
>(data1
, data1
+ arraysize(data1
)));
491 key_ids
.push_back(std::vector
<uint8
>(data2
, data2
+ arraysize(data2
)));
492 key_ids
.push_back(std::vector
<uint8
>(data3
, data3
+ arraysize(data3
)));
493 CreateLicenseRequest(key_ids
, MediaKeys::TEMPORARY_SESSION
, &result
);
494 std::string
s(result
.begin(), result
.end());
496 "{\"kids\":[\"AQI\",\"AQIDBA\",\"AQIDBAUGBwgJCgsMDQ4PEA\"],\"type\":"
501 TEST_F(JSONWebKeyTest
, ExtractKeyIds
) {
502 const uint8 data1
[] = { 0x01, 0x02 };
503 const uint8 data2
[] = { 0x01, 0x02, 0x03, 0x04 };
504 const uint8 data3
[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
505 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 };
508 std::string error_message
;
510 EXPECT_TRUE(ExtractKeyIdsFromKeyIdsInitData("{\"kids\":[\"AQI\"]}", &key_ids
,
512 EXPECT_EQ(1u, key_ids
.size());
513 EXPECT_EQ(0u, error_message
.length());
514 VerifyKeyId(key_ids
[0], data1
, arraysize(data1
));
516 EXPECT_TRUE(ExtractKeyIdsFromKeyIdsInitData(
517 "{\"kids\":[\"AQI\",\"AQIDBA\",\"AQIDBAUGBwgJCgsMDQ4PEA\"]}", &key_ids
,
519 EXPECT_EQ(3u, key_ids
.size());
520 EXPECT_EQ(0u, error_message
.length());
521 VerifyKeyId(key_ids
[0], data1
, arraysize(data1
));
522 VerifyKeyId(key_ids
[1], data2
, arraysize(data2
));
523 VerifyKeyId(key_ids
[2], data3
, arraysize(data3
));
525 // Expect failure when non-ascii.
526 EXPECT_FALSE(ExtractKeyIdsFromKeyIdsInitData(
527 "This is not ASCII due to \xff\xfe\x0a in it.", &key_ids
,
529 EXPECT_EQ(3u, key_ids
.size()); // |key_ids| should be unchanged.
530 EXPECT_EQ(error_message
,
531 "Non ASCII: This is not ASCII due to \\u00FF\\u00FE\\n in it.");
533 // Expect failure when not JSON or not a dictionary.
534 EXPECT_FALSE(ExtractKeyIdsFromKeyIdsInitData("This is invalid.", &key_ids
,
536 EXPECT_EQ(3u, key_ids
.size()); // |key_ids| should be unchanged.
537 EXPECT_EQ(error_message
, "Not valid JSON: This is invalid.");
538 EXPECT_FALSE(ExtractKeyIdsFromKeyIdsInitData("6", &key_ids
, &error_message
));
539 EXPECT_EQ(3u, key_ids
.size()); // |key_ids| should be unchanged.
540 EXPECT_EQ(error_message
, "Not valid JSON: 6");
541 EXPECT_FALSE(ExtractKeyIdsFromKeyIdsInitData(
542 "This is a very long string that is longer than 64 characters and is "
544 &key_ids
, &error_message
));
545 EXPECT_EQ(3u, key_ids
.size()); // |key_ids| should be unchanged.
546 EXPECT_EQ(error_message
,
547 "Not valid JSON: This is a very long string that is longer than 64 "
550 // Expect failure when "kids" not specified.
551 EXPECT_FALSE(ExtractKeyIdsFromKeyIdsInitData("{\"keys\":[\"AQI\"]}", &key_ids
,
553 EXPECT_EQ(3u, key_ids
.size()); // |key_ids| should be unchanged.
554 EXPECT_EQ(error_message
, "Missing 'kids' parameter or not a list");
556 // Expect failure when invalid key_ids specified.
557 EXPECT_FALSE(ExtractKeyIdsFromKeyIdsInitData("{\"kids\":[1]}", &key_ids
,
559 EXPECT_EQ(3u, key_ids
.size()); // |key_ids| should be unchanged.
560 EXPECT_EQ(error_message
, "'kids'[0] is not string.");
561 EXPECT_FALSE(ExtractKeyIdsFromKeyIdsInitData("{\"kids\": {\"id\":\"AQI\" }}",
562 &key_ids
, &error_message
));
563 EXPECT_EQ(3u, key_ids
.size()); // |key_ids| should be unchanged.
564 EXPECT_EQ(error_message
, "Missing 'kids' parameter or not a list");
566 // Expect failure when non-base64 key_ids specified.
567 EXPECT_FALSE(ExtractKeyIdsFromKeyIdsInitData("{\"kids\":[\"AQI+\"]}",
568 &key_ids
, &error_message
));
569 EXPECT_EQ(3u, key_ids
.size()); // |key_ids| should be unchanged.
570 EXPECT_EQ(error_message
,
571 "'kids'[0] is not valid base64url encoded. Value: AQI+");
572 EXPECT_FALSE(ExtractKeyIdsFromKeyIdsInitData("{\"kids\":[\"AQI\",\"AQI/\"]}",
573 &key_ids
, &error_message
));
574 EXPECT_EQ(3u, key_ids
.size()); // |key_ids| should be unchanged.
575 EXPECT_EQ(error_message
,
576 "'kids'[1] is not valid base64url encoded. Value: AQI/");
579 TEST_F(JSONWebKeyTest
, CreateInitData
) {
580 const uint8 data1
[] = { 0x01, 0x02 };
581 const uint8 data2
[] = { 0x01, 0x02, 0x03, 0x04 };
582 const uint8 data3
[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
583 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 };
586 std::string error_message
;
588 key_ids
.push_back(std::vector
<uint8
>(data1
, data1
+ arraysize(data1
)));
589 std::vector
<uint8
> init_data1
;
590 CreateKeyIdsInitData(key_ids
, &init_data1
);
591 std::string
result1(init_data1
.begin(), init_data1
.end());
592 EXPECT_EQ(result1
, "{\"kids\":[\"AQI\"]}");
594 key_ids
.push_back(std::vector
<uint8
>(data2
, data2
+ arraysize(data2
)));
595 std::vector
<uint8
> init_data2
;
596 CreateKeyIdsInitData(key_ids
, &init_data2
);
597 std::string
result2(init_data2
.begin(), init_data2
.end());
598 EXPECT_EQ(result2
, "{\"kids\":[\"AQI\",\"AQIDBA\"]}");
600 key_ids
.push_back(std::vector
<uint8
>(data3
, data3
+ arraysize(data3
)));
601 std::vector
<uint8
> init_data3
;
602 CreateKeyIdsInitData(key_ids
, &init_data3
);
603 std::string
result3(init_data3
.begin(), init_data3
.end());
605 "{\"kids\":[\"AQI\",\"AQIDBA\",\"AQIDBAUGBwgJCgsMDQ4PEA\"]}");