Removing uses of X11 native key events.
[chromium-blink-merge.git] / content / child / webcrypto / test / rsa_oaep_unittest.cc
blob2c0976a2c13baadd00baf5f5f423a60c3d887b8b
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/jwk.h"
10 #include "content/child/webcrypto/status.h"
11 #include "content/child/webcrypto/test/test_helpers.h"
12 #include "content/child/webcrypto/webcrypto_util.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
15 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
17 namespace content {
19 namespace webcrypto {
21 namespace {
23 // Creates an RSA-OAEP algorithm
24 blink::WebCryptoAlgorithm CreateRsaOaepAlgorithm(
25 const std::vector<uint8_t>& label) {
26 return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
27 blink::WebCryptoAlgorithmIdRsaOaep,
28 new blink::WebCryptoRsaOaepParams(
29 !label.empty(), vector_as_array(&label), label.size()));
32 scoped_ptr<base::DictionaryValue> CreatePublicKeyJwkDict() {
33 scoped_ptr<base::DictionaryValue> jwk(new base::DictionaryValue());
34 jwk->SetString("kty", "RSA");
35 jwk->SetString("n",
36 Base64EncodeUrlSafe(HexStringToBytes(kPublicKeyModulusHex)));
37 jwk->SetString("e",
38 Base64EncodeUrlSafe(HexStringToBytes(kPublicKeyExponentHex)));
39 return jwk.Pass();
42 // Import a PKCS#8 private key that uses RSAPrivateKey with the
43 // id-rsaEncryption OID.
44 TEST(WebCryptoRsaOaepTest, ImportPkcs8WithRsaEncryption) {
45 if (!SupportsRsaOaep()) {
46 LOG(WARNING) << "RSA-OAEP support not present; skipping.";
47 return;
50 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
51 ASSERT_EQ(Status::Success(),
52 ImportKey(blink::WebCryptoKeyFormatPkcs8,
53 CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
54 CreateRsaHashedImportAlgorithm(
55 blink::WebCryptoAlgorithmIdRsaOaep,
56 blink::WebCryptoAlgorithmIdSha1),
57 true,
58 blink::WebCryptoKeyUsageDecrypt,
59 &private_key));
62 TEST(WebCryptoRsaOaepTest, ImportPublicJwkWithNoAlg) {
63 if (!SupportsRsaOaep()) {
64 LOG(WARNING) << "RSA-OAEP support not present; skipping.";
65 return;
68 scoped_ptr<base::DictionaryValue> jwk(CreatePublicKeyJwkDict());
70 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
71 ASSERT_EQ(Status::Success(),
72 ImportKeyJwkFromDict(*jwk.get(),
73 CreateRsaHashedImportAlgorithm(
74 blink::WebCryptoAlgorithmIdRsaOaep,
75 blink::WebCryptoAlgorithmIdSha1),
76 true,
77 blink::WebCryptoKeyUsageEncrypt,
78 &public_key));
81 TEST(WebCryptoRsaOaepTest, ImportPublicJwkWithMatchingAlg) {
82 if (!SupportsRsaOaep()) {
83 LOG(WARNING) << "RSA-OAEP support not present; skipping.";
84 return;
87 scoped_ptr<base::DictionaryValue> jwk(CreatePublicKeyJwkDict());
88 jwk->SetString("alg", "RSA-OAEP");
90 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
91 ASSERT_EQ(Status::Success(),
92 ImportKeyJwkFromDict(*jwk.get(),
93 CreateRsaHashedImportAlgorithm(
94 blink::WebCryptoAlgorithmIdRsaOaep,
95 blink::WebCryptoAlgorithmIdSha1),
96 true,
97 blink::WebCryptoKeyUsageEncrypt,
98 &public_key));
101 TEST(WebCryptoRsaOaepTest, ImportPublicJwkWithMismatchedAlgFails) {
102 if (!SupportsRsaOaep()) {
103 LOG(WARNING) << "RSA-OAEP support not present; skipping.";
104 return;
107 scoped_ptr<base::DictionaryValue> jwk(CreatePublicKeyJwkDict());
108 jwk->SetString("alg", "RSA-OAEP-512");
110 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
111 ASSERT_EQ(Status::ErrorJwkAlgorithmInconsistent(),
112 ImportKeyJwkFromDict(*jwk.get(),
113 CreateRsaHashedImportAlgorithm(
114 blink::WebCryptoAlgorithmIdRsaOaep,
115 blink::WebCryptoAlgorithmIdSha1),
116 true,
117 blink::WebCryptoKeyUsageEncrypt,
118 &public_key));
121 TEST(WebCryptoRsaOaepTest, ImportPublicJwkWithMismatchedTypeFails) {
122 if (!SupportsRsaOaep()) {
123 LOG(WARNING) << "RSA-OAEP support not present; skipping.";
124 return;
127 scoped_ptr<base::DictionaryValue> jwk(CreatePublicKeyJwkDict());
128 jwk->SetString("kty", "oct");
129 jwk->SetString("alg", "RSA-OAEP");
131 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
132 ASSERT_EQ(Status::ErrorJwkUnexpectedKty("RSA"),
133 ImportKeyJwkFromDict(*jwk.get(),
134 CreateRsaHashedImportAlgorithm(
135 blink::WebCryptoAlgorithmIdRsaOaep,
136 blink::WebCryptoAlgorithmIdSha1),
137 true,
138 blink::WebCryptoKeyUsageEncrypt,
139 &public_key));
142 TEST(WebCryptoRsaOaepTest, ExportPublicJwk) {
143 if (!SupportsRsaOaep()) {
144 LOG(WARNING) << "RSA-OAEP support not present; skipping.";
145 return;
148 struct TestData {
149 blink::WebCryptoAlgorithmId hash_alg;
150 const char* expected_jwk_alg;
151 } kTestData[] = {{blink::WebCryptoAlgorithmIdSha1, "RSA-OAEP"},
152 {blink::WebCryptoAlgorithmIdSha256, "RSA-OAEP-256"},
153 {blink::WebCryptoAlgorithmIdSha384, "RSA-OAEP-384"},
154 {blink::WebCryptoAlgorithmIdSha512, "RSA-OAEP-512"}};
155 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestData); ++i) {
156 const TestData& test_data = kTestData[i];
157 SCOPED_TRACE(test_data.expected_jwk_alg);
159 scoped_ptr<base::DictionaryValue> jwk(CreatePublicKeyJwkDict());
160 jwk->SetString("alg", test_data.expected_jwk_alg);
162 // Import the key in a known-good format
163 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
164 ASSERT_EQ(Status::Success(),
165 ImportKeyJwkFromDict(
166 *jwk.get(),
167 CreateRsaHashedImportAlgorithm(
168 blink::WebCryptoAlgorithmIdRsaOaep, test_data.hash_alg),
169 true,
170 blink::WebCryptoKeyUsageEncrypt,
171 &public_key));
173 // Now export the key as JWK and verify its contents
174 std::vector<uint8_t> jwk_data;
175 ASSERT_EQ(Status::Success(),
176 ExportKey(blink::WebCryptoKeyFormatJwk, public_key, &jwk_data));
177 EXPECT_TRUE(VerifyPublicJwk(jwk_data,
178 test_data.expected_jwk_alg,
179 kPublicKeyModulusHex,
180 kPublicKeyExponentHex,
181 blink::WebCryptoKeyUsageEncrypt));
185 TEST(WebCryptoRsaOaepTest, EncryptDecryptKnownAnswerTest) {
186 if (!SupportsRsaOaep()) {
187 LOG(WARNING) << "RSA-OAEP support not present; skipping.";
188 return;
191 scoped_ptr<base::ListValue> tests;
192 ASSERT_TRUE(ReadJsonTestFileToList("rsa_oaep.json", &tests));
194 for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
195 SCOPED_TRACE(test_index);
197 base::DictionaryValue* test = NULL;
198 ASSERT_TRUE(tests->GetDictionary(test_index, &test));
200 blink::WebCryptoAlgorithm digest_algorithm =
201 GetDigestAlgorithm(test, "hash");
202 ASSERT_FALSE(digest_algorithm.isNull());
203 std::vector<uint8_t> public_key_der =
204 GetBytesFromHexString(test, "public_key");
205 std::vector<uint8_t> private_key_der =
206 GetBytesFromHexString(test, "private_key");
207 std::vector<uint8_t> ciphertext = GetBytesFromHexString(test, "ciphertext");
208 std::vector<uint8_t> plaintext = GetBytesFromHexString(test, "plaintext");
209 std::vector<uint8_t> label = GetBytesFromHexString(test, "label");
211 blink::WebCryptoAlgorithm import_algorithm = CreateRsaHashedImportAlgorithm(
212 blink::WebCryptoAlgorithmIdRsaOaep, digest_algorithm.id());
213 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
214 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
216 ASSERT_NO_FATAL_FAILURE(ImportRsaKeyPair(public_key_der,
217 private_key_der,
218 import_algorithm,
219 false,
220 blink::WebCryptoKeyUsageEncrypt,
221 blink::WebCryptoKeyUsageDecrypt,
222 &public_key,
223 &private_key));
225 blink::WebCryptoAlgorithm op_algorithm = CreateRsaOaepAlgorithm(label);
226 std::vector<uint8_t> decrypted_data;
227 ASSERT_EQ(Status::Success(),
228 Decrypt(op_algorithm,
229 private_key,
230 CryptoData(ciphertext),
231 &decrypted_data));
232 EXPECT_BYTES_EQ(plaintext, decrypted_data);
233 std::vector<uint8_t> encrypted_data;
234 ASSERT_EQ(
235 Status::Success(),
236 Encrypt(
237 op_algorithm, public_key, CryptoData(plaintext), &encrypted_data));
238 std::vector<uint8_t> redecrypted_data;
239 ASSERT_EQ(Status::Success(),
240 Decrypt(op_algorithm,
241 private_key,
242 CryptoData(encrypted_data),
243 &redecrypted_data));
244 EXPECT_BYTES_EQ(plaintext, redecrypted_data);
248 TEST(WebCryptoRsaOaepTest, EncryptWithLargeMessageFails) {
249 if (!SupportsRsaOaep()) {
250 LOG(WARNING) << "RSA-OAEP support not present; skipping.";
251 return;
254 const blink::WebCryptoAlgorithmId kHash = blink::WebCryptoAlgorithmIdSha1;
255 const size_t kHashSize = 20;
257 scoped_ptr<base::DictionaryValue> jwk(CreatePublicKeyJwkDict());
259 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
260 ASSERT_EQ(Status::Success(),
261 ImportKeyJwkFromDict(*jwk.get(),
262 CreateRsaHashedImportAlgorithm(
263 blink::WebCryptoAlgorithmIdRsaOaep, kHash),
264 true,
265 blink::WebCryptoKeyUsageEncrypt,
266 &public_key));
268 // The maximum size of an encrypted message is:
269 // modulus length
270 // - 1 (leading octet)
271 // - hash size (maskedSeed)
272 // - hash size (lHash portion of maskedDB)
273 // - 1 (at least one octet for the padding string)
274 size_t kMaxMessageSize = (kModulusLengthBits / 8) - 2 - (2 * kHashSize);
276 // The label has no influence on the maximum message size. For simplicity,
277 // use the empty string.
278 std::vector<uint8_t> label;
279 blink::WebCryptoAlgorithm op_algorithm = CreateRsaOaepAlgorithm(label);
281 // Test that a message just before the boundary succeeds.
282 std::string large_message;
283 large_message.resize(kMaxMessageSize - 1, 'A');
285 std::vector<uint8_t> ciphertext;
286 ASSERT_EQ(
287 Status::Success(),
288 Encrypt(
289 op_algorithm, public_key, CryptoData(large_message), &ciphertext));
291 // Test that a message at the boundary succeeds.
292 large_message.resize(kMaxMessageSize, 'A');
293 ciphertext.clear();
295 ASSERT_EQ(
296 Status::Success(),
297 Encrypt(
298 op_algorithm, public_key, CryptoData(large_message), &ciphertext));
300 // Test that a message greater than the largest size fails.
301 large_message.resize(kMaxMessageSize + 1, 'A');
302 ciphertext.clear();
304 ASSERT_EQ(
305 Status::OperationError(),
306 Encrypt(
307 op_algorithm, public_key, CryptoData(large_message), &ciphertext));
310 // Ensures that if the selected hash algorithm for the RSA-OAEP message is too
311 // large, then it is rejected, independent of the actual message to be
312 // encrypted.
313 // For example, a 1024-bit RSA key is too small to accomodate a message that
314 // uses OAEP with SHA-512, since it requires 1040 bits to encode
315 // (2 * hash size + 2 padding bytes).
316 TEST(WebCryptoRsaOaepTest, EncryptWithLargeDigestFails) {
317 if (!SupportsRsaOaep()) {
318 LOG(WARNING) << "RSA-OAEP support not present; skipping.";
319 return;
322 const blink::WebCryptoAlgorithmId kHash = blink::WebCryptoAlgorithmIdSha512;
324 scoped_ptr<base::DictionaryValue> jwk(CreatePublicKeyJwkDict());
326 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
327 ASSERT_EQ(Status::Success(),
328 ImportKeyJwkFromDict(*jwk.get(),
329 CreateRsaHashedImportAlgorithm(
330 blink::WebCryptoAlgorithmIdRsaOaep, kHash),
331 true,
332 blink::WebCryptoKeyUsageEncrypt,
333 &public_key));
335 // The label has no influence on the maximum message size. For simplicity,
336 // use the empty string.
337 std::vector<uint8_t> label;
338 blink::WebCryptoAlgorithm op_algorithm = CreateRsaOaepAlgorithm(label);
340 std::string small_message("A");
341 std::vector<uint8_t> ciphertext;
342 // This is an operation error, as the internal consistency checking of the
343 // algorithm parameters is up to the implementation.
344 ASSERT_EQ(
345 Status::OperationError(),
346 Encrypt(
347 op_algorithm, public_key, CryptoData(small_message), &ciphertext));
350 TEST(WebCryptoRsaOaepTest, DecryptWithLargeMessageFails) {
351 if (!SupportsRsaOaep()) {
352 LOG(WARNING) << "RSA-OAEP support not present; skipping.";
353 return;
356 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
357 ASSERT_EQ(Status::Success(),
358 ImportKey(blink::WebCryptoKeyFormatPkcs8,
359 CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
360 CreateRsaHashedImportAlgorithm(
361 blink::WebCryptoAlgorithmIdRsaOaep,
362 blink::WebCryptoAlgorithmIdSha1),
363 true,
364 blink::WebCryptoKeyUsageDecrypt,
365 &private_key));
367 // The label has no influence on the maximum message size. For simplicity,
368 // use the empty string.
369 std::vector<uint8_t> label;
370 blink::WebCryptoAlgorithm op_algorithm = CreateRsaOaepAlgorithm(label);
372 std::string large_dummy_message(kModulusLengthBits / 8, 'A');
373 std::vector<uint8_t> plaintext;
375 ASSERT_EQ(Status::OperationError(),
376 Decrypt(op_algorithm,
377 private_key,
378 CryptoData(large_dummy_message),
379 &plaintext));
382 TEST(WebCryptoRsaOaepTest, WrapUnwrapRawKey) {
383 if (!SupportsRsaOaep()) {
384 LOG(WARNING) << "RSA-OAEP support not present; skipping.";
385 return;
388 blink::WebCryptoAlgorithm import_algorithm = CreateRsaHashedImportAlgorithm(
389 blink::WebCryptoAlgorithmIdRsaOaep, blink::WebCryptoAlgorithmIdSha1);
390 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
391 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
393 ASSERT_NO_FATAL_FAILURE(ImportRsaKeyPair(
394 HexStringToBytes(kPublicKeySpkiDerHex),
395 HexStringToBytes(kPrivateKeyPkcs8DerHex),
396 import_algorithm,
397 false,
398 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageWrapKey,
399 blink::WebCryptoKeyUsageDecrypt | blink::WebCryptoKeyUsageUnwrapKey,
400 &public_key,
401 &private_key));
403 std::vector<uint8_t> label;
404 blink::WebCryptoAlgorithm wrapping_algorithm = CreateRsaOaepAlgorithm(label);
406 const std::string key_hex = "000102030405060708090A0B0C0D0E0F";
407 const blink::WebCryptoAlgorithm key_algorithm =
408 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
410 blink::WebCryptoKey key =
411 ImportSecretKeyFromRaw(HexStringToBytes(key_hex),
412 key_algorithm,
413 blink::WebCryptoKeyUsageEncrypt);
414 ASSERT_FALSE(key.isNull());
416 std::vector<uint8_t> wrapped_key;
417 ASSERT_EQ(Status::Success(),
418 WrapKey(blink::WebCryptoKeyFormatRaw,
419 key,
420 public_key,
421 wrapping_algorithm,
422 &wrapped_key));
424 // Verify that |wrapped_key| can be decrypted and yields the key data.
425 // Because |private_key| supports both decrypt and unwrap, this is valid.
426 std::vector<uint8_t> decrypted_key;
427 ASSERT_EQ(Status::Success(),
428 Decrypt(wrapping_algorithm,
429 private_key,
430 CryptoData(wrapped_key),
431 &decrypted_key));
432 EXPECT_BYTES_EQ_HEX(key_hex, decrypted_key);
434 // Now attempt to unwrap the key, which should also decrypt the data.
435 blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull();
436 ASSERT_EQ(Status::Success(),
437 UnwrapKey(blink::WebCryptoKeyFormatRaw,
438 CryptoData(wrapped_key),
439 private_key,
440 wrapping_algorithm,
441 key_algorithm,
442 true,
443 blink::WebCryptoKeyUsageEncrypt,
444 &unwrapped_key));
445 ASSERT_FALSE(unwrapped_key.isNull());
447 std::vector<uint8_t> raw_key;
448 ASSERT_EQ(Status::Success(),
449 ExportKey(blink::WebCryptoKeyFormatRaw, unwrapped_key, &raw_key));
450 EXPECT_BYTES_EQ_HEX(key_hex, raw_key);
453 TEST(WebCryptoRsaOaepTest, WrapUnwrapJwkSymKey) {
454 if (!SupportsRsaOaep()) {
455 LOG(WARNING) << "RSA-OAEP support not present; skipping.";
456 return;
459 // The public and private portions of a 2048-bit RSA key with the
460 // id-rsaEncryption OID
461 const char kPublicKey2048SpkiDerHex[] =
462 "30820122300d06092a864886f70d01010105000382010f003082010a0282010100c5d8ce"
463 "137a38168c8ab70229cfa5accc640567159750a312ce2e7d54b6e2fdd59b300c6a6c9764"
464 "f8de6f00519cdb90111453d273a967462786480621f9e7cee5b73d63358448e7183a3a68"
465 "e991186359f26aa88fbca5f53e673e502e4c5a2ba5068aeba60c9d0c44d872458d1b1e2f"
466 "7f339f986076d516e93dc750f0b7680b6f5f02bc0d5590495be04c4ae59d34ba17bc5d08"
467 "a93c75cfda2828f4a55b153af912038438276cb4a14f8116ca94db0ea9893652d02fc606"
468 "36f19975e3d79a4d8ea8bfed6f8e0a24b63d243b08ea70a086ad56dd6341d733711c89ca"
469 "749d4a80b3e6ecd2f8e53731eadeac2ea77788ee55d7b4b47c0f2523fbd61b557c16615d"
470 "5d0203010001";
471 const char kPrivateKey2048Pkcs8DerHex[] =
472 "308204bd020100300d06092a864886f70d0101010500048204a7308204a3020100028201"
473 "0100c5d8ce137a38168c8ab70229cfa5accc640567159750a312ce2e7d54b6e2fdd59b30"
474 "0c6a6c9764f8de6f00519cdb90111453d273a967462786480621f9e7cee5b73d63358448"
475 "e7183a3a68e991186359f26aa88fbca5f53e673e502e4c5a2ba5068aeba60c9d0c44d872"
476 "458d1b1e2f7f339f986076d516e93dc750f0b7680b6f5f02bc0d5590495be04c4ae59d34"
477 "ba17bc5d08a93c75cfda2828f4a55b153af912038438276cb4a14f8116ca94db0ea98936"
478 "52d02fc60636f19975e3d79a4d8ea8bfed6f8e0a24b63d243b08ea70a086ad56dd6341d7"
479 "33711c89ca749d4a80b3e6ecd2f8e53731eadeac2ea77788ee55d7b4b47c0f2523fbd61b"
480 "557c16615d5d02030100010282010074b70feb41a0b0fcbc207670400556c9450042ede3"
481 "d4383fb1ce8f3558a6d4641d26dd4c333fa4db842d2b9cf9d2354d3e16ad027a9f682d8c"
482 "f4145a1ad97b9edcd8a41c402bd9d8db10f62f43df854cdccbbb2100834f083f53ed6d42"
483 "b1b729a59072b004a4e945fc027db15e9c121d1251464d320d4774d5732df6b3dbf751f4"
484 "9b19c9db201e19989c883bbaad5333db47f64f6f7a95b8d4936b10d945aa3f794cfaab62"
485 "e7d47686129358914f3b8085f03698a650ab5b8c7e45813f2b0515ec05b6e5195b6a7c2a"
486 "0d36969745f431ded4fd059f6aa361a4649541016d356297362b778e90f077d48815b339"
487 "ec6f43aba345df93e67fcb6c2cb5b4544e9be902818100e9c90abe5f9f32468c5b6d630c"
488 "54a4d7d75e29a72cf792f21e242aac78fd7995c42dfd4ae871d2619ff7096cb05baa78e3"
489 "23ecab338401a8059adf7a0d8be3b21edc9a9c82c5605634a2ec81ec053271721351868a"
490 "4c2e50c689d7cef94e31ff23658af5843366e2b289c5bf81d72756a7b93487dd8770d69c"
491 "1f4e089d6d89f302818100d8a58a727c4e209132afd9933b98c89aca862a01cc0be74133"
492 "bee517909e5c379e526895ac4af11780c1fe91194c777c9670b6423f0f5a32fd7691a622"
493 "113eef4bed2ef863363a335fd55b0e75088c582437237d7f3ed3f0a643950237bc6e6277"
494 "ccd0d0a1b4170aa1047aa7ffa7c8c54be10e8c7327ae2e0885663963817f6f02818100e5"
495 "aed9ba4d71b7502e6748a1ce247ecb7bd10c352d6d9256031cdf3c11a65e44b0b7ca2945"
496 "134671195af84c6b3bb3d10ebf65ae916f38bd5dbc59a0ad1c69b8beaf57cb3a8335f19b"
497 "c7117b576987b48331cd9fd3d1a293436b7bb5e1a35c6560de4b5688ea834367cb0997eb"
498 "b578f59ed4cb724c47dba94d3b484c1876dcd70281807f15bc7d2406007cac2b138a96af"
499 "2d1e00276b84da593132c253fcb73212732dfd25824c2a615bc3d9b7f2c8d2fa542d3562"
500 "b0c7738e61eeff580a6056239fb367ea9e5efe73d4f846033602e90c36a78db6fa8ea792"
501 "0769675ec58e237bd994d189c8045a96f5dd3a4f12547257ce224e3c9af830a4da3c0eab"
502 "9227a0035ae9028180067caea877e0b23090fc689322b71fbcce63d6596e66ab5fcdbaa0"
503 "0d49e93aba8effb4518c2da637f209028401a68f344865b4956b032c69acde51d29177ca"
504 "3db99fdbf5e74848ed4fa7bdfc2ebb60e2aaa5354770a763e1399ab7a2099762d525fea0"
505 "37f3e1972c45a477e66db95c9609bb27f862700ef93379930786cf751b";
506 blink::WebCryptoAlgorithm import_algorithm = CreateRsaHashedImportAlgorithm(
507 blink::WebCryptoAlgorithmIdRsaOaep, blink::WebCryptoAlgorithmIdSha1);
508 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
509 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
511 ASSERT_NO_FATAL_FAILURE(ImportRsaKeyPair(
512 HexStringToBytes(kPublicKey2048SpkiDerHex),
513 HexStringToBytes(kPrivateKey2048Pkcs8DerHex),
514 import_algorithm,
515 false,
516 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageWrapKey,
517 blink::WebCryptoKeyUsageDecrypt | blink::WebCryptoKeyUsageUnwrapKey,
518 &public_key,
519 &private_key));
521 std::vector<uint8_t> label;
522 blink::WebCryptoAlgorithm wrapping_algorithm = CreateRsaOaepAlgorithm(label);
524 const std::string key_hex = "000102030405060708090a0b0c0d0e0f";
525 const blink::WebCryptoAlgorithm key_algorithm =
526 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
528 blink::WebCryptoKey key =
529 ImportSecretKeyFromRaw(HexStringToBytes(key_hex),
530 key_algorithm,
531 blink::WebCryptoKeyUsageEncrypt);
532 ASSERT_FALSE(key.isNull());
534 std::vector<uint8_t> wrapped_key;
535 ASSERT_EQ(Status::Success(),
536 WrapKey(blink::WebCryptoKeyFormatJwk,
537 key,
538 public_key,
539 wrapping_algorithm,
540 &wrapped_key));
542 // Verify that |wrapped_key| can be decrypted and yields a valid JWK object.
543 // Because |private_key| supports both decrypt and unwrap, this is valid.
544 std::vector<uint8_t> decrypted_jwk;
545 ASSERT_EQ(Status::Success(),
546 Decrypt(wrapping_algorithm,
547 private_key,
548 CryptoData(wrapped_key),
549 &decrypted_jwk));
550 EXPECT_TRUE(VerifySecretJwk(
551 decrypted_jwk, "A128CBC", key_hex, blink::WebCryptoKeyUsageEncrypt));
553 // Now attempt to unwrap the key, which should also decrypt the data.
554 blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull();
555 ASSERT_EQ(Status::Success(),
556 UnwrapKey(blink::WebCryptoKeyFormatJwk,
557 CryptoData(wrapped_key),
558 private_key,
559 wrapping_algorithm,
560 key_algorithm,
561 true,
562 blink::WebCryptoKeyUsageEncrypt,
563 &unwrapped_key));
564 ASSERT_FALSE(unwrapped_key.isNull());
566 std::vector<uint8_t> raw_key;
567 ASSERT_EQ(Status::Success(),
568 ExportKey(blink::WebCryptoKeyFormatRaw, unwrapped_key, &raw_key));
569 EXPECT_BYTES_EQ_HEX(key_hex, raw_key);
572 TEST(WebCryptoRsaOaepTest, ImportExportJwkRsaPublicKey) {
573 if (!SupportsRsaOaep()) {
574 LOG(WARNING) << "RSA-OAEP support not present; skipping.";
575 return;
578 struct TestCase {
579 const blink::WebCryptoAlgorithmId hash;
580 const blink::WebCryptoKeyUsageMask usage;
581 const char* const jwk_alg;
583 const TestCase kTests[] = {{blink::WebCryptoAlgorithmIdSha1,
584 blink::WebCryptoKeyUsageEncrypt, "RSA-OAEP"},
585 {blink::WebCryptoAlgorithmIdSha256,
586 blink::WebCryptoKeyUsageEncrypt, "RSA-OAEP-256"},
587 {blink::WebCryptoAlgorithmIdSha384,
588 blink::WebCryptoKeyUsageEncrypt, "RSA-OAEP-384"},
589 {blink::WebCryptoAlgorithmIdSha512,
590 blink::WebCryptoKeyUsageEncrypt, "RSA-OAEP-512"}};
592 for (size_t test_index = 0; test_index < ARRAYSIZE_UNSAFE(kTests);
593 ++test_index) {
594 SCOPED_TRACE(test_index);
595 const TestCase& test = kTests[test_index];
597 const blink::WebCryptoAlgorithm import_algorithm =
598 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaOaep,
599 test.hash);
601 // Import the spki to create a public key
602 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
603 ASSERT_EQ(Status::Success(),
604 ImportKey(blink::WebCryptoKeyFormatSpki,
605 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
606 import_algorithm,
607 true,
608 test.usage,
609 &public_key));
611 // Export the public key as JWK and verify its contents
612 std::vector<uint8_t> jwk;
613 ASSERT_EQ(Status::Success(),
614 ExportKey(blink::WebCryptoKeyFormatJwk, public_key, &jwk));
615 EXPECT_TRUE(VerifyPublicJwk(jwk,
616 test.jwk_alg,
617 kPublicKeyModulusHex,
618 kPublicKeyExponentHex,
619 test.usage));
621 // Import the JWK back in to create a new key
622 blink::WebCryptoKey public_key2 = blink::WebCryptoKey::createNull();
623 ASSERT_EQ(Status::Success(),
624 ImportKey(blink::WebCryptoKeyFormatJwk,
625 CryptoData(jwk),
626 import_algorithm,
627 true,
628 test.usage,
629 &public_key2));
630 ASSERT_TRUE(public_key2.handle());
631 EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key2.type());
632 EXPECT_TRUE(public_key2.extractable());
633 EXPECT_EQ(import_algorithm.id(), public_key2.algorithm().id());
635 // TODO(eroman): Export the SPKI and verify matches.
639 } // namespace
641 } // namespace webcrypto
643 } // namespace content