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 "content/child/webcrypto/algorithm_dispatch.h"
8 #include "content/child/webcrypto/crypto_data.h"
9 #include "content/child/webcrypto/status.h"
10 #include "content/child/webcrypto/test/test_helpers.h"
11 #include "content/child/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"
23 // Helper for ImportJwkRsaFailures. Restores the JWK JSON
24 // dictionary to a good state
25 void RestoreJwkRsaDictionary(base::DictionaryValue
* dict
) {
27 dict
->SetString("kty", "RSA");
28 dict
->SetString("alg", "RS256");
29 dict
->SetString("use", "sig");
30 dict
->SetBoolean("ext", false);
33 "qLOyhK-OtQs4cDSoYPFGxJGfMYdjzWxVmMiuSBGh4KvEx-CwgtaTpef87Wdc9GaFEncsDLxk"
34 "p0LGxjD1M8jMcvYq6DPEC_JYQumEu3i9v5fAEH1VvbZi9cTg-rmEXLUUjvc5LdOq_5OuHmtm"
35 "e7PUJHYW1PW6ENTP0ibeiNOfFvs");
36 dict
->SetString("e", "AQAB");
39 TEST(WebCryptoRsaSsaTest
, ImportExportSpki
) {
40 // Passing case: Import a valid RSA key in SPKI format.
41 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
42 ASSERT_EQ(Status::Success(),
43 ImportKey(blink::WebCryptoKeyFormatSpki
,
44 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex
)),
45 CreateRsaHashedImportAlgorithm(
46 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
47 blink::WebCryptoAlgorithmIdSha256
),
49 blink::WebCryptoKeyUsageVerify
,
51 EXPECT_TRUE(key
.handle());
52 EXPECT_EQ(blink::WebCryptoKeyTypePublic
, key
.type());
53 EXPECT_TRUE(key
.extractable());
54 EXPECT_EQ(blink::WebCryptoKeyUsageVerify
, key
.usages());
55 EXPECT_EQ(kModulusLengthBits
,
56 key
.algorithm().rsaHashedParams()->modulusLengthBits());
59 CryptoData(key
.algorithm().rsaHashedParams()->publicExponent()));
61 // Failing case: Empty SPKI data
63 Status::ErrorImportEmptyKeyData(),
64 ImportKey(blink::WebCryptoKeyFormatSpki
,
65 CryptoData(std::vector
<uint8_t>()),
66 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
),
68 blink::WebCryptoKeyUsageVerify
,
71 // Failing case: Bad DER encoding.
74 ImportKey(blink::WebCryptoKeyFormatSpki
,
75 CryptoData(HexStringToBytes("618333c4cb")),
76 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
),
78 blink::WebCryptoKeyUsageVerify
,
81 // Failing case: Import RSA key but provide an inconsistent input algorithm.
82 EXPECT_EQ(Status::ErrorUnsupportedImportKeyFormat(),
83 ImportKey(blink::WebCryptoKeyFormatSpki
,
84 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex
)),
85 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
87 blink::WebCryptoKeyUsageEncrypt
,
90 // Passing case: Export a previously imported RSA public key in SPKI format
91 // and compare to original data.
92 std::vector
<uint8_t> output
;
93 ASSERT_EQ(Status::Success(),
94 ExportKey(blink::WebCryptoKeyFormatSpki
, key
, &output
));
95 EXPECT_BYTES_EQ_HEX(kPublicKeySpkiDerHex
, output
);
97 // Failing case: Try to export a previously imported RSA public key in raw
98 // format (not allowed for a public key).
99 EXPECT_EQ(Status::ErrorUnsupportedExportKeyFormat(),
100 ExportKey(blink::WebCryptoKeyFormatRaw
, key
, &output
));
102 // Failing case: Try to export a non-extractable key
103 ASSERT_EQ(Status::Success(),
104 ImportKey(blink::WebCryptoKeyFormatSpki
,
105 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex
)),
106 CreateRsaHashedImportAlgorithm(
107 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
108 blink::WebCryptoAlgorithmIdSha256
),
110 blink::WebCryptoKeyUsageVerify
,
112 EXPECT_TRUE(key
.handle());
113 EXPECT_FALSE(key
.extractable());
114 EXPECT_EQ(Status::ErrorKeyNotExtractable(),
115 ExportKey(blink::WebCryptoKeyFormatSpki
, key
, &output
));
117 // TODO(eroman): Failing test: Import a SPKI with an unrecognized hash OID
118 // TODO(eroman): Failing test: Import a SPKI with invalid algorithm params
119 // TODO(eroman): Failing test: Import a SPKI with inconsistent parameters
120 // (e.g. SHA-1 in OID, SHA-256 in params)
121 // TODO(eroman): Failing test: Import a SPKI for RSA-SSA, but with params
125 TEST(WebCryptoRsaSsaTest
, ImportExportPkcs8
) {
126 if (!SupportsRsaPrivateKeyImport())
129 // Passing case: Import a valid RSA key in PKCS#8 format.
130 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
131 ASSERT_EQ(Status::Success(),
132 ImportKey(blink::WebCryptoKeyFormatPkcs8
,
133 CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex
)),
134 CreateRsaHashedImportAlgorithm(
135 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
136 blink::WebCryptoAlgorithmIdSha1
),
138 blink::WebCryptoKeyUsageSign
,
140 EXPECT_TRUE(key
.handle());
141 EXPECT_EQ(blink::WebCryptoKeyTypePrivate
, key
.type());
142 EXPECT_TRUE(key
.extractable());
143 EXPECT_EQ(blink::WebCryptoKeyUsageSign
, key
.usages());
144 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1
,
145 key
.algorithm().rsaHashedParams()->hash().id());
146 EXPECT_EQ(kModulusLengthBits
,
147 key
.algorithm().rsaHashedParams()->modulusLengthBits());
150 CryptoData(key
.algorithm().rsaHashedParams()->publicExponent()));
152 std::vector
<uint8_t> exported_key
;
153 ASSERT_EQ(Status::Success(),
154 ExportKey(blink::WebCryptoKeyFormatPkcs8
, key
, &exported_key
));
155 EXPECT_BYTES_EQ_HEX(kPrivateKeyPkcs8DerHex
, exported_key
);
157 // Failing case: Empty PKCS#8 data
158 EXPECT_EQ(Status::ErrorImportEmptyKeyData(),
159 ImportKey(blink::WebCryptoKeyFormatPkcs8
,
160 CryptoData(std::vector
<uint8_t>()),
161 CreateRsaHashedImportAlgorithm(
162 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
163 blink::WebCryptoAlgorithmIdSha1
),
165 blink::WebCryptoKeyUsageSign
,
168 // Failing case: Bad DER encoding.
171 ImportKey(blink::WebCryptoKeyFormatPkcs8
,
172 CryptoData(HexStringToBytes("618333c4cb")),
173 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
),
175 blink::WebCryptoKeyUsageSign
,
178 // Failing case: Import RSA key but provide an inconsistent input algorithm
179 // and usage. Several issues here:
180 // * AES-CBC doesn't support PKCS8 key format
181 // * AES-CBC doesn't support "sign" usage
182 EXPECT_EQ(Status::ErrorUnsupportedImportKeyFormat(),
183 ImportKey(blink::WebCryptoKeyFormatPkcs8
,
184 CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex
)),
185 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
187 blink::WebCryptoKeyUsageSign
,
191 // Tests importing of PKCS8 data that does not define a valid RSA key.
192 TEST(WebCryptoRsaSsaTest
, ImportInvalidPkcs8
) {
193 if (!SupportsRsaPrivateKeyImport())
196 // kPrivateKeyPkcs8DerHex defines an RSA private key in PKCS8 format, whose
197 // parameters appear at the following offsets:
199 // n: (offset=36, len=129)
200 // e: (offset=167, len=3)
201 // d: (offset=173, len=128)
202 // p: (offset=303, len=65)
203 // q: (offset=370, len=65)
204 // dp: (offset=437, len=64)
205 // dq; (offset=503, len=64)
206 // qi: (offset=569, len=64)
208 // Do several tests, each of which invert a single byte within the input.
209 const unsigned int kOffsetsToCorrupt
[] = {
220 for (size_t test_index
= 0; test_index
< arraysize(kOffsetsToCorrupt
);
222 SCOPED_TRACE(test_index
);
224 unsigned int i
= kOffsetsToCorrupt
[test_index
];
225 std::vector
<uint8_t> corrupted_data
=
226 HexStringToBytes(kPrivateKeyPkcs8DerHex
);
227 corrupted_data
[i
] = ~corrupted_data
[i
];
229 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
230 EXPECT_EQ(Status::DataError(),
231 ImportKey(blink::WebCryptoKeyFormatPkcs8
,
232 CryptoData(corrupted_data
),
233 CreateRsaHashedImportAlgorithm(
234 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
235 blink::WebCryptoAlgorithmIdSha1
),
237 blink::WebCryptoKeyUsageSign
,
242 // Tests JWK import and export by doing a roundtrip key conversion and ensuring
245 // PKCS8 --> JWK --> PKCS8
246 TEST(WebCryptoRsaSsaTest
, ImportRsaPrivateKeyJwkToPkcs8RoundTrip
) {
247 if (!SupportsRsaPrivateKeyImport())
250 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
251 ASSERT_EQ(Status::Success(),
252 ImportKey(blink::WebCryptoKeyFormatPkcs8
,
253 CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex
)),
254 CreateRsaHashedImportAlgorithm(
255 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
256 blink::WebCryptoAlgorithmIdSha1
),
258 blink::WebCryptoKeyUsageSign
,
261 std::vector
<uint8_t> exported_key_jwk
;
262 ASSERT_EQ(Status::Success(),
263 ExportKey(blink::WebCryptoKeyFormatJwk
, key
, &exported_key_jwk
));
265 // All of the optional parameters (p, q, dp, dq, qi) should be present in the
267 const char* expected_jwk
=
268 "{\"alg\":\"RS1\",\"d\":\"M6UEKpCyfU9UUcqbu9C0R3GhAa-IQ0Cu-YhfKku-"
269 "kuiUpySsPFaMj5eFOtB8AmbIxqPKCSnx6PESMYhEKfxNmuVf7olqEM5wfD7X5zTkRyejlXRQ"
270 "GlMmgxCcKrrKuig8MbS9L1PD7jfjUs7jT55QO9gMBiKtecbc7og1R8ajsyU\",\"dp\":"
272 "KFZy6ylpy6hkMMAieGc0nSlVvNsT24Z9VSzTAd3kEJ7vdjdPt4kSDKPOF2Bsw6OQ7L_-"
273 "gJ4YZeQ\",\"dq\":\"Gos485j6cSBJiY1_t57gp3ZoeRKZzfoJ78DlB6yyHtdDAe9b_Ui-"
274 "RV6utuFnglWCdYCo5OjhQVHRUQqCo_LnKQ\",\"e\":\"AQAB\",\"ext\":true,\"key_"
275 "ops\":[\"sign\"],\"kty\":\"RSA\",\"n\":"
276 "\"pW5KDnAQF1iaUYfcfqhB0Vby7A42rVKkTf6x5h962ZHYxRBW_-2xYrTA8oOhKoijlN_"
277 "1JqtykcuzB86r_OCx39XNlQgJbVsri2311nHvY3fAkhyyPCcKcOJZjm_4nRnxBazC0_"
278 "DLNfKSgOE4a29kxO8i4eHyDQzoz_siSb2aITc\",\"p\":\"5-"
279 "iUJyCod1Fyc6NWBT6iobwMlKpy1VxuhilrLfyWeUjApyy8zKfqyzVwbgmh31WhU1vZs8w0Fg"
280 "s7bc0-2o5kQw\",\"q\":\"tp3KHPfU1-yB51uQ_MqHSrzeEj_"
281 "ScAGAqpBHm25I3o1n7ST58Z2FuidYdPVCzSDccj5pYzZKH5QlRSsmmmeZ_Q\",\"qi\":"
282 "\"JxVqukEm0kqB86Uoy_sn9WiG-"
283 "ECp9uhuF6RLlP6TGVhLjiL93h5aLjvYqluo2FhBlOshkKz4MrhH8To9JKefTQ\"}";
285 ASSERT_EQ(CryptoData(std::string(expected_jwk
)),
286 CryptoData(exported_key_jwk
));
288 ASSERT_EQ(Status::Success(),
289 ImportKey(blink::WebCryptoKeyFormatJwk
,
290 CryptoData(exported_key_jwk
),
291 CreateRsaHashedImportAlgorithm(
292 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
293 blink::WebCryptoAlgorithmIdSha1
),
295 blink::WebCryptoKeyUsageSign
,
298 std::vector
<uint8_t> exported_key_pkcs8
;
301 ExportKey(blink::WebCryptoKeyFormatPkcs8
, key
, &exported_key_pkcs8
));
303 ASSERT_EQ(CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex
)),
304 CryptoData(exported_key_pkcs8
));
307 // Tests importing multiple RSA private keys from JWK, and then exporting to
310 // This is a regression test for http://crbug.com/378315, for which importing
311 // a sequence of keys from JWK could yield the wrong key. The first key would
312 // be imported correctly, however every key after that would actually import
314 TEST(WebCryptoRsaSsaTest
, ImportMultipleRSAPrivateKeysJwk
) {
315 if (!SupportsRsaPrivateKeyImport())
318 scoped_ptr
<base::ListValue
> key_list
;
319 ASSERT_TRUE(ReadJsonTestFileToList("rsa_private_keys.json", &key_list
));
321 // For this test to be meaningful the keys MUST be kept alive before importing
323 std::vector
<blink::WebCryptoKey
> live_keys
;
325 for (size_t key_index
= 0; key_index
< key_list
->GetSize(); ++key_index
) {
326 SCOPED_TRACE(key_index
);
328 base::DictionaryValue
* key_values
;
329 ASSERT_TRUE(key_list
->GetDictionary(key_index
, &key_values
));
331 // Get the JWK representation of the key.
332 base::DictionaryValue
* key_jwk
;
333 ASSERT_TRUE(key_values
->GetDictionary("jwk", &key_jwk
));
335 // Get the PKCS8 representation of the key.
336 std::string pkcs8_hex_string
;
337 ASSERT_TRUE(key_values
->GetString("pkcs8", &pkcs8_hex_string
));
338 std::vector
<uint8_t> pkcs8_bytes
= HexStringToBytes(pkcs8_hex_string
);
340 // Get the modulus length for the key.
341 int modulus_length_bits
= 0;
342 ASSERT_TRUE(key_values
->GetInteger("modulusLength", &modulus_length_bits
));
344 blink::WebCryptoKey private_key
= blink::WebCryptoKey::createNull();
346 // Import the key from JWK.
349 ImportKeyJwkFromDict(*key_jwk
,
350 CreateRsaHashedImportAlgorithm(
351 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
352 blink::WebCryptoAlgorithmIdSha256
),
354 blink::WebCryptoKeyUsageSign
,
357 live_keys
.push_back(private_key
);
362 private_key
.algorithm().rsaHashedParams()->modulusLengthBits()));
364 // Export to PKCS8 and verify that it matches expectation.
365 std::vector
<uint8_t> exported_key_pkcs8
;
369 blink::WebCryptoKeyFormatPkcs8
, private_key
, &exported_key_pkcs8
));
371 EXPECT_BYTES_EQ(pkcs8_bytes
, exported_key_pkcs8
);
375 // Import an RSA private key using JWK. Next import a JWK containing the same
376 // modulus, but mismatched parameters for the rest. It should NOT be possible
377 // that the second import retrieves the first key. See http://crbug.com/378315
378 // for how that could happen.
379 TEST(WebCryptoRsaSsaTest
, ImportJwkExistingModulusAndInvalid
) {
380 if (!SupportsRsaPrivateKeyImport())
383 scoped_ptr
<base::ListValue
> key_list
;
384 ASSERT_TRUE(ReadJsonTestFileToList("rsa_private_keys.json", &key_list
));
386 // Import a 1024-bit private key.
387 base::DictionaryValue
* key1_props
;
388 ASSERT_TRUE(key_list
->GetDictionary(1, &key1_props
));
389 base::DictionaryValue
* key1_jwk
;
390 ASSERT_TRUE(key1_props
->GetDictionary("jwk", &key1_jwk
));
392 blink::WebCryptoKey key1
= blink::WebCryptoKey::createNull();
393 ASSERT_EQ(Status::Success(),
394 ImportKeyJwkFromDict(*key1_jwk
,
395 CreateRsaHashedImportAlgorithm(
396 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
397 blink::WebCryptoAlgorithmIdSha256
),
399 blink::WebCryptoKeyUsageSign
,
402 ASSERT_EQ(1024u, key1
.algorithm().rsaHashedParams()->modulusLengthBits());
404 // Construct a JWK using the modulus of key1, but all the other fields from
405 // another key (also a 1024-bit private key).
406 base::DictionaryValue
* key2_props
;
407 ASSERT_TRUE(key_list
->GetDictionary(5, &key2_props
));
408 base::DictionaryValue
* key2_jwk
;
409 ASSERT_TRUE(key2_props
->GetDictionary("jwk", &key2_jwk
));
411 key1_jwk
->GetString("n", &modulus
);
412 key2_jwk
->SetString("n", modulus
);
414 // This should fail, as the n,e,d parameters are not consistent. It MUST NOT
415 // somehow return the key created earlier.
416 blink::WebCryptoKey key2
= blink::WebCryptoKey::createNull();
417 ASSERT_EQ(Status::OperationError(),
418 ImportKeyJwkFromDict(*key2_jwk
,
419 CreateRsaHashedImportAlgorithm(
420 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
421 blink::WebCryptoAlgorithmIdSha256
),
423 blink::WebCryptoKeyUsageSign
,
427 // Import a JWK RSA private key with some optional parameters missing (q, dp,
430 // The only optional parameter included is "p".
432 // This fails because JWA says that producers must include either ALL optional
433 // parameters or NONE.
434 TEST(WebCryptoRsaSsaTest
, ImportRsaPrivateKeyJwkMissingOptionalParams
) {
435 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
437 base::DictionaryValue dict
;
438 dict
.SetString("kty", "RSA");
439 dict
.SetString("alg", "RS1");
443 "pW5KDnAQF1iaUYfcfqhB0Vby7A42rVKkTf6x5h962ZHYxRBW_-2xYrTA8oOhKoijlN_"
444 "1JqtykcuzB86r_OCx39XNlQgJbVsri2311nHvY3fAkhyyPCcKcOJZjm_4nRnxBazC0_"
445 "DLNfKSgOE4a29kxO8i4eHyDQzoz_siSb2aITc");
446 dict
.SetString("e", "AQAB");
449 "M6UEKpCyfU9UUcqbu9C0R3GhAa-IQ0Cu-YhfKku-"
450 "kuiUpySsPFaMj5eFOtB8AmbIxqPKCSnx6PESMYhEKfxNmuVf7olqEM5wfD7X5zTkRyejlXRQ"
451 "GlMmgxCcKrrKuig8MbS9L1PD7jfjUs7jT55QO9gMBiKtecbc7og1R8ajsyU");
455 "iUJyCod1Fyc6NWBT6iobwMlKpy1VxuhilrLfyWeUjApyy8zKfqyzVwbgmh31W"
456 "hU1vZs8w0Fgs7bc0-2o5kQw");
458 ASSERT_EQ(Status::ErrorJwkPropertyMissing("q"),
459 ImportKeyJwkFromDict(dict
,
460 CreateRsaHashedImportAlgorithm(
461 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
462 blink::WebCryptoAlgorithmIdSha1
),
464 blink::WebCryptoKeyUsageSign
,
468 // Import a JWK RSA private key, without any of the optional parameters.
470 // According to JWA, such keys are valid, but applications SHOULD
471 // include all the parameters when sending, and recipients MAY
472 // accept them, but are not required to. Chromium's WebCrypto does
473 // not allow such degenerate keys.
474 TEST(WebCryptoRsaSsaTest
, ImportRsaPrivateKeyJwkIncorrectOptionalEmpty
) {
475 if (!SupportsRsaPrivateKeyImport())
478 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
480 base::DictionaryValue dict
;
481 dict
.SetString("kty", "RSA");
482 dict
.SetString("alg", "RS1");
486 "pW5KDnAQF1iaUYfcfqhB0Vby7A42rVKkTf6x5h962ZHYxRBW_-2xYrTA8oOhKoijlN_"
487 "1JqtykcuzB86r_OCx39XNlQgJbVsri2311nHvY3fAkhyyPCcKcOJZjm_4nRnxBazC0_"
488 "DLNfKSgOE4a29kxO8i4eHyDQzoz_siSb2aITc");
489 dict
.SetString("e", "AQAB");
492 "M6UEKpCyfU9UUcqbu9C0R3GhAa-IQ0Cu-YhfKku-"
493 "kuiUpySsPFaMj5eFOtB8AmbIxqPKCSnx6PESMYhEKfxNmuVf7olqEM5wfD7X5zTkRyejlXRQ"
494 "GlMmgxCcKrrKuig8MbS9L1PD7jfjUs7jT55QO9gMBiKtecbc7og1R8ajsyU");
496 ASSERT_EQ(Status::ErrorJwkPropertyMissing("p"),
497 ImportKeyJwkFromDict(dict
,
498 CreateRsaHashedImportAlgorithm(
499 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
500 blink::WebCryptoAlgorithmIdSha1
),
502 blink::WebCryptoKeyUsageSign
,
506 // Tries importing a public RSA key whose exponent contains leading zeros.
507 TEST(WebCryptoRsaSsaTest
, ImportJwkRsaNonMinimalExponent
) {
508 base::DictionaryValue dict
;
510 dict
.SetString("kty", "RSA");
511 dict
.SetString("e", "AAEAAQ"); // 00 01 00 01
514 "qLOyhK-OtQs4cDSoYPFGxJGfMYdjzWxVmMiuSBGh4KvEx-CwgtaTpef87Wdc9GaFEncsDLxk"
515 "p0LGxjD1M8jMcvYq6DPEC_JYQumEu3i9v5fAEH1VvbZi9cTg-rmEXLUUjvc5LdOq_5OuHmtm"
516 "e7PUJHYW1PW6ENTP0ibeiNOfFvs");
518 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
520 EXPECT_EQ(Status::ErrorJwkBigIntegerHasLeadingZero("e"),
521 ImportKeyJwkFromDict(dict
,
522 CreateRsaHashedImportAlgorithm(
523 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
524 blink::WebCryptoAlgorithmIdSha256
),
526 blink::WebCryptoKeyUsageVerify
,
530 TEST(WebCryptoRsaSsaTest
, GenerateKeyPairRsa
) {
531 // Note: using unrealistic short key lengths here to avoid bogging down tests.
533 // Successful WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 key generation (sha256)
534 const unsigned int modulus_length
= 256;
535 const std::vector
<uint8_t> public_exponent
= HexStringToBytes("010001");
536 blink::WebCryptoAlgorithm algorithm
=
537 CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
538 blink::WebCryptoAlgorithmIdSha256
,
541 bool extractable
= true;
542 const blink::WebCryptoKeyUsageMask usage_mask
= 0;
543 blink::WebCryptoKey public_key
= blink::WebCryptoKey::createNull();
544 blink::WebCryptoKey private_key
= blink::WebCryptoKey::createNull();
546 EXPECT_EQ(Status::Success(),
548 algorithm
, extractable
, usage_mask
, &public_key
, &private_key
));
549 EXPECT_FALSE(public_key
.isNull());
550 EXPECT_FALSE(private_key
.isNull());
551 EXPECT_EQ(blink::WebCryptoKeyTypePublic
, public_key
.type());
552 EXPECT_EQ(blink::WebCryptoKeyTypePrivate
, private_key
.type());
553 EXPECT_EQ(modulus_length
,
554 public_key
.algorithm().rsaHashedParams()->modulusLengthBits());
555 EXPECT_EQ(modulus_length
,
556 private_key
.algorithm().rsaHashedParams()->modulusLengthBits());
557 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256
,
558 public_key
.algorithm().rsaHashedParams()->hash().id());
559 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256
,
560 private_key
.algorithm().rsaHashedParams()->hash().id());
561 EXPECT_TRUE(public_key
.extractable());
562 EXPECT_EQ(extractable
, private_key
.extractable());
563 EXPECT_EQ(usage_mask
, public_key
.usages());
564 EXPECT_EQ(usage_mask
, private_key
.usages());
566 // Try exporting the generated key pair, and then re-importing to verify that
567 // the exported data was valid.
568 std::vector
<uint8_t> public_key_spki
;
571 ExportKey(blink::WebCryptoKeyFormatSpki
, public_key
, &public_key_spki
));
573 if (SupportsRsaPrivateKeyImport()) {
574 public_key
= blink::WebCryptoKey::createNull();
575 EXPECT_EQ(Status::Success(),
576 ImportKey(blink::WebCryptoKeyFormatSpki
,
577 CryptoData(public_key_spki
),
578 CreateRsaHashedImportAlgorithm(
579 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
580 blink::WebCryptoAlgorithmIdSha256
),
584 EXPECT_EQ(modulus_length
,
585 public_key
.algorithm().rsaHashedParams()->modulusLengthBits());
587 std::vector
<uint8_t> private_key_pkcs8
;
591 blink::WebCryptoKeyFormatPkcs8
, private_key
, &private_key_pkcs8
));
592 private_key
= blink::WebCryptoKey::createNull();
593 EXPECT_EQ(Status::Success(),
594 ImportKey(blink::WebCryptoKeyFormatPkcs8
,
595 CryptoData(private_key_pkcs8
),
596 CreateRsaHashedImportAlgorithm(
597 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
598 blink::WebCryptoAlgorithmIdSha256
),
602 EXPECT_EQ(modulus_length
,
603 private_key
.algorithm().rsaHashedParams()->modulusLengthBits());
606 // Fail with bad modulus.
608 CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
609 blink::WebCryptoAlgorithmIdSha256
,
612 EXPECT_EQ(Status::ErrorGenerateRsaUnsupportedModulus(),
614 algorithm
, extractable
, usage_mask
, &public_key
, &private_key
));
616 // Fail with bad exponent: larger than unsigned long.
617 unsigned int exponent_length
= sizeof(unsigned long) + 1; // NOLINT
618 const std::vector
<uint8_t> long_exponent(exponent_length
, 0x01);
620 CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
621 blink::WebCryptoAlgorithmIdSha256
,
624 EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
626 algorithm
, extractable
, usage_mask
, &public_key
, &private_key
));
628 // Fail with bad exponent: empty.
629 const std::vector
<uint8_t> empty_exponent
;
631 CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
632 blink::WebCryptoAlgorithmIdSha256
,
635 EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
637 algorithm
, extractable
, usage_mask
, &public_key
, &private_key
));
639 // Fail with bad exponent: all zeros.
640 std::vector
<uint8_t> exponent_with_leading_zeros(15, 0x00);
642 CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
643 blink::WebCryptoAlgorithmIdSha256
,
645 exponent_with_leading_zeros
);
646 EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
648 algorithm
, extractable
, usage_mask
, &public_key
, &private_key
));
650 // Key generation success using exponent with leading zeros.
651 exponent_with_leading_zeros
.insert(exponent_with_leading_zeros
.end(),
652 public_exponent
.begin(),
653 public_exponent
.end());
655 CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
656 blink::WebCryptoAlgorithmIdSha256
,
658 exponent_with_leading_zeros
);
659 EXPECT_EQ(Status::Success(),
661 algorithm
, extractable
, usage_mask
, &public_key
, &private_key
));
662 EXPECT_FALSE(public_key
.isNull());
663 EXPECT_FALSE(private_key
.isNull());
664 EXPECT_EQ(blink::WebCryptoKeyTypePublic
, public_key
.type());
665 EXPECT_EQ(blink::WebCryptoKeyTypePrivate
, private_key
.type());
666 EXPECT_TRUE(public_key
.extractable());
667 EXPECT_EQ(extractable
, private_key
.extractable());
668 EXPECT_EQ(usage_mask
, public_key
.usages());
669 EXPECT_EQ(usage_mask
, private_key
.usages());
671 // Successful WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 key generation (sha1)
673 CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
674 blink::WebCryptoAlgorithmIdSha1
,
679 GenerateKeyPair(algorithm
, false, usage_mask
, &public_key
, &private_key
));
680 EXPECT_FALSE(public_key
.isNull());
681 EXPECT_FALSE(private_key
.isNull());
682 EXPECT_EQ(blink::WebCryptoKeyTypePublic
, public_key
.type());
683 EXPECT_EQ(blink::WebCryptoKeyTypePrivate
, private_key
.type());
684 EXPECT_EQ(modulus_length
,
685 public_key
.algorithm().rsaHashedParams()->modulusLengthBits());
686 EXPECT_EQ(modulus_length
,
687 private_key
.algorithm().rsaHashedParams()->modulusLengthBits());
688 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1
,
689 public_key
.algorithm().rsaHashedParams()->hash().id());
690 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1
,
691 private_key
.algorithm().rsaHashedParams()->hash().id());
692 // Even though "extractable" was set to false, the public key remains
694 EXPECT_TRUE(public_key
.extractable());
695 EXPECT_FALSE(private_key
.extractable());
696 EXPECT_EQ(usage_mask
, public_key
.usages());
697 EXPECT_EQ(usage_mask
, private_key
.usages());
699 // Exporting a private key as SPKI format doesn't make sense. However this
700 // will first fail because the key is not extractable.
701 std::vector
<uint8_t> output
;
702 EXPECT_EQ(Status::ErrorKeyNotExtractable(),
703 ExportKey(blink::WebCryptoKeyFormatSpki
, private_key
, &output
));
705 // Re-generate an extractable private_key and try to export it as SPKI format.
706 // This should fail since spki is for public keys.
709 GenerateKeyPair(algorithm
, true, usage_mask
, &public_key
, &private_key
));
710 EXPECT_EQ(Status::ErrorUnexpectedKeyType(),
711 ExportKey(blink::WebCryptoKeyFormatSpki
, private_key
, &output
));
714 TEST(WebCryptoRsaSsaTest
, GenerateKeyPairRsaBadModulusLength
) {
715 const unsigned int kBadModulusBits
[] = {
718 257, // Not a multiple of 8.
719 1023, // Not a multiple of 8.
720 0xFFFFFFFF, // Too big.
721 16384 + 8, // 16384 is the maxmimum length that NSS succeeds for.
724 const std::vector
<uint8_t> public_exponent
= HexStringToBytes("010001");
726 for (size_t i
= 0; i
< arraysize(kBadModulusBits
); ++i
) {
727 const unsigned int modulus_length_bits
= kBadModulusBits
[i
];
728 blink::WebCryptoAlgorithm algorithm
= CreateRsaHashedKeyGenAlgorithm(
729 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
730 blink::WebCryptoAlgorithmIdSha256
,
733 bool extractable
= true;
734 const blink::WebCryptoKeyUsageMask usage_mask
= 0;
735 blink::WebCryptoKey public_key
= blink::WebCryptoKey::createNull();
736 blink::WebCryptoKey private_key
= blink::WebCryptoKey::createNull();
739 Status::ErrorGenerateRsaUnsupportedModulus(),
741 algorithm
, extractable
, usage_mask
, &public_key
, &private_key
));
745 // Try generating RSA key pairs using unsupported public exponents. Only
746 // exponents of 3 and 65537 are supported. While both OpenSSL and NSS can
747 // support other values, OpenSSL hangs when given invalid exponents, so use a
748 // whitelist to validate the parameters.
749 TEST(WebCryptoRsaSsaTest
, GenerateKeyPairRsaBadExponent
) {
750 const unsigned int modulus_length
= 1024;
752 const char* const kPublicExponents
[] = {
753 "11", // 17 - This is a valid public exponent, but currently disallowed.
758 for (size_t i
= 0; i
< arraysize(kPublicExponents
); ++i
) {
760 blink::WebCryptoAlgorithm algorithm
= CreateRsaHashedKeyGenAlgorithm(
761 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
762 blink::WebCryptoAlgorithmIdSha256
,
764 HexStringToBytes(kPublicExponents
[i
]));
766 blink::WebCryptoKey public_key
= blink::WebCryptoKey::createNull();
767 blink::WebCryptoKey private_key
= blink::WebCryptoKey::createNull();
769 EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
770 GenerateKeyPair(algorithm
, true, 0, &public_key
, &private_key
));
774 TEST(WebCryptoRsaSsaTest
, SignVerifyFailures
) {
775 if (!SupportsRsaPrivateKeyImport())
778 // Import a key pair.
779 blink::WebCryptoAlgorithm import_algorithm
=
780 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
781 blink::WebCryptoAlgorithmIdSha1
);
782 blink::WebCryptoKey public_key
= blink::WebCryptoKey::createNull();
783 blink::WebCryptoKey private_key
= blink::WebCryptoKey::createNull();
784 ASSERT_NO_FATAL_FAILURE(
785 ImportRsaKeyPair(HexStringToBytes(kPublicKeySpkiDerHex
),
786 HexStringToBytes(kPrivateKeyPkcs8DerHex
),
789 blink::WebCryptoKeyUsageVerify
,
790 blink::WebCryptoKeyUsageSign
,
794 blink::WebCryptoAlgorithm algorithm
=
795 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
);
797 std::vector
<uint8_t> signature
;
798 bool signature_match
;
800 // Compute a signature.
801 const std::vector
<uint8_t> data
= HexStringToBytes("010203040506070809");
802 ASSERT_EQ(Status::Success(),
803 Sign(algorithm
, private_key
, CryptoData(data
), &signature
));
805 // Ensure truncated signature does not verify by passing one less byte.
810 CryptoData(vector_as_array(&signature
), signature
.size() - 1),
813 EXPECT_FALSE(signature_match
);
815 // Ensure truncated signature does not verify by passing no bytes.
816 EXPECT_EQ(Status::Success(),
822 EXPECT_FALSE(signature_match
);
824 // Ensure corrupted signature does not verify.
825 std::vector
<uint8_t> corrupt_sig
= signature
;
826 corrupt_sig
[corrupt_sig
.size() / 2] ^= 0x1;
827 EXPECT_EQ(Status::Success(),
830 CryptoData(corrupt_sig
),
833 EXPECT_FALSE(signature_match
);
835 // Ensure signatures that are greater than the modulus size fail.
836 const unsigned int long_message_size_bytes
= 1024;
837 DCHECK_GT(long_message_size_bytes
, kModulusLengthBits
/ 8);
838 const unsigned char kLongSignature
[long_message_size_bytes
] = {0};
839 EXPECT_EQ(Status::Success(),
842 CryptoData(kLongSignature
, sizeof(kLongSignature
)),
845 EXPECT_FALSE(signature_match
);
847 // Ensure that signing and verifying with an incompatible algorithm fails.
848 algorithm
= CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaOaep
);
850 EXPECT_EQ(Status::ErrorUnexpected(),
851 Sign(algorithm
, private_key
, CryptoData(data
), &signature
));
852 EXPECT_EQ(Status::ErrorUnexpected(),
855 CryptoData(signature
),
859 // Some crypto libraries (NSS) can automatically select the RSA SSA inner hash
860 // based solely on the contents of the input signature data. In the Web Crypto
861 // implementation, the inner hash should be specified uniquely by the key
862 // algorithm parameter. To validate this behavior, call Verify with a computed
863 // signature that used one hash type (SHA-1), but pass in a key with a
864 // different inner hash type (SHA-256). If the hash type is determined by the
865 // signature itself (undesired), the verify will pass, while if the hash type
866 // is specified by the key algorithm (desired), the verify will fail.
868 // Compute a signature using SHA-1 as the inner hash.
869 EXPECT_EQ(Status::Success(),
870 Sign(CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
),
875 blink::WebCryptoKey public_key_256
= blink::WebCryptoKey::createNull();
876 EXPECT_EQ(Status::Success(),
877 ImportKey(blink::WebCryptoKeyFormatSpki
,
878 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex
)),
879 CreateRsaHashedImportAlgorithm(
880 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
881 blink::WebCryptoAlgorithmIdSha256
),
883 blink::WebCryptoKeyUsageVerify
,
886 // Now verify using an algorithm whose inner hash is SHA-256, not SHA-1. The
887 // signature should not verify.
888 // NOTE: public_key was produced by generateKey, and so its associated
889 // algorithm has WebCryptoRsaKeyGenParams and not WebCryptoRsaSsaParams. Thus
890 // it has no inner hash to conflict with the input algorithm.
891 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1
,
892 private_key
.algorithm().rsaHashedParams()->hash().id());
893 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256
,
894 public_key_256
.algorithm().rsaHashedParams()->hash().id());
897 EXPECT_EQ(Status::Success(),
898 Verify(CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
),
900 CryptoData(signature
),
903 EXPECT_FALSE(is_match
);
906 TEST(WebCryptoRsaSsaTest
, SignVerifyKnownAnswer
) {
907 if (!SupportsRsaPrivateKeyImport())
910 scoped_ptr
<base::ListValue
> tests
;
911 ASSERT_TRUE(ReadJsonTestFileToList("pkcs1v15_sign.json", &tests
));
913 // Import the key pair.
914 blink::WebCryptoAlgorithm import_algorithm
=
915 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
916 blink::WebCryptoAlgorithmIdSha1
);
917 blink::WebCryptoKey public_key
= blink::WebCryptoKey::createNull();
918 blink::WebCryptoKey private_key
= blink::WebCryptoKey::createNull();
919 ASSERT_NO_FATAL_FAILURE(
920 ImportRsaKeyPair(HexStringToBytes(kPublicKeySpkiDerHex
),
921 HexStringToBytes(kPrivateKeyPkcs8DerHex
),
924 blink::WebCryptoKeyUsageVerify
,
925 blink::WebCryptoKeyUsageSign
,
929 blink::WebCryptoAlgorithm algorithm
=
930 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
);
932 // Validate the signatures are computed and verified as expected.
933 std::vector
<uint8_t> signature
;
934 for (size_t test_index
= 0; test_index
< tests
->GetSize(); ++test_index
) {
935 SCOPED_TRACE(test_index
);
937 base::DictionaryValue
* test
;
938 ASSERT_TRUE(tests
->GetDictionary(test_index
, &test
));
940 std::vector
<uint8_t> test_message
=
941 GetBytesFromHexString(test
, "message_hex");
942 std::vector
<uint8_t> test_signature
=
943 GetBytesFromHexString(test
, "signature_hex");
948 Sign(algorithm
, private_key
, CryptoData(test_message
), &signature
));
949 EXPECT_BYTES_EQ(test_signature
, signature
);
951 bool is_match
= false;
952 ASSERT_EQ(Status::Success(),
955 CryptoData(test_signature
),
956 CryptoData(test_message
),
958 EXPECT_TRUE(is_match
);
962 // Try importing an RSA-SSA public key with unsupported key usages using SPKI
963 // format. RSA-SSA public keys only support the 'verify' usage.
964 TEST(WebCryptoRsaSsaTest
, ImportRsaSsaPublicKeyBadUsage_SPKI
) {
965 const blink::WebCryptoAlgorithm algorithm
=
966 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
967 blink::WebCryptoAlgorithmIdSha256
);
969 blink::WebCryptoKeyUsageMask bad_usages
[] = {
970 blink::WebCryptoKeyUsageSign
,
971 blink::WebCryptoKeyUsageSign
| blink::WebCryptoKeyUsageVerify
,
972 blink::WebCryptoKeyUsageEncrypt
,
973 blink::WebCryptoKeyUsageEncrypt
| blink::WebCryptoKeyUsageDecrypt
,
976 for (size_t i
= 0; i
< arraysize(bad_usages
); ++i
) {
979 blink::WebCryptoKey public_key
= blink::WebCryptoKey::createNull();
980 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
981 ImportKey(blink::WebCryptoKeyFormatSpki
,
982 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex
)),
990 // Try importing an RSA-SSA public key with unsupported key usages using JWK
991 // format. RSA-SSA public keys only support the 'verify' usage.
992 TEST(WebCryptoRsaSsaTest
, ImportRsaSsaPublicKeyBadUsage_JWK
) {
993 const blink::WebCryptoAlgorithm algorithm
=
994 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
995 blink::WebCryptoAlgorithmIdSha256
);
997 blink::WebCryptoKeyUsageMask bad_usages
[] = {
998 blink::WebCryptoKeyUsageSign
,
999 blink::WebCryptoKeyUsageSign
| blink::WebCryptoKeyUsageVerify
,
1000 blink::WebCryptoKeyUsageEncrypt
,
1001 blink::WebCryptoKeyUsageEncrypt
| blink::WebCryptoKeyUsageDecrypt
,
1004 base::DictionaryValue dict
;
1005 RestoreJwkRsaDictionary(&dict
);
1006 dict
.Remove("use", NULL
);
1007 dict
.SetString("alg", "RS256");
1009 for (size_t i
= 0; i
< arraysize(bad_usages
); ++i
) {
1012 blink::WebCryptoKey public_key
= blink::WebCryptoKey::createNull();
1013 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
1014 ImportKeyJwkFromDict(
1015 dict
, algorithm
, false, bad_usages
[i
], &public_key
));
1019 // Generate an RSA-SSA key pair with invalid usages. RSA-SSA supports:
1021 TEST(WebCryptoRsaSsaTest
, GenerateKeyBadUsages
) {
1022 blink::WebCryptoKeyUsageMask bad_usages
[] = {
1023 blink::WebCryptoKeyUsageDecrypt
,
1024 blink::WebCryptoKeyUsageVerify
| blink::WebCryptoKeyUsageDecrypt
,
1025 blink::WebCryptoKeyUsageWrapKey
,
1028 const unsigned int modulus_length
= 256;
1029 const std::vector
<uint8_t> public_exponent
= HexStringToBytes("010001");
1031 for (size_t i
= 0; i
< arraysize(bad_usages
); ++i
) {
1034 blink::WebCryptoKey public_key
= blink::WebCryptoKey::createNull();
1035 blink::WebCryptoKey private_key
= blink::WebCryptoKey::createNull();
1037 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
1038 GenerateKeyPair(CreateRsaHashedKeyGenAlgorithm(
1039 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
1040 blink::WebCryptoAlgorithmIdSha256
,
1050 // Generate an RSA-SSA key pair. The public and private keys should select the
1051 // key usages which are applicable, and not have the exact same usages as was
1052 // specified to GenerateKey
1053 TEST(WebCryptoRsaSsaTest
, GenerateKeyPairIntersectUsages
) {
1054 const unsigned int modulus_length
= 256;
1055 const std::vector
<uint8_t> public_exponent
= HexStringToBytes("010001");
1057 blink::WebCryptoKey public_key
= blink::WebCryptoKey::createNull();
1058 blink::WebCryptoKey private_key
= blink::WebCryptoKey::createNull();
1060 ASSERT_EQ(Status::Success(),
1062 CreateRsaHashedKeyGenAlgorithm(
1063 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
1064 blink::WebCryptoAlgorithmIdSha256
,
1068 blink::WebCryptoKeyUsageSign
| blink::WebCryptoKeyUsageVerify
,
1072 EXPECT_EQ(blink::WebCryptoKeyUsageVerify
, public_key
.usages());
1073 EXPECT_EQ(blink::WebCryptoKeyUsageSign
, private_key
.usages());
1075 // Try again but this time without the Verify usages.
1076 ASSERT_EQ(Status::Success(),
1077 GenerateKeyPair(CreateRsaHashedKeyGenAlgorithm(
1078 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
1079 blink::WebCryptoAlgorithmIdSha256
,
1083 blink::WebCryptoKeyUsageSign
,
1087 EXPECT_EQ(0, public_key
.usages());
1088 EXPECT_EQ(blink::WebCryptoKeyUsageSign
, private_key
.usages());
1091 TEST(WebCryptoRsaSsaTest
, ImportExportJwkRsaPublicKey
) {
1093 const blink::WebCryptoAlgorithmId hash
;
1094 const blink::WebCryptoKeyUsageMask usage
;
1095 const char* const jwk_alg
;
1097 const TestCase kTests
[] = {
1098 {blink::WebCryptoAlgorithmIdSha1
, blink::WebCryptoKeyUsageVerify
, "RS1"},
1099 {blink::WebCryptoAlgorithmIdSha256
, blink::WebCryptoKeyUsageVerify
,
1101 {blink::WebCryptoAlgorithmIdSha384
, blink::WebCryptoKeyUsageVerify
,
1103 {blink::WebCryptoAlgorithmIdSha512
, blink::WebCryptoKeyUsageVerify
,
1106 for (size_t test_index
= 0; test_index
< ARRAYSIZE_UNSAFE(kTests
);
1108 SCOPED_TRACE(test_index
);
1109 const TestCase
& test
= kTests
[test_index
];
1111 const blink::WebCryptoAlgorithm import_algorithm
=
1112 CreateRsaHashedImportAlgorithm(
1113 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
, test
.hash
);
1115 // Import the spki to create a public key
1116 blink::WebCryptoKey public_key
= blink::WebCryptoKey::createNull();
1117 ASSERT_EQ(Status::Success(),
1118 ImportKey(blink::WebCryptoKeyFormatSpki
,
1119 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex
)),
1125 // Export the public key as JWK and verify its contents
1126 std::vector
<uint8_t> jwk
;
1127 ASSERT_EQ(Status::Success(),
1128 ExportKey(blink::WebCryptoKeyFormatJwk
, public_key
, &jwk
));
1129 EXPECT_TRUE(VerifyPublicJwk(jwk
,
1131 kPublicKeyModulusHex
,
1132 kPublicKeyExponentHex
,
1135 // Import the JWK back in to create a new key
1136 blink::WebCryptoKey public_key2
= blink::WebCryptoKey::createNull();
1137 ASSERT_EQ(Status::Success(),
1138 ImportKey(blink::WebCryptoKeyFormatJwk
,
1144 ASSERT_TRUE(public_key2
.handle());
1145 EXPECT_EQ(blink::WebCryptoKeyTypePublic
, public_key2
.type());
1146 EXPECT_TRUE(public_key2
.extractable());
1147 EXPECT_EQ(import_algorithm
.id(), public_key2
.algorithm().id());
1149 // Export the new key as spki and compare to the original.
1150 std::vector
<uint8_t> spki
;
1151 ASSERT_EQ(Status::Success(),
1152 ExportKey(blink::WebCryptoKeyFormatSpki
, public_key2
, &spki
));
1153 EXPECT_BYTES_EQ_HEX(kPublicKeySpkiDerHex
, CryptoData(spki
));
1157 TEST(WebCryptoRsaSsaTest
, ImportJwkRsaFailures
) {
1158 base::DictionaryValue dict
;
1159 RestoreJwkRsaDictionary(&dict
);
1160 blink::WebCryptoAlgorithm algorithm
=
1161 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
1162 blink::WebCryptoAlgorithmIdSha256
);
1163 blink::WebCryptoKeyUsageMask usage_mask
= blink::WebCryptoKeyUsageVerify
;
1164 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
1166 // An RSA public key JWK _must_ have an "n" (modulus) and an "e" (exponent)
1167 // entry, while an RSA private key must have those plus at least a "d"
1168 // (private exponent) entry.
1169 // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18,
1173 EXPECT_EQ(Status::Success(),
1174 ImportKeyJwkFromDict(dict
, algorithm
, false, usage_mask
, &key
));
1175 EXPECT_EQ(algorithm
.id(), key
.algorithm().id());
1176 EXPECT_FALSE(key
.extractable());
1177 EXPECT_EQ(blink::WebCryptoKeyUsageVerify
, key
.usages());
1178 EXPECT_EQ(blink::WebCryptoKeyTypePublic
, key
.type());
1180 // The following are specific failure cases for when kty = "RSA".
1182 // Fail if either "n" or "e" is not present or malformed.
1183 const std::string kKtyParmName
[] = {"n", "e"};
1184 for (size_t idx
= 0; idx
< ARRAYSIZE_UNSAFE(kKtyParmName
); ++idx
) {
1185 // Fail on missing parameter.
1186 dict
.Remove(kKtyParmName
[idx
], NULL
);
1187 EXPECT_NE(Status::Success(),
1188 ImportKeyJwkFromDict(dict
, algorithm
, false, usage_mask
, &key
));
1189 RestoreJwkRsaDictionary(&dict
);
1191 // Fail on bad b64 parameter encoding.
1192 dict
.SetString(kKtyParmName
[idx
], "Qk3f0DsytU8lfza2au #$% Htaw2xpop9yTuH0");
1193 EXPECT_NE(Status::Success(),
1194 ImportKeyJwkFromDict(dict
, algorithm
, false, usage_mask
, &key
));
1195 RestoreJwkRsaDictionary(&dict
);
1197 // Fail on empty parameter.
1198 dict
.SetString(kKtyParmName
[idx
], "");
1199 EXPECT_EQ(Status::ErrorJwkEmptyBigInteger(kKtyParmName
[idx
]),
1200 ImportKeyJwkFromDict(dict
, algorithm
, false, usage_mask
, &key
));
1201 RestoreJwkRsaDictionary(&dict
);
1207 } // namespace webcrypto
1209 } // namespace content