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
;
42 ASSERT_EQ(Status::Success(),
43 ImportKey(blink::WebCryptoKeyFormatSpki
,
44 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex
)),
45 CreateRsaHashedImportAlgorithm(
46 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
47 blink::WebCryptoAlgorithmIdSha256
),
48 true, blink::WebCryptoKeyUsageVerify
, &key
));
49 EXPECT_TRUE(key
.handle());
50 EXPECT_EQ(blink::WebCryptoKeyTypePublic
, key
.type());
51 EXPECT_TRUE(key
.extractable());
52 EXPECT_EQ(blink::WebCryptoKeyUsageVerify
, key
.usages());
53 EXPECT_EQ(kModulusLengthBits
,
54 key
.algorithm().rsaHashedParams()->modulusLengthBits());
57 CryptoData(key
.algorithm().rsaHashedParams()->publicExponent()));
59 // Failing case: Import RSA key but provide an inconsistent input algorithm.
60 EXPECT_EQ(Status::ErrorUnsupportedImportKeyFormat(),
61 ImportKey(blink::WebCryptoKeyFormatSpki
,
62 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex
)),
63 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
), true,
64 blink::WebCryptoKeyUsageEncrypt
, &key
));
66 // Passing case: Export a previously imported RSA public key in SPKI format
67 // and compare to original data.
68 std::vector
<uint8_t> output
;
69 ASSERT_EQ(Status::Success(),
70 ExportKey(blink::WebCryptoKeyFormatSpki
, key
, &output
));
71 EXPECT_BYTES_EQ_HEX(kPublicKeySpkiDerHex
, output
);
73 // Failing case: Try to export a previously imported RSA public key in raw
74 // format (not allowed for a public key).
75 EXPECT_EQ(Status::ErrorUnsupportedExportKeyFormat(),
76 ExportKey(blink::WebCryptoKeyFormatRaw
, key
, &output
));
78 // Failing case: Try to export a non-extractable key
79 ASSERT_EQ(Status::Success(),
80 ImportKey(blink::WebCryptoKeyFormatSpki
,
81 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex
)),
82 CreateRsaHashedImportAlgorithm(
83 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
84 blink::WebCryptoAlgorithmIdSha256
),
85 false, blink::WebCryptoKeyUsageVerify
, &key
));
86 EXPECT_TRUE(key
.handle());
87 EXPECT_FALSE(key
.extractable());
88 EXPECT_EQ(Status::ErrorKeyNotExtractable(),
89 ExportKey(blink::WebCryptoKeyFormatSpki
, key
, &output
));
91 // TODO(eroman): Failing test: Import a SPKI with an unrecognized hash OID
92 // TODO(eroman): Failing test: Import a SPKI with invalid algorithm params
93 // TODO(eroman): Failing test: Import a SPKI with inconsistent parameters
94 // (e.g. SHA-1 in OID, SHA-256 in params)
95 // TODO(eroman): Failing test: Import a SPKI for RSA-SSA, but with params
99 TEST(WebCryptoRsaSsaTest
, ImportExportPkcs8
) {
100 if (!SupportsRsaPrivateKeyImport())
103 // Passing case: Import a valid RSA key in PKCS#8 format.
104 blink::WebCryptoKey key
;
105 ASSERT_EQ(Status::Success(),
106 ImportKey(blink::WebCryptoKeyFormatPkcs8
,
107 CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex
)),
108 CreateRsaHashedImportAlgorithm(
109 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
110 blink::WebCryptoAlgorithmIdSha1
),
111 true, blink::WebCryptoKeyUsageSign
, &key
));
112 EXPECT_TRUE(key
.handle());
113 EXPECT_EQ(blink::WebCryptoKeyTypePrivate
, key
.type());
114 EXPECT_TRUE(key
.extractable());
115 EXPECT_EQ(blink::WebCryptoKeyUsageSign
, key
.usages());
116 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1
,
117 key
.algorithm().rsaHashedParams()->hash().id());
118 EXPECT_EQ(kModulusLengthBits
,
119 key
.algorithm().rsaHashedParams()->modulusLengthBits());
122 CryptoData(key
.algorithm().rsaHashedParams()->publicExponent()));
124 std::vector
<uint8_t> exported_key
;
125 ASSERT_EQ(Status::Success(),
126 ExportKey(blink::WebCryptoKeyFormatPkcs8
, key
, &exported_key
));
127 EXPECT_BYTES_EQ_HEX(kPrivateKeyPkcs8DerHex
, exported_key
);
129 // Failing case: Import RSA key but provide an inconsistent input algorithm
130 // and usage. Several issues here:
131 // * AES-CBC doesn't support PKCS8 key format
132 // * AES-CBC doesn't support "sign" usage
133 EXPECT_EQ(Status::ErrorUnsupportedImportKeyFormat(),
134 ImportKey(blink::WebCryptoKeyFormatPkcs8
,
135 CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex
)),
136 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
), true,
137 blink::WebCryptoKeyUsageSign
, &key
));
140 // Tests JWK import and export by doing a roundtrip key conversion and ensuring
143 // PKCS8 --> JWK --> PKCS8
144 TEST(WebCryptoRsaSsaTest
, ImportRsaPrivateKeyJwkToPkcs8RoundTrip
) {
145 if (!SupportsRsaPrivateKeyImport())
148 blink::WebCryptoKey key
;
149 ASSERT_EQ(Status::Success(),
150 ImportKey(blink::WebCryptoKeyFormatPkcs8
,
151 CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex
)),
152 CreateRsaHashedImportAlgorithm(
153 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
154 blink::WebCryptoAlgorithmIdSha1
),
155 true, blink::WebCryptoKeyUsageSign
, &key
));
157 std::vector
<uint8_t> exported_key_jwk
;
158 ASSERT_EQ(Status::Success(),
159 ExportKey(blink::WebCryptoKeyFormatJwk
, key
, &exported_key_jwk
));
161 // All of the optional parameters (p, q, dp, dq, qi) should be present in the
163 const char* expected_jwk
=
164 "{\"alg\":\"RS1\",\"d\":\"M6UEKpCyfU9UUcqbu9C0R3GhAa-IQ0Cu-YhfKku-"
165 "kuiUpySsPFaMj5eFOtB8AmbIxqPKCSnx6PESMYhEKfxNmuVf7olqEM5wfD7X5zTkRyejlXRQ"
166 "GlMmgxCcKrrKuig8MbS9L1PD7jfjUs7jT55QO9gMBiKtecbc7og1R8ajsyU\",\"dp\":"
168 "KFZy6ylpy6hkMMAieGc0nSlVvNsT24Z9VSzTAd3kEJ7vdjdPt4kSDKPOF2Bsw6OQ7L_-"
169 "gJ4YZeQ\",\"dq\":\"Gos485j6cSBJiY1_t57gp3ZoeRKZzfoJ78DlB6yyHtdDAe9b_Ui-"
170 "RV6utuFnglWCdYCo5OjhQVHRUQqCo_LnKQ\",\"e\":\"AQAB\",\"ext\":true,\"key_"
171 "ops\":[\"sign\"],\"kty\":\"RSA\",\"n\":"
172 "\"pW5KDnAQF1iaUYfcfqhB0Vby7A42rVKkTf6x5h962ZHYxRBW_-2xYrTA8oOhKoijlN_"
173 "1JqtykcuzB86r_OCx39XNlQgJbVsri2311nHvY3fAkhyyPCcKcOJZjm_4nRnxBazC0_"
174 "DLNfKSgOE4a29kxO8i4eHyDQzoz_siSb2aITc\",\"p\":\"5-"
175 "iUJyCod1Fyc6NWBT6iobwMlKpy1VxuhilrLfyWeUjApyy8zKfqyzVwbgmh31WhU1vZs8w0Fg"
176 "s7bc0-2o5kQw\",\"q\":\"tp3KHPfU1-yB51uQ_MqHSrzeEj_"
177 "ScAGAqpBHm25I3o1n7ST58Z2FuidYdPVCzSDccj5pYzZKH5QlRSsmmmeZ_Q\",\"qi\":"
178 "\"JxVqukEm0kqB86Uoy_sn9WiG-"
179 "ECp9uhuF6RLlP6TGVhLjiL93h5aLjvYqluo2FhBlOshkKz4MrhH8To9JKefTQ\"}";
181 ASSERT_EQ(CryptoData(std::string(expected_jwk
)),
182 CryptoData(exported_key_jwk
));
186 ImportKey(blink::WebCryptoKeyFormatJwk
, CryptoData(exported_key_jwk
),
187 CreateRsaHashedImportAlgorithm(
188 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
189 blink::WebCryptoAlgorithmIdSha1
),
190 true, blink::WebCryptoKeyUsageSign
, &key
));
192 std::vector
<uint8_t> exported_key_pkcs8
;
193 ASSERT_EQ(Status::Success(), ExportKey(blink::WebCryptoKeyFormatPkcs8
, key
,
194 &exported_key_pkcs8
));
196 ASSERT_EQ(CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex
)),
197 CryptoData(exported_key_pkcs8
));
200 // Tests importing multiple RSA private keys from JWK, and then exporting to
203 // This is a regression test for http://crbug.com/378315, for which importing
204 // a sequence of keys from JWK could yield the wrong key. The first key would
205 // be imported correctly, however every key after that would actually import
207 TEST(WebCryptoRsaSsaTest
, ImportMultipleRSAPrivateKeysJwk
) {
208 if (!SupportsRsaPrivateKeyImport())
211 scoped_ptr
<base::ListValue
> key_list
;
212 ASSERT_TRUE(ReadJsonTestFileToList("rsa_private_keys.json", &key_list
));
214 // For this test to be meaningful the keys MUST be kept alive before importing
216 std::vector
<blink::WebCryptoKey
> live_keys
;
218 for (size_t key_index
= 0; key_index
< key_list
->GetSize(); ++key_index
) {
219 SCOPED_TRACE(key_index
);
221 base::DictionaryValue
* key_values
;
222 ASSERT_TRUE(key_list
->GetDictionary(key_index
, &key_values
));
224 // Get the JWK representation of the key.
225 base::DictionaryValue
* key_jwk
;
226 ASSERT_TRUE(key_values
->GetDictionary("jwk", &key_jwk
));
228 // Get the PKCS8 representation of the key.
229 std::string pkcs8_hex_string
;
230 ASSERT_TRUE(key_values
->GetString("pkcs8", &pkcs8_hex_string
));
231 std::vector
<uint8_t> pkcs8_bytes
= HexStringToBytes(pkcs8_hex_string
);
233 // Get the modulus length for the key.
234 int modulus_length_bits
= 0;
235 ASSERT_TRUE(key_values
->GetInteger("modulusLength", &modulus_length_bits
));
237 blink::WebCryptoKey private_key
;
239 // Import the key from JWK.
240 ASSERT_EQ(Status::Success(),
241 ImportKeyJwkFromDict(
242 *key_jwk
, CreateRsaHashedImportAlgorithm(
243 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
244 blink::WebCryptoAlgorithmIdSha256
),
245 true, blink::WebCryptoKeyUsageSign
, &private_key
));
247 live_keys
.push_back(private_key
);
252 private_key
.algorithm().rsaHashedParams()->modulusLengthBits()));
254 // Export to PKCS8 and verify that it matches expectation.
255 std::vector
<uint8_t> exported_key_pkcs8
;
256 ASSERT_EQ(Status::Success(), ExportKey(blink::WebCryptoKeyFormatPkcs8
,
257 private_key
, &exported_key_pkcs8
));
259 EXPECT_BYTES_EQ(pkcs8_bytes
, exported_key_pkcs8
);
263 // Import an RSA private key using JWK. Next import a JWK containing the same
264 // modulus, but mismatched parameters for the rest. It should NOT be possible
265 // that the second import retrieves the first key. See http://crbug.com/378315
266 // for how that could happen.
267 TEST(WebCryptoRsaSsaTest
, ImportJwkExistingModulusAndInvalid
) {
268 if (!SupportsRsaPrivateKeyImport())
271 scoped_ptr
<base::ListValue
> key_list
;
272 ASSERT_TRUE(ReadJsonTestFileToList("rsa_private_keys.json", &key_list
));
274 // Import a 1024-bit private key.
275 base::DictionaryValue
* key1_props
;
276 ASSERT_TRUE(key_list
->GetDictionary(1, &key1_props
));
277 base::DictionaryValue
* key1_jwk
;
278 ASSERT_TRUE(key1_props
->GetDictionary("jwk", &key1_jwk
));
280 blink::WebCryptoKey key1
;
281 ASSERT_EQ(Status::Success(),
282 ImportKeyJwkFromDict(*key1_jwk
,
283 CreateRsaHashedImportAlgorithm(
284 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
285 blink::WebCryptoAlgorithmIdSha256
),
286 true, blink::WebCryptoKeyUsageSign
, &key1
));
288 ASSERT_EQ(1024u, key1
.algorithm().rsaHashedParams()->modulusLengthBits());
290 // Construct a JWK using the modulus of key1, but all the other fields from
291 // another key (also a 1024-bit private key).
292 base::DictionaryValue
* key2_props
;
293 ASSERT_TRUE(key_list
->GetDictionary(5, &key2_props
));
294 base::DictionaryValue
* key2_jwk
;
295 ASSERT_TRUE(key2_props
->GetDictionary("jwk", &key2_jwk
));
297 key1_jwk
->GetString("n", &modulus
);
298 key2_jwk
->SetString("n", modulus
);
300 // This should fail, as the n,e,d parameters are not consistent. It MUST NOT
301 // somehow return the key created earlier.
302 blink::WebCryptoKey key2
;
303 ASSERT_EQ(Status::OperationError(),
304 ImportKeyJwkFromDict(*key2_jwk
,
305 CreateRsaHashedImportAlgorithm(
306 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
307 blink::WebCryptoAlgorithmIdSha256
),
308 true, blink::WebCryptoKeyUsageSign
, &key2
));
311 TEST(WebCryptoRsaSsaTest
, GenerateKeyPairRsa
) {
312 // Note: using unrealistic short key lengths here to avoid bogging down tests.
314 // Successful WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 key generation (sha256)
315 const unsigned int modulus_length
= 256;
316 const std::vector
<uint8_t> public_exponent
= HexStringToBytes("010001");
317 blink::WebCryptoAlgorithm algorithm
= CreateRsaHashedKeyGenAlgorithm(
318 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
319 blink::WebCryptoAlgorithmIdSha256
, modulus_length
, public_exponent
);
320 bool extractable
= true;
321 const blink::WebCryptoKeyUsageMask public_usages
=
322 blink::WebCryptoKeyUsageVerify
;
323 const blink::WebCryptoKeyUsageMask private_usages
=
324 blink::WebCryptoKeyUsageSign
;
325 const blink::WebCryptoKeyUsageMask usages
= public_usages
| private_usages
;
326 blink::WebCryptoKey public_key
;
327 blink::WebCryptoKey private_key
;
329 EXPECT_EQ(Status::Success(), GenerateKeyPair(algorithm
, extractable
, usages
,
330 &public_key
, &private_key
));
331 ASSERT_FALSE(public_key
.isNull());
332 ASSERT_FALSE(private_key
.isNull());
333 EXPECT_EQ(blink::WebCryptoKeyTypePublic
, public_key
.type());
334 EXPECT_EQ(blink::WebCryptoKeyTypePrivate
, private_key
.type());
335 EXPECT_EQ(modulus_length
,
336 public_key
.algorithm().rsaHashedParams()->modulusLengthBits());
337 EXPECT_EQ(modulus_length
,
338 private_key
.algorithm().rsaHashedParams()->modulusLengthBits());
339 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256
,
340 public_key
.algorithm().rsaHashedParams()->hash().id());
341 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256
,
342 private_key
.algorithm().rsaHashedParams()->hash().id());
343 EXPECT_TRUE(public_key
.extractable());
344 EXPECT_EQ(extractable
, private_key
.extractable());
345 EXPECT_EQ(public_usages
, public_key
.usages());
346 EXPECT_EQ(private_usages
, private_key
.usages());
348 // Try exporting the generated key pair, and then re-importing to verify that
349 // the exported data was valid.
350 std::vector
<uint8_t> public_key_spki
;
351 EXPECT_EQ(Status::Success(), ExportKey(blink::WebCryptoKeyFormatSpki
,
352 public_key
, &public_key_spki
));
354 if (SupportsRsaPrivateKeyImport()) {
355 public_key
= blink::WebCryptoKey::createNull();
358 ImportKey(blink::WebCryptoKeyFormatSpki
, CryptoData(public_key_spki
),
359 CreateRsaHashedImportAlgorithm(
360 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
361 blink::WebCryptoAlgorithmIdSha256
),
362 true, public_usages
, &public_key
));
363 EXPECT_EQ(modulus_length
,
364 public_key
.algorithm().rsaHashedParams()->modulusLengthBits());
366 std::vector
<uint8_t> private_key_pkcs8
;
367 EXPECT_EQ(Status::Success(), ExportKey(blink::WebCryptoKeyFormatPkcs8
,
368 private_key
, &private_key_pkcs8
));
369 private_key
= blink::WebCryptoKey::createNull();
372 ImportKey(blink::WebCryptoKeyFormatPkcs8
, CryptoData(private_key_pkcs8
),
373 CreateRsaHashedImportAlgorithm(
374 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
375 blink::WebCryptoAlgorithmIdSha256
),
376 true, private_usages
, &private_key
));
377 EXPECT_EQ(modulus_length
,
378 private_key
.algorithm().rsaHashedParams()->modulusLengthBits());
381 // Fail with bad modulus.
382 algorithm
= CreateRsaHashedKeyGenAlgorithm(
383 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
384 blink::WebCryptoAlgorithmIdSha256
, 0, public_exponent
);
385 EXPECT_EQ(Status::ErrorGenerateRsaUnsupportedModulus(),
386 GenerateKeyPair(algorithm
, extractable
, usages
, &public_key
,
389 // Fail with bad exponent: larger than unsigned long.
390 unsigned int exponent_length
= sizeof(unsigned long) + 1; // NOLINT
391 const std::vector
<uint8_t> long_exponent(exponent_length
, 0x01);
392 algorithm
= CreateRsaHashedKeyGenAlgorithm(
393 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
394 blink::WebCryptoAlgorithmIdSha256
, modulus_length
, long_exponent
);
395 EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
396 GenerateKeyPair(algorithm
, extractable
, usages
, &public_key
,
399 // Fail with bad exponent: empty.
400 const std::vector
<uint8_t> empty_exponent
;
401 algorithm
= CreateRsaHashedKeyGenAlgorithm(
402 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
403 blink::WebCryptoAlgorithmIdSha256
, modulus_length
, empty_exponent
);
404 EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
405 GenerateKeyPair(algorithm
, extractable
, usages
, &public_key
,
408 // Fail with bad exponent: all zeros.
409 std::vector
<uint8_t> exponent_with_leading_zeros(15, 0x00);
410 algorithm
= CreateRsaHashedKeyGenAlgorithm(
411 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
412 blink::WebCryptoAlgorithmIdSha256
, modulus_length
,
413 exponent_with_leading_zeros
);
414 EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
415 GenerateKeyPair(algorithm
, extractable
, usages
, &public_key
,
418 // Key generation success using exponent with leading zeros.
419 exponent_with_leading_zeros
.insert(exponent_with_leading_zeros
.end(),
420 public_exponent
.begin(),
421 public_exponent
.end());
423 CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
424 blink::WebCryptoAlgorithmIdSha256
,
426 exponent_with_leading_zeros
);
427 EXPECT_EQ(Status::Success(), GenerateKeyPair(algorithm
, extractable
, usages
,
428 &public_key
, &private_key
));
429 EXPECT_FALSE(public_key
.isNull());
430 EXPECT_FALSE(private_key
.isNull());
431 EXPECT_EQ(blink::WebCryptoKeyTypePublic
, public_key
.type());
432 EXPECT_EQ(blink::WebCryptoKeyTypePrivate
, private_key
.type());
433 EXPECT_TRUE(public_key
.extractable());
434 EXPECT_EQ(extractable
, private_key
.extractable());
435 EXPECT_EQ(public_usages
, public_key
.usages());
436 EXPECT_EQ(private_usages
, private_key
.usages());
438 // Successful WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 key generation (sha1)
440 CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
441 blink::WebCryptoAlgorithmIdSha1
,
446 GenerateKeyPair(algorithm
, false, usages
, &public_key
, &private_key
));
447 EXPECT_FALSE(public_key
.isNull());
448 EXPECT_FALSE(private_key
.isNull());
449 EXPECT_EQ(blink::WebCryptoKeyTypePublic
, public_key
.type());
450 EXPECT_EQ(blink::WebCryptoKeyTypePrivate
, private_key
.type());
451 EXPECT_EQ(modulus_length
,
452 public_key
.algorithm().rsaHashedParams()->modulusLengthBits());
453 EXPECT_EQ(modulus_length
,
454 private_key
.algorithm().rsaHashedParams()->modulusLengthBits());
455 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1
,
456 public_key
.algorithm().rsaHashedParams()->hash().id());
457 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1
,
458 private_key
.algorithm().rsaHashedParams()->hash().id());
459 // Even though "extractable" was set to false, the public key remains
461 EXPECT_TRUE(public_key
.extractable());
462 EXPECT_FALSE(private_key
.extractable());
463 EXPECT_EQ(public_usages
, public_key
.usages());
464 EXPECT_EQ(private_usages
, private_key
.usages());
466 // Exporting a private key as SPKI format doesn't make sense. However this
467 // will first fail because the key is not extractable.
468 std::vector
<uint8_t> output
;
469 EXPECT_EQ(Status::ErrorKeyNotExtractable(),
470 ExportKey(blink::WebCryptoKeyFormatSpki
, private_key
, &output
));
472 // Re-generate an extractable private_key and try to export it as SPKI format.
473 // This should fail since spki is for public keys.
474 EXPECT_EQ(Status::Success(), GenerateKeyPair(algorithm
, true, usages
,
475 &public_key
, &private_key
));
476 EXPECT_EQ(Status::ErrorUnexpectedKeyType(),
477 ExportKey(blink::WebCryptoKeyFormatSpki
, private_key
, &output
));
480 TEST(WebCryptoRsaSsaTest
, GenerateKeyPairRsaBadModulusLength
) {
481 const unsigned int kBadModulusBits
[] = {
484 257, // Not a multiple of 8.
485 1023, // Not a multiple of 8.
486 0xFFFFFFFF, // Too big.
487 16384 + 8, // 16384 is the maxmimum length that NSS succeeds for.
490 const std::vector
<uint8_t> public_exponent
= HexStringToBytes("010001");
492 for (size_t i
= 0; i
< arraysize(kBadModulusBits
); ++i
) {
493 const unsigned int modulus_length_bits
= kBadModulusBits
[i
];
494 blink::WebCryptoAlgorithm algorithm
= CreateRsaHashedKeyGenAlgorithm(
495 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
496 blink::WebCryptoAlgorithmIdSha256
, modulus_length_bits
,
498 bool extractable
= true;
499 const blink::WebCryptoKeyUsageMask usages
= blink::WebCryptoKeyUsageSign
;
500 blink::WebCryptoKey public_key
;
501 blink::WebCryptoKey private_key
;
503 EXPECT_EQ(Status::ErrorGenerateRsaUnsupportedModulus(),
504 GenerateKeyPair(algorithm
, extractable
, usages
, &public_key
,
509 // Try generating RSA key pairs using unsupported public exponents. Only
510 // exponents of 3 and 65537 are supported. While both OpenSSL and NSS can
511 // support other values, OpenSSL hangs when given invalid exponents, so use a
512 // whitelist to validate the parameters.
513 TEST(WebCryptoRsaSsaTest
, GenerateKeyPairRsaBadExponent
) {
514 const unsigned int modulus_length
= 1024;
516 const char* const kPublicExponents
[] = {
517 "11", // 17 - This is a valid public exponent, but currently disallowed.
524 for (size_t i
= 0; i
< arraysize(kPublicExponents
); ++i
) {
526 blink::WebCryptoAlgorithm algorithm
= CreateRsaHashedKeyGenAlgorithm(
527 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
528 blink::WebCryptoAlgorithmIdSha256
, modulus_length
,
529 HexStringToBytes(kPublicExponents
[i
]));
531 blink::WebCryptoKey public_key
;
532 blink::WebCryptoKey private_key
;
534 EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
535 GenerateKeyPair(algorithm
, true, blink::WebCryptoKeyUsageSign
,
536 &public_key
, &private_key
));
540 TEST(WebCryptoRsaSsaTest
, SignVerifyFailures
) {
541 if (!SupportsRsaPrivateKeyImport())
544 // Import a key pair.
545 blink::WebCryptoAlgorithm import_algorithm
=
546 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
547 blink::WebCryptoAlgorithmIdSha1
);
548 blink::WebCryptoKey public_key
;
549 blink::WebCryptoKey private_key
;
550 ASSERT_NO_FATAL_FAILURE(ImportRsaKeyPair(
551 HexStringToBytes(kPublicKeySpkiDerHex
),
552 HexStringToBytes(kPrivateKeyPkcs8DerHex
), import_algorithm
, false,
553 blink::WebCryptoKeyUsageVerify
, blink::WebCryptoKeyUsageSign
, &public_key
,
556 blink::WebCryptoAlgorithm algorithm
=
557 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
);
559 std::vector
<uint8_t> signature
;
560 bool signature_match
;
562 // Compute a signature.
563 const std::vector
<uint8_t> data
= HexStringToBytes("010203040506070809");
564 ASSERT_EQ(Status::Success(),
565 Sign(algorithm
, private_key
, CryptoData(data
), &signature
));
567 // Ensure truncated signature does not verify by passing one less byte.
568 EXPECT_EQ(Status::Success(), Verify(algorithm
, public_key
,
569 CryptoData(vector_as_array(&signature
),
570 signature
.size() - 1),
571 CryptoData(data
), &signature_match
));
572 EXPECT_FALSE(signature_match
);
574 // Ensure truncated signature does not verify by passing no bytes.
575 EXPECT_EQ(Status::Success(), Verify(algorithm
, public_key
, CryptoData(),
576 CryptoData(data
), &signature_match
));
577 EXPECT_FALSE(signature_match
);
579 // Ensure corrupted signature does not verify.
580 std::vector
<uint8_t> corrupt_sig
= signature
;
581 corrupt_sig
[corrupt_sig
.size() / 2] ^= 0x1;
582 EXPECT_EQ(Status::Success(),
583 Verify(algorithm
, public_key
, CryptoData(corrupt_sig
),
584 CryptoData(data
), &signature_match
));
585 EXPECT_FALSE(signature_match
);
587 // Ensure signatures that are greater than the modulus size fail.
588 const unsigned int long_message_size_bytes
= 1024;
589 DCHECK_GT(long_message_size_bytes
, kModulusLengthBits
/ 8);
590 const unsigned char kLongSignature
[long_message_size_bytes
] = {0};
591 EXPECT_EQ(Status::Success(),
592 Verify(algorithm
, public_key
,
593 CryptoData(kLongSignature
, sizeof(kLongSignature
)),
594 CryptoData(data
), &signature_match
));
595 EXPECT_FALSE(signature_match
);
597 // Ensure that signing and verifying with an incompatible algorithm fails.
598 algorithm
= CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaOaep
);
600 EXPECT_EQ(Status::ErrorUnexpected(),
601 Sign(algorithm
, private_key
, CryptoData(data
), &signature
));
602 EXPECT_EQ(Status::ErrorUnexpected(),
603 Verify(algorithm
, public_key
, CryptoData(signature
),
604 CryptoData(data
), &signature_match
));
606 // Some crypto libraries (NSS) can automatically select the RSA SSA inner hash
607 // based solely on the contents of the input signature data. In the Web Crypto
608 // implementation, the inner hash should be specified uniquely by the key
609 // algorithm parameter. To validate this behavior, call Verify with a computed
610 // signature that used one hash type (SHA-1), but pass in a key with a
611 // different inner hash type (SHA-256). If the hash type is determined by the
612 // signature itself (undesired), the verify will pass, while if the hash type
613 // is specified by the key algorithm (desired), the verify will fail.
615 // Compute a signature using SHA-1 as the inner hash.
616 EXPECT_EQ(Status::Success(),
617 Sign(CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
),
618 private_key
, CryptoData(data
), &signature
));
620 blink::WebCryptoKey public_key_256
;
621 EXPECT_EQ(Status::Success(),
622 ImportKey(blink::WebCryptoKeyFormatSpki
,
623 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex
)),
624 CreateRsaHashedImportAlgorithm(
625 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
626 blink::WebCryptoAlgorithmIdSha256
),
627 true, blink::WebCryptoKeyUsageVerify
, &public_key_256
));
629 // Now verify using an algorithm whose inner hash is SHA-256, not SHA-1. The
630 // signature should not verify.
631 // NOTE: public_key was produced by generateKey, and so its associated
632 // algorithm has WebCryptoRsaKeyGenParams and not WebCryptoRsaSsaParams. Thus
633 // it has no inner hash to conflict with the input algorithm.
634 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1
,
635 private_key
.algorithm().rsaHashedParams()->hash().id());
636 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256
,
637 public_key_256
.algorithm().rsaHashedParams()->hash().id());
640 EXPECT_EQ(Status::Success(),
641 Verify(CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
),
642 public_key_256
, CryptoData(signature
), CryptoData(data
),
644 EXPECT_FALSE(is_match
);
647 TEST(WebCryptoRsaSsaTest
, SignVerifyKnownAnswer
) {
648 if (!SupportsRsaPrivateKeyImport())
651 scoped_ptr
<base::ListValue
> tests
;
652 ASSERT_TRUE(ReadJsonTestFileToList("pkcs1v15_sign.json", &tests
));
654 // Import the key pair.
655 blink::WebCryptoAlgorithm import_algorithm
=
656 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
657 blink::WebCryptoAlgorithmIdSha1
);
658 blink::WebCryptoKey public_key
;
659 blink::WebCryptoKey private_key
;
660 ASSERT_NO_FATAL_FAILURE(ImportRsaKeyPair(
661 HexStringToBytes(kPublicKeySpkiDerHex
),
662 HexStringToBytes(kPrivateKeyPkcs8DerHex
), import_algorithm
, false,
663 blink::WebCryptoKeyUsageVerify
, blink::WebCryptoKeyUsageSign
, &public_key
,
666 blink::WebCryptoAlgorithm algorithm
=
667 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
);
669 // Validate the signatures are computed and verified as expected.
670 std::vector
<uint8_t> signature
;
671 for (size_t test_index
= 0; test_index
< tests
->GetSize(); ++test_index
) {
672 SCOPED_TRACE(test_index
);
674 base::DictionaryValue
* test
;
675 ASSERT_TRUE(tests
->GetDictionary(test_index
, &test
));
677 std::vector
<uint8_t> test_message
=
678 GetBytesFromHexString(test
, "message_hex");
679 std::vector
<uint8_t> test_signature
=
680 GetBytesFromHexString(test
, "signature_hex");
683 ASSERT_EQ(Status::Success(), Sign(algorithm
, private_key
,
684 CryptoData(test_message
), &signature
));
685 EXPECT_BYTES_EQ(test_signature
, signature
);
687 bool is_match
= false;
688 ASSERT_EQ(Status::Success(),
689 Verify(algorithm
, public_key
, CryptoData(test_signature
),
690 CryptoData(test_message
), &is_match
));
691 EXPECT_TRUE(is_match
);
695 // Try importing an RSA-SSA public key with unsupported key usages using SPKI
696 // format. RSA-SSA public keys only support the 'verify' usage.
697 TEST(WebCryptoRsaSsaTest
, ImportRsaSsaPublicKeyBadUsage_SPKI
) {
698 const blink::WebCryptoAlgorithm algorithm
=
699 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
700 blink::WebCryptoAlgorithmIdSha256
);
702 blink::WebCryptoKeyUsageMask bad_usages
[] = {
703 blink::WebCryptoKeyUsageSign
,
704 blink::WebCryptoKeyUsageSign
| blink::WebCryptoKeyUsageVerify
,
705 blink::WebCryptoKeyUsageEncrypt
,
706 blink::WebCryptoKeyUsageEncrypt
| blink::WebCryptoKeyUsageDecrypt
,
709 for (size_t i
= 0; i
< arraysize(bad_usages
); ++i
) {
712 blink::WebCryptoKey public_key
;
713 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
714 ImportKey(blink::WebCryptoKeyFormatSpki
,
715 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex
)),
716 algorithm
, false, bad_usages
[i
], &public_key
));
720 // Try importing an RSA-SSA public key with unsupported key usages using JWK
721 // format. RSA-SSA public keys only support the 'verify' usage.
722 TEST(WebCryptoRsaSsaTest
, ImportRsaSsaPublicKeyBadUsage_JWK
) {
723 const blink::WebCryptoAlgorithm algorithm
=
724 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
725 blink::WebCryptoAlgorithmIdSha256
);
727 blink::WebCryptoKeyUsageMask bad_usages
[] = {
728 blink::WebCryptoKeyUsageSign
,
729 blink::WebCryptoKeyUsageSign
| blink::WebCryptoKeyUsageVerify
,
730 blink::WebCryptoKeyUsageEncrypt
,
731 blink::WebCryptoKeyUsageEncrypt
| blink::WebCryptoKeyUsageDecrypt
,
734 base::DictionaryValue dict
;
735 RestoreJwkRsaDictionary(&dict
);
736 dict
.Remove("use", NULL
);
737 dict
.SetString("alg", "RS256");
739 for (size_t i
= 0; i
< arraysize(bad_usages
); ++i
) {
742 blink::WebCryptoKey public_key
;
743 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
744 ImportKeyJwkFromDict(dict
, algorithm
, false, bad_usages
[i
],
749 // Generate an RSA-SSA key pair with invalid usages. RSA-SSA supports:
751 TEST(WebCryptoRsaSsaTest
, GenerateKeyBadUsages
) {
752 blink::WebCryptoKeyUsageMask bad_usages
[] = {
753 blink::WebCryptoKeyUsageDecrypt
,
754 blink::WebCryptoKeyUsageVerify
| blink::WebCryptoKeyUsageDecrypt
,
755 blink::WebCryptoKeyUsageWrapKey
,
758 const unsigned int modulus_length
= 256;
759 const std::vector
<uint8_t> public_exponent
= HexStringToBytes("010001");
761 for (size_t i
= 0; i
< arraysize(bad_usages
); ++i
) {
764 blink::WebCryptoKey public_key
;
765 blink::WebCryptoKey private_key
;
767 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
768 GenerateKeyPair(CreateRsaHashedKeyGenAlgorithm(
769 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
770 blink::WebCryptoAlgorithmIdSha256
,
771 modulus_length
, public_exponent
),
772 true, bad_usages
[i
], &public_key
, &private_key
));
776 // Generate an RSA-SSA key pair. The public and private keys should select the
777 // key usages which are applicable, and not have the exact same usages as was
778 // specified to GenerateKey
779 TEST(WebCryptoRsaSsaTest
, GenerateKeyPairIntersectUsages
) {
780 const unsigned int modulus_length
= 256;
781 const std::vector
<uint8_t> public_exponent
= HexStringToBytes("010001");
783 blink::WebCryptoKey public_key
;
784 blink::WebCryptoKey private_key
;
786 ASSERT_EQ(Status::Success(),
787 GenerateKeyPair(CreateRsaHashedKeyGenAlgorithm(
788 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
789 blink::WebCryptoAlgorithmIdSha256
,
790 modulus_length
, public_exponent
),
791 true, blink::WebCryptoKeyUsageSign
|
792 blink::WebCryptoKeyUsageVerify
,
793 &public_key
, &private_key
));
795 EXPECT_EQ(blink::WebCryptoKeyUsageVerify
, public_key
.usages());
796 EXPECT_EQ(blink::WebCryptoKeyUsageSign
, private_key
.usages());
798 // Try again but this time without the Verify usages.
799 ASSERT_EQ(Status::Success(),
800 GenerateKeyPair(CreateRsaHashedKeyGenAlgorithm(
801 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
802 blink::WebCryptoAlgorithmIdSha256
,
803 modulus_length
, public_exponent
),
804 true, blink::WebCryptoKeyUsageSign
, &public_key
,
807 EXPECT_EQ(0, public_key
.usages());
808 EXPECT_EQ(blink::WebCryptoKeyUsageSign
, private_key
.usages());
811 TEST(WebCryptoRsaSsaTest
, GenerateKeyPairEmptyUsages
) {
812 const unsigned int modulus_length
= 256;
813 const std::vector
<uint8_t> public_exponent
= HexStringToBytes("010001");
815 blink::WebCryptoKey public_key
;
816 blink::WebCryptoKey private_key
;
818 ASSERT_EQ(Status::ErrorCreateKeyEmptyUsages(),
819 GenerateKeyPair(CreateRsaHashedKeyGenAlgorithm(
820 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
821 blink::WebCryptoAlgorithmIdSha256
,
822 modulus_length
, public_exponent
),
823 true, 0, &public_key
, &private_key
));
826 TEST(WebCryptoRsaSsaTest
, ImportKeyEmptyUsages
) {
827 if (!SupportsRsaPrivateKeyImport())
830 blink::WebCryptoKey public_key
;
831 blink::WebCryptoKey private_key
;
833 // Public without usage does not throw an error.
834 ASSERT_EQ(Status::Success(),
835 ImportKey(blink::WebCryptoKeyFormatSpki
,
836 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex
)),
837 CreateRsaHashedImportAlgorithm(
838 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
839 blink::WebCryptoAlgorithmIdSha256
),
840 true, 0, &public_key
));
841 EXPECT_EQ(0, public_key
.usages());
843 // Private empty usage will throw an error.
844 ASSERT_EQ(Status::ErrorCreateKeyEmptyUsages(),
845 ImportKey(blink::WebCryptoKeyFormatPkcs8
,
846 CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex
)),
847 CreateRsaHashedImportAlgorithm(
848 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
849 blink::WebCryptoAlgorithmIdSha1
),
850 true, 0, &private_key
));
852 std::vector
<uint8_t> public_jwk
;
853 ASSERT_EQ(Status::Success(),
854 ExportKey(blink::WebCryptoKeyFormatJwk
, public_key
, &public_jwk
));
856 ASSERT_EQ(Status::Success(),
857 ImportKey(blink::WebCryptoKeyFormatJwk
,
858 CryptoData(public_jwk
),
859 CreateRsaHashedImportAlgorithm(
860 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
861 blink::WebCryptoAlgorithmIdSha256
),
862 true, 0, &public_key
));
863 EXPECT_EQ(0, public_key
.usages());
865 // With correct usage to get correct imported private_key
866 std::vector
<uint8_t> private_jwk
;
867 ImportKey(blink::WebCryptoKeyFormatPkcs8
,
868 CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex
)),
869 CreateRsaHashedImportAlgorithm(
870 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
871 blink::WebCryptoAlgorithmIdSha1
),
872 true, blink::WebCryptoKeyUsageSign
, &private_key
);
874 ASSERT_EQ(Status::Success(),
875 ExportKey(blink::WebCryptoKeyFormatJwk
, private_key
, &private_jwk
));
877 ASSERT_EQ(Status::ErrorCreateKeyEmptyUsages(),
878 ImportKey(blink::WebCryptoKeyFormatJwk
,
879 CryptoData(private_jwk
),
880 CreateRsaHashedImportAlgorithm(
881 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
882 blink::WebCryptoAlgorithmIdSha1
),
883 true, 0, &private_key
));
886 TEST(WebCryptoRsaSsaTest
, ImportExportJwkRsaPublicKey
) {
888 const blink::WebCryptoAlgorithmId hash
;
889 const blink::WebCryptoKeyUsageMask usage
;
890 const char* const jwk_alg
;
892 const TestCase kTests
[] = {
893 {blink::WebCryptoAlgorithmIdSha1
, blink::WebCryptoKeyUsageVerify
, "RS1"},
894 {blink::WebCryptoAlgorithmIdSha256
,
895 blink::WebCryptoKeyUsageVerify
,
897 {blink::WebCryptoAlgorithmIdSha384
,
898 blink::WebCryptoKeyUsageVerify
,
900 {blink::WebCryptoAlgorithmIdSha512
,
901 blink::WebCryptoKeyUsageVerify
,
904 for (size_t test_index
= 0; test_index
< arraysize(kTests
); ++test_index
) {
905 SCOPED_TRACE(test_index
);
906 const TestCase
& test
= kTests
[test_index
];
908 const blink::WebCryptoAlgorithm import_algorithm
=
909 CreateRsaHashedImportAlgorithm(
910 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
, test
.hash
);
912 // Import the spki to create a public key
913 blink::WebCryptoKey public_key
;
914 ASSERT_EQ(Status::Success(),
915 ImportKey(blink::WebCryptoKeyFormatSpki
,
916 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex
)),
917 import_algorithm
, true, test
.usage
, &public_key
));
919 // Export the public key as JWK and verify its contents
920 std::vector
<uint8_t> jwk
;
921 ASSERT_EQ(Status::Success(),
922 ExportKey(blink::WebCryptoKeyFormatJwk
, public_key
, &jwk
));
923 EXPECT_TRUE(VerifyPublicJwk(jwk
, test
.jwk_alg
, kPublicKeyModulusHex
,
924 kPublicKeyExponentHex
, test
.usage
));
926 // Import the JWK back in to create a new key
927 blink::WebCryptoKey public_key2
;
928 ASSERT_EQ(Status::Success(),
929 ImportKey(blink::WebCryptoKeyFormatJwk
, CryptoData(jwk
),
930 import_algorithm
, true, test
.usage
, &public_key2
));
931 ASSERT_TRUE(public_key2
.handle());
932 EXPECT_EQ(blink::WebCryptoKeyTypePublic
, public_key2
.type());
933 EXPECT_TRUE(public_key2
.extractable());
934 EXPECT_EQ(import_algorithm
.id(), public_key2
.algorithm().id());
936 // Export the new key as spki and compare to the original.
937 std::vector
<uint8_t> spki
;
938 ASSERT_EQ(Status::Success(),
939 ExportKey(blink::WebCryptoKeyFormatSpki
, public_key2
, &spki
));
940 EXPECT_BYTES_EQ_HEX(kPublicKeySpkiDerHex
, CryptoData(spki
));
944 TEST(WebCryptoRsaSsaTest
, ImportJwkRsaFailures
) {
945 base::DictionaryValue dict
;
946 RestoreJwkRsaDictionary(&dict
);
947 blink::WebCryptoAlgorithm algorithm
=
948 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
949 blink::WebCryptoAlgorithmIdSha256
);
950 blink::WebCryptoKeyUsageMask usages
= blink::WebCryptoKeyUsageVerify
;
951 blink::WebCryptoKey key
;
953 // An RSA public key JWK _must_ have an "n" (modulus) and an "e" (exponent)
954 // entry, while an RSA private key must have those plus at least a "d"
955 // (private exponent) entry.
956 // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18,
960 EXPECT_EQ(Status::Success(),
961 ImportKeyJwkFromDict(dict
, algorithm
, false, usages
, &key
));
962 EXPECT_EQ(algorithm
.id(), key
.algorithm().id());
963 EXPECT_FALSE(key
.extractable());
964 EXPECT_EQ(blink::WebCryptoKeyUsageVerify
, key
.usages());
965 EXPECT_EQ(blink::WebCryptoKeyTypePublic
, key
.type());
967 // The following are specific failure cases for when kty = "RSA".
969 // Fail if either "n" or "e" is not present or malformed.
970 const std::string kKtyParmName
[] = {"n", "e"};
971 for (size_t idx
= 0; idx
< arraysize(kKtyParmName
); ++idx
) {
972 // Fail on missing parameter.
973 dict
.Remove(kKtyParmName
[idx
], NULL
);
974 EXPECT_NE(Status::Success(),
975 ImportKeyJwkFromDict(dict
, algorithm
, false, usages
, &key
));
976 RestoreJwkRsaDictionary(&dict
);
978 // Fail on bad b64 parameter encoding.
979 dict
.SetString(kKtyParmName
[idx
], "Qk3f0DsytU8lfza2au #$% Htaw2xpop9yTuH0");
980 EXPECT_NE(Status::Success(),
981 ImportKeyJwkFromDict(dict
, algorithm
, false, usages
, &key
));
982 RestoreJwkRsaDictionary(&dict
);
984 // Fail on empty parameter.
985 dict
.SetString(kKtyParmName
[idx
], "");
986 EXPECT_EQ(Status::ErrorJwkEmptyBigInteger(kKtyParmName
[idx
]),
987 ImportKeyJwkFromDict(dict
, algorithm
, false, usages
, &key
));
988 RestoreJwkRsaDictionary(&dict
);
992 // Try importing an RSA-SSA key from JWK format, having specified both Sign and
993 // Verify usage, and an invalid JWK.
995 // The test must fail with a usage error BEFORE attempting to read the JWK data.
996 // Although both Sign and Verify are valid usages for RSA-SSA keys, it is
997 // invalid to have them both at the same time for one key (since Sign applies to
998 // private keys, whereas Verify applies to public keys).
1000 // If the implementation does not fail fast, this test will crash dereferencing
1002 TEST(WebCryptoRsaSsaTest
, ImportRsaSsaJwkBadUsageFailFast
) {
1003 CryptoData
bad_data(NULL
, 128); // Invalid buffer of length 128.
1005 blink::WebCryptoKey key
;
1006 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
1007 ImportKey(blink::WebCryptoKeyFormatJwk
, bad_data
,
1008 CreateRsaHashedImportAlgorithm(
1009 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
1010 blink::WebCryptoAlgorithmIdSha256
),
1011 true, blink::WebCryptoKeyUsageVerify
|
1012 blink::WebCryptoKeyUsageSign
,
1016 // Imports invalid JWK/SPKI/PKCS8 data and verifies that it fails as expected.
1017 TEST(WebCryptoRsaSsaTest
, ImportInvalidKeyData
) {
1018 if (!SupportsRsaPrivateKeyImport())
1021 scoped_ptr
<base::ListValue
> tests
;
1022 ASSERT_TRUE(ReadJsonTestFileToList("bad_rsa_keys.json", &tests
));
1024 for (size_t test_index
= 0; test_index
< tests
->GetSize(); ++test_index
) {
1025 SCOPED_TRACE(test_index
);
1027 const base::DictionaryValue
* test
;
1028 ASSERT_TRUE(tests
->GetDictionary(test_index
, &test
));
1030 blink::WebCryptoKeyFormat key_format
= GetKeyFormatFromJsonTestCase(test
);
1031 std::vector
<uint8_t> key_data
=
1032 GetKeyDataFromJsonTestCase(test
, key_format
);
1033 std::string test_error
;
1034 ASSERT_TRUE(test
->GetString("error", &test_error
));
1036 blink::WebCryptoKeyUsageMask usages
= blink::WebCryptoKeyUsageSign
;
1037 if (key_format
== blink::WebCryptoKeyFormatSpki
)
1038 usages
= blink::WebCryptoKeyUsageVerify
;
1039 blink::WebCryptoKey key
;
1040 Status status
= ImportKey(key_format
, CryptoData(key_data
),
1041 CreateRsaHashedImportAlgorithm(
1042 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
1043 blink::WebCryptoAlgorithmIdSha256
),
1044 true, usages
, &key
);
1045 EXPECT_EQ(test_error
, StatusToString(status
));
1051 } // namespace webcrypto
1053 } // namespace content