ExtensionInstallDialogView: fix scrolling behavior on Views (Win,Linux)
[chromium-blink-merge.git] / components / webcrypto / test / rsa_ssa_unittest.cc
blob3170a961f77e0903313a65ff447479c15b6a71b0
1 // Copyright 2014 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 "base/logging.h"
6 #include "base/stl_util.h"
7 #include "components/webcrypto/algorithm_dispatch.h"
8 #include "components/webcrypto/crypto_data.h"
9 #include "components/webcrypto/status.h"
10 #include "components/webcrypto/test/test_helpers.h"
11 #include "components/webcrypto/webcrypto_util.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
14 #include "third_party/WebKit/public/platform/WebCryptoKey.h"
15 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
17 namespace webcrypto {
19 namespace {
21 // Helper for ImportJwkRsaFailures. Restores the JWK JSON
22 // dictionary to a good state
23 void RestoreJwkRsaDictionary(base::DictionaryValue* dict) {
24 dict->Clear();
25 dict->SetString("kty", "RSA");
26 dict->SetString("alg", "RS256");
27 dict->SetString("use", "sig");
28 dict->SetBoolean("ext", false);
29 dict->SetString(
30 "n",
31 "qLOyhK-OtQs4cDSoYPFGxJGfMYdjzWxVmMiuSBGh4KvEx-CwgtaTpef87Wdc9GaFEncsDLxk"
32 "p0LGxjD1M8jMcvYq6DPEC_JYQumEu3i9v5fAEH1VvbZi9cTg-rmEXLUUjvc5LdOq_5OuHmtm"
33 "e7PUJHYW1PW6ENTP0ibeiNOfFvs");
34 dict->SetString("e", "AQAB");
37 TEST(WebCryptoRsaSsaTest, ImportExportSpki) {
38 // Passing case: Import a valid RSA key in SPKI format.
39 blink::WebCryptoKey key;
40 ASSERT_EQ(Status::Success(),
41 ImportKey(blink::WebCryptoKeyFormatSpki,
42 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
43 CreateRsaHashedImportAlgorithm(
44 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
45 blink::WebCryptoAlgorithmIdSha256),
46 true, blink::WebCryptoKeyUsageVerify, &key));
47 EXPECT_TRUE(key.handle());
48 EXPECT_EQ(blink::WebCryptoKeyTypePublic, key.type());
49 EXPECT_TRUE(key.extractable());
50 EXPECT_EQ(blink::WebCryptoKeyUsageVerify, key.usages());
51 EXPECT_EQ(kModulusLengthBits,
52 key.algorithm().rsaHashedParams()->modulusLengthBits());
53 EXPECT_BYTES_EQ_HEX(
54 "010001",
55 CryptoData(key.algorithm().rsaHashedParams()->publicExponent()));
57 // Failing case: Import RSA key but provide an inconsistent input algorithm.
58 EXPECT_EQ(Status::ErrorUnsupportedImportKeyFormat(),
59 ImportKey(blink::WebCryptoKeyFormatSpki,
60 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
61 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), true,
62 blink::WebCryptoKeyUsageEncrypt, &key));
64 // Passing case: Export a previously imported RSA public key in SPKI format
65 // and compare to original data.
66 std::vector<uint8_t> output;
67 ASSERT_EQ(Status::Success(),
68 ExportKey(blink::WebCryptoKeyFormatSpki, key, &output));
69 EXPECT_BYTES_EQ_HEX(kPublicKeySpkiDerHex, output);
71 // Failing case: Try to export a previously imported RSA public key in raw
72 // format (not allowed for a public key).
73 EXPECT_EQ(Status::ErrorUnsupportedExportKeyFormat(),
74 ExportKey(blink::WebCryptoKeyFormatRaw, key, &output));
76 // Failing case: Try to export a non-extractable key
77 ASSERT_EQ(Status::Success(),
78 ImportKey(blink::WebCryptoKeyFormatSpki,
79 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
80 CreateRsaHashedImportAlgorithm(
81 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
82 blink::WebCryptoAlgorithmIdSha256),
83 false, blink::WebCryptoKeyUsageVerify, &key));
84 EXPECT_TRUE(key.handle());
85 EXPECT_FALSE(key.extractable());
86 EXPECT_EQ(Status::ErrorKeyNotExtractable(),
87 ExportKey(blink::WebCryptoKeyFormatSpki, key, &output));
89 // TODO(eroman): Failing test: Import a SPKI with an unrecognized hash OID
90 // TODO(eroman): Failing test: Import a SPKI with invalid algorithm params
91 // TODO(eroman): Failing test: Import a SPKI with inconsistent parameters
92 // (e.g. SHA-1 in OID, SHA-256 in params)
93 // TODO(eroman): Failing test: Import a SPKI for RSA-SSA, but with params
94 // as OAEP/PSS
97 TEST(WebCryptoRsaSsaTest, ImportExportPkcs8) {
98 if (!SupportsRsaPrivateKeyImport())
99 return;
101 // Passing case: Import a valid RSA key in PKCS#8 format.
102 blink::WebCryptoKey key;
103 ASSERT_EQ(Status::Success(),
104 ImportKey(blink::WebCryptoKeyFormatPkcs8,
105 CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
106 CreateRsaHashedImportAlgorithm(
107 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
108 blink::WebCryptoAlgorithmIdSha1),
109 true, blink::WebCryptoKeyUsageSign, &key));
110 EXPECT_TRUE(key.handle());
111 EXPECT_EQ(blink::WebCryptoKeyTypePrivate, key.type());
112 EXPECT_TRUE(key.extractable());
113 EXPECT_EQ(blink::WebCryptoKeyUsageSign, key.usages());
114 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1,
115 key.algorithm().rsaHashedParams()->hash().id());
116 EXPECT_EQ(kModulusLengthBits,
117 key.algorithm().rsaHashedParams()->modulusLengthBits());
118 EXPECT_BYTES_EQ_HEX(
119 "010001",
120 CryptoData(key.algorithm().rsaHashedParams()->publicExponent()));
122 std::vector<uint8_t> exported_key;
123 ASSERT_EQ(Status::Success(),
124 ExportKey(blink::WebCryptoKeyFormatPkcs8, key, &exported_key));
125 EXPECT_BYTES_EQ_HEX(kPrivateKeyPkcs8DerHex, exported_key);
127 // Failing case: Import RSA key but provide an inconsistent input algorithm
128 // and usage. Several issues here:
129 // * AES-CBC doesn't support PKCS8 key format
130 // * AES-CBC doesn't support "sign" usage
131 EXPECT_EQ(Status::ErrorUnsupportedImportKeyFormat(),
132 ImportKey(blink::WebCryptoKeyFormatPkcs8,
133 CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
134 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), true,
135 blink::WebCryptoKeyUsageSign, &key));
138 // Tests JWK import and export by doing a roundtrip key conversion and ensuring
139 // it was lossless:
141 // PKCS8 --> JWK --> PKCS8
142 TEST(WebCryptoRsaSsaTest, ImportRsaPrivateKeyJwkToPkcs8RoundTrip) {
143 if (!SupportsRsaPrivateKeyImport())
144 return;
146 blink::WebCryptoKey key;
147 ASSERT_EQ(Status::Success(),
148 ImportKey(blink::WebCryptoKeyFormatPkcs8,
149 CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
150 CreateRsaHashedImportAlgorithm(
151 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
152 blink::WebCryptoAlgorithmIdSha1),
153 true, blink::WebCryptoKeyUsageSign, &key));
155 std::vector<uint8_t> exported_key_jwk;
156 ASSERT_EQ(Status::Success(),
157 ExportKey(blink::WebCryptoKeyFormatJwk, key, &exported_key_jwk));
159 // All of the optional parameters (p, q, dp, dq, qi) should be present in the
160 // output.
161 const char* expected_jwk =
162 "{\"alg\":\"RS1\",\"d\":\"M6UEKpCyfU9UUcqbu9C0R3GhAa-IQ0Cu-YhfKku-"
163 "kuiUpySsPFaMj5eFOtB8AmbIxqPKCSnx6PESMYhEKfxNmuVf7olqEM5wfD7X5zTkRyejlXRQ"
164 "GlMmgxCcKrrKuig8MbS9L1PD7jfjUs7jT55QO9gMBiKtecbc7og1R8ajsyU\",\"dp\":"
165 "\"KPoTk4ZVvh-"
166 "KFZy6ylpy6hkMMAieGc0nSlVvNsT24Z9VSzTAd3kEJ7vdjdPt4kSDKPOF2Bsw6OQ7L_-"
167 "gJ4YZeQ\",\"dq\":\"Gos485j6cSBJiY1_t57gp3ZoeRKZzfoJ78DlB6yyHtdDAe9b_Ui-"
168 "RV6utuFnglWCdYCo5OjhQVHRUQqCo_LnKQ\",\"e\":\"AQAB\",\"ext\":true,\"key_"
169 "ops\":[\"sign\"],\"kty\":\"RSA\",\"n\":"
170 "\"pW5KDnAQF1iaUYfcfqhB0Vby7A42rVKkTf6x5h962ZHYxRBW_-2xYrTA8oOhKoijlN_"
171 "1JqtykcuzB86r_OCx39XNlQgJbVsri2311nHvY3fAkhyyPCcKcOJZjm_4nRnxBazC0_"
172 "DLNfKSgOE4a29kxO8i4eHyDQzoz_siSb2aITc\",\"p\":\"5-"
173 "iUJyCod1Fyc6NWBT6iobwMlKpy1VxuhilrLfyWeUjApyy8zKfqyzVwbgmh31WhU1vZs8w0Fg"
174 "s7bc0-2o5kQw\",\"q\":\"tp3KHPfU1-yB51uQ_MqHSrzeEj_"
175 "ScAGAqpBHm25I3o1n7ST58Z2FuidYdPVCzSDccj5pYzZKH5QlRSsmmmeZ_Q\",\"qi\":"
176 "\"JxVqukEm0kqB86Uoy_sn9WiG-"
177 "ECp9uhuF6RLlP6TGVhLjiL93h5aLjvYqluo2FhBlOshkKz4MrhH8To9JKefTQ\"}";
179 ASSERT_EQ(CryptoData(std::string(expected_jwk)),
180 CryptoData(exported_key_jwk));
182 ASSERT_EQ(
183 Status::Success(),
184 ImportKey(blink::WebCryptoKeyFormatJwk, CryptoData(exported_key_jwk),
185 CreateRsaHashedImportAlgorithm(
186 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
187 blink::WebCryptoAlgorithmIdSha1),
188 true, blink::WebCryptoKeyUsageSign, &key));
190 std::vector<uint8_t> exported_key_pkcs8;
191 ASSERT_EQ(Status::Success(), ExportKey(blink::WebCryptoKeyFormatPkcs8, key,
192 &exported_key_pkcs8));
194 ASSERT_EQ(CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
195 CryptoData(exported_key_pkcs8));
198 // Tests importing multiple RSA private keys from JWK, and then exporting to
199 // PKCS8.
201 // This is a regression test for http://crbug.com/378315, for which importing
202 // a sequence of keys from JWK could yield the wrong key. The first key would
203 // be imported correctly, however every key after that would actually import
204 // the first key.
205 TEST(WebCryptoRsaSsaTest, ImportMultipleRSAPrivateKeysJwk) {
206 if (!SupportsRsaPrivateKeyImport())
207 return;
209 scoped_ptr<base::ListValue> key_list;
210 ASSERT_TRUE(ReadJsonTestFileToList("rsa_private_keys.json", &key_list));
212 // For this test to be meaningful the keys MUST be kept alive before importing
213 // new keys.
214 std::vector<blink::WebCryptoKey> live_keys;
216 for (size_t key_index = 0; key_index < key_list->GetSize(); ++key_index) {
217 SCOPED_TRACE(key_index);
219 base::DictionaryValue* key_values;
220 ASSERT_TRUE(key_list->GetDictionary(key_index, &key_values));
222 // Get the JWK representation of the key.
223 base::DictionaryValue* key_jwk;
224 ASSERT_TRUE(key_values->GetDictionary("jwk", &key_jwk));
226 // Get the PKCS8 representation of the key.
227 std::string pkcs8_hex_string;
228 ASSERT_TRUE(key_values->GetString("pkcs8", &pkcs8_hex_string));
229 std::vector<uint8_t> pkcs8_bytes = HexStringToBytes(pkcs8_hex_string);
231 // Get the modulus length for the key.
232 int modulus_length_bits = 0;
233 ASSERT_TRUE(key_values->GetInteger("modulusLength", &modulus_length_bits));
235 blink::WebCryptoKey private_key;
237 // Import the key from JWK.
238 ASSERT_EQ(Status::Success(),
239 ImportKeyJwkFromDict(
240 *key_jwk, CreateRsaHashedImportAlgorithm(
241 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
242 blink::WebCryptoAlgorithmIdSha256),
243 true, blink::WebCryptoKeyUsageSign, &private_key));
245 live_keys.push_back(private_key);
247 EXPECT_EQ(
248 modulus_length_bits,
249 static_cast<int>(
250 private_key.algorithm().rsaHashedParams()->modulusLengthBits()));
252 // Export to PKCS8 and verify that it matches expectation.
253 std::vector<uint8_t> exported_key_pkcs8;
254 ASSERT_EQ(Status::Success(), ExportKey(blink::WebCryptoKeyFormatPkcs8,
255 private_key, &exported_key_pkcs8));
257 EXPECT_BYTES_EQ(pkcs8_bytes, exported_key_pkcs8);
261 // Import an RSA private key using JWK. Next import a JWK containing the same
262 // modulus, but mismatched parameters for the rest. It should NOT be possible
263 // that the second import retrieves the first key. See http://crbug.com/378315
264 // for how that could happen.
265 TEST(WebCryptoRsaSsaTest, ImportJwkExistingModulusAndInvalid) {
266 if (!SupportsRsaPrivateKeyImport())
267 return;
269 scoped_ptr<base::ListValue> key_list;
270 ASSERT_TRUE(ReadJsonTestFileToList("rsa_private_keys.json", &key_list));
272 // Import a 1024-bit private key.
273 base::DictionaryValue* key1_props;
274 ASSERT_TRUE(key_list->GetDictionary(1, &key1_props));
275 base::DictionaryValue* key1_jwk;
276 ASSERT_TRUE(key1_props->GetDictionary("jwk", &key1_jwk));
278 blink::WebCryptoKey key1;
279 ASSERT_EQ(Status::Success(),
280 ImportKeyJwkFromDict(*key1_jwk,
281 CreateRsaHashedImportAlgorithm(
282 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
283 blink::WebCryptoAlgorithmIdSha256),
284 true, blink::WebCryptoKeyUsageSign, &key1));
286 ASSERT_EQ(1024u, key1.algorithm().rsaHashedParams()->modulusLengthBits());
288 // Construct a JWK using the modulus of key1, but all the other fields from
289 // another key (also a 1024-bit private key).
290 base::DictionaryValue* key2_props;
291 ASSERT_TRUE(key_list->GetDictionary(5, &key2_props));
292 base::DictionaryValue* key2_jwk;
293 ASSERT_TRUE(key2_props->GetDictionary("jwk", &key2_jwk));
294 std::string modulus;
295 key1_jwk->GetString("n", &modulus);
296 key2_jwk->SetString("n", modulus);
298 // This should fail, as the n,e,d parameters are not consistent. It MUST NOT
299 // somehow return the key created earlier.
300 blink::WebCryptoKey key2;
301 ASSERT_EQ(Status::OperationError(),
302 ImportKeyJwkFromDict(*key2_jwk,
303 CreateRsaHashedImportAlgorithm(
304 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
305 blink::WebCryptoAlgorithmIdSha256),
306 true, blink::WebCryptoKeyUsageSign, &key2));
309 TEST(WebCryptoRsaSsaTest, GenerateKeyPairRsa) {
310 // Note: using unrealistic short key lengths here to avoid bogging down tests.
312 // Successful WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 key generation (sha256)
313 const unsigned int modulus_length = 256;
314 const std::vector<uint8_t> public_exponent = HexStringToBytes("010001");
315 blink::WebCryptoAlgorithm algorithm = CreateRsaHashedKeyGenAlgorithm(
316 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
317 blink::WebCryptoAlgorithmIdSha256, modulus_length, public_exponent);
318 bool extractable = true;
319 const blink::WebCryptoKeyUsageMask public_usages =
320 blink::WebCryptoKeyUsageVerify;
321 const blink::WebCryptoKeyUsageMask private_usages =
322 blink::WebCryptoKeyUsageSign;
323 const blink::WebCryptoKeyUsageMask usages = public_usages | private_usages;
324 blink::WebCryptoKey public_key;
325 blink::WebCryptoKey private_key;
327 EXPECT_EQ(Status::Success(), GenerateKeyPair(algorithm, extractable, usages,
328 &public_key, &private_key));
329 ASSERT_FALSE(public_key.isNull());
330 ASSERT_FALSE(private_key.isNull());
331 EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type());
332 EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type());
333 EXPECT_EQ(modulus_length,
334 public_key.algorithm().rsaHashedParams()->modulusLengthBits());
335 EXPECT_EQ(modulus_length,
336 private_key.algorithm().rsaHashedParams()->modulusLengthBits());
337 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256,
338 public_key.algorithm().rsaHashedParams()->hash().id());
339 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256,
340 private_key.algorithm().rsaHashedParams()->hash().id());
341 EXPECT_TRUE(public_key.extractable());
342 EXPECT_EQ(extractable, private_key.extractable());
343 EXPECT_EQ(public_usages, public_key.usages());
344 EXPECT_EQ(private_usages, private_key.usages());
346 // Try exporting the generated key pair, and then re-importing to verify that
347 // the exported data was valid.
348 std::vector<uint8_t> public_key_spki;
349 EXPECT_EQ(Status::Success(), ExportKey(blink::WebCryptoKeyFormatSpki,
350 public_key, &public_key_spki));
352 if (SupportsRsaPrivateKeyImport()) {
353 public_key = blink::WebCryptoKey::createNull();
354 ASSERT_EQ(
355 Status::Success(),
356 ImportKey(blink::WebCryptoKeyFormatSpki, CryptoData(public_key_spki),
357 CreateRsaHashedImportAlgorithm(
358 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
359 blink::WebCryptoAlgorithmIdSha256),
360 true, public_usages, &public_key));
361 EXPECT_EQ(modulus_length,
362 public_key.algorithm().rsaHashedParams()->modulusLengthBits());
364 std::vector<uint8_t> private_key_pkcs8;
365 EXPECT_EQ(Status::Success(), ExportKey(blink::WebCryptoKeyFormatPkcs8,
366 private_key, &private_key_pkcs8));
367 private_key = blink::WebCryptoKey::createNull();
368 ASSERT_EQ(
369 Status::Success(),
370 ImportKey(blink::WebCryptoKeyFormatPkcs8, CryptoData(private_key_pkcs8),
371 CreateRsaHashedImportAlgorithm(
372 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
373 blink::WebCryptoAlgorithmIdSha256),
374 true, private_usages, &private_key));
375 EXPECT_EQ(modulus_length,
376 private_key.algorithm().rsaHashedParams()->modulusLengthBits());
379 // Fail with bad modulus.
380 algorithm = CreateRsaHashedKeyGenAlgorithm(
381 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
382 blink::WebCryptoAlgorithmIdSha256, 0, public_exponent);
383 EXPECT_EQ(Status::ErrorGenerateRsaUnsupportedModulus(),
384 GenerateKeyPair(algorithm, extractable, usages, &public_key,
385 &private_key));
387 // Fail with bad exponent: larger than unsigned long.
388 unsigned int exponent_length = sizeof(unsigned long) + 1; // NOLINT
389 const std::vector<uint8_t> long_exponent(exponent_length, 0x01);
390 algorithm = CreateRsaHashedKeyGenAlgorithm(
391 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
392 blink::WebCryptoAlgorithmIdSha256, modulus_length, long_exponent);
393 EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
394 GenerateKeyPair(algorithm, extractable, usages, &public_key,
395 &private_key));
397 // Fail with bad exponent: empty.
398 const std::vector<uint8_t> empty_exponent;
399 algorithm = CreateRsaHashedKeyGenAlgorithm(
400 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
401 blink::WebCryptoAlgorithmIdSha256, modulus_length, empty_exponent);
402 EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
403 GenerateKeyPair(algorithm, extractable, usages, &public_key,
404 &private_key));
406 // Fail with bad exponent: all zeros.
407 std::vector<uint8_t> exponent_with_leading_zeros(15, 0x00);
408 algorithm = CreateRsaHashedKeyGenAlgorithm(
409 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
410 blink::WebCryptoAlgorithmIdSha256, modulus_length,
411 exponent_with_leading_zeros);
412 EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
413 GenerateKeyPair(algorithm, extractable, usages, &public_key,
414 &private_key));
416 // Key generation success using exponent with leading zeros.
417 exponent_with_leading_zeros.insert(exponent_with_leading_zeros.end(),
418 public_exponent.begin(),
419 public_exponent.end());
420 algorithm = CreateRsaHashedKeyGenAlgorithm(
421 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
422 blink::WebCryptoAlgorithmIdSha256, modulus_length,
423 exponent_with_leading_zeros);
424 EXPECT_EQ(Status::Success(), GenerateKeyPair(algorithm, extractable, usages,
425 &public_key, &private_key));
426 EXPECT_FALSE(public_key.isNull());
427 EXPECT_FALSE(private_key.isNull());
428 EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type());
429 EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type());
430 EXPECT_TRUE(public_key.extractable());
431 EXPECT_EQ(extractable, private_key.extractable());
432 EXPECT_EQ(public_usages, public_key.usages());
433 EXPECT_EQ(private_usages, private_key.usages());
435 // Successful WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 key generation (sha1)
436 algorithm = CreateRsaHashedKeyGenAlgorithm(
437 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
438 blink::WebCryptoAlgorithmIdSha1, modulus_length, public_exponent);
439 EXPECT_EQ(Status::Success(), GenerateKeyPair(algorithm, false, usages,
440 &public_key, &private_key));
441 EXPECT_FALSE(public_key.isNull());
442 EXPECT_FALSE(private_key.isNull());
443 EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type());
444 EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type());
445 EXPECT_EQ(modulus_length,
446 public_key.algorithm().rsaHashedParams()->modulusLengthBits());
447 EXPECT_EQ(modulus_length,
448 private_key.algorithm().rsaHashedParams()->modulusLengthBits());
449 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1,
450 public_key.algorithm().rsaHashedParams()->hash().id());
451 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1,
452 private_key.algorithm().rsaHashedParams()->hash().id());
453 // Even though "extractable" was set to false, the public key remains
454 // extractable.
455 EXPECT_TRUE(public_key.extractable());
456 EXPECT_FALSE(private_key.extractable());
457 EXPECT_EQ(public_usages, public_key.usages());
458 EXPECT_EQ(private_usages, private_key.usages());
460 // Exporting a private key as SPKI format doesn't make sense. However this
461 // will first fail because the key is not extractable.
462 std::vector<uint8_t> output;
463 EXPECT_EQ(Status::ErrorKeyNotExtractable(),
464 ExportKey(blink::WebCryptoKeyFormatSpki, private_key, &output));
466 // Re-generate an extractable private_key and try to export it as SPKI format.
467 // This should fail since spki is for public keys.
468 EXPECT_EQ(Status::Success(), GenerateKeyPair(algorithm, true, usages,
469 &public_key, &private_key));
470 EXPECT_EQ(Status::ErrorUnexpectedKeyType(),
471 ExportKey(blink::WebCryptoKeyFormatSpki, private_key, &output));
474 TEST(WebCryptoRsaSsaTest, GenerateKeyPairRsaBadModulusLength) {
475 const unsigned int kBadModulusBits[] = {
477 248, // Too small.
478 257, // Not a multiple of 8.
479 1023, // Not a multiple of 8.
480 0xFFFFFFFF, // Too big.
481 16384 + 8, // 16384 is the maxmimum length that NSS succeeds for.
484 const std::vector<uint8_t> public_exponent = HexStringToBytes("010001");
486 for (size_t i = 0; i < arraysize(kBadModulusBits); ++i) {
487 const unsigned int modulus_length_bits = kBadModulusBits[i];
488 blink::WebCryptoAlgorithm algorithm = CreateRsaHashedKeyGenAlgorithm(
489 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
490 blink::WebCryptoAlgorithmIdSha256, modulus_length_bits,
491 public_exponent);
492 bool extractable = true;
493 const blink::WebCryptoKeyUsageMask usages = blink::WebCryptoKeyUsageSign;
494 blink::WebCryptoKey public_key;
495 blink::WebCryptoKey private_key;
497 EXPECT_EQ(Status::ErrorGenerateRsaUnsupportedModulus(),
498 GenerateKeyPair(algorithm, extractable, usages, &public_key,
499 &private_key));
503 // Try generating RSA key pairs using unsupported public exponents. Only
504 // exponents of 3 and 65537 are supported. While both OpenSSL and NSS can
505 // support other values, OpenSSL hangs when given invalid exponents, so use a
506 // whitelist to validate the parameters.
507 TEST(WebCryptoRsaSsaTest, GenerateKeyPairRsaBadExponent) {
508 const unsigned int modulus_length = 1024;
510 const char* const kPublicExponents[] = {
511 "11", // 17 - This is a valid public exponent, but currently disallowed.
512 "00",
513 "01",
514 "02",
515 "010000", // 65536
518 for (size_t i = 0; i < arraysize(kPublicExponents); ++i) {
519 SCOPED_TRACE(i);
520 blink::WebCryptoAlgorithm algorithm = CreateRsaHashedKeyGenAlgorithm(
521 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
522 blink::WebCryptoAlgorithmIdSha256, modulus_length,
523 HexStringToBytes(kPublicExponents[i]));
525 blink::WebCryptoKey public_key;
526 blink::WebCryptoKey private_key;
528 EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
529 GenerateKeyPair(algorithm, true, blink::WebCryptoKeyUsageSign,
530 &public_key, &private_key));
534 TEST(WebCryptoRsaSsaTest, SignVerifyFailures) {
535 if (!SupportsRsaPrivateKeyImport())
536 return;
538 // Import a key pair.
539 blink::WebCryptoAlgorithm import_algorithm =
540 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
541 blink::WebCryptoAlgorithmIdSha1);
542 blink::WebCryptoKey public_key;
543 blink::WebCryptoKey private_key;
544 ASSERT_NO_FATAL_FAILURE(ImportRsaKeyPair(
545 HexStringToBytes(kPublicKeySpkiDerHex),
546 HexStringToBytes(kPrivateKeyPkcs8DerHex), import_algorithm, false,
547 blink::WebCryptoKeyUsageVerify, blink::WebCryptoKeyUsageSign, &public_key,
548 &private_key));
550 blink::WebCryptoAlgorithm algorithm =
551 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5);
553 std::vector<uint8_t> signature;
554 bool signature_match;
556 // Compute a signature.
557 const std::vector<uint8_t> data = HexStringToBytes("010203040506070809");
558 ASSERT_EQ(Status::Success(),
559 Sign(algorithm, private_key, CryptoData(data), &signature));
561 // Ensure truncated signature does not verify by passing one less byte.
562 EXPECT_EQ(Status::Success(),
563 Verify(algorithm, public_key,
564 CryptoData(vector_as_array(&signature),
565 static_cast<unsigned int>(signature.size()) - 1),
566 CryptoData(data), &signature_match));
567 EXPECT_FALSE(signature_match);
569 // Ensure truncated signature does not verify by passing no bytes.
570 EXPECT_EQ(Status::Success(), Verify(algorithm, public_key, CryptoData(),
571 CryptoData(data), &signature_match));
572 EXPECT_FALSE(signature_match);
574 // Ensure corrupted signature does not verify.
575 std::vector<uint8_t> corrupt_sig = signature;
576 corrupt_sig[corrupt_sig.size() / 2] ^= 0x1;
577 EXPECT_EQ(Status::Success(),
578 Verify(algorithm, public_key, CryptoData(corrupt_sig),
579 CryptoData(data), &signature_match));
580 EXPECT_FALSE(signature_match);
582 // Ensure signatures that are greater than the modulus size fail.
583 const unsigned int long_message_size_bytes = 1024;
584 DCHECK_GT(long_message_size_bytes, kModulusLengthBits / 8);
585 const unsigned char kLongSignature[long_message_size_bytes] = {0};
586 EXPECT_EQ(Status::Success(),
587 Verify(algorithm, public_key,
588 CryptoData(kLongSignature, sizeof(kLongSignature)),
589 CryptoData(data), &signature_match));
590 EXPECT_FALSE(signature_match);
592 // Ensure that signing and verifying with an incompatible algorithm fails.
593 algorithm = CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaOaep);
595 EXPECT_EQ(Status::ErrorUnexpected(),
596 Sign(algorithm, private_key, CryptoData(data), &signature));
597 EXPECT_EQ(Status::ErrorUnexpected(),
598 Verify(algorithm, public_key, CryptoData(signature),
599 CryptoData(data), &signature_match));
601 // Some crypto libraries (NSS) can automatically select the RSA SSA inner hash
602 // based solely on the contents of the input signature data. In the Web Crypto
603 // implementation, the inner hash should be specified uniquely by the key
604 // algorithm parameter. To validate this behavior, call Verify with a computed
605 // signature that used one hash type (SHA-1), but pass in a key with a
606 // different inner hash type (SHA-256). If the hash type is determined by the
607 // signature itself (undesired), the verify will pass, while if the hash type
608 // is specified by the key algorithm (desired), the verify will fail.
610 // Compute a signature using SHA-1 as the inner hash.
611 EXPECT_EQ(Status::Success(),
612 Sign(CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5),
613 private_key, CryptoData(data), &signature));
615 blink::WebCryptoKey public_key_256;
616 EXPECT_EQ(Status::Success(),
617 ImportKey(blink::WebCryptoKeyFormatSpki,
618 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
619 CreateRsaHashedImportAlgorithm(
620 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
621 blink::WebCryptoAlgorithmIdSha256),
622 true, blink::WebCryptoKeyUsageVerify, &public_key_256));
624 // Now verify using an algorithm whose inner hash is SHA-256, not SHA-1. The
625 // signature should not verify.
626 // NOTE: public_key was produced by generateKey, and so its associated
627 // algorithm has WebCryptoRsaKeyGenParams and not WebCryptoRsaSsaParams. Thus
628 // it has no inner hash to conflict with the input algorithm.
629 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1,
630 private_key.algorithm().rsaHashedParams()->hash().id());
631 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256,
632 public_key_256.algorithm().rsaHashedParams()->hash().id());
634 bool is_match;
635 EXPECT_EQ(Status::Success(),
636 Verify(CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5),
637 public_key_256, CryptoData(signature), CryptoData(data),
638 &is_match));
639 EXPECT_FALSE(is_match);
642 TEST(WebCryptoRsaSsaTest, SignVerifyKnownAnswer) {
643 if (!SupportsRsaPrivateKeyImport())
644 return;
646 scoped_ptr<base::ListValue> tests;
647 ASSERT_TRUE(ReadJsonTestFileToList("pkcs1v15_sign.json", &tests));
649 // Import the key pair.
650 blink::WebCryptoAlgorithm import_algorithm =
651 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
652 blink::WebCryptoAlgorithmIdSha1);
653 blink::WebCryptoKey public_key;
654 blink::WebCryptoKey private_key;
655 ASSERT_NO_FATAL_FAILURE(ImportRsaKeyPair(
656 HexStringToBytes(kPublicKeySpkiDerHex),
657 HexStringToBytes(kPrivateKeyPkcs8DerHex), import_algorithm, false,
658 blink::WebCryptoKeyUsageVerify, blink::WebCryptoKeyUsageSign, &public_key,
659 &private_key));
661 blink::WebCryptoAlgorithm algorithm =
662 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5);
664 // Validate the signatures are computed and verified as expected.
665 std::vector<uint8_t> signature;
666 for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
667 SCOPED_TRACE(test_index);
669 base::DictionaryValue* test;
670 ASSERT_TRUE(tests->GetDictionary(test_index, &test));
672 std::vector<uint8_t> test_message =
673 GetBytesFromHexString(test, "message_hex");
674 std::vector<uint8_t> test_signature =
675 GetBytesFromHexString(test, "signature_hex");
677 signature.clear();
678 ASSERT_EQ(Status::Success(), Sign(algorithm, private_key,
679 CryptoData(test_message), &signature));
680 EXPECT_BYTES_EQ(test_signature, signature);
682 bool is_match = false;
683 ASSERT_EQ(Status::Success(),
684 Verify(algorithm, public_key, CryptoData(test_signature),
685 CryptoData(test_message), &is_match));
686 EXPECT_TRUE(is_match);
690 // Try importing an RSA-SSA public key with unsupported key usages using SPKI
691 // format. RSA-SSA public keys only support the 'verify' usage.
692 TEST(WebCryptoRsaSsaTest, ImportRsaSsaPublicKeyBadUsage_SPKI) {
693 const blink::WebCryptoAlgorithm algorithm =
694 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
695 blink::WebCryptoAlgorithmIdSha256);
697 blink::WebCryptoKeyUsageMask bad_usages[] = {
698 blink::WebCryptoKeyUsageSign,
699 blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify,
700 blink::WebCryptoKeyUsageEncrypt,
701 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt,
704 for (size_t i = 0; i < arraysize(bad_usages); ++i) {
705 SCOPED_TRACE(i);
707 blink::WebCryptoKey public_key;
708 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
709 ImportKey(blink::WebCryptoKeyFormatSpki,
710 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
711 algorithm, false, bad_usages[i], &public_key));
715 // Try importing an RSA-SSA public key with unsupported key usages using JWK
716 // format. RSA-SSA public keys only support the 'verify' usage.
717 TEST(WebCryptoRsaSsaTest, ImportRsaSsaPublicKeyBadUsage_JWK) {
718 const blink::WebCryptoAlgorithm algorithm =
719 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
720 blink::WebCryptoAlgorithmIdSha256);
722 blink::WebCryptoKeyUsageMask bad_usages[] = {
723 blink::WebCryptoKeyUsageSign,
724 blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify,
725 blink::WebCryptoKeyUsageEncrypt,
726 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt,
729 base::DictionaryValue dict;
730 RestoreJwkRsaDictionary(&dict);
731 dict.Remove("use", NULL);
732 dict.SetString("alg", "RS256");
734 for (size_t i = 0; i < arraysize(bad_usages); ++i) {
735 SCOPED_TRACE(i);
737 blink::WebCryptoKey public_key;
738 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
739 ImportKeyJwkFromDict(dict, algorithm, false, bad_usages[i],
740 &public_key));
744 // Generate an RSA-SSA key pair with invalid usages. RSA-SSA supports:
745 // 'sign', 'verify'
746 TEST(WebCryptoRsaSsaTest, GenerateKeyBadUsages) {
747 blink::WebCryptoKeyUsageMask bad_usages[] = {
748 blink::WebCryptoKeyUsageDecrypt,
749 blink::WebCryptoKeyUsageVerify | blink::WebCryptoKeyUsageDecrypt,
750 blink::WebCryptoKeyUsageWrapKey,
753 const unsigned int modulus_length = 256;
754 const std::vector<uint8_t> public_exponent = HexStringToBytes("010001");
756 for (size_t i = 0; i < arraysize(bad_usages); ++i) {
757 SCOPED_TRACE(i);
759 blink::WebCryptoKey public_key;
760 blink::WebCryptoKey private_key;
762 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
763 GenerateKeyPair(CreateRsaHashedKeyGenAlgorithm(
764 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
765 blink::WebCryptoAlgorithmIdSha256,
766 modulus_length, public_exponent),
767 true, bad_usages[i], &public_key, &private_key));
771 // Generate an RSA-SSA key pair. The public and private keys should select the
772 // key usages which are applicable, and not have the exact same usages as was
773 // specified to GenerateKey
774 TEST(WebCryptoRsaSsaTest, GenerateKeyPairIntersectUsages) {
775 const unsigned int modulus_length = 256;
776 const std::vector<uint8_t> public_exponent = HexStringToBytes("010001");
778 blink::WebCryptoKey public_key;
779 blink::WebCryptoKey private_key;
781 ASSERT_EQ(Status::Success(),
782 GenerateKeyPair(CreateRsaHashedKeyGenAlgorithm(
783 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
784 blink::WebCryptoAlgorithmIdSha256,
785 modulus_length, public_exponent),
786 true, blink::WebCryptoKeyUsageSign |
787 blink::WebCryptoKeyUsageVerify,
788 &public_key, &private_key));
790 EXPECT_EQ(blink::WebCryptoKeyUsageVerify, public_key.usages());
791 EXPECT_EQ(blink::WebCryptoKeyUsageSign, private_key.usages());
793 // Try again but this time without the Verify usages.
794 ASSERT_EQ(Status::Success(),
795 GenerateKeyPair(CreateRsaHashedKeyGenAlgorithm(
796 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
797 blink::WebCryptoAlgorithmIdSha256,
798 modulus_length, public_exponent),
799 true, blink::WebCryptoKeyUsageSign, &public_key,
800 &private_key));
802 EXPECT_EQ(0, public_key.usages());
803 EXPECT_EQ(blink::WebCryptoKeyUsageSign, private_key.usages());
806 TEST(WebCryptoRsaSsaTest, GenerateKeyPairEmptyUsages) {
807 const unsigned int modulus_length = 256;
808 const std::vector<uint8_t> public_exponent = HexStringToBytes("010001");
810 blink::WebCryptoKey public_key;
811 blink::WebCryptoKey private_key;
813 ASSERT_EQ(Status::ErrorCreateKeyEmptyUsages(),
814 GenerateKeyPair(CreateRsaHashedKeyGenAlgorithm(
815 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
816 blink::WebCryptoAlgorithmIdSha256,
817 modulus_length, public_exponent),
818 true, 0, &public_key, &private_key));
821 TEST(WebCryptoRsaSsaTest, ImportKeyEmptyUsages) {
822 if (!SupportsRsaPrivateKeyImport())
823 return;
825 blink::WebCryptoKey public_key;
826 blink::WebCryptoKey private_key;
828 // Public without usage does not throw an error.
829 ASSERT_EQ(Status::Success(),
830 ImportKey(blink::WebCryptoKeyFormatSpki,
831 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
832 CreateRsaHashedImportAlgorithm(
833 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
834 blink::WebCryptoAlgorithmIdSha256),
835 true, 0, &public_key));
836 EXPECT_EQ(0, public_key.usages());
838 // Private empty usage will throw an error.
839 ASSERT_EQ(Status::ErrorCreateKeyEmptyUsages(),
840 ImportKey(blink::WebCryptoKeyFormatPkcs8,
841 CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
842 CreateRsaHashedImportAlgorithm(
843 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
844 blink::WebCryptoAlgorithmIdSha1),
845 true, 0, &private_key));
847 std::vector<uint8_t> public_jwk;
848 ASSERT_EQ(Status::Success(),
849 ExportKey(blink::WebCryptoKeyFormatJwk, public_key, &public_jwk));
851 ASSERT_EQ(Status::Success(),
852 ImportKey(blink::WebCryptoKeyFormatJwk, CryptoData(public_jwk),
853 CreateRsaHashedImportAlgorithm(
854 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
855 blink::WebCryptoAlgorithmIdSha256),
856 true, 0, &public_key));
857 EXPECT_EQ(0, public_key.usages());
859 // With correct usage to get correct imported private_key
860 std::vector<uint8_t> private_jwk;
861 ImportKey(
862 blink::WebCryptoKeyFormatPkcs8,
863 CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
864 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
865 blink::WebCryptoAlgorithmIdSha1),
866 true, blink::WebCryptoKeyUsageSign, &private_key);
868 ASSERT_EQ(Status::Success(),
869 ExportKey(blink::WebCryptoKeyFormatJwk, private_key, &private_jwk));
871 ASSERT_EQ(Status::ErrorCreateKeyEmptyUsages(),
872 ImportKey(blink::WebCryptoKeyFormatJwk, CryptoData(private_jwk),
873 CreateRsaHashedImportAlgorithm(
874 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
875 blink::WebCryptoAlgorithmIdSha1),
876 true, 0, &private_key));
879 TEST(WebCryptoRsaSsaTest, ImportExportJwkRsaPublicKey) {
880 struct TestCase {
881 const blink::WebCryptoAlgorithmId hash;
882 const blink::WebCryptoKeyUsageMask usage;
883 const char* const jwk_alg;
885 const TestCase kTests[] = {
886 {blink::WebCryptoAlgorithmIdSha1, blink::WebCryptoKeyUsageVerify, "RS1"},
887 {blink::WebCryptoAlgorithmIdSha256,
888 blink::WebCryptoKeyUsageVerify,
889 "RS256"},
890 {blink::WebCryptoAlgorithmIdSha384,
891 blink::WebCryptoKeyUsageVerify,
892 "RS384"},
893 {blink::WebCryptoAlgorithmIdSha512,
894 blink::WebCryptoKeyUsageVerify,
895 "RS512"}};
897 for (size_t test_index = 0; test_index < arraysize(kTests); ++test_index) {
898 SCOPED_TRACE(test_index);
899 const TestCase& test = kTests[test_index];
901 const blink::WebCryptoAlgorithm import_algorithm =
902 CreateRsaHashedImportAlgorithm(
903 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, test.hash);
905 // Import the spki to create a public key
906 blink::WebCryptoKey public_key;
907 ASSERT_EQ(Status::Success(),
908 ImportKey(blink::WebCryptoKeyFormatSpki,
909 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
910 import_algorithm, true, test.usage, &public_key));
912 // Export the public key as JWK and verify its contents
913 std::vector<uint8_t> jwk;
914 ASSERT_EQ(Status::Success(),
915 ExportKey(blink::WebCryptoKeyFormatJwk, public_key, &jwk));
916 EXPECT_TRUE(VerifyPublicJwk(jwk, test.jwk_alg, kPublicKeyModulusHex,
917 kPublicKeyExponentHex, test.usage));
919 // Import the JWK back in to create a new key
920 blink::WebCryptoKey public_key2;
921 ASSERT_EQ(Status::Success(),
922 ImportKey(blink::WebCryptoKeyFormatJwk, CryptoData(jwk),
923 import_algorithm, true, test.usage, &public_key2));
924 ASSERT_TRUE(public_key2.handle());
925 EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key2.type());
926 EXPECT_TRUE(public_key2.extractable());
927 EXPECT_EQ(import_algorithm.id(), public_key2.algorithm().id());
929 // Export the new key as spki and compare to the original.
930 std::vector<uint8_t> spki;
931 ASSERT_EQ(Status::Success(),
932 ExportKey(blink::WebCryptoKeyFormatSpki, public_key2, &spki));
933 EXPECT_BYTES_EQ_HEX(kPublicKeySpkiDerHex, CryptoData(spki));
937 TEST(WebCryptoRsaSsaTest, ImportJwkRsaFailures) {
938 base::DictionaryValue dict;
939 RestoreJwkRsaDictionary(&dict);
940 blink::WebCryptoAlgorithm algorithm =
941 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
942 blink::WebCryptoAlgorithmIdSha256);
943 blink::WebCryptoKeyUsageMask usages = blink::WebCryptoKeyUsageVerify;
944 blink::WebCryptoKey key;
946 // An RSA public key JWK _must_ have an "n" (modulus) and an "e" (exponent)
947 // entry, while an RSA private key must have those plus at least a "d"
948 // (private exponent) entry.
949 // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18,
950 // section 6.3.
952 // Baseline pass.
953 EXPECT_EQ(Status::Success(),
954 ImportKeyJwkFromDict(dict, algorithm, false, usages, &key));
955 EXPECT_EQ(algorithm.id(), key.algorithm().id());
956 EXPECT_FALSE(key.extractable());
957 EXPECT_EQ(blink::WebCryptoKeyUsageVerify, key.usages());
958 EXPECT_EQ(blink::WebCryptoKeyTypePublic, key.type());
960 // The following are specific failure cases for when kty = "RSA".
962 // Fail if either "n" or "e" is not present or malformed.
963 const std::string kKtyParmName[] = {"n", "e"};
964 for (size_t idx = 0; idx < arraysize(kKtyParmName); ++idx) {
965 // Fail on missing parameter.
966 dict.Remove(kKtyParmName[idx], NULL);
967 EXPECT_NE(Status::Success(),
968 ImportKeyJwkFromDict(dict, algorithm, false, usages, &key));
969 RestoreJwkRsaDictionary(&dict);
971 // Fail on bad b64 parameter encoding.
972 dict.SetString(kKtyParmName[idx], "Qk3f0DsytU8lfza2au #$% Htaw2xpop9yTuH0");
973 EXPECT_NE(Status::Success(),
974 ImportKeyJwkFromDict(dict, algorithm, false, usages, &key));
975 RestoreJwkRsaDictionary(&dict);
977 // Fail on empty parameter.
978 dict.SetString(kKtyParmName[idx], "");
979 EXPECT_EQ(Status::ErrorJwkEmptyBigInteger(kKtyParmName[idx]),
980 ImportKeyJwkFromDict(dict, algorithm, false, usages, &key));
981 RestoreJwkRsaDictionary(&dict);
985 // Try importing an RSA-SSA key from JWK format, having specified both Sign and
986 // Verify usage, and an invalid JWK.
988 // The test must fail with a usage error BEFORE attempting to read the JWK data.
989 // Although both Sign and Verify are valid usages for RSA-SSA keys, it is
990 // invalid to have them both at the same time for one key (since Sign applies to
991 // private keys, whereas Verify applies to public keys).
993 // If the implementation does not fail fast, this test will crash dereferencing
994 // invalid memory.
995 TEST(WebCryptoRsaSsaTest, ImportRsaSsaJwkBadUsageFailFast) {
996 CryptoData bad_data(NULL, 128); // Invalid buffer of length 128.
998 blink::WebCryptoKey key;
999 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
1000 ImportKey(blink::WebCryptoKeyFormatJwk, bad_data,
1001 CreateRsaHashedImportAlgorithm(
1002 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
1003 blink::WebCryptoAlgorithmIdSha256),
1004 true, blink::WebCryptoKeyUsageVerify |
1005 blink::WebCryptoKeyUsageSign,
1006 &key));
1009 // Imports invalid JWK/SPKI/PKCS8 data and verifies that it fails as expected.
1010 TEST(WebCryptoRsaSsaTest, ImportInvalidKeyData) {
1011 if (!SupportsRsaPrivateKeyImport())
1012 return;
1014 scoped_ptr<base::ListValue> tests;
1015 ASSERT_TRUE(ReadJsonTestFileToList("bad_rsa_keys.json", &tests));
1017 for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
1018 SCOPED_TRACE(test_index);
1020 const base::DictionaryValue* test;
1021 ASSERT_TRUE(tests->GetDictionary(test_index, &test));
1023 blink::WebCryptoKeyFormat key_format = GetKeyFormatFromJsonTestCase(test);
1024 std::vector<uint8_t> key_data =
1025 GetKeyDataFromJsonTestCase(test, key_format);
1026 std::string test_error;
1027 ASSERT_TRUE(test->GetString("error", &test_error));
1029 blink::WebCryptoKeyUsageMask usages = blink::WebCryptoKeyUsageSign;
1030 if (key_format == blink::WebCryptoKeyFormatSpki)
1031 usages = blink::WebCryptoKeyUsageVerify;
1032 blink::WebCryptoKey key;
1033 Status status = ImportKey(key_format, CryptoData(key_data),
1034 CreateRsaHashedImportAlgorithm(
1035 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
1036 blink::WebCryptoAlgorithmIdSha256),
1037 true, usages, &key);
1038 EXPECT_EQ(test_error, StatusToString(status));
1042 } // namespace
1044 } // namespace webcrypto