Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / components / webcrypto / algorithms / rsa_ssa_unittest.cc
blob60caa508ef7cfd0bbf142b439ca721e0e80c08c0
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/algorithms/test_helpers.h"
9 #include "components/webcrypto/crypto_data.h"
10 #include "components/webcrypto/status.h"
11 #include "components/webcrypto/webcrypto_util.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
14 #include "third_party/WebKit/public/platform/WebCryptoKey.h"
15 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
17 namespace webcrypto {
19 namespace {
21 // Helper for ImportJwkRsaFailures. Restores the JWK JSON
22 // dictionary to a good state
23 void RestoreJwkRsaDictionary(base::DictionaryValue* dict) {
24 dict->Clear();
25 dict->SetString("kty", "RSA");
26 dict->SetString("alg", "RS256");
27 dict->SetString("use", "sig");
28 dict->SetBoolean("ext", false);
29 dict->SetString(
30 "n",
31 "qLOyhK-OtQs4cDSoYPFGxJGfMYdjzWxVmMiuSBGh4KvEx-CwgtaTpef87Wdc9GaFEncsDLxk"
32 "p0LGxjD1M8jMcvYq6DPEC_JYQumEu3i9v5fAEH1VvbZi9cTg-rmEXLUUjvc5LdOq_5OuHmtm"
33 "e7PUJHYW1PW6ENTP0ibeiNOfFvs");
34 dict->SetString("e", "AQAB");
37 class WebCryptoRsaSsaTest : public WebCryptoTestBase {};
39 TEST_F(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());
55 EXPECT_BYTES_EQ_HEX(
56 "010001",
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
96 // as OAEP/PSS
99 TEST_F(WebCryptoRsaSsaTest, ImportExportPkcs8) {
100 // Passing case: Import a valid RSA key in PKCS#8 format.
101 blink::WebCryptoKey key;
102 ASSERT_EQ(Status::Success(),
103 ImportKey(blink::WebCryptoKeyFormatPkcs8,
104 CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
105 CreateRsaHashedImportAlgorithm(
106 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
107 blink::WebCryptoAlgorithmIdSha1),
108 true, blink::WebCryptoKeyUsageSign, &key));
109 EXPECT_TRUE(key.handle());
110 EXPECT_EQ(blink::WebCryptoKeyTypePrivate, key.type());
111 EXPECT_TRUE(key.extractable());
112 EXPECT_EQ(blink::WebCryptoKeyUsageSign, key.usages());
113 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1,
114 key.algorithm().rsaHashedParams()->hash().id());
115 EXPECT_EQ(kModulusLengthBits,
116 key.algorithm().rsaHashedParams()->modulusLengthBits());
117 EXPECT_BYTES_EQ_HEX(
118 "010001",
119 CryptoData(key.algorithm().rsaHashedParams()->publicExponent()));
121 std::vector<uint8_t> exported_key;
122 ASSERT_EQ(Status::Success(),
123 ExportKey(blink::WebCryptoKeyFormatPkcs8, key, &exported_key));
124 EXPECT_BYTES_EQ_HEX(kPrivateKeyPkcs8DerHex, exported_key);
126 // Failing case: Import RSA key but provide an inconsistent input algorithm
127 // and usage. Several issues here:
128 // * AES-CBC doesn't support PKCS8 key format
129 // * AES-CBC doesn't support "sign" usage
130 EXPECT_EQ(Status::ErrorUnsupportedImportKeyFormat(),
131 ImportKey(blink::WebCryptoKeyFormatPkcs8,
132 CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
133 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), true,
134 blink::WebCryptoKeyUsageSign, &key));
137 // Tests JWK import and export by doing a roundtrip key conversion and ensuring
138 // it was lossless:
140 // PKCS8 --> JWK --> PKCS8
141 TEST_F(WebCryptoRsaSsaTest, ImportRsaPrivateKeyJwkToPkcs8RoundTrip) {
142 blink::WebCryptoKey key;
143 ASSERT_EQ(Status::Success(),
144 ImportKey(blink::WebCryptoKeyFormatPkcs8,
145 CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
146 CreateRsaHashedImportAlgorithm(
147 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
148 blink::WebCryptoAlgorithmIdSha1),
149 true, blink::WebCryptoKeyUsageSign, &key));
151 std::vector<uint8_t> exported_key_jwk;
152 ASSERT_EQ(Status::Success(),
153 ExportKey(blink::WebCryptoKeyFormatJwk, key, &exported_key_jwk));
155 // All of the optional parameters (p, q, dp, dq, qi) should be present in the
156 // output.
157 const char* expected_jwk =
158 "{\"alg\":\"RS1\",\"d\":\"M6UEKpCyfU9UUcqbu9C0R3GhAa-IQ0Cu-YhfKku-"
159 "kuiUpySsPFaMj5eFOtB8AmbIxqPKCSnx6PESMYhEKfxNmuVf7olqEM5wfD7X5zTkRyejlXRQ"
160 "GlMmgxCcKrrKuig8MbS9L1PD7jfjUs7jT55QO9gMBiKtecbc7og1R8ajsyU\",\"dp\":"
161 "\"KPoTk4ZVvh-"
162 "KFZy6ylpy6hkMMAieGc0nSlVvNsT24Z9VSzTAd3kEJ7vdjdPt4kSDKPOF2Bsw6OQ7L_-"
163 "gJ4YZeQ\",\"dq\":\"Gos485j6cSBJiY1_t57gp3ZoeRKZzfoJ78DlB6yyHtdDAe9b_Ui-"
164 "RV6utuFnglWCdYCo5OjhQVHRUQqCo_LnKQ\",\"e\":\"AQAB\",\"ext\":true,\"key_"
165 "ops\":[\"sign\"],\"kty\":\"RSA\",\"n\":"
166 "\"pW5KDnAQF1iaUYfcfqhB0Vby7A42rVKkTf6x5h962ZHYxRBW_-2xYrTA8oOhKoijlN_"
167 "1JqtykcuzB86r_OCx39XNlQgJbVsri2311nHvY3fAkhyyPCcKcOJZjm_4nRnxBazC0_"
168 "DLNfKSgOE4a29kxO8i4eHyDQzoz_siSb2aITc\",\"p\":\"5-"
169 "iUJyCod1Fyc6NWBT6iobwMlKpy1VxuhilrLfyWeUjApyy8zKfqyzVwbgmh31WhU1vZs8w0Fg"
170 "s7bc0-2o5kQw\",\"q\":\"tp3KHPfU1-yB51uQ_MqHSrzeEj_"
171 "ScAGAqpBHm25I3o1n7ST58Z2FuidYdPVCzSDccj5pYzZKH5QlRSsmmmeZ_Q\",\"qi\":"
172 "\"JxVqukEm0kqB86Uoy_sn9WiG-"
173 "ECp9uhuF6RLlP6TGVhLjiL93h5aLjvYqluo2FhBlOshkKz4MrhH8To9JKefTQ\"}";
175 ASSERT_EQ(CryptoData(std::string(expected_jwk)),
176 CryptoData(exported_key_jwk));
178 ASSERT_EQ(
179 Status::Success(),
180 ImportKey(blink::WebCryptoKeyFormatJwk, CryptoData(exported_key_jwk),
181 CreateRsaHashedImportAlgorithm(
182 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
183 blink::WebCryptoAlgorithmIdSha1),
184 true, blink::WebCryptoKeyUsageSign, &key));
186 std::vector<uint8_t> exported_key_pkcs8;
187 ASSERT_EQ(Status::Success(), ExportKey(blink::WebCryptoKeyFormatPkcs8, key,
188 &exported_key_pkcs8));
190 ASSERT_EQ(CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
191 CryptoData(exported_key_pkcs8));
194 // Tests importing multiple RSA private keys from JWK, and then exporting to
195 // PKCS8.
197 // This is a regression test for http://crbug.com/378315, for which importing
198 // a sequence of keys from JWK could yield the wrong key. The first key would
199 // be imported correctly, however every key after that would actually import
200 // the first key.
201 TEST_F(WebCryptoRsaSsaTest, ImportMultipleRSAPrivateKeysJwk) {
202 scoped_ptr<base::ListValue> key_list;
203 ASSERT_TRUE(ReadJsonTestFileToList("rsa_private_keys.json", &key_list));
205 // For this test to be meaningful the keys MUST be kept alive before importing
206 // new keys.
207 std::vector<blink::WebCryptoKey> live_keys;
209 for (size_t key_index = 0; key_index < key_list->GetSize(); ++key_index) {
210 SCOPED_TRACE(key_index);
212 base::DictionaryValue* key_values;
213 ASSERT_TRUE(key_list->GetDictionary(key_index, &key_values));
215 // Get the JWK representation of the key.
216 base::DictionaryValue* key_jwk;
217 ASSERT_TRUE(key_values->GetDictionary("jwk", &key_jwk));
219 // Get the PKCS8 representation of the key.
220 std::string pkcs8_hex_string;
221 ASSERT_TRUE(key_values->GetString("pkcs8", &pkcs8_hex_string));
222 std::vector<uint8_t> pkcs8_bytes = HexStringToBytes(pkcs8_hex_string);
224 // Get the modulus length for the key.
225 int modulus_length_bits = 0;
226 ASSERT_TRUE(key_values->GetInteger("modulusLength", &modulus_length_bits));
228 blink::WebCryptoKey private_key;
230 // Import the key from JWK.
231 ASSERT_EQ(Status::Success(),
232 ImportKeyJwkFromDict(
233 *key_jwk, CreateRsaHashedImportAlgorithm(
234 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
235 blink::WebCryptoAlgorithmIdSha256),
236 true, blink::WebCryptoKeyUsageSign, &private_key));
238 live_keys.push_back(private_key);
240 EXPECT_EQ(
241 modulus_length_bits,
242 static_cast<int>(
243 private_key.algorithm().rsaHashedParams()->modulusLengthBits()));
245 // Export to PKCS8 and verify that it matches expectation.
246 std::vector<uint8_t> exported_key_pkcs8;
247 ASSERT_EQ(Status::Success(), ExportKey(blink::WebCryptoKeyFormatPkcs8,
248 private_key, &exported_key_pkcs8));
250 EXPECT_BYTES_EQ(pkcs8_bytes, exported_key_pkcs8);
254 // Import an RSA private key using JWK. Next import a JWK containing the same
255 // modulus, but mismatched parameters for the rest. It should NOT be possible
256 // that the second import retrieves the first key. See http://crbug.com/378315
257 // for how that could happen.
258 TEST_F(WebCryptoRsaSsaTest, ImportJwkExistingModulusAndInvalid) {
259 scoped_ptr<base::ListValue> key_list;
260 ASSERT_TRUE(ReadJsonTestFileToList("rsa_private_keys.json", &key_list));
262 // Import a 1024-bit private key.
263 base::DictionaryValue* key1_props;
264 ASSERT_TRUE(key_list->GetDictionary(1, &key1_props));
265 base::DictionaryValue* key1_jwk;
266 ASSERT_TRUE(key1_props->GetDictionary("jwk", &key1_jwk));
268 blink::WebCryptoKey key1;
269 ASSERT_EQ(Status::Success(),
270 ImportKeyJwkFromDict(*key1_jwk,
271 CreateRsaHashedImportAlgorithm(
272 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
273 blink::WebCryptoAlgorithmIdSha256),
274 true, blink::WebCryptoKeyUsageSign, &key1));
276 ASSERT_EQ(1024u, key1.algorithm().rsaHashedParams()->modulusLengthBits());
278 // Construct a JWK using the modulus of key1, but all the other fields from
279 // another key (also a 1024-bit private key).
280 base::DictionaryValue* key2_props;
281 ASSERT_TRUE(key_list->GetDictionary(5, &key2_props));
282 base::DictionaryValue* key2_jwk;
283 ASSERT_TRUE(key2_props->GetDictionary("jwk", &key2_jwk));
284 std::string modulus;
285 key1_jwk->GetString("n", &modulus);
286 key2_jwk->SetString("n", modulus);
288 // This should fail, as the n,e,d parameters are not consistent. It MUST NOT
289 // somehow return the key created earlier.
290 blink::WebCryptoKey key2;
291 ASSERT_EQ(Status::OperationError(),
292 ImportKeyJwkFromDict(*key2_jwk,
293 CreateRsaHashedImportAlgorithm(
294 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
295 blink::WebCryptoAlgorithmIdSha256),
296 true, blink::WebCryptoKeyUsageSign, &key2));
299 TEST_F(WebCryptoRsaSsaTest, GenerateKeyPairRsa) {
300 // Note: using unrealistic short key lengths here to avoid bogging down tests.
302 // Successful WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 key generation (sha256)
303 const unsigned int modulus_length = 256;
304 const std::vector<uint8_t> public_exponent = HexStringToBytes("010001");
305 blink::WebCryptoAlgorithm algorithm = CreateRsaHashedKeyGenAlgorithm(
306 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
307 blink::WebCryptoAlgorithmIdSha256, modulus_length, public_exponent);
308 bool extractable = true;
309 const blink::WebCryptoKeyUsageMask public_usages =
310 blink::WebCryptoKeyUsageVerify;
311 const blink::WebCryptoKeyUsageMask private_usages =
312 blink::WebCryptoKeyUsageSign;
313 const blink::WebCryptoKeyUsageMask usages = public_usages | private_usages;
314 blink::WebCryptoKey public_key;
315 blink::WebCryptoKey private_key;
317 EXPECT_EQ(Status::Success(), GenerateKeyPair(algorithm, extractable, usages,
318 &public_key, &private_key));
319 ASSERT_FALSE(public_key.isNull());
320 ASSERT_FALSE(private_key.isNull());
321 EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type());
322 EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type());
323 EXPECT_EQ(modulus_length,
324 public_key.algorithm().rsaHashedParams()->modulusLengthBits());
325 EXPECT_EQ(modulus_length,
326 private_key.algorithm().rsaHashedParams()->modulusLengthBits());
327 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256,
328 public_key.algorithm().rsaHashedParams()->hash().id());
329 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256,
330 private_key.algorithm().rsaHashedParams()->hash().id());
331 EXPECT_TRUE(public_key.extractable());
332 EXPECT_EQ(extractable, private_key.extractable());
333 EXPECT_EQ(public_usages, public_key.usages());
334 EXPECT_EQ(private_usages, private_key.usages());
336 // Try exporting the generated key pair, and then re-importing to verify that
337 // the exported data was valid.
338 std::vector<uint8_t> public_key_spki;
339 EXPECT_EQ(Status::Success(), ExportKey(blink::WebCryptoKeyFormatSpki,
340 public_key, &public_key_spki));
342 public_key = blink::WebCryptoKey::createNull();
343 ASSERT_EQ(
344 Status::Success(),
345 ImportKey(blink::WebCryptoKeyFormatSpki, CryptoData(public_key_spki),
346 CreateRsaHashedImportAlgorithm(
347 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
348 blink::WebCryptoAlgorithmIdSha256),
349 true, public_usages, &public_key));
350 EXPECT_EQ(modulus_length,
351 public_key.algorithm().rsaHashedParams()->modulusLengthBits());
353 std::vector<uint8_t> private_key_pkcs8;
354 EXPECT_EQ(Status::Success(), ExportKey(blink::WebCryptoKeyFormatPkcs8,
355 private_key, &private_key_pkcs8));
356 private_key = blink::WebCryptoKey::createNull();
357 ASSERT_EQ(
358 Status::Success(),
359 ImportKey(blink::WebCryptoKeyFormatPkcs8, CryptoData(private_key_pkcs8),
360 CreateRsaHashedImportAlgorithm(
361 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
362 blink::WebCryptoAlgorithmIdSha256),
363 true, private_usages, &private_key));
364 EXPECT_EQ(modulus_length,
365 private_key.algorithm().rsaHashedParams()->modulusLengthBits());
367 // Fail with bad modulus.
368 algorithm = CreateRsaHashedKeyGenAlgorithm(
369 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
370 blink::WebCryptoAlgorithmIdSha256, 0, public_exponent);
371 EXPECT_EQ(Status::ErrorGenerateRsaUnsupportedModulus(),
372 GenerateKeyPair(algorithm, extractable, usages, &public_key,
373 &private_key));
375 // Fail with bad exponent: larger than unsigned long.
376 unsigned int exponent_length = sizeof(unsigned long) + 1; // NOLINT
377 const std::vector<uint8_t> long_exponent(exponent_length, 0x01);
378 algorithm = CreateRsaHashedKeyGenAlgorithm(
379 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
380 blink::WebCryptoAlgorithmIdSha256, modulus_length, long_exponent);
381 EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
382 GenerateKeyPair(algorithm, extractable, usages, &public_key,
383 &private_key));
385 // Fail with bad exponent: empty.
386 const std::vector<uint8_t> empty_exponent;
387 algorithm = CreateRsaHashedKeyGenAlgorithm(
388 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
389 blink::WebCryptoAlgorithmIdSha256, modulus_length, empty_exponent);
390 EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
391 GenerateKeyPair(algorithm, extractable, usages, &public_key,
392 &private_key));
394 // Fail with bad exponent: all zeros.
395 std::vector<uint8_t> exponent_with_leading_zeros(15, 0x00);
396 algorithm = CreateRsaHashedKeyGenAlgorithm(
397 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
398 blink::WebCryptoAlgorithmIdSha256, modulus_length,
399 exponent_with_leading_zeros);
400 EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
401 GenerateKeyPair(algorithm, extractable, usages, &public_key,
402 &private_key));
404 // Key generation success using exponent with leading zeros.
405 exponent_with_leading_zeros.insert(exponent_with_leading_zeros.end(),
406 public_exponent.begin(),
407 public_exponent.end());
408 algorithm = CreateRsaHashedKeyGenAlgorithm(
409 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
410 blink::WebCryptoAlgorithmIdSha256, modulus_length,
411 exponent_with_leading_zeros);
412 EXPECT_EQ(Status::Success(), GenerateKeyPair(algorithm, extractable, usages,
413 &public_key, &private_key));
414 EXPECT_FALSE(public_key.isNull());
415 EXPECT_FALSE(private_key.isNull());
416 EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type());
417 EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type());
418 EXPECT_TRUE(public_key.extractable());
419 EXPECT_EQ(extractable, private_key.extractable());
420 EXPECT_EQ(public_usages, public_key.usages());
421 EXPECT_EQ(private_usages, private_key.usages());
423 // Successful WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 key generation (sha1)
424 algorithm = CreateRsaHashedKeyGenAlgorithm(
425 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
426 blink::WebCryptoAlgorithmIdSha1, modulus_length, public_exponent);
427 EXPECT_EQ(Status::Success(), GenerateKeyPair(algorithm, false, 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_EQ(modulus_length,
434 public_key.algorithm().rsaHashedParams()->modulusLengthBits());
435 EXPECT_EQ(modulus_length,
436 private_key.algorithm().rsaHashedParams()->modulusLengthBits());
437 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1,
438 public_key.algorithm().rsaHashedParams()->hash().id());
439 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1,
440 private_key.algorithm().rsaHashedParams()->hash().id());
441 // Even though "extractable" was set to false, the public key remains
442 // extractable.
443 EXPECT_TRUE(public_key.extractable());
444 EXPECT_FALSE(private_key.extractable());
445 EXPECT_EQ(public_usages, public_key.usages());
446 EXPECT_EQ(private_usages, private_key.usages());
448 // Exporting a private key as SPKI format doesn't make sense. However this
449 // will first fail because the key is not extractable.
450 std::vector<uint8_t> output;
451 EXPECT_EQ(Status::ErrorKeyNotExtractable(),
452 ExportKey(blink::WebCryptoKeyFormatSpki, private_key, &output));
454 // Re-generate an extractable private_key and try to export it as SPKI format.
455 // This should fail since spki is for public keys.
456 EXPECT_EQ(Status::Success(), GenerateKeyPair(algorithm, true, usages,
457 &public_key, &private_key));
458 EXPECT_EQ(Status::ErrorUnexpectedKeyType(),
459 ExportKey(blink::WebCryptoKeyFormatSpki, private_key, &output));
462 TEST_F(WebCryptoRsaSsaTest, GenerateKeyPairRsaBadModulusLength) {
463 const unsigned int kBadModulusBits[] = {
465 248, // Too small.
466 257, // Not a multiple of 8.
467 1023, // Not a multiple of 8.
468 0xFFFFFFFF, // Too big.
469 16384 + 8, // 16384 is the maxmimum length that NSS succeeds for.
472 const std::vector<uint8_t> public_exponent = HexStringToBytes("010001");
474 for (size_t i = 0; i < arraysize(kBadModulusBits); ++i) {
475 const unsigned int modulus_length_bits = kBadModulusBits[i];
476 blink::WebCryptoAlgorithm algorithm = CreateRsaHashedKeyGenAlgorithm(
477 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
478 blink::WebCryptoAlgorithmIdSha256, modulus_length_bits,
479 public_exponent);
480 bool extractable = true;
481 const blink::WebCryptoKeyUsageMask usages = blink::WebCryptoKeyUsageSign;
482 blink::WebCryptoKey public_key;
483 blink::WebCryptoKey private_key;
485 EXPECT_EQ(Status::ErrorGenerateRsaUnsupportedModulus(),
486 GenerateKeyPair(algorithm, extractable, usages, &public_key,
487 &private_key));
491 // Try generating RSA key pairs using unsupported public exponents. Only
492 // exponents of 3 and 65537 are supported. Although OpenSSL can support other
493 // values, it can also hang when given invalid exponents. To avoid hanging, use
494 // a whitelist of known safe exponents.
495 TEST_F(WebCryptoRsaSsaTest, GenerateKeyPairRsaBadExponent) {
496 const unsigned int modulus_length = 1024;
498 const char* const kPublicExponents[] = {
499 "11", // 17 - This is a valid public exponent, but currently disallowed.
500 "00",
501 "01",
502 "02",
503 "010000", // 65536
506 for (size_t i = 0; i < arraysize(kPublicExponents); ++i) {
507 SCOPED_TRACE(i);
508 blink::WebCryptoAlgorithm algorithm = CreateRsaHashedKeyGenAlgorithm(
509 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
510 blink::WebCryptoAlgorithmIdSha256, modulus_length,
511 HexStringToBytes(kPublicExponents[i]));
513 blink::WebCryptoKey public_key;
514 blink::WebCryptoKey private_key;
516 EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
517 GenerateKeyPair(algorithm, true, blink::WebCryptoKeyUsageSign,
518 &public_key, &private_key));
522 TEST_F(WebCryptoRsaSsaTest, SignVerifyFailures) {
523 // Import a key pair.
524 blink::WebCryptoAlgorithm import_algorithm =
525 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
526 blink::WebCryptoAlgorithmIdSha1);
527 blink::WebCryptoKey public_key;
528 blink::WebCryptoKey private_key;
529 ASSERT_NO_FATAL_FAILURE(ImportRsaKeyPair(
530 HexStringToBytes(kPublicKeySpkiDerHex),
531 HexStringToBytes(kPrivateKeyPkcs8DerHex), import_algorithm, false,
532 blink::WebCryptoKeyUsageVerify, blink::WebCryptoKeyUsageSign, &public_key,
533 &private_key));
535 blink::WebCryptoAlgorithm algorithm =
536 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5);
538 std::vector<uint8_t> signature;
539 bool signature_match;
541 // Compute a signature.
542 const std::vector<uint8_t> data = HexStringToBytes("010203040506070809");
543 ASSERT_EQ(Status::Success(),
544 Sign(algorithm, private_key, CryptoData(data), &signature));
546 // Ensure truncated signature does not verify by passing one less byte.
547 EXPECT_EQ(Status::Success(),
548 Verify(algorithm, public_key,
549 CryptoData(vector_as_array(&signature),
550 static_cast<unsigned int>(signature.size()) - 1),
551 CryptoData(data), &signature_match));
552 EXPECT_FALSE(signature_match);
554 // Ensure truncated signature does not verify by passing no bytes.
555 EXPECT_EQ(Status::Success(), Verify(algorithm, public_key, CryptoData(),
556 CryptoData(data), &signature_match));
557 EXPECT_FALSE(signature_match);
559 // Ensure corrupted signature does not verify.
560 std::vector<uint8_t> corrupt_sig = signature;
561 corrupt_sig[corrupt_sig.size() / 2] ^= 0x1;
562 EXPECT_EQ(Status::Success(),
563 Verify(algorithm, public_key, CryptoData(corrupt_sig),
564 CryptoData(data), &signature_match));
565 EXPECT_FALSE(signature_match);
567 // Ensure signatures that are greater than the modulus size fail.
568 const unsigned int long_message_size_bytes = 1024;
569 DCHECK_GT(long_message_size_bytes, kModulusLengthBits / 8);
570 const unsigned char kLongSignature[long_message_size_bytes] = {0};
571 EXPECT_EQ(Status::Success(),
572 Verify(algorithm, public_key,
573 CryptoData(kLongSignature, sizeof(kLongSignature)),
574 CryptoData(data), &signature_match));
575 EXPECT_FALSE(signature_match);
577 // Ensure that signing and verifying with an incompatible algorithm fails.
578 algorithm = CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaOaep);
580 EXPECT_EQ(Status::ErrorUnexpected(),
581 Sign(algorithm, private_key, CryptoData(data), &signature));
582 EXPECT_EQ(Status::ErrorUnexpected(),
583 Verify(algorithm, public_key, CryptoData(signature),
584 CryptoData(data), &signature_match));
586 // Some crypto libraries (NSS) can automatically select the RSA SSA inner hash
587 // based solely on the contents of the input signature data. In the Web Crypto
588 // implementation, the inner hash should be specified uniquely by the key
589 // algorithm parameter. To validate this behavior, call Verify with a computed
590 // signature that used one hash type (SHA-1), but pass in a key with a
591 // different inner hash type (SHA-256). If the hash type is determined by the
592 // signature itself (undesired), the verify will pass, while if the hash type
593 // is specified by the key algorithm (desired), the verify will fail.
595 // Compute a signature using SHA-1 as the inner hash.
596 EXPECT_EQ(Status::Success(),
597 Sign(CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5),
598 private_key, CryptoData(data), &signature));
600 blink::WebCryptoKey public_key_256;
601 EXPECT_EQ(Status::Success(),
602 ImportKey(blink::WebCryptoKeyFormatSpki,
603 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
604 CreateRsaHashedImportAlgorithm(
605 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
606 blink::WebCryptoAlgorithmIdSha256),
607 true, blink::WebCryptoKeyUsageVerify, &public_key_256));
609 // Now verify using an algorithm whose inner hash is SHA-256, not SHA-1. The
610 // signature should not verify.
611 // NOTE: public_key was produced by generateKey, and so its associated
612 // algorithm has WebCryptoRsaKeyGenParams and not WebCryptoRsaSsaParams. Thus
613 // it has no inner hash to conflict with the input algorithm.
614 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1,
615 private_key.algorithm().rsaHashedParams()->hash().id());
616 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256,
617 public_key_256.algorithm().rsaHashedParams()->hash().id());
619 bool is_match;
620 EXPECT_EQ(Status::Success(),
621 Verify(CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5),
622 public_key_256, CryptoData(signature), CryptoData(data),
623 &is_match));
624 EXPECT_FALSE(is_match);
627 TEST_F(WebCryptoRsaSsaTest, SignVerifyKnownAnswer) {
628 scoped_ptr<base::ListValue> tests;
629 ASSERT_TRUE(ReadJsonTestFileToList("pkcs1v15_sign.json", &tests));
631 // Import the key pair.
632 blink::WebCryptoAlgorithm import_algorithm =
633 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
634 blink::WebCryptoAlgorithmIdSha1);
635 blink::WebCryptoKey public_key;
636 blink::WebCryptoKey private_key;
637 ASSERT_NO_FATAL_FAILURE(ImportRsaKeyPair(
638 HexStringToBytes(kPublicKeySpkiDerHex),
639 HexStringToBytes(kPrivateKeyPkcs8DerHex), import_algorithm, false,
640 blink::WebCryptoKeyUsageVerify, blink::WebCryptoKeyUsageSign, &public_key,
641 &private_key));
643 blink::WebCryptoAlgorithm algorithm =
644 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5);
646 // Validate the signatures are computed and verified as expected.
647 std::vector<uint8_t> signature;
648 for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
649 SCOPED_TRACE(test_index);
651 base::DictionaryValue* test;
652 ASSERT_TRUE(tests->GetDictionary(test_index, &test));
654 std::vector<uint8_t> test_message =
655 GetBytesFromHexString(test, "message_hex");
656 std::vector<uint8_t> test_signature =
657 GetBytesFromHexString(test, "signature_hex");
659 signature.clear();
660 ASSERT_EQ(Status::Success(), Sign(algorithm, private_key,
661 CryptoData(test_message), &signature));
662 EXPECT_BYTES_EQ(test_signature, signature);
664 bool is_match = false;
665 ASSERT_EQ(Status::Success(),
666 Verify(algorithm, public_key, CryptoData(test_signature),
667 CryptoData(test_message), &is_match));
668 EXPECT_TRUE(is_match);
672 // Try importing an RSA-SSA public key with unsupported key usages using SPKI
673 // format. RSA-SSA public keys only support the 'verify' usage.
674 TEST_F(WebCryptoRsaSsaTest, ImportRsaSsaPublicKeyBadUsage_SPKI) {
675 const blink::WebCryptoAlgorithm algorithm =
676 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
677 blink::WebCryptoAlgorithmIdSha256);
679 blink::WebCryptoKeyUsageMask bad_usages[] = {
680 blink::WebCryptoKeyUsageSign,
681 blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify,
682 blink::WebCryptoKeyUsageEncrypt,
683 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt,
686 for (size_t i = 0; i < arraysize(bad_usages); ++i) {
687 SCOPED_TRACE(i);
689 blink::WebCryptoKey public_key;
690 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
691 ImportKey(blink::WebCryptoKeyFormatSpki,
692 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
693 algorithm, false, bad_usages[i], &public_key));
697 // Try importing an RSA-SSA public key with unsupported key usages using JWK
698 // format. RSA-SSA public keys only support the 'verify' usage.
699 TEST_F(WebCryptoRsaSsaTest, ImportRsaSsaPublicKeyBadUsage_JWK) {
700 const blink::WebCryptoAlgorithm algorithm =
701 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
702 blink::WebCryptoAlgorithmIdSha256);
704 blink::WebCryptoKeyUsageMask bad_usages[] = {
705 blink::WebCryptoKeyUsageSign,
706 blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify,
707 blink::WebCryptoKeyUsageEncrypt,
708 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt,
711 base::DictionaryValue dict;
712 RestoreJwkRsaDictionary(&dict);
713 dict.Remove("use", NULL);
714 dict.SetString("alg", "RS256");
716 for (size_t i = 0; i < arraysize(bad_usages); ++i) {
717 SCOPED_TRACE(i);
719 blink::WebCryptoKey public_key;
720 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
721 ImportKeyJwkFromDict(dict, algorithm, false, bad_usages[i],
722 &public_key));
726 // Generate an RSA-SSA key pair with invalid usages. RSA-SSA supports:
727 // 'sign', 'verify'
728 TEST_F(WebCryptoRsaSsaTest, GenerateKeyBadUsages) {
729 blink::WebCryptoKeyUsageMask bad_usages[] = {
730 blink::WebCryptoKeyUsageDecrypt,
731 blink::WebCryptoKeyUsageVerify | blink::WebCryptoKeyUsageDecrypt,
732 blink::WebCryptoKeyUsageWrapKey,
735 const unsigned int modulus_length = 256;
736 const std::vector<uint8_t> public_exponent = HexStringToBytes("010001");
738 for (size_t i = 0; i < arraysize(bad_usages); ++i) {
739 SCOPED_TRACE(i);
741 blink::WebCryptoKey public_key;
742 blink::WebCryptoKey private_key;
744 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
745 GenerateKeyPair(CreateRsaHashedKeyGenAlgorithm(
746 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
747 blink::WebCryptoAlgorithmIdSha256,
748 modulus_length, public_exponent),
749 true, bad_usages[i], &public_key, &private_key));
753 // Generate an RSA-SSA key pair. The public and private keys should select the
754 // key usages which are applicable, and not have the exact same usages as was
755 // specified to GenerateKey
756 TEST_F(WebCryptoRsaSsaTest, GenerateKeyPairIntersectUsages) {
757 const unsigned int modulus_length = 256;
758 const std::vector<uint8_t> public_exponent = HexStringToBytes("010001");
760 blink::WebCryptoKey public_key;
761 blink::WebCryptoKey private_key;
763 ASSERT_EQ(Status::Success(),
764 GenerateKeyPair(CreateRsaHashedKeyGenAlgorithm(
765 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
766 blink::WebCryptoAlgorithmIdSha256,
767 modulus_length, public_exponent),
768 true, blink::WebCryptoKeyUsageSign |
769 blink::WebCryptoKeyUsageVerify,
770 &public_key, &private_key));
772 EXPECT_EQ(blink::WebCryptoKeyUsageVerify, public_key.usages());
773 EXPECT_EQ(blink::WebCryptoKeyUsageSign, private_key.usages());
775 // Try again but this time without the Verify usages.
776 ASSERT_EQ(Status::Success(),
777 GenerateKeyPair(CreateRsaHashedKeyGenAlgorithm(
778 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
779 blink::WebCryptoAlgorithmIdSha256,
780 modulus_length, public_exponent),
781 true, blink::WebCryptoKeyUsageSign, &public_key,
782 &private_key));
784 EXPECT_EQ(0, public_key.usages());
785 EXPECT_EQ(blink::WebCryptoKeyUsageSign, private_key.usages());
788 TEST_F(WebCryptoRsaSsaTest, GenerateKeyPairEmptyUsages) {
789 const unsigned int modulus_length = 256;
790 const std::vector<uint8_t> public_exponent = HexStringToBytes("010001");
792 blink::WebCryptoKey public_key;
793 blink::WebCryptoKey private_key;
795 ASSERT_EQ(Status::ErrorCreateKeyEmptyUsages(),
796 GenerateKeyPair(CreateRsaHashedKeyGenAlgorithm(
797 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
798 blink::WebCryptoAlgorithmIdSha256,
799 modulus_length, public_exponent),
800 true, 0, &public_key, &private_key));
803 TEST_F(WebCryptoRsaSsaTest, ImportKeyEmptyUsages) {
804 blink::WebCryptoKey public_key;
805 blink::WebCryptoKey private_key;
807 // Public without usage does not throw an error.
808 ASSERT_EQ(Status::Success(),
809 ImportKey(blink::WebCryptoKeyFormatSpki,
810 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
811 CreateRsaHashedImportAlgorithm(
812 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
813 blink::WebCryptoAlgorithmIdSha256),
814 true, 0, &public_key));
815 EXPECT_EQ(0, public_key.usages());
817 // Private empty usage will throw an error.
818 ASSERT_EQ(Status::ErrorCreateKeyEmptyUsages(),
819 ImportKey(blink::WebCryptoKeyFormatPkcs8,
820 CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
821 CreateRsaHashedImportAlgorithm(
822 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
823 blink::WebCryptoAlgorithmIdSha1),
824 true, 0, &private_key));
826 std::vector<uint8_t> public_jwk;
827 ASSERT_EQ(Status::Success(),
828 ExportKey(blink::WebCryptoKeyFormatJwk, public_key, &public_jwk));
830 ASSERT_EQ(Status::Success(),
831 ImportKey(blink::WebCryptoKeyFormatJwk, CryptoData(public_jwk),
832 CreateRsaHashedImportAlgorithm(
833 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
834 blink::WebCryptoAlgorithmIdSha256),
835 true, 0, &public_key));
836 EXPECT_EQ(0, public_key.usages());
838 // With correct usage to get correct imported private_key
839 std::vector<uint8_t> private_jwk;
840 ImportKey(
841 blink::WebCryptoKeyFormatPkcs8,
842 CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
843 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
844 blink::WebCryptoAlgorithmIdSha1),
845 true, blink::WebCryptoKeyUsageSign, &private_key);
847 ASSERT_EQ(Status::Success(),
848 ExportKey(blink::WebCryptoKeyFormatJwk, private_key, &private_jwk));
850 ASSERT_EQ(Status::ErrorCreateKeyEmptyUsages(),
851 ImportKey(blink::WebCryptoKeyFormatJwk, CryptoData(private_jwk),
852 CreateRsaHashedImportAlgorithm(
853 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
854 blink::WebCryptoAlgorithmIdSha1),
855 true, 0, &private_key));
858 TEST_F(WebCryptoRsaSsaTest, ImportExportJwkRsaPublicKey) {
859 struct TestCase {
860 const blink::WebCryptoAlgorithmId hash;
861 const blink::WebCryptoKeyUsageMask usage;
862 const char* const jwk_alg;
864 const TestCase kTests[] = {
865 {blink::WebCryptoAlgorithmIdSha1, blink::WebCryptoKeyUsageVerify, "RS1"},
866 {blink::WebCryptoAlgorithmIdSha256,
867 blink::WebCryptoKeyUsageVerify,
868 "RS256"},
869 {blink::WebCryptoAlgorithmIdSha384,
870 blink::WebCryptoKeyUsageVerify,
871 "RS384"},
872 {blink::WebCryptoAlgorithmIdSha512,
873 blink::WebCryptoKeyUsageVerify,
874 "RS512"}};
876 for (size_t test_index = 0; test_index < arraysize(kTests); ++test_index) {
877 SCOPED_TRACE(test_index);
878 const TestCase& test = kTests[test_index];
880 const blink::WebCryptoAlgorithm import_algorithm =
881 CreateRsaHashedImportAlgorithm(
882 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, test.hash);
884 // Import the spki to create a public key
885 blink::WebCryptoKey public_key;
886 ASSERT_EQ(Status::Success(),
887 ImportKey(blink::WebCryptoKeyFormatSpki,
888 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
889 import_algorithm, true, test.usage, &public_key));
891 // Export the public key as JWK and verify its contents
892 std::vector<uint8_t> jwk;
893 ASSERT_EQ(Status::Success(),
894 ExportKey(blink::WebCryptoKeyFormatJwk, public_key, &jwk));
895 EXPECT_TRUE(VerifyPublicJwk(jwk, test.jwk_alg, kPublicKeyModulusHex,
896 kPublicKeyExponentHex, test.usage));
898 // Import the JWK back in to create a new key
899 blink::WebCryptoKey public_key2;
900 ASSERT_EQ(Status::Success(),
901 ImportKey(blink::WebCryptoKeyFormatJwk, CryptoData(jwk),
902 import_algorithm, true, test.usage, &public_key2));
903 ASSERT_TRUE(public_key2.handle());
904 EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key2.type());
905 EXPECT_TRUE(public_key2.extractable());
906 EXPECT_EQ(import_algorithm.id(), public_key2.algorithm().id());
908 // Export the new key as spki and compare to the original.
909 std::vector<uint8_t> spki;
910 ASSERT_EQ(Status::Success(),
911 ExportKey(blink::WebCryptoKeyFormatSpki, public_key2, &spki));
912 EXPECT_BYTES_EQ_HEX(kPublicKeySpkiDerHex, CryptoData(spki));
916 TEST_F(WebCryptoRsaSsaTest, ImportJwkRsaFailures) {
917 base::DictionaryValue dict;
918 RestoreJwkRsaDictionary(&dict);
919 blink::WebCryptoAlgorithm algorithm =
920 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
921 blink::WebCryptoAlgorithmIdSha256);
922 blink::WebCryptoKeyUsageMask usages = blink::WebCryptoKeyUsageVerify;
923 blink::WebCryptoKey key;
925 // An RSA public key JWK _must_ have an "n" (modulus) and an "e" (exponent)
926 // entry, while an RSA private key must have those plus at least a "d"
927 // (private exponent) entry.
928 // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18,
929 // section 6.3.
931 // Baseline pass.
932 EXPECT_EQ(Status::Success(),
933 ImportKeyJwkFromDict(dict, algorithm, false, usages, &key));
934 EXPECT_EQ(algorithm.id(), key.algorithm().id());
935 EXPECT_FALSE(key.extractable());
936 EXPECT_EQ(blink::WebCryptoKeyUsageVerify, key.usages());
937 EXPECT_EQ(blink::WebCryptoKeyTypePublic, key.type());
939 // The following are specific failure cases for when kty = "RSA".
941 // Fail if either "n" or "e" is not present or malformed.
942 const std::string kKtyParmName[] = {"n", "e"};
943 for (size_t idx = 0; idx < arraysize(kKtyParmName); ++idx) {
944 // Fail on missing parameter.
945 dict.Remove(kKtyParmName[idx], NULL);
946 EXPECT_NE(Status::Success(),
947 ImportKeyJwkFromDict(dict, algorithm, false, usages, &key));
948 RestoreJwkRsaDictionary(&dict);
950 // Fail on bad b64 parameter encoding.
951 dict.SetString(kKtyParmName[idx], "Qk3f0DsytU8lfza2au #$% Htaw2xpop9yTuH0");
952 EXPECT_NE(Status::Success(),
953 ImportKeyJwkFromDict(dict, algorithm, false, usages, &key));
954 RestoreJwkRsaDictionary(&dict);
956 // Fail on empty parameter.
957 dict.SetString(kKtyParmName[idx], "");
958 EXPECT_EQ(Status::ErrorJwkEmptyBigInteger(kKtyParmName[idx]),
959 ImportKeyJwkFromDict(dict, algorithm, false, usages, &key));
960 RestoreJwkRsaDictionary(&dict);
964 // Try importing an RSA-SSA key from JWK format, having specified both Sign and
965 // Verify usage, and an invalid JWK.
967 // The test must fail with a usage error BEFORE attempting to read the JWK data.
968 // Although both Sign and Verify are valid usages for RSA-SSA keys, it is
969 // invalid to have them both at the same time for one key (since Sign applies to
970 // private keys, whereas Verify applies to public keys).
972 // If the implementation does not fail fast, this test will crash dereferencing
973 // invalid memory.
974 TEST_F(WebCryptoRsaSsaTest, ImportRsaSsaJwkBadUsageFailFast) {
975 CryptoData bad_data(NULL, 128); // Invalid buffer of length 128.
977 blink::WebCryptoKey key;
978 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
979 ImportKey(blink::WebCryptoKeyFormatJwk, bad_data,
980 CreateRsaHashedImportAlgorithm(
981 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
982 blink::WebCryptoAlgorithmIdSha256),
983 true, blink::WebCryptoKeyUsageVerify |
984 blink::WebCryptoKeyUsageSign,
985 &key));
988 // Imports invalid JWK/SPKI/PKCS8 data and verifies that it fails as expected.
989 TEST_F(WebCryptoRsaSsaTest, ImportInvalidKeyData) {
990 scoped_ptr<base::ListValue> tests;
991 ASSERT_TRUE(ReadJsonTestFileToList("bad_rsa_keys.json", &tests));
993 for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
994 SCOPED_TRACE(test_index);
996 const base::DictionaryValue* test;
997 ASSERT_TRUE(tests->GetDictionary(test_index, &test));
999 blink::WebCryptoKeyFormat key_format = GetKeyFormatFromJsonTestCase(test);
1000 std::vector<uint8_t> key_data =
1001 GetKeyDataFromJsonTestCase(test, key_format);
1002 std::string test_error;
1003 ASSERT_TRUE(test->GetString("error", &test_error));
1005 blink::WebCryptoKeyUsageMask usages = blink::WebCryptoKeyUsageSign;
1006 if (key_format == blink::WebCryptoKeyFormatSpki)
1007 usages = blink::WebCryptoKeyUsageVerify;
1008 blink::WebCryptoKey key;
1009 Status status = ImportKey(key_format, CryptoData(key_data),
1010 CreateRsaHashedImportAlgorithm(
1011 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
1012 blink::WebCryptoAlgorithmIdSha256),
1013 true, usages, &key);
1014 EXPECT_EQ(test_error, StatusToString(status));
1018 } // namespace
1020 } // namespace webcrypto