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"
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 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());
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_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());
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
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
157 const char* expected_jwk
=
158 "{\"alg\":\"RS1\",\"d\":\"M6UEKpCyfU9UUcqbu9C0R3GhAa-IQ0Cu-YhfKku-"
159 "kuiUpySsPFaMj5eFOtB8AmbIxqPKCSnx6PESMYhEKfxNmuVf7olqEM5wfD7X5zTkRyejlXRQ"
160 "GlMmgxCcKrrKuig8MbS9L1PD7jfjUs7jT55QO9gMBiKtecbc7og1R8ajsyU\",\"dp\":"
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
));
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
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
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
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
);
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
));
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();
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();
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
,
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
,
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
,
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
,
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
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
[] = {
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
,
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
,
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.
506 for (size_t i
= 0; i
< arraysize(kPublicExponents
); ++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
,
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());
620 EXPECT_EQ(Status::Success(),
621 Verify(CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
),
622 public_key_256
, CryptoData(signature
), CryptoData(data
),
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
,
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");
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
) {
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
) {
719 blink::WebCryptoKey public_key
;
720 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
721 ImportKeyJwkFromDict(dict
, algorithm
, false, bad_usages
[i
],
726 // Generate an RSA-SSA key pair with invalid usages. RSA-SSA supports:
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
) {
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
,
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
;
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
) {
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
,
869 {blink::WebCryptoAlgorithmIdSha384
,
870 blink::WebCryptoKeyUsageVerify
,
872 {blink::WebCryptoAlgorithmIdSha512
,
873 blink::WebCryptoKeyUsageVerify
,
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,
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
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
,
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
));
1020 } // namespace webcrypto