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"
21 // Helper for ImportJwkRsaFailures. Restores the JWK JSON
22 // dictionary to a good state
23 void RestoreJwkRsaDictionary(base::DictionaryValue
* dict
) {
25 dict
->SetString("kty", "RSA");
26 dict
->SetString("alg", "RS256");
27 dict
->SetString("use", "sig");
28 dict
->SetBoolean("ext", false);
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());
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
97 TEST(WebCryptoRsaSsaTest
, ImportExportPkcs8
) {
98 if (!SupportsRsaPrivateKeyImport())
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());
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
141 // PKCS8 --> JWK --> PKCS8
142 TEST(WebCryptoRsaSsaTest
, ImportRsaPrivateKeyJwkToPkcs8RoundTrip
) {
143 if (!SupportsRsaPrivateKeyImport())
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
161 const char* expected_jwk
=
162 "{\"alg\":\"RS1\",\"d\":\"M6UEKpCyfU9UUcqbu9C0R3GhAa-IQ0Cu-YhfKku-"
163 "kuiUpySsPFaMj5eFOtB8AmbIxqPKCSnx6PESMYhEKfxNmuVf7olqEM5wfD7X5zTkRyejlXRQ"
164 "GlMmgxCcKrrKuig8MbS9L1PD7jfjUs7jT55QO9gMBiKtecbc7og1R8ajsyU\",\"dp\":"
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
));
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
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
205 TEST(WebCryptoRsaSsaTest
, ImportMultipleRSAPrivateKeysJwk
) {
206 if (!SupportsRsaPrivateKeyImport())
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
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
);
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())
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
));
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();
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();
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
,
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
,
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
,
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
,
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
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
[] = {
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
,
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
,
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.
518 for (size_t i
= 0; i
< arraysize(kPublicExponents
); ++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())
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
,
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());
635 EXPECT_EQ(Status::Success(),
636 Verify(CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
),
637 public_key_256
, CryptoData(signature
), CryptoData(data
),
639 EXPECT_FALSE(is_match
);
642 TEST(WebCryptoRsaSsaTest
, SignVerifyKnownAnswer
) {
643 if (!SupportsRsaPrivateKeyImport())
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
,
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");
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
) {
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
) {
737 blink::WebCryptoKey public_key
;
738 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
739 ImportKeyJwkFromDict(dict
, algorithm
, false, bad_usages
[i
],
744 // Generate an RSA-SSA key pair with invalid usages. RSA-SSA supports:
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
) {
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
,
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())
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
;
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
) {
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
,
890 {blink::WebCryptoAlgorithmIdSha384
,
891 blink::WebCryptoKeyUsageVerify
,
893 {blink::WebCryptoAlgorithmIdSha512
,
894 blink::WebCryptoKeyUsageVerify
,
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,
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
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
,
1009 // Imports invalid JWK/SPKI/PKCS8 data and verifies that it fails as expected.
1010 TEST(WebCryptoRsaSsaTest
, ImportInvalidKeyData
) {
1011 if (!SupportsRsaPrivateKeyImport())
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
));
1044 } // namespace webcrypto