All instances of addresses as void* are changed to uintptr_t in
[chromium-blink-merge.git] / media / cdm / json_web_key_unittest.cc
blob90d19e30f20142298bb2a05851f7e9fc719c7f27
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"
11 namespace media {
13 class JSONWebKeyTest : public testing::Test {
14 public:
15 JSONWebKeyTest() {}
17 protected:
18 void ExtractJWKKeysAndExpect(const std::string& jwk,
19 bool expected_result,
20 size_t expected_number_of_keys) {
21 DCHECK(!jwk.empty());
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,
30 bool expected_result,
31 MediaKeys::SessionType expected_type) {
32 DCHECK(!jwk.empty());
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,
44 int key_id_length,
45 MediaKeys::SessionType session_type,
46 const std::string& expected_result) {
47 std::vector<uint8> result;
48 KeyIdList key_ids;
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,
56 bool expected_result,
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));
63 if (expected_result)
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);
75 KeyIdAndKeyPair MakeKeyIdAndKeyPair(const uint8* key,
76 int key_length,
77 const uint8* key_id,
78 int key_id_length) {
79 return std::make_pair(std::string(key_id, key_id + key_id_length),
80 std::string(key, key + key_length));
84 TEST_F(JSONWebKeyTest, GenerateJWKSet) {
85 const uint8 data1[] = { 0x01, 0x02 };
86 const uint8 data2[] = { 0x01, 0x02, 0x03, 0x04 };
87 const uint8 data3[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
88 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 };
90 EXPECT_EQ("{\"keys\":[{\"k\":\"AQI\",\"kid\":\"AQI\",\"kty\":\"oct\"}]}",
91 GenerateJWKSet(data1, arraysize(data1), data1, arraysize(data1)));
92 EXPECT_EQ(
93 "{\"keys\":[{\"k\":\"AQIDBA\",\"kid\":\"AQIDBA\",\"kty\":\"oct\"}]}",
94 GenerateJWKSet(data2, arraysize(data2), data2, arraysize(data2)));
95 EXPECT_EQ("{\"keys\":[{\"k\":\"AQI\",\"kid\":\"AQIDBA\",\"kty\":\"oct\"}]}",
96 GenerateJWKSet(data1, arraysize(data1), data2, arraysize(data2)));
97 EXPECT_EQ("{\"keys\":[{\"k\":\"AQIDBA\",\"kid\":\"AQI\",\"kty\":\"oct\"}]}",
98 GenerateJWKSet(data2, arraysize(data2), data1, arraysize(data1)));
99 EXPECT_EQ(
100 "{\"keys\":[{\"k\":\"AQIDBAUGBwgJCgsMDQ4PEA\",\"kid\":"
101 "\"AQIDBAUGBwgJCgsMDQ4PEA\",\"kty\":\"oct\"}]}",
102 GenerateJWKSet(data3, arraysize(data3), data3, arraysize(data3)));
104 KeyIdAndKeyPairs keys;
105 keys.push_back(
106 MakeKeyIdAndKeyPair(data1, arraysize(data1), data1, arraysize(data1)));
107 EXPECT_EQ(
108 "{\"keys\":[{\"k\":\"AQI\",\"kid\":\"AQI\",\"kty\":\"oct\"}],\"type\":"
109 "\"temporary\"}",
110 GenerateJWKSet(keys, MediaKeys::TEMPORARY_SESSION));
111 keys.push_back(
112 MakeKeyIdAndKeyPair(data2, arraysize(data2), data2, arraysize(data2)));
113 EXPECT_EQ(
114 "{\"keys\":[{\"k\":\"AQI\",\"kid\":\"AQI\",\"kty\":\"oct\"},{\"k\":"
115 "\"AQIDBA\",\"kid\":\"AQIDBA\",\"kty\":\"oct\"}],\"type\":\"persistent-"
116 "license\"}",
117 GenerateJWKSet(keys, MediaKeys::PERSISTENT_LICENSE_SESSION));
118 keys.push_back(
119 MakeKeyIdAndKeyPair(data3, arraysize(data3), data3, arraysize(data3)));
120 EXPECT_EQ(
121 "{\"keys\":[{\"k\":\"AQI\",\"kid\":\"AQI\",\"kty\":\"oct\"},{\"k\":"
122 "\"AQIDBA\",\"kid\":\"AQIDBA\",\"kty\":\"oct\"},{\"k\":"
123 "\"AQIDBAUGBwgJCgsMDQ4PEA\",\"kid\":\"AQIDBAUGBwgJCgsMDQ4PEA\",\"kty\":"
124 "\"oct\"}],\"type\":\"persistent-release-message\"}",
125 GenerateJWKSet(keys, MediaKeys::PERSISTENT_RELEASE_MESSAGE_SESSION));
128 TEST_F(JSONWebKeyTest, ExtractValidJWKKeys) {
129 // Try an empty 'keys' dictionary.
130 ExtractJWKKeysAndExpect("{ \"keys\": [] }", true, 0);
132 // Try a key list with one entry.
133 const std::string kJwksOneEntry =
135 " \"keys\": ["
136 " {"
137 " \"kty\": \"oct\","
138 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
139 " \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
140 " }"
141 " ]"
142 "}";
143 ExtractJWKKeysAndExpect(kJwksOneEntry, true, 1);
145 // Try a key list with multiple entries.
146 const std::string kJwksMultipleEntries =
148 " \"keys\": ["
149 " {"
150 " \"kty\": \"oct\","
151 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
152 " \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
153 " },"
154 " {"
155 " \"kty\": \"oct\","
156 " \"kid\": \"JCUmJygpKissLS4vMA\","
157 " \"k\":\"MTIzNDU2Nzg5Ojs8PT4_QA\""
158 " }"
159 " ]"
160 "}";
161 ExtractJWKKeysAndExpect(kJwksMultipleEntries, true, 2);
163 // Try a key with no spaces and some \n plus additional fields.
164 const std::string kJwksNoSpaces =
165 "\n\n{\"something\":1,\"keys\":[{\n\n\"kty\":\"oct\","
166 "\"kid\":\"AAECAwQFBgcICQoLDA0ODxAREhM\",\"k\":\"GawgguFyGrWKav7AX4VKUg"
167 "\",\"foo\":\"bar\"}]}\n\n";
168 ExtractJWKKeysAndExpect(kJwksNoSpaces, true, 1);
170 // Try a list with multiple keys with the same kid.
171 const std::string kJwksDuplicateKids =
173 " \"keys\": ["
174 " {"
175 " \"kty\": \"oct\","
176 " \"kid\": \"JCUmJygpKissLS4vMA\","
177 " \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
178 " },"
179 " {"
180 " \"kty\": \"oct\","
181 " \"kid\": \"JCUmJygpKissLS4vMA\","
182 " \"k\":\"MTIzNDU2Nzg5Ojs8PT4_QA\""
183 " }"
184 " ]"
185 "}";
186 ExtractJWKKeysAndExpect(kJwksDuplicateKids, true, 2);
189 TEST_F(JSONWebKeyTest, ExtractInvalidJWKKeys) {
190 // Try a simple JWK key (i.e. not in a set)
191 const std::string kJwkSimple =
193 " \"kty\": \"oct\","
194 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
195 " \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
196 "}";
197 ExtractJWKKeysAndExpect(kJwkSimple, false, 0);
199 // Try some non-ASCII characters.
200 ExtractJWKKeysAndExpect(
201 "This is not ASCII due to \xff\xfe\xfd in it.", false, 0);
203 // Try some non-ASCII characters in an otherwise valid JWK.
204 const std::string kJwksInvalidCharacters =
205 "\n\n{\"something\":1,\"keys\":[{\n\n\"kty\":\"oct\","
206 "\"kid\":\"AAECAwQFBgcICQoLDA0ODxAREhM\",\"k\":\"\xff\xfe\xfd"
207 "\",\"foo\":\"bar\"}]}\n\n";
208 ExtractJWKKeysAndExpect(kJwksInvalidCharacters, false, 0);
210 // Try a badly formatted key. Assume that the JSON parser is fully tested,
211 // so we won't try a lot of combinations. However, need a test to ensure
212 // that the code doesn't crash if invalid JSON received.
213 ExtractJWKKeysAndExpect("This is not a JSON key.", false, 0);
215 // Try passing some valid JSON that is not a dictionary at the top level.
216 ExtractJWKKeysAndExpect("40", false, 0);
218 // Try an empty dictionary.
219 ExtractJWKKeysAndExpect("{ }", false, 0);
221 // Try with 'keys' not a dictionary.
222 ExtractJWKKeysAndExpect("{ \"keys\":\"1\" }", false, 0);
224 // Try with 'keys' a list of integers.
225 ExtractJWKKeysAndExpect("{ \"keys\": [ 1, 2, 3 ] }", false, 0);
227 // Try padding(=) at end of 'k' base64 string.
228 const std::string kJwksWithPaddedKey =
230 " \"keys\": ["
231 " {"
232 " \"kty\": \"oct\","
233 " \"kid\": \"AAECAw\","
234 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw==\""
235 " }"
236 " ]"
237 "}";
238 ExtractJWKKeysAndExpect(kJwksWithPaddedKey, false, 0);
240 // Try padding(=) at end of 'kid' base64 string.
241 const std::string kJwksWithPaddedKeyId =
243 " \"keys\": ["
244 " {"
245 " \"kty\": \"oct\","
246 " \"kid\": \"AAECAw==\","
247 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
248 " }"
249 " ]"
250 "}";
251 ExtractJWKKeysAndExpect(kJwksWithPaddedKeyId, false, 0);
253 // Try a key with invalid base64 encoding.
254 const std::string kJwksWithInvalidBase64 =
256 " \"keys\": ["
257 " {"
258 " \"kty\": \"oct\","
259 " \"kid\": \"!@#$%^&*()\","
260 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
261 " }"
262 " ]"
263 "}";
264 ExtractJWKKeysAndExpect(kJwksWithInvalidBase64, false, 0);
266 // Empty key id.
267 const std::string kJwksWithEmptyKeyId =
269 " \"keys\": ["
270 " {"
271 " \"kty\": \"oct\","
272 " \"kid\": \"\","
273 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
274 " }"
275 " ]"
276 "}";
277 ExtractJWKKeysAndExpect(kJwksWithEmptyKeyId, false, 0);
280 TEST_F(JSONWebKeyTest, KeyType) {
281 // Valid key type.
282 const std::string kJwksWithValidKeyType =
284 " \"keys\": ["
285 " {"
286 " \"kty\": \"oct\","
287 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
288 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
289 " }"
290 " ]"
291 "}";
292 ExtractJWKKeysAndExpect(kJwksWithValidKeyType, true, 1);
294 // Empty key type.
295 const std::string kJwksWithEmptyKeyType =
297 " \"keys\": ["
298 " {"
299 " \"kty\": \"\","
300 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
301 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
302 " }"
303 " ]"
304 "}";
305 ExtractJWKKeysAndExpect(kJwksWithEmptyKeyType, false, 0);
307 // Key type is case sensitive.
308 const std::string kJwksWithUppercaseKeyType =
310 " \"keys\": ["
311 " {"
312 " \"kty\": \"OCT\","
313 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
314 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
315 " }"
316 " ]"
317 "}";
318 ExtractJWKKeysAndExpect(kJwksWithUppercaseKeyType, false, 0);
320 // Wrong key type.
321 const std::string kJwksWithWrongKeyType =
323 " \"keys\": ["
324 " {"
325 " \"kty\": \"RSA\","
326 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
327 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
328 " }"
329 " ]"
330 "}";
331 ExtractJWKKeysAndExpect(kJwksWithWrongKeyType, false, 0);
334 TEST_F(JSONWebKeyTest, Alg) {
335 // 'alg' is ignored, so verify that anything is allowed.
336 // Valid alg.
337 const std::string kJwksWithValidAlg =
339 " \"keys\": ["
340 " {"
341 " \"kty\": \"oct\","
342 " \"alg\": \"A128KW\","
343 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
344 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
345 " }"
346 " ]"
347 "}";
348 ExtractJWKKeysAndExpect(kJwksWithValidAlg, true, 1);
350 // Empty alg.
351 const std::string kJwksWithEmptyAlg =
353 " \"keys\": ["
354 " {"
355 " \"kty\": \"oct\","
356 " \"alg\": \"\","
357 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
358 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
359 " }"
360 " ]"
361 "}";
362 ExtractJWKKeysAndExpect(kJwksWithEmptyAlg, true, 1);
364 // Alg is case sensitive.
365 const std::string kJwksWithLowercaseAlg =
367 " \"keys\": ["
368 " {"
369 " \"kty\": \"oct\","
370 " \"alg\": \"a128kw\","
371 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
372 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
373 " }"
374 " ]"
375 "}";
376 ExtractJWKKeysAndExpect(kJwksWithLowercaseAlg, true, 1);
378 // Wrong alg.
379 const std::string kJwksWithWrongAlg =
381 " \"keys\": ["
382 " {"
383 " \"kty\": \"oct\","
384 " \"alg\": \"RS256\","
385 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
386 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
387 " }"
388 " ]"
389 "}";
390 ExtractJWKKeysAndExpect(kJwksWithWrongAlg, true, 1);
393 TEST_F(JSONWebKeyTest, SessionType) {
394 ExtractSessionTypeAndExpect(
395 "{\"keys\":[{\"k\":\"AQI\",\"kid\":\"AQI\",\"kty\":\"oct\"}]}", true,
396 MediaKeys::TEMPORARY_SESSION);
397 ExtractSessionTypeAndExpect(
398 "{\"keys\":[{\"k\":\"AQI\",\"kid\":\"AQI\",\"kty\":\"oct\"}],\"type\":"
399 "\"temporary\"}",
400 true, MediaKeys::TEMPORARY_SESSION);
401 ExtractSessionTypeAndExpect(
402 "{\"keys\":[{\"k\":\"AQI\",\"kid\":\"AQI\",\"kty\":\"oct\"}],\"type\":"
403 "\"persistent-license\"}",
404 true, MediaKeys::PERSISTENT_LICENSE_SESSION);
405 ExtractSessionTypeAndExpect(
406 "{\"keys\":[{\"k\":\"AQI\",\"kid\":\"AQI\",\"kty\":\"oct\"}],\"type\":"
407 "\"persistent-release-message\"}",
408 true, MediaKeys::PERSISTENT_RELEASE_MESSAGE_SESSION);
409 ExtractSessionTypeAndExpect(
410 "{\"keys\":[{\"k\":\"AQI\",\"kid\":\"AQI\",\"kty\":\"oct\"}],\"type\":"
411 "\"unknown\"}",
412 false, MediaKeys::TEMPORARY_SESSION);
413 ExtractSessionTypeAndExpect(
414 "{\"keys\":[{\"k\":\"AQI\",\"kid\":\"AQI\",\"kty\":\"oct\"}],\"type\":3}",
415 false, MediaKeys::TEMPORARY_SESSION);
418 TEST_F(JSONWebKeyTest, CreateLicense) {
419 const uint8 data1[] = { 0x01, 0x02 };
420 const uint8 data2[] = { 0x01, 0x02, 0x03, 0x04 };
421 const uint8 data3[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
422 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 };
424 CreateLicenseAndExpect(data1,
425 arraysize(data1),
426 MediaKeys::TEMPORARY_SESSION,
427 "{\"kids\":[\"AQI\"],\"type\":\"temporary\"}");
428 CreateLicenseAndExpect(
429 data1, arraysize(data1), MediaKeys::PERSISTENT_LICENSE_SESSION,
430 "{\"kids\":[\"AQI\"],\"type\":\"persistent-license\"}");
431 CreateLicenseAndExpect(
432 data1, arraysize(data1), MediaKeys::PERSISTENT_RELEASE_MESSAGE_SESSION,
433 "{\"kids\":[\"AQI\"],\"type\":\"persistent-release-message\"}");
434 CreateLicenseAndExpect(data2,
435 arraysize(data2),
436 MediaKeys::TEMPORARY_SESSION,
437 "{\"kids\":[\"AQIDBA\"],\"type\":\"temporary\"}");
438 CreateLicenseAndExpect(data3, arraysize(data3),
439 MediaKeys::PERSISTENT_LICENSE_SESSION,
440 "{\"kids\":[\"AQIDBAUGBwgJCgsMDQ4PEA\"],\"type\":"
441 "\"persistent-license\"}");
444 TEST_F(JSONWebKeyTest, ExtractLicense) {
445 const uint8 data1[] = { 0x01, 0x02 };
446 const uint8 data2[] = { 0x01, 0x02, 0x03, 0x04 };
447 const uint8 data3[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
448 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 };
450 ExtractKeyFromLicenseAndExpect(
451 "{\"kids\":[\"AQI\"],\"type\":\"temporary\"}",
452 true,
453 data1,
454 arraysize(data1));
455 ExtractKeyFromLicenseAndExpect(
456 "{\"kids\":[\"AQIDBA\"],\"type\":\"temporary\"}",
457 true,
458 data2,
459 arraysize(data2));
460 ExtractKeyFromLicenseAndExpect(
461 "{\"kids\":[\"AQIDBAUGBwgJCgsMDQ4PEA\"],\"type\":\"persistent\"}",
462 true,
463 data3,
464 arraysize(data3));
466 // Try some incorrect JSON.
467 ExtractKeyFromLicenseAndExpect("", false, NULL, 0);
468 ExtractKeyFromLicenseAndExpect("!@#$%^&*()", false, NULL, 0);
470 // Valid JSON, but not a dictionary.
471 ExtractKeyFromLicenseAndExpect("6", false, NULL, 0);
472 ExtractKeyFromLicenseAndExpect("[\"AQI\"]", false, NULL, 0);
474 // Dictionary, but missing expected tag.
475 ExtractKeyFromLicenseAndExpect("{\"kid\":[\"AQI\"]}", false, NULL, 0);
477 // Correct tag, but empty list.
478 ExtractKeyFromLicenseAndExpect("{\"kids\":[]}", false, NULL, 0);
480 // Correct tag, but list doesn't contain a string.
481 ExtractKeyFromLicenseAndExpect("{\"kids\":[[\"AQI\"]]}", false, NULL, 0);
483 // Correct tag, but invalid base64 encoding.
484 ExtractKeyFromLicenseAndExpect("{\"kids\":[\"!@#$%^&*()\"]}", false, NULL, 0);
487 TEST_F(JSONWebKeyTest, Base64UrlEncoding) {
488 const uint8 data1[] = { 0xfb, 0xfd, 0xfb, 0xfd, 0xfb, 0xfd, 0xfb };
490 // Verify that |data1| contains invalid base64url characters '+' and '/'
491 // and is padded with = when converted to base64.
492 std::string encoded_text;
493 base::Base64Encode(
494 std::string(reinterpret_cast<const char*>(&data1[0]), arraysize(data1)),
495 &encoded_text);
496 EXPECT_EQ(encoded_text, "+/37/fv9+w==");
497 EXPECT_NE(encoded_text.find('+'), std::string::npos);
498 EXPECT_NE(encoded_text.find('/'), std::string::npos);
499 EXPECT_NE(encoded_text.find('='), std::string::npos);
501 // base64url characters '-' and '_' not in base64 encoding.
502 EXPECT_EQ(encoded_text.find('-'), std::string::npos);
503 EXPECT_EQ(encoded_text.find('_'), std::string::npos);
505 CreateLicenseAndExpect(data1, arraysize(data1), MediaKeys::TEMPORARY_SESSION,
506 "{\"kids\":[\"-_37_fv9-w\"],\"type\":\"temporary\"}");
508 ExtractKeyFromLicenseAndExpect(
509 "{\"kids\":[\"-_37_fv9-w\"],\"type\":\"temporary\"}", true, data1,
510 arraysize(data1));
513 TEST_F(JSONWebKeyTest, MultipleKeys) {
514 const uint8 data1[] = { 0x01, 0x02 };
515 const uint8 data2[] = { 0x01, 0x02, 0x03, 0x04 };
516 const uint8 data3[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
517 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 };
519 std::vector<uint8> result;
520 KeyIdList key_ids;
521 key_ids.push_back(std::vector<uint8>(data1, data1 + arraysize(data1)));
522 key_ids.push_back(std::vector<uint8>(data2, data2 + arraysize(data2)));
523 key_ids.push_back(std::vector<uint8>(data3, data3 + arraysize(data3)));
524 CreateLicenseRequest(key_ids, MediaKeys::TEMPORARY_SESSION, &result);
525 std::string s(result.begin(), result.end());
526 EXPECT_EQ(
527 "{\"kids\":[\"AQI\",\"AQIDBA\",\"AQIDBAUGBwgJCgsMDQ4PEA\"],\"type\":"
528 "\"temporary\"}",
532 TEST_F(JSONWebKeyTest, ExtractKeyIds) {
533 const uint8 data1[] = { 0x01, 0x02 };
534 const uint8 data2[] = { 0x01, 0x02, 0x03, 0x04 };
535 const uint8 data3[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
536 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 };
538 KeyIdList key_ids;
539 std::string error_message;
541 EXPECT_TRUE(ExtractKeyIdsFromKeyIdsInitData("{\"kids\":[\"AQI\"]}", &key_ids,
542 &error_message));
543 EXPECT_EQ(1u, key_ids.size());
544 EXPECT_EQ(0u, error_message.length());
545 VerifyKeyId(key_ids[0], data1, arraysize(data1));
547 EXPECT_TRUE(ExtractKeyIdsFromKeyIdsInitData(
548 "{\"kids\":[\"AQI\",\"AQIDBA\",\"AQIDBAUGBwgJCgsMDQ4PEA\"]}", &key_ids,
549 &error_message));
550 EXPECT_EQ(3u, key_ids.size());
551 EXPECT_EQ(0u, error_message.length());
552 VerifyKeyId(key_ids[0], data1, arraysize(data1));
553 VerifyKeyId(key_ids[1], data2, arraysize(data2));
554 VerifyKeyId(key_ids[2], data3, arraysize(data3));
556 // Expect failure when non-ascii.
557 EXPECT_FALSE(ExtractKeyIdsFromKeyIdsInitData(
558 "This is not ASCII due to \xff\xfe\x0a in it.", &key_ids,
559 &error_message));
560 EXPECT_EQ(3u, key_ids.size()); // |key_ids| should be unchanged.
561 EXPECT_EQ(error_message,
562 "Non ASCII: This is not ASCII due to \\u00FF\\u00FE\\n in it.");
564 // Expect failure when not JSON or not a dictionary.
565 EXPECT_FALSE(ExtractKeyIdsFromKeyIdsInitData("This is invalid.", &key_ids,
566 &error_message));
567 EXPECT_EQ(3u, key_ids.size()); // |key_ids| should be unchanged.
568 EXPECT_EQ(error_message, "Not valid JSON: This is invalid.");
569 EXPECT_FALSE(ExtractKeyIdsFromKeyIdsInitData("6", &key_ids, &error_message));
570 EXPECT_EQ(3u, key_ids.size()); // |key_ids| should be unchanged.
571 EXPECT_EQ(error_message, "Not valid JSON: 6");
572 EXPECT_FALSE(ExtractKeyIdsFromKeyIdsInitData(
573 "This is a very long string that is longer than 64 characters and is "
574 "invalid.",
575 &key_ids, &error_message));
576 EXPECT_EQ(3u, key_ids.size()); // |key_ids| should be unchanged.
577 EXPECT_EQ(error_message,
578 "Not valid JSON: This is a very long string that is longer than 64 "
579 "characters ...");
581 // Expect failure when "kids" not specified.
582 EXPECT_FALSE(ExtractKeyIdsFromKeyIdsInitData("{\"keys\":[\"AQI\"]}", &key_ids,
583 &error_message));
584 EXPECT_EQ(3u, key_ids.size()); // |key_ids| should be unchanged.
585 EXPECT_EQ(error_message, "Missing 'kids' parameter or not a list");
587 // Expect failure when invalid key_ids specified.
588 EXPECT_FALSE(ExtractKeyIdsFromKeyIdsInitData("{\"kids\":[1]}", &key_ids,
589 &error_message));
590 EXPECT_EQ(3u, key_ids.size()); // |key_ids| should be unchanged.
591 EXPECT_EQ(error_message, "'kids'[0] is not string.");
592 EXPECT_FALSE(ExtractKeyIdsFromKeyIdsInitData("{\"kids\": {\"id\":\"AQI\" }}",
593 &key_ids, &error_message));
594 EXPECT_EQ(3u, key_ids.size()); // |key_ids| should be unchanged.
595 EXPECT_EQ(error_message, "Missing 'kids' parameter or not a list");
597 // Expect failure when non-base64 key_ids specified.
598 EXPECT_FALSE(ExtractKeyIdsFromKeyIdsInitData("{\"kids\":[\"AQI+\"]}",
599 &key_ids, &error_message));
600 EXPECT_EQ(3u, key_ids.size()); // |key_ids| should be unchanged.
601 EXPECT_EQ(error_message,
602 "'kids'[0] is not valid base64url encoded. Value: AQI+");
603 EXPECT_FALSE(ExtractKeyIdsFromKeyIdsInitData("{\"kids\":[\"AQI\",\"AQI/\"]}",
604 &key_ids, &error_message));
605 EXPECT_EQ(3u, key_ids.size()); // |key_ids| should be unchanged.
606 EXPECT_EQ(error_message,
607 "'kids'[1] is not valid base64url encoded. Value: AQI/");
610 TEST_F(JSONWebKeyTest, CreateInitData) {
611 const uint8 data1[] = { 0x01, 0x02 };
612 const uint8 data2[] = { 0x01, 0x02, 0x03, 0x04 };
613 const uint8 data3[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
614 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 };
616 KeyIdList key_ids;
617 std::string error_message;
619 key_ids.push_back(std::vector<uint8>(data1, data1 + arraysize(data1)));
620 std::vector<uint8> init_data1;
621 CreateKeyIdsInitData(key_ids, &init_data1);
622 std::string result1(init_data1.begin(), init_data1.end());
623 EXPECT_EQ(result1, "{\"kids\":[\"AQI\"]}");
625 key_ids.push_back(std::vector<uint8>(data2, data2 + arraysize(data2)));
626 std::vector<uint8> init_data2;
627 CreateKeyIdsInitData(key_ids, &init_data2);
628 std::string result2(init_data2.begin(), init_data2.end());
629 EXPECT_EQ(result2, "{\"kids\":[\"AQI\",\"AQIDBA\"]}");
631 key_ids.push_back(std::vector<uint8>(data3, data3 + arraysize(data3)));
632 std::vector<uint8> init_data3;
633 CreateKeyIdsInitData(key_ids, &init_data3);
634 std::string result3(init_data3.begin(), init_data3.end());
635 EXPECT_EQ(result3,
636 "{\"kids\":[\"AQI\",\"AQIDBA\",\"AQIDBAUGBwgJCgsMDQ4PEA\"]}");
639 } // namespace media