1 // Copyright 2013 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 "content/renderer/webcrypto/webcrypto_impl.h"
11 #include "base/basictypes.h"
12 #include "base/json/json_writer.h"
13 #include "base/logging.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "content/public/renderer/content_renderer_client.h"
17 #include "content/renderer/renderer_webkitplatformsupport_impl.h"
18 #include "content/renderer/webcrypto/webcrypto_util.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 #include "third_party/WebKit/public/platform/WebArrayBuffer.h"
21 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h"
22 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
23 #include "third_party/WebKit/public/platform/WebCryptoKey.h"
25 // The OpenSSL implementation of WebCrypto is less complete, so don't run all of
26 // the tests: http://crbug.com/267888
27 #if defined(USE_OPENSSL)
28 #define MAYBE(test_name) DISABLED_##test_name
30 #define MAYBE(test_name) test_name
37 std::vector
<uint8
> HexStringToBytes(const std::string
& hex
) {
38 std::vector
<uint8
> bytes
;
39 base::HexStringToBytes(hex
, &bytes
);
43 void ExpectArrayBufferMatchesHex(const std::string
& expected_hex
,
44 const blink::WebArrayBuffer
& array_buffer
) {
47 base::HexEncode(array_buffer
.data(), array_buffer
.byteLength()).c_str());
50 std::vector
<uint8
> MakeJsonVector(const std::string
& json_string
) {
51 return std::vector
<uint8
>(json_string
.begin(), json_string
.end());
54 std::vector
<uint8
> MakeJsonVector(const base::DictionaryValue
& dict
) {
56 base::JSONWriter::Write(&dict
, &json
);
57 return MakeJsonVector(json
);
60 // Helper for ImportJwkFailures and ImportJwkOctFailures. Restores the JWK JSON
61 // dictionary to a good state
62 void RestoreJwkOctDictionary(base::DictionaryValue
* dict
) {
64 dict
->SetString("kty", "oct");
65 dict
->SetString("alg", "A128CBC");
66 dict
->SetString("use", "enc");
67 dict
->SetBoolean("extractable", false);
68 dict
->SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
71 // Helper for ImportJwkRsaFailures. Restores the JWK JSON
72 // dictionary to a good state
73 void RestoreJwkRsaDictionary(base::DictionaryValue
* dict
) {
75 dict
->SetString("kty", "RSA");
76 dict
->SetString("alg", "RSA1_5");
77 dict
->SetString("use", "enc");
78 dict
->SetBoolean("extractable", false);
80 "qLOyhK-OtQs4cDSoYPFGxJGfMYdjzWxVmMiuSBGh4KvEx-CwgtaTpef87Wdc9GaFEncsDLxk"
81 "p0LGxjD1M8jMcvYq6DPEC_JYQumEu3i9v5fAEH1VvbZi9cTg-rmEXLUUjvc5LdOq_5OuHmtm"
82 "e7PUJHYW1PW6ENTP0ibeiNOfFvs");
83 dict
->SetString("e", "AQAB");
86 // Determines if two ArrayBuffers have identical content.
87 bool ArrayBuffersEqual(
88 const blink::WebArrayBuffer
& a
,
89 const blink::WebArrayBuffer
& b
) {
90 return a
.byteLength() == b
.byteLength() &&
91 memcmp(a
.data(), b
.data(), a
.byteLength()) == 0;
94 // Given a vector of WebArrayBuffers, determines if there are any copies.
95 bool CopiesExist(std::vector
<blink::WebArrayBuffer
> bufs
) {
96 for (size_t i
= 0; i
< bufs
.size(); ++i
) {
97 for (size_t j
= i
+ 1; j
< bufs
.size(); ++j
) {
98 if (ArrayBuffersEqual(bufs
[i
], bufs
[j
]))
105 blink::WebCryptoAlgorithm
CreateAesKeyGenAlgorithm(
106 blink::WebCryptoAlgorithmId aes_alg_id
,
107 unsigned short length
) {
108 return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
109 aes_alg_id
, new blink::WebCryptoAesKeyGenParams(length
));
112 blink::WebCryptoAlgorithm
CreateAesCbcKeyGenAlgorithm(
113 unsigned short key_length_bits
) {
114 return CreateAesKeyGenAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
,
118 blink::WebCryptoAlgorithm
CreateAesGcmKeyGenAlgorithm(
119 unsigned short key_length_bits
) {
120 return CreateAesKeyGenAlgorithm(blink::WebCryptoAlgorithmIdAesGcm
,
124 blink::WebCryptoAlgorithm
CreateAesKwKeyGenAlgorithm(
125 unsigned short key_length_bits
) {
126 return CreateAesKeyGenAlgorithm(blink::WebCryptoAlgorithmIdAesKw
,
132 class WebCryptoImplTest
: public testing::Test
{
134 blink::WebCryptoKey
ImportSecretKeyFromRawHexString(
135 const std::string
& key_hex
,
136 const blink::WebCryptoAlgorithm
& algorithm
,
137 blink::WebCryptoKeyUsageMask usage
) {
138 std::vector
<uint8
> key_raw
= HexStringToBytes(key_hex
);
140 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
141 bool extractable
= true;
142 EXPECT_TRUE(crypto_
.ImportKeyInternal(blink::WebCryptoKeyFormatRaw
,
143 webcrypto::Uint8VectorStart(key_raw
),
150 EXPECT_FALSE(key
.isNull());
151 EXPECT_TRUE(key
.handle());
152 EXPECT_EQ(blink::WebCryptoKeyTypeSecret
, key
.type());
153 EXPECT_EQ(algorithm
.id(), key
.algorithm().id());
154 EXPECT_EQ(extractable
, key
.extractable());
155 EXPECT_EQ(usage
, key
.usages());
159 // Forwarding methods to gain access to protected methods of
163 const blink::WebCryptoAlgorithm
& algorithm
,
164 const std::vector
<uint8
>& data
,
165 blink::WebArrayBuffer
* buffer
) {
166 return crypto_
.DigestInternal(
167 algorithm
, webcrypto::Uint8VectorStart(data
), data
.size(), buffer
);
170 bool GenerateKeyInternal(
171 const blink::WebCryptoAlgorithm
& algorithm
,
172 blink::WebCryptoKey
* key
) {
173 bool extractable
= true;
174 blink::WebCryptoKeyUsageMask usage_mask
= 0;
175 return crypto_
.GenerateKeyInternal(algorithm
, extractable
, usage_mask
, key
);
178 bool GenerateKeyPairInternal(
179 const blink::WebCryptoAlgorithm
& algorithm
,
181 blink::WebCryptoKeyUsageMask usage_mask
,
182 blink::WebCryptoKey
* public_key
,
183 blink::WebCryptoKey
* private_key
) {
184 return crypto_
.GenerateKeyPairInternal(
185 algorithm
, extractable
, usage_mask
, public_key
, private_key
);
188 bool ImportKeyInternal(
189 blink::WebCryptoKeyFormat format
,
190 const std::vector
<uint8
>& key_data
,
191 const blink::WebCryptoAlgorithm
& algorithm
,
193 blink::WebCryptoKeyUsageMask usage_mask
,
194 blink::WebCryptoKey
* key
) {
195 return crypto_
.ImportKeyInternal(format
,
196 webcrypto::Uint8VectorStart(key_data
),
204 bool ExportKeyInternal(
205 blink::WebCryptoKeyFormat format
,
206 const blink::WebCryptoKey
& key
,
207 blink::WebArrayBuffer
* buffer
) {
208 return crypto_
.ExportKeyInternal(format
, key
, buffer
);
212 const blink::WebCryptoAlgorithm
& algorithm
,
213 const blink::WebCryptoKey
& key
,
214 const std::vector
<uint8
>& data
,
215 blink::WebArrayBuffer
* buffer
) {
216 return crypto_
.SignInternal(
217 algorithm
, key
, webcrypto::Uint8VectorStart(data
), data
.size(), buffer
);
220 bool VerifySignatureInternal(
221 const blink::WebCryptoAlgorithm
& algorithm
,
222 const blink::WebCryptoKey
& key
,
223 const unsigned char* signature
,
224 unsigned signature_size
,
225 const std::vector
<uint8
>& data
,
226 bool* signature_match
) {
227 return crypto_
.VerifySignatureInternal(algorithm
,
231 webcrypto::Uint8VectorStart(data
),
236 bool EncryptInternal(
237 const blink::WebCryptoAlgorithm
& algorithm
,
238 const blink::WebCryptoKey
& key
,
239 const unsigned char* data
,
241 blink::WebArrayBuffer
* buffer
) {
242 return crypto_
.EncryptInternal(algorithm
, key
, data
, data_size
, buffer
);
245 bool EncryptInternal(
246 const blink::WebCryptoAlgorithm
& algorithm
,
247 const blink::WebCryptoKey
& key
,
248 const std::vector
<uint8
>& data
,
249 blink::WebArrayBuffer
* buffer
) {
250 return crypto_
.EncryptInternal(
251 algorithm
, key
, webcrypto::Uint8VectorStart(data
), data
.size(), buffer
);
254 bool DecryptInternal(
255 const blink::WebCryptoAlgorithm
& algorithm
,
256 const blink::WebCryptoKey
& key
,
257 const unsigned char* data
,
259 blink::WebArrayBuffer
* buffer
) {
260 return crypto_
.DecryptInternal(algorithm
, key
, data
, data_size
, buffer
);
263 bool DecryptInternal(
264 const blink::WebCryptoAlgorithm
& algorithm
,
265 const blink::WebCryptoKey
& key
,
266 const std::vector
<uint8
>& data
,
267 blink::WebArrayBuffer
* buffer
) {
268 return crypto_
.DecryptInternal(
269 algorithm
, key
, webcrypto::Uint8VectorStart(data
), data
.size(), buffer
);
273 const std::vector
<uint8
>& key_data
,
274 const blink::WebCryptoAlgorithm
& algorithm
,
276 blink::WebCryptoKeyUsageMask usage_mask
,
277 blink::WebCryptoKey
* key
) {
278 return crypto_
.ImportKeyJwk(webcrypto::Uint8VectorStart(key_data
),
287 WebCryptoImpl crypto_
;
290 TEST_F(WebCryptoImplTest
, DigestSampleSets
) {
291 // The results are stored here in hex format for readability.
293 // TODO(bryaneyler): Eventually, all these sample test sets should be replaced
294 // with the sets here: http://csrc.nist.gov/groups/STM/cavp/index.html#03
296 // Results were generated using the command sha{1,224,256,384,512}sum.
298 blink::WebCryptoAlgorithmId algorithm
;
299 const std::string hex_input
;
300 const char* hex_result
;
303 const TestCase kTests
[] = {
304 { blink::WebCryptoAlgorithmIdSha1
, "",
305 "da39a3ee5e6b4b0d3255bfef95601890afd80709"
307 { blink::WebCryptoAlgorithmIdSha224
, "",
308 "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f"
310 { blink::WebCryptoAlgorithmIdSha256
, "",
311 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
313 { blink::WebCryptoAlgorithmIdSha384
, "",
314 "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274e"
315 "debfe76f65fbd51ad2f14898b95b"
317 { blink::WebCryptoAlgorithmIdSha512
, "",
318 "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0"
319 "d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e",
321 { blink::WebCryptoAlgorithmIdSha1
, "00",
322 "5ba93c9db0cff93f52b521d7420e43f6eda2784f",
324 { blink::WebCryptoAlgorithmIdSha224
, "00",
325 "fff9292b4201617bdc4d3053fce02734166a683d7d858a7f5f59b073",
327 { blink::WebCryptoAlgorithmIdSha256
, "00",
328 "6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d",
330 { blink::WebCryptoAlgorithmIdSha384
, "00",
331 "bec021b4f368e3069134e012c2b4307083d3a9bdd206e24e5f0d86e13d6636655933"
332 "ec2b413465966817a9c208a11717",
334 { blink::WebCryptoAlgorithmIdSha512
, "00",
335 "b8244d028981d693af7b456af8efa4cad63d282e19ff14942c246e50d9351d22704a"
336 "802a71c3580b6370de4ceb293c324a8423342557d4e5c38438f0e36910ee",
338 { blink::WebCryptoAlgorithmIdSha1
, "000102030405",
339 "868460d98d09d8bbb93d7b6cdd15cc7fbec676b9",
341 { blink::WebCryptoAlgorithmIdSha224
, "000102030405",
342 "7d92e7f1cad1818ed1d13ab41f04ebabfe1fef6bb4cbeebac34c29bc",
344 { blink::WebCryptoAlgorithmIdSha256
, "000102030405",
345 "17e88db187afd62c16e5debf3e6527cd006bc012bc90b51a810cd80c2d511f43",
347 { blink::WebCryptoAlgorithmIdSha384
, "000102030405",
348 "79f4738706fce9650ac60266675c3cd07298b09923850d525604d040e6e448adc7dc"
349 "22780d7e1b95bfeaa86a678e4552",
351 { blink::WebCryptoAlgorithmIdSha512
, "000102030405",
352 "2f3831bccc94cf061bcfa5f8c23c1429d26e3bc6b76edad93d9025cb91c903af6cf9"
353 "c935dc37193c04c2c66e7d9de17c358284418218afea2160147aaa912f4c",
357 for (size_t test_index
= 0; test_index
< ARRAYSIZE_UNSAFE(kTests
);
359 SCOPED_TRACE(test_index
);
360 const TestCase
& test
= kTests
[test_index
];
362 blink::WebCryptoAlgorithm algorithm
=
363 webcrypto::CreateAlgorithm(test
.algorithm
);
364 std::vector
<uint8
> input
= HexStringToBytes(test
.hex_input
);
366 blink::WebArrayBuffer output
;
367 ASSERT_TRUE(DigestInternal(algorithm
, input
, &output
));
368 ExpectArrayBufferMatchesHex(test
.hex_result
, output
);
372 TEST_F(WebCryptoImplTest
, HMACSampleSets
) {
374 blink::WebCryptoAlgorithmId algorithm
;
380 const TestCase kTests
[] = {
381 // Empty sets. Result generated via OpenSSL commandline tool. These
382 // particular results are also posted on the Wikipedia page examples:
383 // http://en.wikipedia.org/wiki/Hash-based_message_authentication_code
385 blink::WebCryptoAlgorithmIdSha1
,
388 // openssl dgst -sha1 -hmac "" < /dev/null
389 "fbdb1d1b18aa6c08324b7d64b71fb76370690e1d",
392 blink::WebCryptoAlgorithmIdSha256
,
395 // openssl dgst -sha256 -hmac "" < /dev/null
396 "b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad",
398 // For this data, see http://csrc.nist.gov/groups/STM/cavp/index.html#07
400 // http://csrc.nist.gov/groups/STM/cavp/documents/mac/hmactestvectors.zip
403 blink::WebCryptoAlgorithmIdSha1
,
405 "59785928d72516e31272",
407 "a3ce8899df1022e8d2d539b47bf0e309c66f84095e21438ec355bf119ce5fdcb4e73a6"
408 "19cdf36f25b369d8c38ff419997f0c59830108223606e31223483fd39edeaa4d3f0d21"
409 "198862d239c9fd26074130ff6c86493f5227ab895c8f244bd42c7afce5d147a20a5907"
410 "98c68e708e964902d124dadecdbda9dbd0051ed710e9bf",
412 "3c8162589aafaee024fc9a5ca50dd2336fe3eb28",
416 blink::WebCryptoAlgorithmIdSha1
,
418 "ceb9aedf8d6efcf0ae52bea0fa99a9e26ae81bacea0cff4d5eecf201e3bca3c3577480"
419 "621b818fd717ba99d6ff958ea3d59b2527b019c343bb199e648090225867d994607962"
420 "f5866aa62930d75b58f6",
422 "99958aa459604657c7bf6e4cdfcc8785f0abf06ffe636b5b64ecd931bd8a4563055924"
423 "21fc28dbcccb8a82acea2be8e54161d7a78e0399a6067ebaca3f2510274dc9f92f2c8a"
424 "e4265eec13d7d42e9f8612d7bc258f913ecb5a3a5c610339b49fb90e9037b02d684fc6"
425 "0da835657cb24eab352750c8b463b1a8494660d36c3ab2",
427 "4ac41ab89f625c60125ed65ffa958c6b490ea670",
431 blink::WebCryptoAlgorithmIdSha256
,
433 "9779d9120642797f1747025d5b22b7ac607cab08e1758f2f3a46c8be1e25c53b8c6a8f"
436 "b1689c2591eaf3c9e66070f8a77954ffb81749f1b00346f9dfe0b2ee905dcc288baf4a"
437 "92de3f4001dd9f44c468c3d07d6c6ee82faceafc97c2fc0fc0601719d2dcd0aa2aec92"
438 "d1b0ae933c65eb06a03c9c935c2bad0459810241347ab87e9f11adb30415424c6c7f5f"
439 "22a003b8ab8de54f6ded0e3ab9245fa79568451dfa258e",
441 "769f00d3e6a6cc1fb426a14a4f76c6462e6149726e0dee0ec0cf97a16605ac8b",
445 blink::WebCryptoAlgorithmIdSha256
,
447 "4b7ab133efe99e02fc89a28409ee187d579e774f4cba6fc223e13504e3511bef8d4f63"
448 "8b9aca55d4a43b8fbd64cf9d74dcc8c9e8d52034898c70264ea911a3fd70813fa73b08"
451 "138efc832c64513d11b9873c6fd4d8a65dbf367092a826ddd587d141b401580b798c69"
452 "025ad510cff05fcfbceb6cf0bb03201aaa32e423d5200925bddfadd418d8e30e18050e"
453 "b4f0618eb9959d9f78c1157d4b3e02cd5961f138afd57459939917d9144c95d8e6a94c"
454 "8f6d4eef3418c17b1ef0b46c2a7188305d9811dccb3d99",
456 "4f1ee7cb36c58803a8721d4ac8c4cf8cae5d8832392eed2a96dc59694252801b",
460 blink::WebCryptoAlgorithmIdSha224
,
462 "6c2539f4d0453efbbacc137794930413aeb392e029e0724715f9d943d6dcf7cdcc7fc19"
463 "7333df4fc476d5737ac3940d40eae",
465 "1f207b3fa6c905529c9f9f7894b8941b616974df2c0cc482c400f50734f293139b5bbf9"
466 "7384adfafc56494ca0629ed0ca179daf03056e33295eb19ec8dcd4dff898281b4b9409c"
467 "a369f662d49091a225a678b1ebb75818dcb6278a2d136319f78f9ba9df5031a4f6305ee"
468 "fde5b761d2f196ee318e89bcc4acebc2e11ed3b5dc4",
470 "4a7d9d13705b0faba0db75356c8ee0635afff1544911c69c2fbb1ab2"
474 blink::WebCryptoAlgorithmIdSha384
,
476 "d137f3e6cc4af28554beb03ba7a97e60c9d3959cd3bb08068edbf68d402d0498c6ee0ae"
477 "9e3a20dc7d8586e5c352f605cee19",
479 "64a884670d1c1dff555483dcd3da305dfba54bdc4d817c33ccb8fe7eb2ebf6236241031"
480 "09ec41644fa078491900c59a0f666f0356d9bc0b45bcc79e5fc9850f4543d96bc680090"
481 "44add0838ac1260e80592fbc557b2ddaf5ed1b86d3ed8f09e622e567f1d39a340857f6a"
482 "850cceef6060c48dac3dd0071fe68eb4ed2ed9aca01",
484 "c550fa53514da34f15e7f98ea87226ab6896cdfae25d3ec2335839f755cdc9a4992092e"
485 "70b7e5bd422784380b6396cf5"
489 blink::WebCryptoAlgorithmIdSha512
,
491 "c367aeb5c02b727883ffe2a4ceebf911b01454beb328fb5d57fc7f11bf744576aba421e2"
492 "a63426ea8109bd28ff21f53cd2bf1a11c6c989623d6ec27cdb0bbf458250857d819ff844"
493 "08b4f3dce08b98b1587ee59683af8852a0a5f55bda3ab5e132b4010e",
495 "1a7331c8ff1b748e3cee96952190fdbbe4ee2f79e5753bbb368255ee5b19c05a4ed9f1b2"
496 "c72ff1e9b9cb0348205087befa501e7793770faf0606e9c901836a9bc8afa00d7db94ee2"
497 "9eb191d5cf3fc3e8da95a0f9f4a2a7964289c3129b512bd890de8700a9205420f28a8965"
498 "b6c67be28ba7fe278e5fcd16f0f22cf2b2eacbb9",
500 "4459066109cb11e6870fa9c6bfd251adfa304c0a2928ca915049704972edc560cc7c0bc3"
501 "8249e9101aae2f7d4da62eaff83fb07134efc277de72b9e4ab360425"
505 for (size_t test_index
= 0; test_index
< ARRAYSIZE_UNSAFE(kTests
);
507 SCOPED_TRACE(test_index
);
508 const TestCase
& test
= kTests
[test_index
];
510 blink::WebCryptoAlgorithm algorithm
=
511 webcrypto::CreateHmacAlgorithmByHashId(test
.algorithm
);
513 blink::WebCryptoKey key
= ImportSecretKeyFromRawHexString(
514 test
.key
, algorithm
, blink::WebCryptoKeyUsageSign
);
516 // Verify exported raw key is identical to the imported data
517 blink::WebArrayBuffer raw_key
;
518 EXPECT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw
, key
, &raw_key
));
519 ExpectArrayBufferMatchesHex(test
.key
, raw_key
);
521 std::vector
<uint8
> message_raw
= HexStringToBytes(test
.message
);
523 blink::WebArrayBuffer output
;
525 ASSERT_TRUE(SignInternal(algorithm
, key
, message_raw
, &output
));
527 ExpectArrayBufferMatchesHex(test
.mac
, output
);
529 bool signature_match
= false;
530 EXPECT_TRUE(VerifySignatureInternal(
533 static_cast<const unsigned char*>(output
.data()),
537 EXPECT_TRUE(signature_match
);
539 // Ensure truncated signature does not verify by passing one less byte.
540 EXPECT_TRUE(VerifySignatureInternal(
543 static_cast<const unsigned char*>(output
.data()),
544 output
.byteLength() - 1,
547 EXPECT_FALSE(signature_match
);
549 // Ensure extra long signature does not cause issues and fails.
550 const unsigned char kLongSignature
[1024] = { 0 };
551 EXPECT_TRUE(VerifySignatureInternal(
555 sizeof(kLongSignature
),
558 EXPECT_FALSE(signature_match
);
562 TEST_F(WebCryptoImplTest
, AesCbcFailures
) {
563 const std::string key_hex
= "2b7e151628aed2a6abf7158809cf4f3c";
564 blink::WebCryptoKey key
= ImportSecretKeyFromRawHexString(
566 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
567 blink::WebCryptoKeyUsageEncrypt
| blink::WebCryptoKeyUsageDecrypt
);
569 // Verify exported raw key is identical to the imported data
570 blink::WebArrayBuffer raw_key
;
571 EXPECT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw
, key
, &raw_key
));
572 ExpectArrayBufferMatchesHex(key_hex
, raw_key
);
574 blink::WebArrayBuffer output
;
576 // Use an invalid |iv| (fewer than 16 bytes)
578 std::vector
<uint8
> input(32);
579 std::vector
<uint8
> iv
;
580 EXPECT_FALSE(EncryptInternal(
581 webcrypto::CreateAesCbcAlgorithm(iv
), key
, input
, &output
));
582 EXPECT_FALSE(DecryptInternal(
583 webcrypto::CreateAesCbcAlgorithm(iv
), key
, input
, &output
));
586 // Use an invalid |iv| (more than 16 bytes)
588 std::vector
<uint8
> input(32);
589 std::vector
<uint8
> iv(17);
590 EXPECT_FALSE(EncryptInternal(
591 webcrypto::CreateAesCbcAlgorithm(iv
), key
, input
, &output
));
592 EXPECT_FALSE(DecryptInternal(
593 webcrypto::CreateAesCbcAlgorithm(iv
), key
, input
, &output
));
596 // Give an input that is too large (would cause integer overflow when
597 // narrowing to an int).
599 std::vector
<uint8
> iv(16);
601 // Pretend the input is large. Don't pass data pointer as NULL in case that
602 // is special cased; the implementation shouldn't actually dereference the
604 const unsigned char* input
= &iv
[0];
605 unsigned input_len
= INT_MAX
- 3;
607 EXPECT_FALSE(EncryptInternal(
608 webcrypto::CreateAesCbcAlgorithm(iv
), key
, input
, input_len
, &output
));
609 EXPECT_FALSE(DecryptInternal(
610 webcrypto::CreateAesCbcAlgorithm(iv
), key
, input
, input_len
, &output
));
613 // Fail importing the key (too few bytes specified)
615 std::vector
<uint8
> key_raw(1);
616 std::vector
<uint8
> iv(16);
618 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
619 EXPECT_FALSE(ImportKeyInternal(blink::WebCryptoKeyFormatRaw
,
621 webcrypto::CreateAesCbcAlgorithm(iv
),
623 blink::WebCryptoKeyUsageEncrypt
,
627 // Fail exporting the key in SPKI and PKCS#8 formats (not allowed for secret
629 EXPECT_FALSE(ExportKeyInternal(blink::WebCryptoKeyFormatSpki
, key
, &output
));
630 EXPECT_FALSE(ExportKeyInternal(blink::WebCryptoKeyFormatPkcs8
, key
, &output
));
633 TEST_F(WebCryptoImplTest
, MAYBE(AesCbcSampleSets
)) {
637 const char* plain_text
;
638 const char* cipher_text
;
641 TestCase kTests
[] = {
642 // F.2.1 (CBC-AES128.Encrypt)
643 // http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
646 "2b7e151628aed2a6abf7158809cf4f3c",
649 "000102030405060708090a0b0c0d0e0f",
652 "6bc1bee22e409f96e93d7e117393172a"
653 "ae2d8a571e03ac9c9eb76fac45af8e51"
654 "30c81c46a35ce411e5fbc1191a0a52ef"
655 "f69f2445df4f9b17ad2b417be66c3710",
658 "7649abac8119b246cee98e9b12e9197d"
659 "5086cb9b507219ee95db113a917678b2"
660 "73bed6b8e3c1743b7116e69e22229516"
661 "3ff1caa1681fac09120eca307586e1a7"
662 // Padding block: encryption of {0x10, 0x10, ... 0x10}) (not given by the
664 "8cb82807230e1321d3fae00d18cc2012"
667 // F.2.6 CBC-AES256.Decrypt [*]
668 // http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
670 // [*] Truncated 3 bytes off the plain text, so block 4 differs from the
674 "603deb1015ca71be2b73aef0857d7781"
675 "1f352c073b6108d72d9810a30914dff4",
678 "000102030405060708090a0b0c0d0e0f",
681 "6bc1bee22e409f96e93d7e117393172a"
682 "ae2d8a571e03ac9c9eb76fac45af8e51"
683 "30c81c46a35ce411e5fbc1191a0a52ef"
684 // Truncated this last block to make it more interesting.
685 "f69f2445df4f9b17ad2b417be6",
688 "f58c4c04d6e5f1ba779eabfb5f7bfbd6"
689 "9cfc4e967edb808d679f777bc6702c7d"
690 "39f23369a9d9bacfa530e26304231461"
691 // This block differs from source vector (due to truncation)
692 "c9aaf02a6a54e9e242ccbf48c59daca6"
695 // Taken from encryptor_unittest.cc (EncryptorTest.EmptyEncrypt())
698 "3132383d5369787465656e4279746573",
701 "5377656574205369787465656e204956",
707 "8518b8878d34e7185e300d0fcc426396"
711 for (size_t index
= 0; index
< ARRAYSIZE_UNSAFE(kTests
); index
++) {
713 const TestCase
& test
= kTests
[index
];
715 blink::WebCryptoKey key
= ImportSecretKeyFromRawHexString(
717 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
718 blink::WebCryptoKeyUsageEncrypt
| blink::WebCryptoKeyUsageDecrypt
);
720 // Verify exported raw key is identical to the imported data
721 blink::WebArrayBuffer raw_key
;
722 EXPECT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw
, key
, &raw_key
));
723 ExpectArrayBufferMatchesHex(test
.key
, raw_key
);
725 std::vector
<uint8
> plain_text
= HexStringToBytes(test
.plain_text
);
726 std::vector
<uint8
> iv
= HexStringToBytes(test
.iv
);
728 blink::WebArrayBuffer output
;
731 EXPECT_TRUE(EncryptInternal(webcrypto::CreateAesCbcAlgorithm(iv
),
735 ExpectArrayBufferMatchesHex(test
.cipher_text
, output
);
738 std::vector
<uint8
> cipher_text
= HexStringToBytes(test
.cipher_text
);
739 EXPECT_TRUE(DecryptInternal(webcrypto::CreateAesCbcAlgorithm(iv
),
743 ExpectArrayBufferMatchesHex(test
.plain_text
, output
);
745 const unsigned kAesCbcBlockSize
= 16;
747 // Decrypt with a padding error by stripping the last block. This also ends
748 // up testing decryption over empty cipher text.
749 if (cipher_text
.size() >= kAesCbcBlockSize
) {
750 EXPECT_FALSE(DecryptInternal(webcrypto::CreateAesCbcAlgorithm(iv
),
753 cipher_text
.size() - kAesCbcBlockSize
,
757 // Decrypt cipher text which is not a multiple of block size by stripping
758 // a few bytes off the cipher text.
759 if (cipher_text
.size() > 3) {
760 EXPECT_FALSE(DecryptInternal(webcrypto::CreateAesCbcAlgorithm(iv
),
763 cipher_text
.size() - 3,
769 TEST_F(WebCryptoImplTest
, MAYBE(GenerateKeyAes
)) {
770 // Check key generation for each of AES-CBC, AES-GCM, and AES-KW, and for each
771 // allowed key length.
772 std::vector
<blink::WebCryptoAlgorithm
> algorithm
;
773 const unsigned short kKeyLength
[] = {128, 192, 256};
774 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(kKeyLength
); ++i
) {
775 algorithm
.push_back(CreateAesCbcKeyGenAlgorithm(kKeyLength
[i
]));
776 algorithm
.push_back(CreateAesGcmKeyGenAlgorithm(kKeyLength
[i
]));
777 algorithm
.push_back(CreateAesKwKeyGenAlgorithm(kKeyLength
[i
]));
779 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
780 std::vector
<blink::WebArrayBuffer
> keys
;
781 blink::WebArrayBuffer key_bytes
;
782 for (size_t i
= 0; i
< algorithm
.size(); ++i
) {
784 // Generate a small sample of keys.
786 for (int j
= 0; j
< 16; ++j
) {
787 ASSERT_TRUE(GenerateKeyInternal(algorithm
[i
], &key
));
788 EXPECT_TRUE(key
.handle());
789 EXPECT_EQ(blink::WebCryptoKeyTypeSecret
, key
.type());
791 ExportKeyInternal(blink::WebCryptoKeyFormatRaw
, key
, &key_bytes
));
792 keys
.push_back(key_bytes
);
794 // Ensure all entries in the key sample set are unique. This is a simplistic
795 // estimate of whether the generated keys appear random.
796 EXPECT_FALSE(CopiesExist(keys
));
800 TEST_F(WebCryptoImplTest
, MAYBE(GenerateKeyAesBadLength
)) {
801 const unsigned short kKeyLen
[] = {0, 127, 257};
802 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
803 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(kKeyLen
); ++i
) {
805 EXPECT_FALSE(GenerateKeyInternal(
806 CreateAesCbcKeyGenAlgorithm(kKeyLen
[i
]), &key
));
807 EXPECT_FALSE(GenerateKeyInternal(
808 CreateAesGcmKeyGenAlgorithm(kKeyLen
[i
]), &key
));
809 EXPECT_FALSE(GenerateKeyInternal(
810 CreateAesKwKeyGenAlgorithm(kKeyLen
[i
]), &key
));
814 TEST_F(WebCryptoImplTest
, MAYBE(GenerateKeyHmac
)) {
815 // Generate a small sample of HMAC keys.
816 std::vector
<blink::WebArrayBuffer
> keys
;
817 for (int i
= 0; i
< 16; ++i
) {
818 blink::WebArrayBuffer key_bytes
;
819 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
820 blink::WebCryptoAlgorithm algorithm
= webcrypto::CreateHmacKeyGenAlgorithm(
821 blink::WebCryptoAlgorithmIdSha1
, 64);
822 ASSERT_TRUE(GenerateKeyInternal(algorithm
, &key
));
823 EXPECT_FALSE(key
.isNull());
824 EXPECT_TRUE(key
.handle());
825 EXPECT_EQ(blink::WebCryptoKeyTypeSecret
, key
.type());
826 EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac
, key
.algorithm().id());
828 blink::WebArrayBuffer raw_key
;
829 ASSERT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw
, key
, &raw_key
));
830 EXPECT_EQ(64U, raw_key
.byteLength());
831 keys
.push_back(raw_key
);
833 // Ensure all entries in the key sample set are unique. This is a simplistic
834 // estimate of whether the generated keys appear random.
835 EXPECT_FALSE(CopiesExist(keys
));
838 // If the key length is not provided, then the block size is used.
839 TEST_F(WebCryptoImplTest
, MAYBE(GenerateKeyHmacNoLength
)) {
840 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
841 blink::WebCryptoAlgorithm algorithm
=
842 webcrypto::CreateHmacKeyGenAlgorithm(blink::WebCryptoAlgorithmIdSha1
, 0);
843 ASSERT_TRUE(GenerateKeyInternal(algorithm
, &key
));
844 EXPECT_TRUE(key
.handle());
845 EXPECT_EQ(blink::WebCryptoKeyTypeSecret
, key
.type());
846 blink::WebArrayBuffer raw_key
;
847 ASSERT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw
, key
, &raw_key
));
848 EXPECT_EQ(64U, raw_key
.byteLength());
850 // The block size for HMAC SHA-512 is larger.
851 algorithm
= webcrypto::CreateHmacKeyGenAlgorithm(
852 blink::WebCryptoAlgorithmIdSha512
, 0);
853 ASSERT_TRUE(GenerateKeyInternal(algorithm
, &key
));
854 ASSERT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw
, key
, &raw_key
));
855 EXPECT_EQ(128U, raw_key
.byteLength());
858 TEST_F(WebCryptoImplTest
, MAYBE(ImportSecretKeyNoAlgorithm
)) {
859 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
861 // This fails because the algorithm is null.
862 EXPECT_FALSE(ImportKeyInternal(
863 blink::WebCryptoKeyFormatRaw
,
864 HexStringToBytes("00000000000000000000"),
865 blink::WebCryptoAlgorithm::createNull(),
867 blink::WebCryptoKeyUsageEncrypt
,
872 TEST_F(WebCryptoImplTest
, ImportJwkFailures
) {
874 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
875 blink::WebCryptoAlgorithm algorithm
=
876 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
);
877 blink::WebCryptoKeyUsageMask usage_mask
= blink::WebCryptoKeyUsageEncrypt
;
879 // Baseline pass: each test below breaks a single item, so we start with a
880 // passing case to make sure each failure is caused by the isolated break.
881 // Each breaking subtest below resets the dictionary to this passing case when
883 base::DictionaryValue dict
;
884 RestoreJwkOctDictionary(&dict
);
885 EXPECT_TRUE(ImportKeyJwk(
886 MakeJsonVector(dict
), algorithm
, false, usage_mask
, &key
));
888 // Fail on empty JSON.
889 EXPECT_FALSE(ImportKeyJwk(
890 MakeJsonVector(""), algorithm
, false, usage_mask
, &key
));
892 // Fail on invalid JSON.
893 const std::vector
<uint8
> bad_json_vec
= MakeJsonVector(
896 "\"alg\" : \"HS256\","
899 EXPECT_FALSE(ImportKeyJwk(bad_json_vec
, algorithm
, false, usage_mask
, &key
));
901 // Fail on JWK alg present but unrecognized.
902 dict
.SetString("alg", "A127CBC");
903 EXPECT_FALSE(ImportKeyJwk(
904 MakeJsonVector(dict
), algorithm
, false, usage_mask
, &key
));
905 RestoreJwkOctDictionary(&dict
);
907 // Fail on both JWK and input algorithm missing.
908 dict
.Remove("alg", NULL
);
909 EXPECT_FALSE(ImportKeyJwk(MakeJsonVector(dict
),
910 blink::WebCryptoAlgorithm::createNull(),
914 RestoreJwkOctDictionary(&dict
);
916 // Fail on invalid kty.
917 dict
.SetString("kty", "foo");
918 EXPECT_FALSE(ImportKeyJwk(
919 MakeJsonVector(dict
), algorithm
, false, usage_mask
, &key
));
920 RestoreJwkOctDictionary(&dict
);
922 // Fail on missing kty.
923 dict
.Remove("kty", NULL
);
924 EXPECT_FALSE(ImportKeyJwk(
925 MakeJsonVector(dict
), algorithm
, false, usage_mask
, &key
));
926 RestoreJwkOctDictionary(&dict
);
928 // Fail on invalid use.
929 dict
.SetString("use", "foo");
930 EXPECT_FALSE(ImportKeyJwk(
931 MakeJsonVector(dict
), algorithm
, false, usage_mask
, &key
));
932 RestoreJwkOctDictionary(&dict
);
935 TEST_F(WebCryptoImplTest
, ImportJwkOctFailures
) {
937 base::DictionaryValue dict
;
938 RestoreJwkOctDictionary(&dict
);
939 blink::WebCryptoAlgorithm algorithm
=
940 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
);
941 blink::WebCryptoKeyUsageMask usage_mask
= blink::WebCryptoKeyUsageEncrypt
;
942 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
945 EXPECT_TRUE(ImportKeyJwk(
946 MakeJsonVector(dict
), algorithm
, false, usage_mask
, &key
));
947 EXPECT_EQ(algorithm
.id(), key
.algorithm().id());
948 EXPECT_FALSE(key
.extractable());
949 EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt
, key
.usages());
950 EXPECT_EQ(blink::WebCryptoKeyTypeSecret
, key
.type());
952 // The following are specific failure cases for when kty = "oct".
954 // Fail on missing k.
955 dict
.Remove("k", NULL
);
956 EXPECT_FALSE(ImportKeyJwk(
957 MakeJsonVector(dict
), algorithm
, false, usage_mask
, &key
));
958 RestoreJwkOctDictionary(&dict
);
960 // Fail on bad b64 encoding for k.
961 dict
.SetString("k", "Qk3f0DsytU8lfza2au #$% Htaw2xpop9GYyTuH0p5GghxTI=");
962 EXPECT_FALSE(ImportKeyJwk(
963 MakeJsonVector(dict
), algorithm
, false, usage_mask
, &key
));
964 RestoreJwkOctDictionary(&dict
);
967 dict
.SetString("k", "");
968 EXPECT_FALSE(ImportKeyJwk(
969 MakeJsonVector(dict
), algorithm
, false, usage_mask
, &key
));
970 RestoreJwkOctDictionary(&dict
);
972 // Fail on k actual length (120 bits) inconsistent with the embedded JWK alg
973 // value (128) for an AES key.
974 dict
.SetString("k", "AVj42h0Y5aqGtE3yluKL");
975 EXPECT_FALSE(ImportKeyJwk(
976 MakeJsonVector(dict
), algorithm
, false, usage_mask
, &key
));
977 RestoreJwkOctDictionary(&dict
);
980 TEST_F(WebCryptoImplTest
, MAYBE(ImportJwkRsaFailures
)) {
982 base::DictionaryValue dict
;
983 RestoreJwkRsaDictionary(&dict
);
984 blink::WebCryptoAlgorithm algorithm
=
985 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5
);
986 blink::WebCryptoKeyUsageMask usage_mask
= blink::WebCryptoKeyUsageEncrypt
;
987 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
989 // An RSA public key JWK _must_ have an "n" (modulus) and an "e" (exponent)
990 // entry, while an RSA private key must have those plus at least a "d"
991 // (private exponent) entry.
992 // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18,
996 EXPECT_TRUE(ImportKeyJwk(
997 MakeJsonVector(dict
), algorithm
, false, usage_mask
, &key
));
998 EXPECT_EQ(algorithm
.id(), key
.algorithm().id());
999 EXPECT_FALSE(key
.extractable());
1000 EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt
, key
.usages());
1001 EXPECT_EQ(blink::WebCryptoKeyTypePublic
, key
.type());
1003 // The following are specific failure cases for when kty = "RSA".
1005 // Fail if either "n" or "e" is not present or malformed.
1006 const std::string kKtyParmName
[] = {"n", "e"};
1007 for (size_t idx
= 0; idx
< ARRAYSIZE_UNSAFE(kKtyParmName
); ++idx
) {
1009 // Fail on missing parameter.
1010 dict
.Remove(kKtyParmName
[idx
], NULL
);
1011 EXPECT_FALSE(ImportKeyJwk(
1012 MakeJsonVector(dict
), algorithm
, false, usage_mask
, &key
));
1013 RestoreJwkRsaDictionary(&dict
);
1015 // Fail on bad b64 parameter encoding.
1016 dict
.SetString(kKtyParmName
[idx
], "Qk3f0DsytU8lfza2au #$% Htaw2xpop9yTuH0");
1017 EXPECT_FALSE(ImportKeyJwk(
1018 MakeJsonVector(dict
), algorithm
, false, usage_mask
, &key
));
1019 RestoreJwkRsaDictionary(&dict
);
1021 // Fail on empty parameter.
1022 dict
.SetString(kKtyParmName
[idx
], "");
1023 EXPECT_FALSE(ImportKeyJwk(
1024 MakeJsonVector(dict
), algorithm
, false, usage_mask
, &key
));
1025 RestoreJwkRsaDictionary(&dict
);
1028 // Fail if "d" parameter is present, implying the JWK is a private key, which
1029 // is not supported.
1030 dict
.SetString("d", "Qk3f0Dsyt");
1031 EXPECT_FALSE(ImportKeyJwk(
1032 MakeJsonVector(dict
), algorithm
, false, usage_mask
, &key
));
1033 RestoreJwkRsaDictionary(&dict
);
1036 TEST_F(WebCryptoImplTest
, MAYBE(ImportJwkInputConsistency
)) {
1037 // The Web Crypto spec says that if a JWK value is present, but is
1038 // inconsistent with the input value, the operation must fail.
1040 // Consistency rules when JWK value is not present: Inputs should be used.
1041 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
1042 bool extractable
= false;
1043 blink::WebCryptoAlgorithm algorithm
=
1044 webcrypto::CreateHmacAlgorithmByHashId(blink::WebCryptoAlgorithmIdSha256
);
1045 blink::WebCryptoKeyUsageMask usage_mask
= blink::WebCryptoKeyUsageVerify
;
1046 base::DictionaryValue dict
;
1047 dict
.SetString("kty", "oct");
1048 dict
.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg");
1049 std::vector
<uint8
> json_vec
= MakeJsonVector(dict
);
1050 EXPECT_TRUE(ImportKeyJwk(json_vec
, algorithm
, extractable
, usage_mask
, &key
));
1051 EXPECT_TRUE(key
.handle());
1052 EXPECT_EQ(blink::WebCryptoKeyTypeSecret
, key
.type());
1053 EXPECT_EQ(extractable
, key
.extractable());
1054 EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac
, key
.algorithm().id());
1055 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256
,
1056 key
.algorithm().hmacParams()->hash().id());
1057 EXPECT_EQ(blink::WebCryptoKeyUsageVerify
, key
.usages());
1058 key
= blink::WebCryptoKey::createNull();
1060 // Consistency rules when JWK value exists: Fail if inconsistency is found.
1062 // Pass: All input values are consistent with the JWK values.
1064 dict
.SetString("kty", "oct");
1065 dict
.SetString("alg", "HS256");
1066 dict
.SetString("use", "sig");
1067 dict
.SetBoolean("extractable", false);
1068 dict
.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg");
1069 json_vec
= MakeJsonVector(dict
);
1070 EXPECT_TRUE(ImportKeyJwk(json_vec
, algorithm
, extractable
, usage_mask
, &key
));
1072 // Extractable cases:
1073 // 1. input=T, JWK=F ==> fail (inconsistent)
1074 // 4. input=F, JWK=F ==> pass, result extractable is F
1075 // 2. input=T, JWK=T ==> pass, result extractable is T
1076 // 3. input=F, JWK=T ==> pass, result extractable is F
1077 EXPECT_FALSE(ImportKeyJwk(json_vec
, algorithm
, true, usage_mask
, &key
));
1078 EXPECT_TRUE(ImportKeyJwk(json_vec
, algorithm
, false, usage_mask
, &key
));
1079 EXPECT_FALSE(key
.extractable());
1080 dict
.SetBoolean("extractable", true);
1082 ImportKeyJwk(MakeJsonVector(dict
), algorithm
, true, usage_mask
, &key
));
1083 EXPECT_TRUE(key
.extractable());
1085 ImportKeyJwk(MakeJsonVector(dict
), algorithm
, false, usage_mask
, &key
));
1086 EXPECT_FALSE(key
.extractable());
1087 dict
.SetBoolean("extractable", true); // restore previous value
1089 // Fail: Input algorithm (AES-CBC) is inconsistent with JWK value
1091 EXPECT_FALSE(ImportKeyJwk(
1093 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
1098 // Fail: Input algorithm (HMAC SHA1) is inconsistent with JWK value
1100 EXPECT_FALSE(ImportKeyJwk(
1102 webcrypto::CreateHmacAlgorithmByHashId(blink::WebCryptoAlgorithmIdSha1
),
1107 // Pass: JWK alg valid but input algorithm isNull: use JWK algorithm value.
1108 EXPECT_TRUE(ImportKeyJwk(json_vec
,
1109 blink::WebCryptoAlgorithm::createNull(),
1113 EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac
, algorithm
.id());
1115 // Pass: JWK alg missing but input algorithm specified: use input value
1116 dict
.Remove("alg", NULL
);
1117 EXPECT_TRUE(ImportKeyJwk(
1118 MakeJsonVector(dict
),
1119 webcrypto::CreateHmacAlgorithmByHashId(blink::WebCryptoAlgorithmIdSha256
),
1123 EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac
, algorithm
.id());
1124 dict
.SetString("alg", "HS256");
1126 // Fail: Input usage_mask (encrypt) is not a subset of the JWK value
1128 EXPECT_FALSE(ImportKeyJwk(
1129 json_vec
, algorithm
, extractable
, blink::WebCryptoKeyUsageEncrypt
, &key
));
1131 // Fail: Input usage_mask (encrypt|sign|verify) is not a subset of the JWK
1132 // value (sign|verify)
1133 usage_mask
= blink::WebCryptoKeyUsageEncrypt
| blink::WebCryptoKeyUsageSign
|
1134 blink::WebCryptoKeyUsageVerify
;
1136 ImportKeyJwk(json_vec
, algorithm
, extractable
, usage_mask
, &key
));
1137 usage_mask
= blink::WebCryptoKeyUsageSign
| blink::WebCryptoKeyUsageVerify
;
1139 // TODO(padolph): kty vs alg consistency tests: Depending on the kty value,
1140 // only certain alg values are permitted. For example, when kty = "RSA" alg
1141 // must be of the RSA family, or when kty = "oct" alg must be symmetric
1145 TEST_F(WebCryptoImplTest
, MAYBE(ImportJwkHappy
)) {
1147 // This test verifies the happy path of JWK import, including the application
1148 // of the imported key material.
1150 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
1151 bool extractable
= false;
1152 blink::WebCryptoAlgorithm algorithm
=
1153 webcrypto::CreateHmacAlgorithmByHashId(blink::WebCryptoAlgorithmIdSha256
);
1154 blink::WebCryptoKeyUsageMask usage_mask
= blink::WebCryptoKeyUsageSign
;
1156 // Import a symmetric key JWK and HMAC-SHA256 sign()
1157 // Uses the first SHA256 test vector from the HMAC sample set above.
1159 base::DictionaryValue dict
;
1160 dict
.SetString("kty", "oct");
1161 dict
.SetString("alg", "HS256");
1162 dict
.SetString("use", "sig");
1163 dict
.SetBoolean("extractable", false);
1164 dict
.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg");
1165 std::vector
<uint8
> json_vec
= MakeJsonVector(dict
);
1167 ASSERT_TRUE(ImportKeyJwk(json_vec
, algorithm
, extractable
, usage_mask
, &key
));
1169 const std::vector
<uint8
> message_raw
= HexStringToBytes(
1170 "b1689c2591eaf3c9e66070f8a77954ffb81749f1b00346f9dfe0b2ee905dcc288baf4a"
1171 "92de3f4001dd9f44c468c3d07d6c6ee82faceafc97c2fc0fc0601719d2dcd0aa2aec92"
1172 "d1b0ae933c65eb06a03c9c935c2bad0459810241347ab87e9f11adb30415424c6c7f5f"
1173 "22a003b8ab8de54f6ded0e3ab9245fa79568451dfa258e");
1175 blink::WebArrayBuffer output
;
1177 ASSERT_TRUE(SignInternal(algorithm
, key
, message_raw
, &output
));
1179 const std::string mac_raw
=
1180 "769f00d3e6a6cc1fb426a14a4f76c6462e6149726e0dee0ec0cf97a16605ac8b";
1182 ExpectArrayBufferMatchesHex(mac_raw
, output
);
1184 // TODO(padolph): Import an RSA public key JWK and use it
1187 TEST_F(WebCryptoImplTest
, MAYBE(ImportExportSpki
)) {
1188 // openssl genrsa -out pair.pem 2048
1189 // openssl rsa -in pair.pem -out pubkey.der -outform DER -pubout
1190 // xxd -p pubkey.der
1191 const std::string hex_rsa_spki_der
=
1192 "30820122300d06092a864886f70d01010105000382010f003082010a0282"
1193 "010100f19e40f94e3780858701577a571cca000cb9795db89ddf8e98ab0e"
1194 "5eecfa47516cb08dc591cae5ab7fa43d6db402e95991d4a2de52e7cd3a66"
1195 "4f58284be2eb4675d5a849a2582c585d2b3c6c225a8f2c53a0414d5dbd06"
1196 "172371cefdf953e9ec3000fc9ad000743023f74e82d12aa93917a2c9b832"
1197 "696085ee0711154cf98a6d098f44cee00ea3b7584236503a5483ba8b6792"
1198 "fee588d1a8f4a0618333c4cb3447d760b43d5a0d9ed6ef79763df670cd8b"
1199 "5eb869a20833f1e3e6d8b88240a5d4335c73fd20487f2a7d112af8692357"
1200 "6425e44a273e5ad2e93d6b50a28e65f9e133958e4f0c7d12e0adc90fedd4"
1201 "f6b6848e7b6900666642a08b520a6534a35d4f0203010001";
1203 // Passing case: Import a valid RSA key in SPKI format.
1204 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
1205 ASSERT_TRUE(ImportKeyInternal(
1206 blink::WebCryptoKeyFormatSpki
,
1207 HexStringToBytes(hex_rsa_spki_der
),
1208 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5
),
1210 blink::WebCryptoKeyUsageEncrypt
,
1212 EXPECT_TRUE(key
.handle());
1213 EXPECT_EQ(blink::WebCryptoKeyTypePublic
, key
.type());
1214 EXPECT_TRUE(key
.extractable());
1215 EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt
, key
.usages());
1217 // Failing case: Empty SPKI data
1218 EXPECT_FALSE(ImportKeyInternal(
1219 blink::WebCryptoKeyFormatSpki
,
1220 std::vector
<uint8
>(),
1221 blink::WebCryptoAlgorithm::createNull(),
1223 blink::WebCryptoKeyUsageEncrypt
,
1226 // Failing case: Import RSA key with NULL input algorithm. This is not
1227 // allowed because the SPKI ASN.1 format for RSA keys is not specific enough
1228 // to map to a Web Crypto algorithm.
1229 EXPECT_FALSE(ImportKeyInternal(
1230 blink::WebCryptoKeyFormatSpki
,
1231 HexStringToBytes(hex_rsa_spki_der
),
1232 blink::WebCryptoAlgorithm::createNull(),
1234 blink::WebCryptoKeyUsageEncrypt
,
1237 // Failing case: Bad DER encoding.
1238 EXPECT_FALSE(ImportKeyInternal(
1239 blink::WebCryptoKeyFormatSpki
,
1240 HexStringToBytes("618333c4cb"),
1241 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5
),
1243 blink::WebCryptoKeyUsageEncrypt
,
1246 // Failing case: Import RSA key but provide an inconsistent input algorithm.
1247 EXPECT_FALSE(ImportKeyInternal(
1248 blink::WebCryptoKeyFormatSpki
,
1249 HexStringToBytes(hex_rsa_spki_der
),
1250 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
1252 blink::WebCryptoKeyUsageEncrypt
,
1255 // Passing case: Export a previously imported RSA public key in SPKI format
1256 // and compare to original data.
1257 blink::WebArrayBuffer output
;
1258 ASSERT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatSpki
, key
, &output
));
1259 ExpectArrayBufferMatchesHex(hex_rsa_spki_der
, output
);
1261 // Failing case: Try to export a previously imported RSA public key in raw
1262 // format (not allowed for a public key).
1263 EXPECT_FALSE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw
, key
, &output
));
1265 // Failing case: Try to export a non-extractable key
1266 ASSERT_TRUE(ImportKeyInternal(
1267 blink::WebCryptoKeyFormatSpki
,
1268 HexStringToBytes(hex_rsa_spki_der
),
1269 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5
),
1271 blink::WebCryptoKeyUsageEncrypt
,
1273 EXPECT_TRUE(key
.handle());
1274 EXPECT_FALSE(key
.extractable());
1275 EXPECT_FALSE(ExportKeyInternal(blink::WebCryptoKeyFormatSpki
, key
, &output
));
1278 TEST_F(WebCryptoImplTest
, MAYBE(ImportPkcs8
)) {
1280 // The following is a DER-encoded PKCS#8 representation of the RSA key from
1281 // Example 1 of NIST's "Test vectors for RSA PKCS#1 v1.5 Signature".
1282 // ftp://ftp.rsa.com/pub/rsalabs/tmp/pkcs1v15sign-vectors.txt
1283 const std::string hex_rsa_pkcs8_der
=
1284 "30820275020100300D06092A864886F70D01010105000482025F3082025B020100028181"
1285 "00A56E4A0E701017589A5187DC7EA841D156F2EC0E36AD52A44DFEB1E61F7AD991D8C510"
1286 "56FFEDB162B4C0F283A12A88A394DFF526AB7291CBB307CEABFCE0B1DFD5CD9508096D5B"
1287 "2B8B6DF5D671EF6377C0921CB23C270A70E2598E6FF89D19F105ACC2D3F0CB35F29280E1"
1288 "386B6F64C4EF22E1E1F20D0CE8CFFB2249BD9A2137020301000102818033A5042A90B27D"
1289 "4F5451CA9BBBD0B44771A101AF884340AEF9885F2A4BBE92E894A724AC3C568C8F97853A"
1290 "D07C0266C8C6A3CA0929F1E8F11231884429FC4D9AE55FEE896A10CE707C3ED7E734E447"
1291 "27A39574501A532683109C2ABACABA283C31B4BD2F53C3EE37E352CEE34F9E503BD80C06"
1292 "22AD79C6DCEE883547C6A3B325024100E7E8942720A877517273A356053EA2A1BC0C94AA"
1293 "72D55C6E86296B2DFC967948C0A72CBCCCA7EACB35706E09A1DF55A1535BD9B3CC34160B"
1294 "3B6DCD3EDA8E6443024100B69DCA1CF7D4D7EC81E75B90FCCA874ABCDE123FD2700180AA"
1295 "90479B6E48DE8D67ED24F9F19D85BA275874F542CD20DC723E6963364A1F9425452B269A"
1296 "6799FD024028FA13938655BE1F8A159CBACA5A72EA190C30089E19CD274A556F36C4F6E1"
1297 "9F554B34C077790427BBDD8DD3EDE2448328F385D81B30E8E43B2FFFA02786197902401A"
1298 "8B38F398FA712049898D7FB79EE0A77668791299CDFA09EFC0E507ACB21ED74301EF5BFD"
1299 "48BE455EAEB6E1678255827580A8E4E8E14151D1510A82A3F2E729024027156ABA4126D2"
1300 "4A81F3A528CBFB27F56886F840A9F6E86E17A44B94FE9319584B8E22FDDE1E5A2E3BD8AA"
1301 "5BA8D8584194EB2190ACF832B847F13A3D24A79F4D";
1303 // Passing case: Import a valid RSA key in PKCS#8 format.
1304 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
1305 ASSERT_TRUE(ImportKeyInternal(
1306 blink::WebCryptoKeyFormatPkcs8
,
1307 HexStringToBytes(hex_rsa_pkcs8_der
),
1308 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
),
1310 blink::WebCryptoKeyUsageSign
,
1312 EXPECT_TRUE(key
.handle());
1313 EXPECT_EQ(blink::WebCryptoKeyTypePrivate
, key
.type());
1314 EXPECT_TRUE(key
.extractable());
1315 EXPECT_EQ(blink::WebCryptoKeyUsageSign
, key
.usages());
1317 // Failing case: Empty PKCS#8 data
1318 EXPECT_FALSE(ImportKeyInternal(
1319 blink::WebCryptoKeyFormatPkcs8
,
1320 std::vector
<uint8
>(),
1321 blink::WebCryptoAlgorithm::createNull(),
1323 blink::WebCryptoKeyUsageSign
,
1326 // Failing case: Import RSA key with NULL input algorithm. This is not
1327 // allowed because the PKCS#8 ASN.1 format for RSA keys is not specific enough
1328 // to map to a Web Crypto algorithm.
1329 EXPECT_FALSE(ImportKeyInternal(
1330 blink::WebCryptoKeyFormatPkcs8
,
1331 HexStringToBytes(hex_rsa_pkcs8_der
),
1332 blink::WebCryptoAlgorithm::createNull(),
1334 blink::WebCryptoKeyUsageSign
,
1337 // Failing case: Bad DER encoding.
1338 EXPECT_FALSE(ImportKeyInternal(
1339 blink::WebCryptoKeyFormatPkcs8
,
1340 HexStringToBytes("618333c4cb"),
1341 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
),
1343 blink::WebCryptoKeyUsageSign
,
1346 // Failing case: Import RSA key but provide an inconsistent input algorithm.
1347 EXPECT_FALSE(ImportKeyInternal(
1348 blink::WebCryptoKeyFormatPkcs8
,
1349 HexStringToBytes(hex_rsa_pkcs8_der
),
1350 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
1352 blink::WebCryptoKeyUsageSign
,
1356 TEST_F(WebCryptoImplTest
, MAYBE(GenerateKeyPairRsa
)) {
1357 // Note: using unrealistic short key lengths here to avoid bogging down tests.
1359 // Successful WebCryptoAlgorithmIdRsaEsPkcs1v1_5 key generation.
1360 const unsigned modulus_length
= 256;
1361 const std::vector
<uint8
> public_exponent
= HexStringToBytes("010001");
1362 blink::WebCryptoAlgorithm algorithm
= webcrypto::CreateRsaKeyGenAlgorithm(
1363 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5
,
1366 bool extractable
= false;
1367 const blink::WebCryptoKeyUsageMask usage_mask
= 0;
1368 blink::WebCryptoKey public_key
= blink::WebCryptoKey::createNull();
1369 blink::WebCryptoKey private_key
= blink::WebCryptoKey::createNull();
1370 EXPECT_TRUE(GenerateKeyPairInternal(
1371 algorithm
, extractable
, usage_mask
, &public_key
, &private_key
));
1372 EXPECT_FALSE(public_key
.isNull());
1373 EXPECT_FALSE(private_key
.isNull());
1374 EXPECT_EQ(blink::WebCryptoKeyTypePublic
, public_key
.type());
1375 EXPECT_EQ(blink::WebCryptoKeyTypePrivate
, private_key
.type());
1376 EXPECT_EQ(true, public_key
.extractable());
1377 EXPECT_EQ(extractable
, private_key
.extractable());
1378 EXPECT_EQ(usage_mask
, public_key
.usages());
1379 EXPECT_EQ(usage_mask
, private_key
.usages());
1381 // Fail with bad modulus.
1382 algorithm
= webcrypto::CreateRsaKeyGenAlgorithm(
1383 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5
, 0, public_exponent
);
1384 EXPECT_FALSE(GenerateKeyPairInternal(
1385 algorithm
, extractable
, usage_mask
, &public_key
, &private_key
));
1387 // Fail with bad exponent: larger than unsigned long.
1388 unsigned exponent_length
= sizeof(unsigned long) + 1; // NOLINT
1389 const std::vector
<uint8
> long_exponent(exponent_length
, 0x01);
1390 algorithm
= webcrypto::CreateRsaKeyGenAlgorithm(
1391 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5
, modulus_length
, long_exponent
);
1392 EXPECT_FALSE(GenerateKeyPairInternal(
1393 algorithm
, extractable
, usage_mask
, &public_key
, &private_key
));
1395 // Fail with bad exponent: empty.
1396 const std::vector
<uint8
> empty_exponent
;
1397 algorithm
= webcrypto::CreateRsaKeyGenAlgorithm(
1398 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5
,
1401 EXPECT_FALSE(GenerateKeyPairInternal(
1402 algorithm
, extractable
, usage_mask
, &public_key
, &private_key
));
1404 // Fail with bad exponent: all zeros.
1405 std::vector
<uint8
> exponent_with_leading_zeros(15, 0x00);
1406 algorithm
= webcrypto::CreateRsaKeyGenAlgorithm(
1407 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5
,
1409 exponent_with_leading_zeros
);
1410 EXPECT_FALSE(GenerateKeyPairInternal(
1411 algorithm
, extractable
, usage_mask
, &public_key
, &private_key
));
1413 // Key generation success using exponent with leading zeros.
1414 exponent_with_leading_zeros
.insert(exponent_with_leading_zeros
.end(),
1415 public_exponent
.begin(),
1416 public_exponent
.end());
1417 algorithm
= webcrypto::CreateRsaKeyGenAlgorithm(
1418 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5
,
1420 exponent_with_leading_zeros
);
1421 EXPECT_TRUE(GenerateKeyPairInternal(
1422 algorithm
, extractable
, usage_mask
, &public_key
, &private_key
));
1423 EXPECT_FALSE(public_key
.isNull());
1424 EXPECT_FALSE(private_key
.isNull());
1425 EXPECT_EQ(blink::WebCryptoKeyTypePublic
, public_key
.type());
1426 EXPECT_EQ(blink::WebCryptoKeyTypePrivate
, private_key
.type());
1427 EXPECT_EQ(true, public_key
.extractable());
1428 EXPECT_EQ(extractable
, private_key
.extractable());
1429 EXPECT_EQ(usage_mask
, public_key
.usages());
1430 EXPECT_EQ(usage_mask
, private_key
.usages());
1432 // Successful WebCryptoAlgorithmIdRsaOaep key generation.
1433 algorithm
= webcrypto::CreateRsaKeyGenAlgorithm(
1434 blink::WebCryptoAlgorithmIdRsaOaep
, modulus_length
, public_exponent
);
1435 EXPECT_TRUE(GenerateKeyPairInternal(
1436 algorithm
, extractable
, usage_mask
, &public_key
, &private_key
));
1437 EXPECT_FALSE(public_key
.isNull());
1438 EXPECT_FALSE(private_key
.isNull());
1439 EXPECT_EQ(blink::WebCryptoKeyTypePublic
, public_key
.type());
1440 EXPECT_EQ(blink::WebCryptoKeyTypePrivate
, private_key
.type());
1441 EXPECT_EQ(true, public_key
.extractable());
1442 EXPECT_EQ(extractable
, private_key
.extractable());
1443 EXPECT_EQ(usage_mask
, public_key
.usages());
1444 EXPECT_EQ(usage_mask
, private_key
.usages());
1446 // Successful WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 key generation.
1447 algorithm
= webcrypto::CreateRsaKeyGenAlgorithm(
1448 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
1451 EXPECT_TRUE(GenerateKeyPairInternal(
1452 algorithm
, extractable
, usage_mask
, &public_key
, &private_key
));
1453 EXPECT_FALSE(public_key
.isNull());
1454 EXPECT_FALSE(private_key
.isNull());
1455 EXPECT_EQ(blink::WebCryptoKeyTypePublic
, public_key
.type());
1456 EXPECT_EQ(blink::WebCryptoKeyTypePrivate
, private_key
.type());
1457 EXPECT_EQ(true, public_key
.extractable());
1458 EXPECT_EQ(extractable
, private_key
.extractable());
1459 EXPECT_EQ(usage_mask
, public_key
.usages());
1460 EXPECT_EQ(usage_mask
, private_key
.usages());
1462 // Fail SPKI export of private key. This is an ExportKey test, but do it here
1463 // since it is expensive to generate an RSA key pair and we already have a
1464 // private key here.
1465 blink::WebArrayBuffer output
;
1467 ExportKeyInternal(blink::WebCryptoKeyFormatSpki
, private_key
, &output
));
1470 TEST_F(WebCryptoImplTest
, MAYBE(RsaEsRoundTrip
)) {
1471 // Note: using unrealistic short key length here to avoid bogging down tests.
1473 // Create a key pair.
1474 const unsigned kModulusLength
= 256;
1475 blink::WebCryptoAlgorithm algorithm
=
1476 webcrypto::CreateRsaKeyGenAlgorithm(
1477 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5
,
1479 HexStringToBytes("010001"));
1480 const blink::WebCryptoKeyUsageMask usage_mask
=
1481 blink::WebCryptoKeyUsageEncrypt
| blink::WebCryptoKeyUsageDecrypt
;
1482 blink::WebCryptoKey public_key
= blink::WebCryptoKey::createNull();
1483 blink::WebCryptoKey private_key
= blink::WebCryptoKey::createNull();
1484 EXPECT_TRUE(GenerateKeyPairInternal(
1485 algorithm
, false, usage_mask
, &public_key
, &private_key
));
1486 EXPECT_FALSE(public_key
.isNull());
1487 EXPECT_FALSE(private_key
.isNull());
1489 // Make a maximum-length data message. RSAES can operate on messages up to
1490 // length of k - 11 bytes, where k is the octet length of the RSA modulus.
1491 const unsigned kMaxMsgSizeBytes
= kModulusLength
/ 8 - 11;
1492 // There are two hex chars for each byte.
1493 const unsigned kMsgHexSize
= kMaxMsgSizeBytes
* 2;
1494 char max_data_hex
[kMsgHexSize
+1];
1495 std::fill(&max_data_hex
[0], &max_data_hex
[0] + kMsgHexSize
, 'a');
1496 max_data_hex
[kMsgHexSize
] = '\0';
1498 // Verify encrypt / decrypt round trip on a few messages. Note that RSA
1499 // encryption does not support empty input.
1501 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5
);
1502 const char* const kTestDataHex
[] = {
1504 "0102030405060708090a0b0c0d0e0f",
1507 blink::WebArrayBuffer encrypted_data
;
1508 blink::WebArrayBuffer decrypted_data
;
1509 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(kTestDataHex
); ++i
) {
1511 ASSERT_TRUE(EncryptInternal(
1514 HexStringToBytes(kTestDataHex
[i
]),
1516 EXPECT_EQ(kModulusLength
/8, encrypted_data
.byteLength());
1517 ASSERT_TRUE(DecryptInternal(
1520 reinterpret_cast<const unsigned char*>(encrypted_data
.data()),
1521 encrypted_data
.byteLength(),
1523 ExpectArrayBufferMatchesHex(kTestDataHex
[i
], decrypted_data
);
1527 TEST_F(WebCryptoImplTest
, MAYBE(RsaEsKnownAnswer
)) {
1528 // Because the random data in PKCS1.5 padding makes the encryption output non-
1529 // deterministic, we cannot easily do a typical known-answer test for RSA
1530 // encryption / decryption. Instead we will take a known-good encrypted
1531 // message, decrypt it, re-encrypt it, then decrypt again, verifying that the
1532 // original known cleartext is the result.
1534 // The RSA public and private keys used for this test are produced by the
1535 // openssl command line:
1536 // % openssl genrsa -out pair.pem 1024
1537 // % openssl rsa -in pair.pem -out spki.der -outform DER -pubout
1538 // % openssl pkcs8 -topk8 -inform PEM -outform DER -in pair.pem -out
1539 // pkcs8.der -nocrypt
1540 // % xxd -p spki.der
1541 // % xxd -p pkcs8.der
1542 const std::string rsa_spki_der_hex
=
1543 "30819f300d06092a864886f70d010101050003818d0030818902818100a8"
1544 "d30894b93f376f7822229bfd2483e50da944c4ab803ca31979e0f47e70bf"
1545 "683c687c6b3e80f280a237cea3643fd1f7f10f7cc664dbc2ecd45be53e1c"
1546 "9b15a53c37dbdad846c0f8340c472abc7821e4aa7df185867bf38228ac3e"
1547 "cc1d97d3c8b57e21ea6ba57b2bc3814a436e910ee8ab64a0b7743a927e94"
1548 "4d3420401f7dd50203010001";
1549 const std::string rsa_pkcs8_der_hex
=
1550 "30820276020100300d06092a864886f70d0101010500048202603082025c"
1551 "02010002818100a8d30894b93f376f7822229bfd2483e50da944c4ab803c"
1552 "a31979e0f47e70bf683c687c6b3e80f280a237cea3643fd1f7f10f7cc664"
1553 "dbc2ecd45be53e1c9b15a53c37dbdad846c0f8340c472abc7821e4aa7df1"
1554 "85867bf38228ac3ecc1d97d3c8b57e21ea6ba57b2bc3814a436e910ee8ab"
1555 "64a0b7743a927e944d3420401f7dd5020301000102818100896cdffb50a0"
1556 "691bd00ad9696933243a7c5861a64684e8d74b91aed0d76c28234da9303e"
1557 "8c6ea2f89b141a9d5ea9a4ddd3d8eb9503dcf05ba0b1fd76060b281e3ae4"
1558 "b9d497fb5519bdf1127db8ad412d6a722686c78df3e3002acca960c6b2a2"
1559 "42a83ace5410693c03ce3d74cb9c9a7bacc8e271812920d1f53fee9312ef"
1560 "4eb1024100d09c14418ce92af7cc62f7cdc79836d8c6e3d0d33e7229cc11"
1561 "d732cbac75aa4c56c92e409a3ccbe75d4ce63ac5adca33080690782c6371"
1562 "e3628134c3534ca603024100cf2d3206f6deea2f39b70351c51f85436200"
1563 "5aa8f643e49e22486736d536e040dc30a2b4f9be3ab212a88d1891280874"
1564 "b9a170cdeb22eaf61c27c4b082c7d1470240638411a5b3b307ec6e744802"
1565 "c2d4ba556f8bfe72c7b76e790b89bd91ac13f5c9b51d04138d80b3450c1d"
1566 "4337865601bf96748b36c8f627be719f71ac3c70b441024065ce92cfe34e"
1567 "a58bf173a2b8f3024b4d5282540ac581957db3e11a7f528535ec098808dc"
1568 "a0013ffcb3b88a25716757c86c540e07d2ad8502cdd129118822c30f0240"
1569 "420a4983040e9db46eb29f1315a0d7b41cf60428f7460fce748e9a1a7d22"
1570 "d7390fa328948e7e9d1724401374e99d45eb41474781201378a4330e8e80"
1573 // Similarly, the cleartext and public key encrypted ciphertext for this test
1574 // are also produced by openssl. Note that since we are using a 1024-bit key,
1575 // the cleartext size must be less than or equal to 117 bytes (modulusLength /
1577 // % openssl rand -out cleartext.bin 64
1578 // % openssl rsautl -encrypt -inkey spki.der -keyform DER -pubin -in
1579 // cleartext.bin -out ciphertext.bin
1580 // % xxd -p cleartext.bin
1581 // % xxd -p ciphertext.bin
1582 const std::string cleartext_hex
=
1583 "ec358ed141c45d7e03d4c6338aebad718e8bcbbf8f8ee6f8d9f4b9ef06d8"
1584 "84739a398c6bcbc688418b2ff64761dc0ccd40e7d52bed03e06946d0957a"
1586 const std::string ciphertext_hex
=
1587 "6106441c2b7a4b1a16260ed1ae4fe6135247345dc8e674754bbda6588c6c"
1588 "0d95a3d4d26bb34cdbcbe327723e80343bd7a15cd4c91c3a44e6cb9c6cd6"
1589 "7ad2e8bf41523188d9b36dc364a838642dcbc2c25e85dfb2106ba47578ca"
1590 "3bbf8915055aea4fa7c3cbfdfbcc163f04c234fb6d847f39bab9612ecbee"
1593 // Import the public key.
1594 const blink::WebCryptoAlgorithm algorithm
=
1595 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5
);
1596 blink::WebCryptoKey public_key
= blink::WebCryptoKey::createNull();
1597 ASSERT_TRUE(ImportKeyInternal(
1598 blink::WebCryptoKeyFormatSpki
,
1599 HexStringToBytes(rsa_spki_der_hex
),
1602 blink::WebCryptoKeyUsageEncrypt
,
1604 EXPECT_FALSE(public_key
.isNull());
1605 EXPECT_TRUE(public_key
.handle());
1607 // Import the private key.
1608 blink::WebCryptoKey private_key
= blink::WebCryptoKey::createNull();
1609 ASSERT_TRUE(ImportKeyInternal(
1610 blink::WebCryptoKeyFormatPkcs8
,
1611 HexStringToBytes(rsa_pkcs8_der_hex
),
1614 blink::WebCryptoKeyUsageDecrypt
,
1616 EXPECT_FALSE(private_key
.isNull());
1617 EXPECT_TRUE(private_key
.handle());
1619 // Decrypt the known-good ciphertext with the private key. As a check we must
1620 // get the known original cleartext.
1621 blink::WebArrayBuffer decrypted_data
;
1622 ASSERT_TRUE(DecryptInternal(
1625 HexStringToBytes(ciphertext_hex
),
1627 EXPECT_FALSE(decrypted_data
.isNull());
1628 ExpectArrayBufferMatchesHex(cleartext_hex
, decrypted_data
);
1630 // Encrypt this decrypted data with the public key.
1631 blink::WebArrayBuffer encrypted_data
;
1632 ASSERT_TRUE(EncryptInternal(
1635 reinterpret_cast<const unsigned char*>(decrypted_data
.data()),
1636 decrypted_data
.byteLength(),
1638 EXPECT_EQ(128u, encrypted_data
.byteLength());
1640 // Finally, decrypt the newly encrypted result with the private key, and
1641 // compare to the known original cleartext.
1642 decrypted_data
.reset();
1643 ASSERT_TRUE(DecryptInternal(
1646 reinterpret_cast<const unsigned char*>(encrypted_data
.data()),
1647 encrypted_data
.byteLength(),
1649 EXPECT_FALSE(decrypted_data
.isNull());
1650 ExpectArrayBufferMatchesHex(cleartext_hex
, decrypted_data
);
1653 TEST_F(WebCryptoImplTest
, MAYBE(RsaEsFailures
)) {
1654 // Note: using unrealistic short key length here to avoid bogging down tests.
1656 // Create a key pair.
1657 const unsigned kModulusLength
= 256;
1658 blink::WebCryptoAlgorithm algorithm
=
1659 webcrypto::CreateRsaKeyGenAlgorithm(
1660 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5
,
1662 HexStringToBytes("010001"));
1663 const blink::WebCryptoKeyUsageMask usage_mask
=
1664 blink::WebCryptoKeyUsageEncrypt
| blink::WebCryptoKeyUsageDecrypt
;
1665 blink::WebCryptoKey public_key
= blink::WebCryptoKey::createNull();
1666 blink::WebCryptoKey private_key
= blink::WebCryptoKey::createNull();
1667 EXPECT_TRUE(GenerateKeyPairInternal(
1668 algorithm
, false, usage_mask
, &public_key
, &private_key
));
1669 EXPECT_FALSE(public_key
.isNull());
1670 EXPECT_FALSE(private_key
.isNull());
1672 // Fail encrypt with a private key.
1674 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5
);
1675 blink::WebArrayBuffer encrypted_data
;
1676 const std::string
message_hex_str("0102030405060708090a0b0c0d0e0f");
1677 const std::vector
<uint8
> message_hex(HexStringToBytes(message_hex_str
));
1679 EncryptInternal(algorithm
, private_key
, message_hex
, &encrypted_data
));
1681 // Fail encrypt with empty message.
1682 EXPECT_FALSE(EncryptInternal(
1683 algorithm
, public_key
, std::vector
<uint8
>(), &encrypted_data
));
1685 // Fail encrypt with message too large. RSAES can operate on messages up to
1686 // length of k - 11 bytes, where k is the octet length of the RSA modulus.
1687 const unsigned kMaxMsgSizeBytes
= kModulusLength
/ 8 - 11;
1688 EXPECT_FALSE(EncryptInternal(algorithm
,
1690 std::vector
<uint8
>(kMaxMsgSizeBytes
+ 1, '0'),
1693 // Generate encrypted data.
1695 EncryptInternal(algorithm
, public_key
, message_hex
, &encrypted_data
));
1697 // Fail decrypt with a public key.
1698 blink::WebArrayBuffer decrypted_data
;
1699 EXPECT_FALSE(DecryptInternal(
1702 reinterpret_cast<const unsigned char*>(encrypted_data
.data()),
1703 encrypted_data
.byteLength(),
1706 // Corrupt encrypted data; ensure decrypt fails because padding was disrupted.
1707 std::vector
<uint8
> corrupted_data(
1708 static_cast<uint8
*>(encrypted_data
.data()),
1709 static_cast<uint8
*>(encrypted_data
.data()) + encrypted_data
.byteLength());
1710 corrupted_data
[corrupted_data
.size() / 2] ^= 0x01;
1712 DecryptInternal(algorithm
, private_key
, corrupted_data
, &decrypted_data
));
1714 // TODO(padolph): Are there other specific data corruption scenarios to
1717 // Do a successful decrypt with good data just for confirmation.
1718 EXPECT_TRUE(DecryptInternal(
1721 reinterpret_cast<const unsigned char*>(encrypted_data
.data()),
1722 encrypted_data
.byteLength(),
1724 ExpectArrayBufferMatchesHex(message_hex_str
, decrypted_data
);
1727 TEST_F(WebCryptoImplTest
, MAYBE(AesKwKeyImport
)) {
1728 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
1729 blink::WebCryptoAlgorithm algorithm
=
1730 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw
);
1732 // Import a 128-bit Key Encryption Key (KEK)
1733 std::string key_raw_hex_in
= "025a8cf3f08b4f6c5f33bbc76a471939";
1734 ASSERT_TRUE(ImportKeyInternal(blink::WebCryptoKeyFormatRaw
,
1735 HexStringToBytes(key_raw_hex_in
),
1738 blink::WebCryptoKeyUsageWrapKey
,
1740 blink::WebArrayBuffer key_raw_out
;
1741 EXPECT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw
,
1744 ExpectArrayBufferMatchesHex(key_raw_hex_in
, key_raw_out
);
1746 // Import a 192-bit KEK
1747 key_raw_hex_in
= "c0192c6466b2370decbb62b2cfef4384544ffeb4d2fbc103";
1748 ASSERT_TRUE(ImportKeyInternal(blink::WebCryptoKeyFormatRaw
,
1749 HexStringToBytes(key_raw_hex_in
),
1752 blink::WebCryptoKeyUsageWrapKey
,
1754 EXPECT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw
,
1757 ExpectArrayBufferMatchesHex(key_raw_hex_in
, key_raw_out
);
1759 // Import a 256-bit Key Encryption Key (KEK)
1761 "e11fe66380d90fa9ebefb74e0478e78f95664d0c67ca20ce4a0b5842863ac46f";
1762 ASSERT_TRUE(ImportKeyInternal(blink::WebCryptoKeyFormatRaw
,
1763 HexStringToBytes(key_raw_hex_in
),
1766 blink::WebCryptoKeyUsageWrapKey
,
1768 EXPECT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw
,
1771 ExpectArrayBufferMatchesHex(key_raw_hex_in
, key_raw_out
);
1773 // Fail import of 0 length key
1774 EXPECT_FALSE(ImportKeyInternal(blink::WebCryptoKeyFormatRaw
,
1775 HexStringToBytes(""),
1778 blink::WebCryptoKeyUsageWrapKey
,
1781 // Fail import of 124-bit KEK
1782 key_raw_hex_in
= "3e4566a2bdaa10cb68134fa66c15ddb";
1783 EXPECT_FALSE(ImportKeyInternal(blink::WebCryptoKeyFormatRaw
,
1784 HexStringToBytes(key_raw_hex_in
),
1787 blink::WebCryptoKeyUsageWrapKey
,
1790 // Fail import of 200-bit KEK
1791 key_raw_hex_in
= "0a1d88608a5ad9fec64f1ada269ebab4baa2feeb8d95638c0e";
1792 EXPECT_FALSE(ImportKeyInternal(blink::WebCryptoKeyFormatRaw
,
1793 HexStringToBytes(key_raw_hex_in
),
1796 blink::WebCryptoKeyUsageWrapKey
,
1799 // Fail import of 260-bit KEK
1801 "72d4e475ff34215416c9ad9c8281247a4d730c5f275ac23f376e73e3bce8d7d5a";
1802 EXPECT_FALSE(ImportKeyInternal(blink::WebCryptoKeyFormatRaw
,
1803 HexStringToBytes(key_raw_hex_in
),
1806 blink::WebCryptoKeyUsageWrapKey
,
1810 } // namespace content