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. 4 5 #include "media/cdm/json_web_key.h" 6 7 #include "base/logging.h" 8 #include "testing/gtest/include/gtest/gtest.h" 9 10 namespace media { 11 12 class JSONWebKeyTest : public testing::Test { 13 public: 14 JSONWebKeyTest() {} 15 16 protected: 17 void ExtractJWKKeysAndExpect(const std::string& jwk, 18 bool expected_result, 19 size_t expected_number_of_keys) { 20 DCHECK(!jwk.empty()); 21 KeyIdAndKeyPairs keys; 22 EXPECT_EQ(expected_result, ExtractKeysFromJWKSet(jwk, &keys)); 23 EXPECT_EQ(expected_number_of_keys, keys.size()); 24 } 25 }; 26 27 TEST_F(JSONWebKeyTest, GenerateJWKSet) { 28 const uint8 data1[] = { 0x01, 0x02 }; 29 const uint8 data2[] = { 0x01, 0x02, 0x03, 0x04 }; 30 const uint8 data3[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 31 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 }; 32 33 EXPECT_EQ("{\"keys\":[{\"k\":\"AQI\",\"kid\":\"AQI\",\"kty\":\"oct\"}]}", 34 GenerateJWKSet(data1, arraysize(data1), data1, arraysize(data1))); 35 EXPECT_EQ( 36 "{\"keys\":[{\"k\":\"AQIDBA\",\"kid\":\"AQIDBA\",\"kty\":\"oct\"}]}", 37 GenerateJWKSet(data2, arraysize(data2), data2, arraysize(data2))); 38 EXPECT_EQ("{\"keys\":[{\"k\":\"AQI\",\"kid\":\"AQIDBA\",\"kty\":\"oct\"}]}", 39 GenerateJWKSet(data1, arraysize(data1), data2, arraysize(data2))); 40 EXPECT_EQ("{\"keys\":[{\"k\":\"AQIDBA\",\"kid\":\"AQI\",\"kty\":\"oct\"}]}", 41 GenerateJWKSet(data2, arraysize(data2), data1, arraysize(data1))); 42 EXPECT_EQ( 43 "{\"keys\":[{\"k\":\"AQIDBAUGBwgJCgsMDQ4PEA\",\"kid\":" 44 "\"AQIDBAUGBwgJCgsMDQ4PEA\",\"kty\":\"oct\"}]}", 45 GenerateJWKSet(data3, arraysize(data3), data3, arraysize(data3))); 46 } 47 48 TEST_F(JSONWebKeyTest, ExtractJWKKeys) { 49 // Try a simple JWK key (i.e. not in a set) 50 const std::string kJwkSimple = 51 "{" 52 " \"kty\": \"oct\"," 53 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\"," 54 " \"k\": \"FBUWFxgZGhscHR4fICEiIw\"" 55 "}"; 56 ExtractJWKKeysAndExpect(kJwkSimple, false, 0); 57 58 // Try a key list with multiple entries. 59 const std::string kJwksMultipleEntries = 60 "{" 61 " \"keys\": [" 62 " {" 63 " \"kty\": \"oct\"," 64 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\"," 65 " \"k\": \"FBUWFxgZGhscHR4fICEiIw\"" 66 " }," 67 " {" 68 " \"kty\": \"oct\"," 69 " \"kid\": \"JCUmJygpKissLS4vMA\"," 70 " \"k\":\"MTIzNDU2Nzg5Ojs8PT4/QA\"" 71 " }" 72 " ]" 73 "}"; 74 ExtractJWKKeysAndExpect(kJwksMultipleEntries, true, 2); 75 76 // Try a key with no spaces and some \n plus additional fields. 77 const std::string kJwksNoSpaces = 78 "\n\n{\"something\":1,\"keys\":[{\n\n\"kty\":\"oct\",\"alg\":\"A128KW\"," 79 "\"kid\":\"AAECAwQFBgcICQoLDA0ODxAREhM\",\"k\":\"GawgguFyGrWKav7AX4VKUg" 80 "\",\"foo\":\"bar\"}]}\n\n"; 81 ExtractJWKKeysAndExpect(kJwksNoSpaces, true, 1); 82 83 // Try some non-ASCII characters. 84 ExtractJWKKeysAndExpect( 85 "This is not ASCII due to \xff\xfe\xfd in it.", false, 0); 86 87 // Try some non-ASCII characters in an otherwise valid JWK. 88 const std::string kJwksInvalidCharacters = 89 "\n\n{\"something\":1,\"keys\":[{\n\n\"kty\":\"oct\",\"alg\":\"A128KW\"," 90 "\"kid\":\"AAECAwQFBgcICQoLDA0ODxAREhM\",\"k\":\"\xff\xfe\xfd" 91 "\",\"foo\":\"bar\"}]}\n\n"; 92 ExtractJWKKeysAndExpect(kJwksInvalidCharacters, false, 0); 93 94 // Try a badly formatted key. Assume that the JSON parser is fully tested, 95 // so we won't try a lot of combinations. However, need a test to ensure 96 // that the code doesn't crash if invalid JSON received. 97 ExtractJWKKeysAndExpect("This is not a JSON key.", false, 0); 98 99 // Try passing some valid JSON that is not a dictionary at the top level. 100 ExtractJWKKeysAndExpect("40", false, 0); 101 102 // Try an empty dictionary. 103 ExtractJWKKeysAndExpect("{ }", false, 0); 104 105 // Try an empty 'keys' dictionary. 106 ExtractJWKKeysAndExpect("{ \"keys\": [] }", true, 0); 107 108 // Try with 'keys' not a dictionary. 109 ExtractJWKKeysAndExpect("{ \"keys\":\"1\" }", false, 0); 110 111 // Try with 'keys' a list of integers. 112 ExtractJWKKeysAndExpect("{ \"keys\": [ 1, 2, 3 ] }", false, 0); 113 114 // Try padding(=) at end of 'k' base64 string. 115 const std::string kJwksWithPaddedKey = 116 "{" 117 " \"keys\": [" 118 " {" 119 " \"kty\": \"oct\"," 120 " \"kid\": \"AAECAw\"," 121 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw==\"" 122 " }" 123 " ]" 124 "}"; 125 ExtractJWKKeysAndExpect(kJwksWithPaddedKey, false, 0); 126 127 // Try padding(=) at end of 'kid' base64 string. 128 const std::string kJwksWithPaddedKeyId = 129 "{" 130 " \"keys\": [" 131 " {" 132 " \"kty\": \"oct\"," 133 " \"kid\": \"AAECAw==\"," 134 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\"" 135 " }" 136 " ]" 137 "}"; 138 ExtractJWKKeysAndExpect(kJwksWithPaddedKeyId, false, 0); 139 140 // Try a key with invalid base64 encoding. 141 const std::string kJwksWithInvalidBase64 = 142 "{" 143 " \"keys\": [" 144 " {" 145 " \"kty\": \"oct\"," 146 " \"kid\": \"!@#$%^&*()\"," 147 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\"" 148 " }" 149 " ]" 150 "}"; 151 ExtractJWKKeysAndExpect(kJwksWithInvalidBase64, false, 0); 152 153 // Empty key id. 154 const std::string kJwksWithEmptyKeyId = 155 "{" 156 " \"keys\": [" 157 " {" 158 " \"kty\": \"oct\"," 159 " \"kid\": \"\"," 160 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\"" 161 " }" 162 " ]" 163 "}"; 164 ExtractJWKKeysAndExpect(kJwksWithEmptyKeyId, false, 0); 165 166 // Try a list with multiple keys with the same kid. 167 const std::string kJwksDuplicateKids = 168 "{" 169 " \"keys\": [" 170 " {" 171 " \"kty\": \"oct\"," 172 " \"kid\": \"JCUmJygpKissLS4vMA\"," 173 " \"k\": \"FBUWFxgZGhscHR4fICEiIw\"" 174 " }," 175 " {" 176 " \"kty\": \"oct\"," 177 " \"kid\": \"JCUmJygpKissLS4vMA\"," 178 " \"k\":\"MTIzNDU2Nzg5Ojs8PT4/QA\"" 179 " }" 180 " ]" 181 "}"; 182 ExtractJWKKeysAndExpect(kJwksDuplicateKids, true, 2); 183 } 184 185 } // namespace media 186 187