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 "content/child/webcrypto/shared_crypto.h"
11 #include "base/basictypes.h"
12 #include "base/file_util.h"
13 #include "base/json/json_reader.h"
14 #include "base/json/json_writer.h"
15 #include "base/logging.h"
16 #include "base/memory/ref_counted.h"
17 #include "base/path_service.h"
18 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_util.h"
20 #include "base/strings/stringprintf.h"
21 #include "content/child/webcrypto/crypto_data.h"
22 #include "content/child/webcrypto/status.h"
23 #include "content/child/webcrypto/webcrypto_util.h"
24 #include "content/public/common/content_paths.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h"
27 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
28 #include "third_party/WebKit/public/platform/WebCryptoKey.h"
29 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
30 #include "third_party/re2/re2/re2.h"
32 #if !defined(USE_OPENSSL)
36 #include "crypto/scoped_nss_types.h"
39 // The OpenSSL implementation of WebCrypto is less complete, so don't run all of
40 // the tests: http://crbug.com/267888
41 #if defined(USE_OPENSSL)
42 #define MAYBE(test_name) DISABLED_##test_name
44 #define MAYBE(test_name) test_name
47 #define EXPECT_BYTES_EQ(expected, actual) \
48 EXPECT_EQ(CryptoData(expected), CryptoData(actual))
50 #define EXPECT_BYTES_EQ_HEX(expected_hex, actual_bytes) \
51 EXPECT_BYTES_EQ(HexStringToBytes(expected_hex), actual_bytes)
57 // These functions are used by GTEST to support EXPECT_EQ() for
58 // webcrypto::Status and webcrypto::CryptoData
60 void PrintTo(const Status
& status
, ::std::ostream
* os
) {
61 if (status
.IsSuccess())
64 *os
<< "Error type: " << status
.error_type()
65 << " Error details: " << status
.error_details();
68 bool operator==(const content::webcrypto::Status
& a
,
69 const content::webcrypto::Status
& b
) {
70 if (a
.IsSuccess() != b
.IsSuccess())
74 return a
.error_type() == b
.error_type() &&
75 a
.error_details() == b
.error_details();
78 bool operator!=(const content::webcrypto::Status
& a
,
79 const content::webcrypto::Status
& b
) {
83 void PrintTo(const CryptoData
& data
, ::std::ostream
* os
) {
84 *os
<< "[" << base::HexEncode(data
.bytes(), data
.byte_length()) << "]";
87 bool operator==(const content::webcrypto::CryptoData
& a
,
88 const content::webcrypto::CryptoData
& b
) {
89 return a
.byte_length() == b
.byte_length() &&
90 memcmp(a
.bytes(), b
.bytes(), a
.byte_length()) == 0;
93 bool operator!=(const content::webcrypto::CryptoData
& a
,
94 const content::webcrypto::CryptoData
& b
) {
100 // -----------------------------------------------------------------------------
102 // TODO(eroman): For Linux builds using system NSS, AES-GCM support is a
103 // runtime dependency. Test it by trying to import a key.
104 // TODO(padolph): Consider caching the result of the import key test.
105 bool SupportsAesGcm() {
106 std::vector
<uint8
> key_raw(16, 0);
108 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
109 Status status
= ImportKey(blink::WebCryptoKeyFormatRaw
,
111 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesGcm
),
113 blink::WebCryptoKeyUsageEncrypt
,
116 if (status
.IsError())
117 EXPECT_EQ(Status::ErrorUnsupported(), status
);
118 return status
.IsSuccess();
121 bool SupportsRsaOaep() {
122 #if defined(USE_OPENSSL)
126 if (!NSS_VersionCheck("3.16.2"))
129 crypto::ScopedPK11Slot
slot(PK11_GetInternalKeySlot());
130 return !!PK11_DoesMechanism(slot
.get(), CKM_RSA_PKCS_OAEP
);
134 blink::WebCryptoAlgorithm
CreateRsaHashedKeyGenAlgorithm(
135 blink::WebCryptoAlgorithmId algorithm_id
,
136 const blink::WebCryptoAlgorithmId hash_id
,
137 unsigned int modulus_length
,
138 const std::vector
<uint8
>& public_exponent
) {
139 DCHECK(algorithm_id
== blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
||
140 algorithm_id
== blink::WebCryptoAlgorithmIdRsaOaep
);
141 DCHECK(blink::WebCryptoAlgorithm::isHash(hash_id
));
142 return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
144 new blink::WebCryptoRsaHashedKeyGenParams(
145 CreateAlgorithm(hash_id
),
147 webcrypto::Uint8VectorStart(public_exponent
),
148 public_exponent
.size()));
151 // Creates an RSA-OAEP algorithm
152 blink::WebCryptoAlgorithm
CreateRsaOaepAlgorithm(
153 const std::vector
<uint8
>& label
) {
154 return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
155 blink::WebCryptoAlgorithmIdRsaOaep
,
156 new blink::WebCryptoRsaOaepParams(
157 !label
.empty(), Uint8VectorStart(label
), label
.size()));
160 // Creates an AES-CBC algorithm.
161 blink::WebCryptoAlgorithm
CreateAesCbcAlgorithm(const std::vector
<uint8
>& iv
) {
162 return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
163 blink::WebCryptoAlgorithmIdAesCbc
,
164 new blink::WebCryptoAesCbcParams(Uint8VectorStart(iv
), iv
.size()));
167 // Creates an AES-GCM algorithm.
168 blink::WebCryptoAlgorithm
CreateAesGcmAlgorithm(
169 const std::vector
<uint8
>& iv
,
170 const std::vector
<uint8
>& additional_data
,
171 unsigned int tag_length_bits
) {
172 EXPECT_TRUE(SupportsAesGcm());
173 return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
174 blink::WebCryptoAlgorithmIdAesGcm
,
175 new blink::WebCryptoAesGcmParams(Uint8VectorStart(iv
),
178 Uint8VectorStart(additional_data
),
179 additional_data
.size(),
184 // Creates an HMAC algorithm whose parameters struct is compatible with key
185 // generation. It is an error to call this with a hash_id that is not a SHA*.
186 // The key_length_bits parameter is optional, with zero meaning unspecified.
187 blink::WebCryptoAlgorithm
CreateHmacKeyGenAlgorithm(
188 blink::WebCryptoAlgorithmId hash_id
,
189 unsigned int key_length_bits
) {
190 DCHECK(blink::WebCryptoAlgorithm::isHash(hash_id
));
191 // key_length_bytes == 0 means unspecified
192 return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
193 blink::WebCryptoAlgorithmIdHmac
,
194 new blink::WebCryptoHmacKeyGenParams(
195 CreateAlgorithm(hash_id
), (key_length_bits
!= 0), key_length_bits
));
198 // Returns a slightly modified version of the input vector.
200 // - For non-empty inputs a single bit is inverted.
201 // - For empty inputs, a byte is added.
202 std::vector
<uint8
> Corrupted(const std::vector
<uint8
>& input
) {
203 std::vector
<uint8
> corrupted_data(input
);
204 if (corrupted_data
.empty())
205 corrupted_data
.push_back(0);
206 corrupted_data
[corrupted_data
.size() / 2] ^= 0x01;
207 return corrupted_data
;
210 std::vector
<uint8
> HexStringToBytes(const std::string
& hex
) {
211 std::vector
<uint8
> bytes
;
212 base::HexStringToBytes(hex
, &bytes
);
216 std::vector
<uint8
> MakeJsonVector(const std::string
& json_string
) {
217 return std::vector
<uint8
>(json_string
.begin(), json_string
.end());
220 std::vector
<uint8
> MakeJsonVector(const base::DictionaryValue
& dict
) {
222 base::JSONWriter::Write(&dict
, &json
);
223 return MakeJsonVector(json
);
226 // ----------------------------------------------------------------
227 // Helpers for working with JSON data files for test expectations.
228 // ----------------------------------------------------------------
230 // Reads a file in "src/content/test/data/webcrypto" to a base::Value.
231 // The file must be JSON, however it can also include C++ style comments.
232 ::testing::AssertionResult
ReadJsonTestFile(const char* test_file_name
,
233 scoped_ptr
<base::Value
>* value
) {
234 base::FilePath test_data_dir
;
235 if (!PathService::Get(DIR_TEST_DATA
, &test_data_dir
))
236 return ::testing::AssertionFailure() << "Couldn't retrieve test dir";
238 base::FilePath file_path
=
239 test_data_dir
.AppendASCII("webcrypto").AppendASCII(test_file_name
);
241 std::string file_contents
;
242 if (!base::ReadFileToString(file_path
, &file_contents
)) {
243 return ::testing::AssertionFailure()
244 << "Couldn't read test file: " << file_path
.value();
247 // Strip C++ style comments out of the "json" file, otherwise it cannot be
249 re2::RE2::GlobalReplace(&file_contents
, re2::RE2("\\s*//.*"), "");
251 // Parse the JSON to a dictionary.
252 value
->reset(base::JSONReader::Read(file_contents
));
254 return ::testing::AssertionFailure()
255 << "Couldn't parse test file JSON: " << file_path
.value();
258 return ::testing::AssertionSuccess();
261 // Same as ReadJsonTestFile(), but return the value as a List.
262 ::testing::AssertionResult
ReadJsonTestFileToList(
263 const char* test_file_name
,
264 scoped_ptr
<base::ListValue
>* list
) {
266 scoped_ptr
<base::Value
> json
;
267 ::testing::AssertionResult result
= ReadJsonTestFile(test_file_name
, &json
);
271 // Cast to an ListValue.
272 base::ListValue
* list_value
= NULL
;
273 if (!json
->GetAsList(&list_value
) || !list_value
)
274 return ::testing::AssertionFailure() << "The JSON was not a list";
276 list
->reset(list_value
);
277 ignore_result(json
.release());
279 return ::testing::AssertionSuccess();
282 // Read a string property from the dictionary with path |property_name|
283 // (which can include periods for nested dictionaries). Interprets the
284 // string as a hex encoded string and converts it to a bytes list.
286 // Returns empty vector on failure.
287 std::vector
<uint8
> GetBytesFromHexString(base::DictionaryValue
* dict
,
288 const char* property_name
) {
289 std::string hex_string
;
290 if (!dict
->GetString(property_name
, &hex_string
)) {
291 EXPECT_TRUE(false) << "Couldn't get string property: " << property_name
;
292 return std::vector
<uint8
>();
295 return HexStringToBytes(hex_string
);
298 // Reads a string property with path "property_name" and converts it to a
299 // WebCryptoAlgorith. Returns null algorithm on failure.
300 blink::WebCryptoAlgorithm
GetDigestAlgorithm(base::DictionaryValue
* dict
,
301 const char* property_name
) {
302 std::string algorithm_name
;
303 if (!dict
->GetString(property_name
, &algorithm_name
)) {
304 EXPECT_TRUE(false) << "Couldn't get string property: " << property_name
;
305 return blink::WebCryptoAlgorithm::createNull();
310 blink::WebCryptoAlgorithmId id
;
311 } kDigestNameToId
[] = {
312 {"sha-1", blink::WebCryptoAlgorithmIdSha1
},
313 {"sha-256", blink::WebCryptoAlgorithmIdSha256
},
314 {"sha-384", blink::WebCryptoAlgorithmIdSha384
},
315 {"sha-512", blink::WebCryptoAlgorithmIdSha512
},
318 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(kDigestNameToId
); ++i
) {
319 if (kDigestNameToId
[i
].name
== algorithm_name
)
320 return CreateAlgorithm(kDigestNameToId
[i
].id
);
323 return blink::WebCryptoAlgorithm::createNull();
326 // Helper for ImportJwkFailures and ImportJwkOctFailures. Restores the JWK JSON
327 // dictionary to a good state
328 void RestoreJwkOctDictionary(base::DictionaryValue
* dict
) {
330 dict
->SetString("kty", "oct");
331 dict
->SetString("alg", "A128CBC");
332 dict
->SetString("use", "enc");
333 dict
->SetBoolean("ext", false);
334 dict
->SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
337 // Helper for ImportJwkRsaFailures. Restores the JWK JSON
338 // dictionary to a good state
339 void RestoreJwkRsaDictionary(base::DictionaryValue
* dict
) {
341 dict
->SetString("kty", "RSA");
342 dict
->SetString("alg", "RS256");
343 dict
->SetString("use", "sig");
344 dict
->SetBoolean("ext", false);
347 "qLOyhK-OtQs4cDSoYPFGxJGfMYdjzWxVmMiuSBGh4KvEx-CwgtaTpef87Wdc9GaFEncsDLxk"
348 "p0LGxjD1M8jMcvYq6DPEC_JYQumEu3i9v5fAEH1VvbZi9cTg-rmEXLUUjvc5LdOq_5OuHmtm"
349 "e7PUJHYW1PW6ENTP0ibeiNOfFvs");
350 dict
->SetString("e", "AQAB");
353 // Returns true if any of the vectors in the input list have identical content.
354 // Dumb O(n^2) implementation but should be fast enough for the input sizes that
356 bool CopiesExist(const std::vector
<std::vector
<uint8
> >& bufs
) {
357 for (size_t i
= 0; i
< bufs
.size(); ++i
) {
358 for (size_t j
= i
+ 1; j
< bufs
.size(); ++j
) {
359 if (CryptoData(bufs
[i
]) == CryptoData(bufs
[j
]))
366 blink::WebCryptoAlgorithm
CreateAesKeyGenAlgorithm(
367 blink::WebCryptoAlgorithmId aes_alg_id
,
368 unsigned short length
) {
369 return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
370 aes_alg_id
, new blink::WebCryptoAesKeyGenParams(length
));
373 blink::WebCryptoAlgorithm
CreateAesCbcKeyGenAlgorithm(
374 unsigned short key_length_bits
) {
375 return CreateAesKeyGenAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
,
379 blink::WebCryptoAlgorithm
CreateAesGcmKeyGenAlgorithm(
380 unsigned short key_length_bits
) {
381 EXPECT_TRUE(SupportsAesGcm());
382 return CreateAesKeyGenAlgorithm(blink::WebCryptoAlgorithmIdAesGcm
,
386 blink::WebCryptoAlgorithm
CreateAesKwKeyGenAlgorithm(
387 unsigned short key_length_bits
) {
388 return CreateAesKeyGenAlgorithm(blink::WebCryptoAlgorithmIdAesKw
,
392 // The following key pair is comprised of the SPKI (public key) and PKCS#8
393 // (private key) representations of the key pair provided in Example 1 of the
394 // NIST test vectors at
395 // ftp://ftp.rsa.com/pub/rsalabs/tmp/pkcs1v15sign-vectors.txt
396 const unsigned int kModulusLengthBits
= 1024;
397 const char* const kPublicKeySpkiDerHex
=
398 "30819f300d06092a864886f70d010101050003818d0030818902818100a5"
399 "6e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad9"
400 "91d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfc"
401 "e0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e"
402 "6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cf"
403 "fb2249bd9a21370203010001";
404 const char* const kPrivateKeyPkcs8DerHex
=
405 "30820275020100300d06092a864886f70d01010105000482025f3082025b"
406 "02010002818100a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52"
407 "a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab"
408 "7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921c"
409 "b23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef"
410 "22e1e1f20d0ce8cffb2249bd9a2137020301000102818033a5042a90b27d"
411 "4f5451ca9bbbd0b44771a101af884340aef9885f2a4bbe92e894a724ac3c"
412 "568c8f97853ad07c0266c8c6a3ca0929f1e8f11231884429fc4d9ae55fee"
413 "896a10ce707c3ed7e734e44727a39574501a532683109c2abacaba283c31"
414 "b4bd2f53c3ee37e352cee34f9e503bd80c0622ad79c6dcee883547c6a3b3"
415 "25024100e7e8942720a877517273a356053ea2a1bc0c94aa72d55c6e8629"
416 "6b2dfc967948c0a72cbccca7eacb35706e09a1df55a1535bd9b3cc34160b"
417 "3b6dcd3eda8e6443024100b69dca1cf7d4d7ec81e75b90fcca874abcde12"
418 "3fd2700180aa90479b6e48de8d67ed24f9f19d85ba275874f542cd20dc72"
419 "3e6963364a1f9425452b269a6799fd024028fa13938655be1f8a159cbaca"
420 "5a72ea190c30089e19cd274a556f36c4f6e19f554b34c077790427bbdd8d"
421 "d3ede2448328f385d81b30e8e43b2fffa02786197902401a8b38f398fa71"
422 "2049898d7fb79ee0a77668791299cdfa09efc0e507acb21ed74301ef5bfd"
423 "48be455eaeb6e1678255827580a8e4e8e14151d1510a82a3f2e729024027"
424 "156aba4126d24a81f3a528cbfb27f56886f840a9f6e86e17a44b94fe9319"
425 "584b8e22fdde1e5a2e3bd8aa5ba8d8584194eb2190acf832b847f13a3d24"
427 // The modulus and exponent (in hex) of kPublicKeySpkiDerHex
428 const char* const kPublicKeyModulusHex
=
429 "A56E4A0E701017589A5187DC7EA841D156F2EC0E36AD52A44DFEB1E61F7AD991D8C51056"
430 "FFEDB162B4C0F283A12A88A394DFF526AB7291CBB307CEABFCE0B1DFD5CD9508096D5B2B"
431 "8B6DF5D671EF6377C0921CB23C270A70E2598E6FF89D19F105ACC2D3F0CB35F29280E138"
432 "6B6F64C4EF22E1E1F20D0CE8CFFB2249BD9A2137";
433 const char* const kPublicKeyExponentHex
= "010001";
435 class SharedCryptoTest
: public testing::Test
{
437 virtual void SetUp() OVERRIDE
{ Init(); }
440 blink::WebCryptoKey
ImportSecretKeyFromRaw(
441 const std::vector
<uint8
>& key_raw
,
442 const blink::WebCryptoAlgorithm
& algorithm
,
443 blink::WebCryptoKeyUsageMask usage
) {
444 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
445 bool extractable
= true;
446 EXPECT_EQ(Status::Success(),
447 ImportKey(blink::WebCryptoKeyFormatRaw
,
454 EXPECT_FALSE(key
.isNull());
455 EXPECT_TRUE(key
.handle());
456 EXPECT_EQ(blink::WebCryptoKeyTypeSecret
, key
.type());
457 EXPECT_EQ(algorithm
.id(), key
.algorithm().id());
458 EXPECT_EQ(extractable
, key
.extractable());
459 EXPECT_EQ(usage
, key
.usages());
463 void ImportRsaKeyPair(const std::vector
<uint8
>& spki_der
,
464 const std::vector
<uint8
>& pkcs8_der
,
465 const blink::WebCryptoAlgorithm
& algorithm
,
467 blink::WebCryptoKeyUsageMask public_key_usage_mask
,
468 blink::WebCryptoKeyUsageMask private_key_usage_mask
,
469 blink::WebCryptoKey
* public_key
,
470 blink::WebCryptoKey
* private_key
) {
471 ASSERT_EQ(Status::Success(),
472 ImportKey(blink::WebCryptoKeyFormatSpki
,
473 CryptoData(spki_der
),
476 public_key_usage_mask
,
478 EXPECT_FALSE(public_key
->isNull());
479 EXPECT_TRUE(public_key
->handle());
480 EXPECT_EQ(blink::WebCryptoKeyTypePublic
, public_key
->type());
481 EXPECT_EQ(algorithm
.id(), public_key
->algorithm().id());
482 EXPECT_TRUE(public_key
->extractable());
483 EXPECT_EQ(public_key_usage_mask
, public_key
->usages());
485 ASSERT_EQ(Status::Success(),
486 ImportKey(blink::WebCryptoKeyFormatPkcs8
,
487 CryptoData(pkcs8_der
),
490 private_key_usage_mask
,
492 EXPECT_FALSE(private_key
->isNull());
493 EXPECT_TRUE(private_key
->handle());
494 EXPECT_EQ(blink::WebCryptoKeyTypePrivate
, private_key
->type());
495 EXPECT_EQ(algorithm
.id(), private_key
->algorithm().id());
496 EXPECT_EQ(extractable
, private_key
->extractable());
497 EXPECT_EQ(private_key_usage_mask
, private_key
->usages());
500 Status
AesGcmEncrypt(const blink::WebCryptoKey
& key
,
501 const std::vector
<uint8
>& iv
,
502 const std::vector
<uint8
>& additional_data
,
503 unsigned int tag_length_bits
,
504 const std::vector
<uint8
>& plain_text
,
505 std::vector
<uint8
>* cipher_text
,
506 std::vector
<uint8
>* authentication_tag
) {
507 EXPECT_TRUE(SupportsAesGcm());
508 blink::WebCryptoAlgorithm algorithm
=
509 CreateAesGcmAlgorithm(iv
, additional_data
, tag_length_bits
);
511 std::vector
<uint8
> output
;
512 Status status
= Encrypt(algorithm
, key
, CryptoData(plain_text
), &output
);
513 if (status
.IsError())
516 if ((tag_length_bits
% 8) != 0) {
517 EXPECT_TRUE(false) << "Encrypt should have failed.";
518 return Status::OperationError();
521 size_t tag_length_bytes
= tag_length_bits
/ 8;
523 if (tag_length_bytes
> output
.size()) {
524 EXPECT_TRUE(false) << "tag length is larger than output";
525 return Status::OperationError();
528 // The encryption result is cipher text with authentication tag appended.
529 cipher_text
->assign(output
.begin(),
530 output
.begin() + (output
.size() - tag_length_bytes
));
531 authentication_tag
->assign(output
.begin() + cipher_text
->size(),
534 return Status::Success();
537 Status
AesGcmDecrypt(const blink::WebCryptoKey
& key
,
538 const std::vector
<uint8
>& iv
,
539 const std::vector
<uint8
>& additional_data
,
540 unsigned int tag_length_bits
,
541 const std::vector
<uint8
>& cipher_text
,
542 const std::vector
<uint8
>& authentication_tag
,
543 std::vector
<uint8
>* plain_text
) {
544 EXPECT_TRUE(SupportsAesGcm());
545 blink::WebCryptoAlgorithm algorithm
=
546 CreateAesGcmAlgorithm(iv
, additional_data
, tag_length_bits
);
548 // Join cipher text and authentication tag.
549 std::vector
<uint8
> cipher_text_with_tag
;
550 cipher_text_with_tag
.reserve(cipher_text
.size() + authentication_tag
.size());
551 cipher_text_with_tag
.insert(
552 cipher_text_with_tag
.end(), cipher_text
.begin(), cipher_text
.end());
553 cipher_text_with_tag
.insert(cipher_text_with_tag
.end(),
554 authentication_tag
.begin(),
555 authentication_tag
.end());
557 return Decrypt(algorithm
, key
, CryptoData(cipher_text_with_tag
), plain_text
);
560 Status
ImportKeyJwk(const CryptoData
& key_data
,
561 const blink::WebCryptoAlgorithm
& algorithm
,
563 blink::WebCryptoKeyUsageMask usage_mask
,
564 blink::WebCryptoKey
* key
) {
565 return ImportKey(blink::WebCryptoKeyFormatJwk
,
573 Status
ImportKeyJwkFromDict(const base::DictionaryValue
& dict
,
574 const blink::WebCryptoAlgorithm
& algorithm
,
576 blink::WebCryptoKeyUsageMask usage_mask
,
577 blink::WebCryptoKey
* key
) {
578 return ImportKeyJwk(CryptoData(MakeJsonVector(dict
)),
585 // Parses a vector of JSON into a dictionary.
586 scoped_ptr
<base::DictionaryValue
> GetJwkDictionary(
587 const std::vector
<uint8
>& json
) {
588 base::StringPiece
json_string(
589 reinterpret_cast<const char*>(Uint8VectorStart(json
)), json
.size());
590 base::Value
* value
= base::JSONReader::Read(json_string
);
592 base::DictionaryValue
* dict_value
= NULL
;
593 value
->GetAsDictionary(&dict_value
);
594 return scoped_ptr
<base::DictionaryValue
>(dict_value
);
597 // Verifies the input dictionary contains the expected values. Exact matches are
598 // required on the fields examined.
599 ::testing::AssertionResult
VerifyJwk(
600 const scoped_ptr
<base::DictionaryValue
>& dict
,
601 const std::string
& kty_expected
,
602 const std::string
& alg_expected
,
603 blink::WebCryptoKeyUsageMask use_mask_expected
) {
605 std::string value_string
;
606 if (!dict
->GetString("kty", &value_string
))
607 return ::testing::AssertionFailure() << "Missing 'kty'";
608 if (value_string
!= kty_expected
)
609 return ::testing::AssertionFailure() << "Expected 'kty' to be "
610 << kty_expected
<< "but found "
614 if (!dict
->GetString("alg", &value_string
))
615 return ::testing::AssertionFailure() << "Missing 'alg'";
616 if (value_string
!= alg_expected
)
617 return ::testing::AssertionFailure() << "Expected 'alg' to be "
618 << alg_expected
<< " but found "
622 // always expect ext == true in this case
624 if (!dict
->GetBoolean("ext", &ext_value
))
625 return ::testing::AssertionFailure() << "Missing 'ext'";
627 return ::testing::AssertionFailure()
628 << "Expected 'ext' to be true but found false";
631 base::ListValue
* key_ops
;
632 if (!dict
->GetList("key_ops", &key_ops
))
633 return ::testing::AssertionFailure() << "Missing 'key_ops'";
634 blink::WebCryptoKeyUsageMask key_ops_mask
= 0;
635 Status status
= GetWebCryptoUsagesFromJwkKeyOps(key_ops
, &key_ops_mask
);
636 if (status
.IsError())
637 return ::testing::AssertionFailure() << "Failure extracting 'key_ops'";
638 if (key_ops_mask
!= use_mask_expected
)
639 return ::testing::AssertionFailure()
640 << "Expected 'key_ops' mask to be " << use_mask_expected
641 << " but found " << key_ops_mask
<< " (" << value_string
<< ")";
643 return ::testing::AssertionSuccess();
646 // Verifies that the JSON in the input vector contains the provided
647 // expected values. Exact matches are required on the fields examined.
648 ::testing::AssertionResult
VerifySecretJwk(
649 const std::vector
<uint8
>& json
,
650 const std::string
& alg_expected
,
651 const std::string
& k_expected_hex
,
652 blink::WebCryptoKeyUsageMask use_mask_expected
) {
653 scoped_ptr
<base::DictionaryValue
> dict
= GetJwkDictionary(json
);
654 if (!dict
.get() || dict
->empty())
655 return ::testing::AssertionFailure() << "JSON parsing failed";
658 std::string value_string
;
659 if (!dict
->GetString("k", &value_string
))
660 return ::testing::AssertionFailure() << "Missing 'k'";
662 if (!webcrypto::Base64DecodeUrlSafe(value_string
, &k_value
))
663 return ::testing::AssertionFailure() << "Base64DecodeUrlSafe(k) failed";
664 if (!LowerCaseEqualsASCII(base::HexEncode(k_value
.data(), k_value
.size()),
665 k_expected_hex
.c_str())) {
666 return ::testing::AssertionFailure() << "Expected 'k' to be "
668 << " but found something different";
671 return VerifyJwk(dict
, "oct", alg_expected
, use_mask_expected
);
674 // Verifies that the JSON in the input vector contains the provided
675 // expected values. Exact matches are required on the fields examined.
676 ::testing::AssertionResult
VerifyPublicJwk(
677 const std::vector
<uint8
>& json
,
678 const std::string
& alg_expected
,
679 const std::string
& n_expected_hex
,
680 const std::string
& e_expected_hex
,
681 blink::WebCryptoKeyUsageMask use_mask_expected
) {
682 scoped_ptr
<base::DictionaryValue
> dict
= GetJwkDictionary(json
);
683 if (!dict
.get() || dict
->empty())
684 return ::testing::AssertionFailure() << "JSON parsing failed";
687 std::string value_string
;
688 if (!dict
->GetString("n", &value_string
))
689 return ::testing::AssertionFailure() << "Missing 'n'";
691 if (!webcrypto::Base64DecodeUrlSafe(value_string
, &n_value
))
692 return ::testing::AssertionFailure() << "Base64DecodeUrlSafe(n) failed";
693 if (base::HexEncode(n_value
.data(), n_value
.size()) != n_expected_hex
) {
694 return ::testing::AssertionFailure() << "'n' does not match the expected "
697 // TODO(padolph): LowerCaseEqualsASCII() does not work for above!
700 if (!dict
->GetString("e", &value_string
))
701 return ::testing::AssertionFailure() << "Missing 'e'";
703 if (!webcrypto::Base64DecodeUrlSafe(value_string
, &e_value
))
704 return ::testing::AssertionFailure() << "Base64DecodeUrlSafe(e) failed";
705 if (!LowerCaseEqualsASCII(base::HexEncode(e_value
.data(), e_value
.size()),
706 e_expected_hex
.c_str())) {
707 return ::testing::AssertionFailure() << "Expected 'e' to be "
709 << " but found something different";
712 return VerifyJwk(dict
, "RSA", alg_expected
, use_mask_expected
);
717 TEST_F(SharedCryptoTest
, CheckAesGcm
) {
718 if (!SupportsAesGcm()) {
719 LOG(WARNING
) << "AES GCM not supported on this platform, so some tests "
720 "will be skipped. Consider upgrading local NSS libraries";
725 // Tests several Status objects against their expected hard coded values, as
726 // well as ensuring that comparison of Status objects works.
727 // Comparison should take into account both the error details, as well as the
729 TEST_F(SharedCryptoTest
, Status
) {
730 // Even though the error message is the same, these should not be considered
731 // the same by the tests because the error type is different.
732 EXPECT_NE(Status::DataError(), Status::OperationError());
733 EXPECT_NE(Status::Success(), Status::OperationError());
735 EXPECT_EQ(Status::Success(), Status::Success());
736 EXPECT_EQ(Status::ErrorJwkPropertyWrongType("kty", "string"),
737 Status::ErrorJwkPropertyWrongType("kty", "string"));
739 Status status
= Status::Success();
741 EXPECT_FALSE(status
.IsError());
742 EXPECT_EQ("", status
.error_details());
744 status
= Status::OperationError();
745 EXPECT_TRUE(status
.IsError());
746 EXPECT_EQ("", status
.error_details());
747 EXPECT_EQ(blink::WebCryptoErrorTypeOperation
, status
.error_type());
749 status
= Status::DataError();
750 EXPECT_TRUE(status
.IsError());
751 EXPECT_EQ("", status
.error_details());
752 EXPECT_EQ(blink::WebCryptoErrorTypeData
, status
.error_type());
754 status
= Status::ErrorUnsupported();
755 EXPECT_TRUE(status
.IsError());
756 EXPECT_EQ("The requested operation is unsupported", status
.error_details());
757 EXPECT_EQ(blink::WebCryptoErrorTypeNotSupported
, status
.error_type());
759 status
= Status::ErrorJwkPropertyMissing("kty");
760 EXPECT_TRUE(status
.IsError());
761 EXPECT_EQ("The required JWK property \"kty\" was missing",
762 status
.error_details());
763 EXPECT_EQ(blink::WebCryptoErrorTypeData
, status
.error_type());
765 status
= Status::ErrorJwkPropertyWrongType("kty", "string");
766 EXPECT_TRUE(status
.IsError());
767 EXPECT_EQ("The JWK property \"kty\" must be a string",
768 status
.error_details());
769 EXPECT_EQ(blink::WebCryptoErrorTypeData
, status
.error_type());
771 status
= Status::ErrorJwkBase64Decode("n");
772 EXPECT_TRUE(status
.IsError());
773 EXPECT_EQ("The JWK property \"n\" could not be base64 decoded",
774 status
.error_details());
775 EXPECT_EQ(blink::WebCryptoErrorTypeData
, status
.error_type());
778 TEST_F(SharedCryptoTest
, DigestSampleSets
) {
779 scoped_ptr
<base::ListValue
> tests
;
780 ASSERT_TRUE(ReadJsonTestFileToList("digest.json", &tests
));
782 for (size_t test_index
= 0; test_index
< tests
->GetSize(); ++test_index
) {
783 SCOPED_TRACE(test_index
);
784 base::DictionaryValue
* test
;
785 ASSERT_TRUE(tests
->GetDictionary(test_index
, &test
));
787 blink::WebCryptoAlgorithm test_algorithm
=
788 GetDigestAlgorithm(test
, "algorithm");
789 std::vector
<uint8
> test_input
= GetBytesFromHexString(test
, "input");
790 std::vector
<uint8
> test_output
= GetBytesFromHexString(test
, "output");
792 std::vector
<uint8
> output
;
793 ASSERT_EQ(Status::Success(),
794 Digest(test_algorithm
, CryptoData(test_input
), &output
));
795 EXPECT_BYTES_EQ(test_output
, output
);
799 TEST_F(SharedCryptoTest
, DigestSampleSetsInChunks
) {
800 scoped_ptr
<base::ListValue
> tests
;
801 ASSERT_TRUE(ReadJsonTestFileToList("digest.json", &tests
));
803 for (size_t test_index
= 0; test_index
< tests
->GetSize(); ++test_index
) {
804 SCOPED_TRACE(test_index
);
805 base::DictionaryValue
* test
;
806 ASSERT_TRUE(tests
->GetDictionary(test_index
, &test
));
808 blink::WebCryptoAlgorithm test_algorithm
=
809 GetDigestAlgorithm(test
, "algorithm");
810 std::vector
<uint8
> test_input
= GetBytesFromHexString(test
, "input");
811 std::vector
<uint8
> test_output
= GetBytesFromHexString(test
, "output");
813 // Test the chunk version of the digest functions. Test with 129 byte chunks
814 // because the SHA-512 chunk size is 128 bytes.
815 unsigned char* output
;
816 unsigned int output_length
;
817 static const size_t kChunkSizeBytes
= 129;
818 size_t length
= test_input
.size();
819 scoped_ptr
<blink::WebCryptoDigestor
> digestor(
820 CreateDigestor(test_algorithm
.id()));
821 std::vector
<uint8
>::iterator begin
= test_input
.begin();
822 size_t chunk_index
= 0;
823 while (begin
!= test_input
.end()) {
824 size_t chunk_length
= std::min(kChunkSizeBytes
, length
- chunk_index
);
825 std::vector
<uint8
> chunk(begin
, begin
+ chunk_length
);
826 ASSERT_TRUE(chunk
.size() > 0);
827 EXPECT_TRUE(digestor
->consume(&chunk
.front(), chunk
.size()));
828 chunk_index
= chunk_index
+ chunk_length
;
829 begin
= begin
+ chunk_length
;
831 EXPECT_TRUE(digestor
->finish(output
, output_length
));
832 EXPECT_BYTES_EQ(test_output
, CryptoData(output
, output_length
));
836 TEST_F(SharedCryptoTest
, HMACSampleSets
) {
837 scoped_ptr
<base::ListValue
> tests
;
838 ASSERT_TRUE(ReadJsonTestFileToList("hmac.json", &tests
));
839 // TODO(padolph): Missing known answer tests for HMAC SHA384, and SHA512.
840 for (size_t test_index
= 0; test_index
< tests
->GetSize(); ++test_index
) {
841 SCOPED_TRACE(test_index
);
842 base::DictionaryValue
* test
;
843 ASSERT_TRUE(tests
->GetDictionary(test_index
, &test
));
845 blink::WebCryptoAlgorithm test_hash
= GetDigestAlgorithm(test
, "hash");
846 const std::vector
<uint8
> test_key
= GetBytesFromHexString(test
, "key");
847 const std::vector
<uint8
> test_message
=
848 GetBytesFromHexString(test
, "message");
849 const std::vector
<uint8
> test_mac
= GetBytesFromHexString(test
, "mac");
851 blink::WebCryptoAlgorithm algorithm
=
852 CreateAlgorithm(blink::WebCryptoAlgorithmIdHmac
);
854 blink::WebCryptoAlgorithm import_algorithm
=
855 CreateHmacImportAlgorithm(test_hash
.id());
857 blink::WebCryptoKey key
= ImportSecretKeyFromRaw(
860 blink::WebCryptoKeyUsageSign
| blink::WebCryptoKeyUsageVerify
);
862 EXPECT_EQ(test_hash
.id(), key
.algorithm().hmacParams()->hash().id());
863 EXPECT_EQ(test_key
.size() * 8, key
.algorithm().hmacParams()->lengthBits());
865 // Verify exported raw key is identical to the imported data
866 std::vector
<uint8
> raw_key
;
867 EXPECT_EQ(Status::Success(),
868 ExportKey(blink::WebCryptoKeyFormatRaw
, key
, &raw_key
));
869 EXPECT_BYTES_EQ(test_key
, raw_key
);
871 std::vector
<uint8
> output
;
873 ASSERT_EQ(Status::Success(),
874 Sign(algorithm
, key
, CryptoData(test_message
), &output
));
876 EXPECT_BYTES_EQ(test_mac
, output
);
878 bool signature_match
= false;
879 EXPECT_EQ(Status::Success(),
880 VerifySignature(algorithm
,
883 CryptoData(test_message
),
885 EXPECT_TRUE(signature_match
);
887 // Ensure truncated signature does not verify by passing one less byte.
890 VerifySignature(algorithm
,
892 CryptoData(Uint8VectorStart(output
), output
.size() - 1),
893 CryptoData(test_message
),
895 EXPECT_FALSE(signature_match
);
897 // Ensure truncated signature does not verify by passing no bytes.
898 EXPECT_EQ(Status::Success(),
899 VerifySignature(algorithm
,
902 CryptoData(test_message
),
904 EXPECT_FALSE(signature_match
);
906 // Ensure extra long signature does not cause issues and fails.
907 const unsigned char kLongSignature
[1024] = {0};
910 VerifySignature(algorithm
,
912 CryptoData(kLongSignature
, sizeof(kLongSignature
)),
913 CryptoData(test_message
),
915 EXPECT_FALSE(signature_match
);
919 TEST_F(SharedCryptoTest
, AesCbcFailures
) {
920 const std::string key_hex
= "2b7e151628aed2a6abf7158809cf4f3c";
921 blink::WebCryptoKey key
= ImportSecretKeyFromRaw(
922 HexStringToBytes(key_hex
),
923 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
924 blink::WebCryptoKeyUsageEncrypt
| blink::WebCryptoKeyUsageDecrypt
);
926 // Verify exported raw key is identical to the imported data
927 std::vector
<uint8
> raw_key
;
928 EXPECT_EQ(Status::Success(),
929 ExportKey(blink::WebCryptoKeyFormatRaw
, key
, &raw_key
));
930 EXPECT_BYTES_EQ_HEX(key_hex
, raw_key
);
932 std::vector
<uint8
> output
;
934 // Use an invalid |iv| (fewer than 16 bytes)
936 std::vector
<uint8
> input(32);
937 std::vector
<uint8
> iv
;
938 EXPECT_EQ(Status::ErrorIncorrectSizeAesCbcIv(),
939 Encrypt(webcrypto::CreateAesCbcAlgorithm(iv
),
943 EXPECT_EQ(Status::ErrorIncorrectSizeAesCbcIv(),
944 Decrypt(webcrypto::CreateAesCbcAlgorithm(iv
),
950 // Use an invalid |iv| (more than 16 bytes)
952 std::vector
<uint8
> input(32);
953 std::vector
<uint8
> iv(17);
954 EXPECT_EQ(Status::ErrorIncorrectSizeAesCbcIv(),
955 Encrypt(webcrypto::CreateAesCbcAlgorithm(iv
),
959 EXPECT_EQ(Status::ErrorIncorrectSizeAesCbcIv(),
960 Decrypt(webcrypto::CreateAesCbcAlgorithm(iv
),
966 // Give an input that is too large (would cause integer overflow when
967 // narrowing to an int).
969 std::vector
<uint8
> iv(16);
971 // Pretend the input is large. Don't pass data pointer as NULL in case that
972 // is special cased; the implementation shouldn't actually dereference the
974 CryptoData
input(&iv
[0], INT_MAX
- 3);
976 EXPECT_EQ(Status::ErrorDataTooLarge(),
977 Encrypt(CreateAesCbcAlgorithm(iv
), key
, input
, &output
));
978 EXPECT_EQ(Status::ErrorDataTooLarge(),
979 Decrypt(CreateAesCbcAlgorithm(iv
), key
, input
, &output
));
982 // Fail importing the key (too few bytes specified)
984 std::vector
<uint8
> key_raw(1);
985 std::vector
<uint8
> iv(16);
987 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
988 EXPECT_EQ(Status::ErrorImportAesKeyLength(),
989 ImportKey(blink::WebCryptoKeyFormatRaw
,
991 CreateAesCbcAlgorithm(iv
),
993 blink::WebCryptoKeyUsageEncrypt
,
997 // Fail exporting the key in SPKI and PKCS#8 formats (not allowed for secret
999 EXPECT_EQ(Status::ErrorUnexpectedKeyType(),
1000 ExportKey(blink::WebCryptoKeyFormatSpki
, key
, &output
));
1001 EXPECT_EQ(Status::ErrorUnexpectedKeyType(),
1002 ExportKey(blink::WebCryptoKeyFormatPkcs8
, key
, &output
));
1005 TEST_F(SharedCryptoTest
, MAYBE(AesCbcSampleSets
)) {
1006 scoped_ptr
<base::ListValue
> tests
;
1007 ASSERT_TRUE(ReadJsonTestFileToList("aes_cbc.json", &tests
));
1009 for (size_t test_index
= 0; test_index
< tests
->GetSize(); ++test_index
) {
1010 SCOPED_TRACE(test_index
);
1011 base::DictionaryValue
* test
;
1012 ASSERT_TRUE(tests
->GetDictionary(test_index
, &test
));
1014 std::vector
<uint8
> test_key
= GetBytesFromHexString(test
, "key");
1015 std::vector
<uint8
> test_iv
= GetBytesFromHexString(test
, "iv");
1016 std::vector
<uint8
> test_plain_text
=
1017 GetBytesFromHexString(test
, "plain_text");
1018 std::vector
<uint8
> test_cipher_text
=
1019 GetBytesFromHexString(test
, "cipher_text");
1021 blink::WebCryptoKey key
= ImportSecretKeyFromRaw(
1023 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
1024 blink::WebCryptoKeyUsageEncrypt
| blink::WebCryptoKeyUsageDecrypt
);
1026 EXPECT_EQ(test_key
.size() * 8, key
.algorithm().aesParams()->lengthBits());
1028 // Verify exported raw key is identical to the imported data
1029 std::vector
<uint8
> raw_key
;
1030 EXPECT_EQ(Status::Success(),
1031 ExportKey(blink::WebCryptoKeyFormatRaw
, key
, &raw_key
));
1032 EXPECT_BYTES_EQ(test_key
, raw_key
);
1034 std::vector
<uint8
> output
;
1037 EXPECT_EQ(Status::Success(),
1038 Encrypt(webcrypto::CreateAesCbcAlgorithm(test_iv
),
1040 CryptoData(test_plain_text
),
1042 EXPECT_BYTES_EQ(test_cipher_text
, output
);
1045 EXPECT_EQ(Status::Success(),
1046 Decrypt(webcrypto::CreateAesCbcAlgorithm(test_iv
),
1048 CryptoData(test_cipher_text
),
1050 EXPECT_BYTES_EQ(test_plain_text
, output
);
1052 const unsigned int kAesCbcBlockSize
= 16;
1054 // Decrypt with a padding error by stripping the last block. This also ends
1055 // up testing decryption over empty cipher text.
1056 if (test_cipher_text
.size() >= kAesCbcBlockSize
) {
1057 EXPECT_EQ(Status::OperationError(),
1058 Decrypt(CreateAesCbcAlgorithm(test_iv
),
1060 CryptoData(&test_cipher_text
[0],
1061 test_cipher_text
.size() - kAesCbcBlockSize
),
1065 // Decrypt cipher text which is not a multiple of block size by stripping
1066 // a few bytes off the cipher text.
1067 if (test_cipher_text
.size() > 3) {
1069 Status::OperationError(),
1070 Decrypt(CreateAesCbcAlgorithm(test_iv
),
1072 CryptoData(&test_cipher_text
[0], test_cipher_text
.size() - 3),
1078 TEST_F(SharedCryptoTest
, MAYBE(GenerateKeyAes
)) {
1079 // Check key generation for each of AES-CBC, AES-GCM, and AES-KW, and for each
1080 // allowed key length.
1081 std::vector
<blink::WebCryptoAlgorithm
> algorithm
;
1082 const unsigned short kKeyLength
[] = {128, 192, 256};
1083 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(kKeyLength
); ++i
) {
1084 algorithm
.push_back(CreateAesCbcKeyGenAlgorithm(kKeyLength
[i
]));
1085 algorithm
.push_back(CreateAesKwKeyGenAlgorithm(kKeyLength
[i
]));
1086 if (SupportsAesGcm())
1087 algorithm
.push_back(CreateAesGcmKeyGenAlgorithm(kKeyLength
[i
]));
1089 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
1090 std::vector
<std::vector
<uint8
> > keys
;
1091 std::vector
<uint8
> key_bytes
;
1092 for (size_t i
= 0; i
< algorithm
.size(); ++i
) {
1094 // Generate a small sample of keys.
1096 for (int j
= 0; j
< 16; ++j
) {
1097 ASSERT_EQ(Status::Success(),
1098 GenerateSecretKey(algorithm
[i
], true, 0, &key
));
1099 EXPECT_TRUE(key
.handle());
1100 EXPECT_EQ(blink::WebCryptoKeyTypeSecret
, key
.type());
1101 ASSERT_EQ(Status::Success(),
1102 ExportKey(blink::WebCryptoKeyFormatRaw
, key
, &key_bytes
));
1103 EXPECT_EQ(key_bytes
.size() * 8,
1104 key
.algorithm().aesParams()->lengthBits());
1105 keys
.push_back(key_bytes
);
1107 // Ensure all entries in the key sample set are unique. This is a simplistic
1108 // estimate of whether the generated keys appear random.
1109 EXPECT_FALSE(CopiesExist(keys
));
1113 TEST_F(SharedCryptoTest
, MAYBE(GenerateKeyAesBadLength
)) {
1114 const unsigned short kKeyLen
[] = {0, 127, 257};
1115 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
1116 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(kKeyLen
); ++i
) {
1118 EXPECT_EQ(Status::ErrorGenerateKeyLength(),
1120 CreateAesCbcKeyGenAlgorithm(kKeyLen
[i
]), true, 0, &key
));
1121 EXPECT_EQ(Status::ErrorGenerateKeyLength(),
1123 CreateAesKwKeyGenAlgorithm(kKeyLen
[i
]), true, 0, &key
));
1124 if (SupportsAesGcm()) {
1125 EXPECT_EQ(Status::ErrorGenerateKeyLength(),
1127 CreateAesGcmKeyGenAlgorithm(kKeyLen
[i
]), true, 0, &key
));
1132 TEST_F(SharedCryptoTest
, MAYBE(GenerateKeyHmac
)) {
1133 // Generate a small sample of HMAC keys.
1134 std::vector
<std::vector
<uint8
> > keys
;
1135 for (int i
= 0; i
< 16; ++i
) {
1136 std::vector
<uint8
> key_bytes
;
1137 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
1138 blink::WebCryptoAlgorithm algorithm
=
1139 CreateHmacKeyGenAlgorithm(blink::WebCryptoAlgorithmIdSha1
, 512);
1140 ASSERT_EQ(Status::Success(), GenerateSecretKey(algorithm
, true, 0, &key
));
1141 EXPECT_FALSE(key
.isNull());
1142 EXPECT_TRUE(key
.handle());
1143 EXPECT_EQ(blink::WebCryptoKeyTypeSecret
, key
.type());
1144 EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac
, key
.algorithm().id());
1145 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1
,
1146 key
.algorithm().hmacParams()->hash().id());
1147 EXPECT_EQ(512u, key
.algorithm().hmacParams()->lengthBits());
1149 std::vector
<uint8
> raw_key
;
1150 ASSERT_EQ(Status::Success(),
1151 ExportKey(blink::WebCryptoKeyFormatRaw
, key
, &raw_key
));
1152 EXPECT_EQ(64U, raw_key
.size());
1153 keys
.push_back(raw_key
);
1155 // Ensure all entries in the key sample set are unique. This is a simplistic
1156 // estimate of whether the generated keys appear random.
1157 EXPECT_FALSE(CopiesExist(keys
));
1160 // If the key length is not provided, then the block size is used.
1161 TEST_F(SharedCryptoTest
, MAYBE(GenerateKeyHmacNoLength
)) {
1162 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
1163 blink::WebCryptoAlgorithm algorithm
=
1164 CreateHmacKeyGenAlgorithm(blink::WebCryptoAlgorithmIdSha1
, 0);
1165 ASSERT_EQ(Status::Success(), GenerateSecretKey(algorithm
, true, 0, &key
));
1166 EXPECT_TRUE(key
.handle());
1167 EXPECT_EQ(blink::WebCryptoKeyTypeSecret
, key
.type());
1168 EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac
, key
.algorithm().id());
1169 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1
,
1170 key
.algorithm().hmacParams()->hash().id());
1171 EXPECT_EQ(512u, key
.algorithm().hmacParams()->lengthBits());
1172 std::vector
<uint8
> raw_key
;
1173 ASSERT_EQ(Status::Success(),
1174 ExportKey(blink::WebCryptoKeyFormatRaw
, key
, &raw_key
));
1175 EXPECT_EQ(64U, raw_key
.size());
1177 // The block size for HMAC SHA-512 is larger.
1178 algorithm
= CreateHmacKeyGenAlgorithm(blink::WebCryptoAlgorithmIdSha512
, 0);
1179 ASSERT_EQ(Status::Success(), GenerateSecretKey(algorithm
, true, 0, &key
));
1180 EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac
, key
.algorithm().id());
1181 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha512
,
1182 key
.algorithm().hmacParams()->hash().id());
1183 EXPECT_EQ(1024u, key
.algorithm().hmacParams()->lengthBits());
1184 ASSERT_EQ(Status::Success(),
1185 ExportKey(blink::WebCryptoKeyFormatRaw
, key
, &raw_key
));
1186 EXPECT_EQ(128U, raw_key
.size());
1189 TEST_F(SharedCryptoTest
, ImportJwkKeyUsage
) {
1190 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
1191 base::DictionaryValue dict
;
1192 dict
.SetString("kty", "oct");
1193 dict
.SetBoolean("ext", false);
1194 dict
.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
1195 const blink::WebCryptoAlgorithm aes_cbc_algorithm
=
1196 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
);
1197 const blink::WebCryptoAlgorithm hmac_algorithm
=
1198 webcrypto::CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha256
);
1199 const blink::WebCryptoAlgorithm aes_kw_algorithm
=
1200 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw
);
1203 base::ListValue
* key_ops
= new base::ListValue
;
1204 // Note: the following call makes dict assume ownership of key_ops.
1205 dict
.Set("key_ops", key_ops
);
1206 EXPECT_EQ(Status::Success(),
1207 ImportKeyJwkFromDict(dict
, aes_cbc_algorithm
, false, 0, &key
));
1208 EXPECT_EQ(0, key
.usages());
1210 // Test each key_ops value translates to the correct Web Crypto value.
1212 const char* jwk_key_op
;
1213 const char* jwk_alg
;
1214 const blink::WebCryptoAlgorithm algorithm
;
1215 const blink::WebCryptoKeyUsage usage
;
1217 // TODO(padolph): Add 'deriveBits' key_ops value once it is supported.
1218 const TestCase test_case
[] = {
1219 {"encrypt", "A128CBC", aes_cbc_algorithm
,
1220 blink::WebCryptoKeyUsageEncrypt
},
1221 {"decrypt", "A128CBC", aes_cbc_algorithm
,
1222 blink::WebCryptoKeyUsageDecrypt
},
1223 {"sign", "HS256", hmac_algorithm
, blink::WebCryptoKeyUsageSign
},
1224 {"verify", "HS256", hmac_algorithm
, blink::WebCryptoKeyUsageVerify
},
1225 {"wrapKey", "A128KW", aes_kw_algorithm
, blink::WebCryptoKeyUsageWrapKey
},
1226 {"unwrapKey", "A128KW", aes_kw_algorithm
,
1227 blink::WebCryptoKeyUsageUnwrapKey
}};
1228 for (size_t test_index
= 0; test_index
< ARRAYSIZE_UNSAFE(test_case
);
1230 SCOPED_TRACE(test_index
);
1231 dict
.SetString("alg", test_case
[test_index
].jwk_alg
);
1233 key_ops
->AppendString(test_case
[test_index
].jwk_key_op
);
1234 EXPECT_EQ(Status::Success(),
1235 ImportKeyJwkFromDict(dict
,
1236 test_case
[test_index
].algorithm
,
1238 test_case
[test_index
].usage
,
1240 EXPECT_EQ(test_case
[test_index
].usage
, key
.usages());
1243 // Test discrete multiple usages.
1244 dict
.SetString("alg", "A128CBC");
1246 key_ops
->AppendString("encrypt");
1247 key_ops
->AppendString("decrypt");
1248 EXPECT_EQ(Status::Success(),
1249 ImportKeyJwkFromDict(dict
,
1252 blink::WebCryptoKeyUsageDecrypt
|
1253 blink::WebCryptoKeyUsageEncrypt
,
1255 EXPECT_EQ(blink::WebCryptoKeyUsageDecrypt
| blink::WebCryptoKeyUsageEncrypt
,
1258 // Test constrained key usage (input usage is a subset of JWK usage).
1260 key_ops
->AppendString("encrypt");
1261 key_ops
->AppendString("decrypt");
1262 EXPECT_EQ(Status::Success(),
1263 ImportKeyJwkFromDict(dict
,
1266 blink::WebCryptoKeyUsageDecrypt
,
1268 EXPECT_EQ(blink::WebCryptoKeyUsageDecrypt
, key
.usages());
1270 // Test failure if input usage is NOT a strict subset of the JWK usage.
1272 key_ops
->AppendString("encrypt");
1273 EXPECT_EQ(Status::ErrorJwkKeyopsInconsistent(),
1274 ImportKeyJwkFromDict(dict
,
1277 blink::WebCryptoKeyUsageEncrypt
|
1278 blink::WebCryptoKeyUsageDecrypt
,
1281 // Test 'use' inconsistent with 'key_ops'.
1282 dict
.SetString("alg", "HS256");
1283 dict
.SetString("use", "sig");
1284 key_ops
->AppendString("sign");
1285 key_ops
->AppendString("verify");
1286 key_ops
->AppendString("encrypt");
1287 EXPECT_EQ(Status::ErrorJwkUseAndKeyopsInconsistent(),
1288 ImportKeyJwkFromDict(
1292 blink::WebCryptoKeyUsageSign
| blink::WebCryptoKeyUsageVerify
,
1295 // Test JWK composite 'sig' use
1296 dict
.Remove("key_ops", NULL
);
1297 dict
.SetString("use", "sig");
1298 EXPECT_EQ(Status::Success(),
1299 ImportKeyJwkFromDict(
1303 blink::WebCryptoKeyUsageSign
| blink::WebCryptoKeyUsageVerify
,
1305 EXPECT_EQ(blink::WebCryptoKeyUsageSign
| blink::WebCryptoKeyUsageVerify
,
1308 // Test JWK composite use 'enc' usage
1309 dict
.SetString("alg", "A128CBC");
1310 dict
.SetString("use", "enc");
1311 EXPECT_EQ(Status::Success(),
1312 ImportKeyJwkFromDict(dict
,
1315 blink::WebCryptoKeyUsageDecrypt
|
1316 blink::WebCryptoKeyUsageEncrypt
|
1317 blink::WebCryptoKeyUsageWrapKey
|
1318 blink::WebCryptoKeyUsageUnwrapKey
,
1320 EXPECT_EQ(blink::WebCryptoKeyUsageDecrypt
| blink::WebCryptoKeyUsageEncrypt
|
1321 blink::WebCryptoKeyUsageWrapKey
|
1322 blink::WebCryptoKeyUsageUnwrapKey
,
1326 TEST_F(SharedCryptoTest
, ImportJwkFailures
) {
1327 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
1328 blink::WebCryptoAlgorithm algorithm
=
1329 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
);
1330 blink::WebCryptoKeyUsageMask usage_mask
= blink::WebCryptoKeyUsageEncrypt
;
1332 // Baseline pass: each test below breaks a single item, so we start with a
1333 // passing case to make sure each failure is caused by the isolated break.
1334 // Each breaking subtest below resets the dictionary to this passing case when
1336 base::DictionaryValue dict
;
1337 RestoreJwkOctDictionary(&dict
);
1338 EXPECT_EQ(Status::Success(),
1339 ImportKeyJwkFromDict(dict
, algorithm
, false, usage_mask
, &key
));
1341 // Fail on empty JSON.
1343 Status::ErrorImportEmptyKeyData(),
1345 CryptoData(MakeJsonVector("")), algorithm
, false, usage_mask
, &key
));
1347 // Fail on invalid JSON.
1348 const std::vector
<uint8
> bad_json_vec
= MakeJsonVector(
1350 "\"kty\" : \"oct\","
1351 "\"alg\" : \"HS256\","
1353 EXPECT_EQ(Status::ErrorJwkNotDictionary(),
1355 CryptoData(bad_json_vec
), algorithm
, false, usage_mask
, &key
));
1357 // Fail on JWK alg present but unrecognized.
1358 dict
.SetString("alg", "A127CBC");
1359 EXPECT_EQ(Status::ErrorJwkUnrecognizedAlgorithm(),
1360 ImportKeyJwkFromDict(dict
, algorithm
, false, usage_mask
, &key
));
1361 RestoreJwkOctDictionary(&dict
);
1363 // Fail on invalid kty.
1364 dict
.SetString("kty", "foo");
1365 EXPECT_EQ(Status::ErrorJwkUnrecognizedKty(),
1366 ImportKeyJwkFromDict(dict
, algorithm
, false, usage_mask
, &key
));
1367 RestoreJwkOctDictionary(&dict
);
1369 // Fail on missing kty.
1370 dict
.Remove("kty", NULL
);
1371 EXPECT_EQ(Status::ErrorJwkPropertyMissing("kty"),
1372 ImportKeyJwkFromDict(dict
, algorithm
, false, usage_mask
, &key
));
1373 RestoreJwkOctDictionary(&dict
);
1375 // Fail on kty wrong type.
1376 dict
.SetDouble("kty", 0.1);
1377 EXPECT_EQ(Status::ErrorJwkPropertyWrongType("kty", "string"),
1378 ImportKeyJwkFromDict(dict
, algorithm
, false, usage_mask
, &key
));
1379 RestoreJwkOctDictionary(&dict
);
1381 // Fail on invalid use.
1382 dict
.SetString("use", "foo");
1383 EXPECT_EQ(Status::ErrorJwkUnrecognizedUse(),
1384 ImportKeyJwkFromDict(dict
, algorithm
, false, usage_mask
, &key
));
1385 RestoreJwkOctDictionary(&dict
);
1387 // Fail on invalid use (wrong type).
1388 dict
.SetBoolean("use", true);
1389 EXPECT_EQ(Status::ErrorJwkPropertyWrongType("use", "string"),
1390 ImportKeyJwkFromDict(dict
, algorithm
, false, usage_mask
, &key
));
1391 RestoreJwkOctDictionary(&dict
);
1393 // Fail on invalid extractable (wrong type).
1394 dict
.SetInteger("ext", 0);
1395 EXPECT_EQ(Status::ErrorJwkPropertyWrongType("ext", "boolean"),
1396 ImportKeyJwkFromDict(dict
, algorithm
, false, usage_mask
, &key
));
1397 RestoreJwkOctDictionary(&dict
);
1399 // Fail on invalid key_ops (wrong type).
1400 dict
.SetBoolean("key_ops", true);
1401 EXPECT_EQ(Status::ErrorJwkPropertyWrongType("key_ops", "list"),
1402 ImportKeyJwkFromDict(dict
, algorithm
, false, usage_mask
, &key
));
1403 RestoreJwkOctDictionary(&dict
);
1405 // Fail on inconsistent key_ops - asking for "encrypt" however JWK contains
1407 base::ListValue
* key_ops
= new base::ListValue
;
1408 // Note: the following call makes dict assume ownership of key_ops.
1409 dict
.Set("key_ops", key_ops
);
1410 key_ops
->AppendString("foo");
1411 EXPECT_EQ(Status::ErrorJwkKeyopsInconsistent(),
1412 ImportKeyJwkFromDict(dict
, algorithm
, false, usage_mask
, &key
));
1413 RestoreJwkOctDictionary(&dict
);
1416 // Import a JWK with unrecognized values for "key_ops".
1417 TEST_F(SharedCryptoTest
, ImportJwkUnrecognizedKeyOps
) {
1418 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
1419 blink::WebCryptoAlgorithm algorithm
=
1420 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
);
1421 blink::WebCryptoKeyUsageMask usage_mask
= blink::WebCryptoKeyUsageEncrypt
;
1423 base::DictionaryValue dict
;
1424 RestoreJwkOctDictionary(&dict
);
1426 base::ListValue
* key_ops
= new base::ListValue
;
1427 dict
.Set("key_ops", key_ops
);
1428 key_ops
->AppendString("foo");
1429 key_ops
->AppendString("bar");
1430 key_ops
->AppendString("baz");
1431 key_ops
->AppendString("encrypt");
1432 EXPECT_EQ(Status::Success(),
1433 ImportKeyJwkFromDict(dict
, algorithm
, false, usage_mask
, &key
));
1436 // Import a JWK with a value in key_ops array that is not a string.
1437 TEST_F(SharedCryptoTest
, ImportJwkNonStringKeyOp
) {
1438 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
1439 blink::WebCryptoAlgorithm algorithm
=
1440 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
);
1441 blink::WebCryptoKeyUsageMask usage_mask
= blink::WebCryptoKeyUsageEncrypt
;
1443 base::DictionaryValue dict
;
1444 RestoreJwkOctDictionary(&dict
);
1446 base::ListValue
* key_ops
= new base::ListValue
;
1447 dict
.Set("key_ops", key_ops
);
1448 key_ops
->AppendString("encrypt");
1449 key_ops
->AppendInteger(3);
1450 EXPECT_EQ(Status::ErrorJwkPropertyWrongType("key_ops[1]", "string"),
1451 ImportKeyJwkFromDict(dict
, algorithm
, false, usage_mask
, &key
));
1454 TEST_F(SharedCryptoTest
, ImportJwkOctFailures
) {
1455 base::DictionaryValue dict
;
1456 RestoreJwkOctDictionary(&dict
);
1457 blink::WebCryptoAlgorithm algorithm
=
1458 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
);
1459 blink::WebCryptoKeyUsageMask usage_mask
= blink::WebCryptoKeyUsageEncrypt
;
1460 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
1463 EXPECT_EQ(Status::Success(),
1464 ImportKeyJwkFromDict(dict
, algorithm
, false, usage_mask
, &key
));
1465 EXPECT_EQ(algorithm
.id(), key
.algorithm().id());
1466 EXPECT_FALSE(key
.extractable());
1467 EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt
, key
.usages());
1468 EXPECT_EQ(blink::WebCryptoKeyTypeSecret
, key
.type());
1470 // The following are specific failure cases for when kty = "oct".
1472 // Fail on missing k.
1473 dict
.Remove("k", NULL
);
1474 EXPECT_EQ(Status::ErrorJwkPropertyMissing("k"),
1475 ImportKeyJwkFromDict(dict
, algorithm
, false, usage_mask
, &key
));
1476 RestoreJwkOctDictionary(&dict
);
1478 // Fail on bad b64 encoding for k.
1479 dict
.SetString("k", "Qk3f0DsytU8lfza2au #$% Htaw2xpop9GYyTuH0p5GghxTI=");
1480 EXPECT_EQ(Status::ErrorJwkBase64Decode("k"),
1481 ImportKeyJwkFromDict(dict
, algorithm
, false, usage_mask
, &key
));
1482 RestoreJwkOctDictionary(&dict
);
1485 dict
.SetString("k", "");
1486 EXPECT_EQ(Status::ErrorJwkIncorrectKeyLength(),
1487 ImportKeyJwkFromDict(dict
, algorithm
, false, usage_mask
, &key
));
1488 RestoreJwkOctDictionary(&dict
);
1490 // Fail on k actual length (120 bits) inconsistent with the embedded JWK alg
1491 // value (128) for an AES key.
1492 dict
.SetString("k", "AVj42h0Y5aqGtE3yluKL");
1493 EXPECT_EQ(Status::ErrorJwkIncorrectKeyLength(),
1494 ImportKeyJwkFromDict(dict
, algorithm
, false, usage_mask
, &key
));
1495 RestoreJwkOctDictionary(&dict
);
1497 // Fail on k actual length (192 bits) inconsistent with the embedded JWK alg
1498 // value (128) for an AES key.
1499 dict
.SetString("k", "dGhpcyAgaXMgIDI0ICBieXRlcyBsb25n");
1500 EXPECT_EQ(Status::ErrorJwkIncorrectKeyLength(),
1501 ImportKeyJwkFromDict(dict
, algorithm
, false, usage_mask
, &key
));
1502 RestoreJwkOctDictionary(&dict
);
1505 TEST_F(SharedCryptoTest
, MAYBE(ImportExportJwkRsaPublicKey
)) {
1506 const bool supports_rsa_oaep
= SupportsRsaOaep();
1507 if (!supports_rsa_oaep
) {
1508 LOG(WARNING
) << "RSA-OAEP not supported on this platform. Skipping some"
1513 const blink::WebCryptoAlgorithm algorithm
;
1514 const blink::WebCryptoKeyUsageMask usage
;
1515 const char* const jwk_alg
;
1517 const TestCase kTests
[] = {
1518 // RSASSA-PKCS1-v1_5 SHA-1
1519 {CreateRsaHashedImportAlgorithm(
1520 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
1521 blink::WebCryptoAlgorithmIdSha1
),
1522 blink::WebCryptoKeyUsageVerify
, "RS1"},
1523 // RSASSA-PKCS1-v1_5 SHA-256
1524 {CreateRsaHashedImportAlgorithm(
1525 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
1526 blink::WebCryptoAlgorithmIdSha256
),
1527 blink::WebCryptoKeyUsageVerify
, "RS256"},
1528 // RSASSA-PKCS1-v1_5 SHA-384
1529 {CreateRsaHashedImportAlgorithm(
1530 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
1531 blink::WebCryptoAlgorithmIdSha384
),
1532 blink::WebCryptoKeyUsageVerify
, "RS384"},
1533 // RSASSA-PKCS1-v1_5 SHA-512
1534 {CreateRsaHashedImportAlgorithm(
1535 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
1536 blink::WebCryptoAlgorithmIdSha512
),
1537 blink::WebCryptoKeyUsageVerify
, "RS512"},
1538 // RSA-OAEP with SHA-1 and MGF-1 / SHA-1
1539 {CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaOaep
,
1540 blink::WebCryptoAlgorithmIdSha1
),
1541 blink::WebCryptoKeyUsageEncrypt
, "RSA-OAEP"},
1542 // RSA-OAEP with SHA-256 and MGF-1 / SHA-256
1543 {CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaOaep
,
1544 blink::WebCryptoAlgorithmIdSha256
),
1545 blink::WebCryptoKeyUsageEncrypt
, "RSA-OAEP-256"},
1546 // RSA-OAEP with SHA-384 and MGF-1 / SHA-384
1547 {CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaOaep
,
1548 blink::WebCryptoAlgorithmIdSha384
),
1549 blink::WebCryptoKeyUsageEncrypt
, "RSA-OAEP-384"},
1550 // RSA-OAEP with SHA-512 and MGF-1 / SHA-512
1551 {CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaOaep
,
1552 blink::WebCryptoAlgorithmIdSha512
),
1553 blink::WebCryptoKeyUsageEncrypt
, "RSA-OAEP-512"}};
1555 for (size_t test_index
= 0; test_index
< ARRAYSIZE_UNSAFE(kTests
);
1557 SCOPED_TRACE(test_index
);
1558 const TestCase
& test
= kTests
[test_index
];
1559 if (!supports_rsa_oaep
&&
1560 test
.algorithm
.id() == blink::WebCryptoAlgorithmIdRsaOaep
) {
1564 // Import the spki to create a public key
1565 blink::WebCryptoKey public_key
= blink::WebCryptoKey::createNull();
1566 ASSERT_EQ(Status::Success(),
1567 ImportKey(blink::WebCryptoKeyFormatSpki
,
1568 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex
)),
1574 // Export the public key as JWK and verify its contents
1575 std::vector
<uint8
> jwk
;
1576 ASSERT_EQ(Status::Success(),
1577 ExportKey(blink::WebCryptoKeyFormatJwk
, public_key
, &jwk
));
1578 EXPECT_TRUE(VerifyPublicJwk(jwk
,
1580 kPublicKeyModulusHex
,
1581 kPublicKeyExponentHex
,
1584 // Import the JWK back in to create a new key
1585 blink::WebCryptoKey public_key2
= blink::WebCryptoKey::createNull();
1589 CryptoData(jwk
), test
.algorithm
, true, test
.usage
, &public_key2
));
1590 ASSERT_TRUE(public_key2
.handle());
1591 EXPECT_EQ(blink::WebCryptoKeyTypePublic
, public_key2
.type());
1592 EXPECT_TRUE(public_key2
.extractable());
1593 EXPECT_EQ(test
.algorithm
.id(), public_key2
.algorithm().id());
1595 // Only perform SPKI consistency test for RSA-SSA as its
1596 // export format is the same as kPublicKeySpkiDerHex
1597 if (test
.algorithm
.id() == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
) {
1598 // Export the new key as spki and compare to the original.
1599 std::vector
<uint8
> spki
;
1600 ASSERT_EQ(Status::Success(),
1601 ExportKey(blink::WebCryptoKeyFormatSpki
, public_key2
, &spki
));
1602 EXPECT_BYTES_EQ_HEX(kPublicKeySpkiDerHex
, CryptoData(spki
));
1607 TEST_F(SharedCryptoTest
, MAYBE(ImportJwkRsaFailures
)) {
1608 base::DictionaryValue dict
;
1609 RestoreJwkRsaDictionary(&dict
);
1610 blink::WebCryptoAlgorithm algorithm
=
1611 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
1612 blink::WebCryptoAlgorithmIdSha256
);
1613 blink::WebCryptoKeyUsageMask usage_mask
= blink::WebCryptoKeyUsageVerify
;
1614 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
1616 // An RSA public key JWK _must_ have an "n" (modulus) and an "e" (exponent)
1617 // entry, while an RSA private key must have those plus at least a "d"
1618 // (private exponent) entry.
1619 // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18,
1623 EXPECT_EQ(Status::Success(),
1624 ImportKeyJwkFromDict(dict
, algorithm
, false, usage_mask
, &key
));
1625 EXPECT_EQ(algorithm
.id(), key
.algorithm().id());
1626 EXPECT_FALSE(key
.extractable());
1627 EXPECT_EQ(blink::WebCryptoKeyUsageVerify
, key
.usages());
1628 EXPECT_EQ(blink::WebCryptoKeyTypePublic
, key
.type());
1630 // The following are specific failure cases for when kty = "RSA".
1632 // Fail if either "n" or "e" is not present or malformed.
1633 const std::string kKtyParmName
[] = {"n", "e"};
1634 for (size_t idx
= 0; idx
< ARRAYSIZE_UNSAFE(kKtyParmName
); ++idx
) {
1635 // Fail on missing parameter.
1636 dict
.Remove(kKtyParmName
[idx
], NULL
);
1637 EXPECT_NE(Status::Success(),
1638 ImportKeyJwkFromDict(dict
, algorithm
, false, usage_mask
, &key
));
1639 RestoreJwkRsaDictionary(&dict
);
1641 // Fail on bad b64 parameter encoding.
1642 dict
.SetString(kKtyParmName
[idx
], "Qk3f0DsytU8lfza2au #$% Htaw2xpop9yTuH0");
1643 EXPECT_NE(Status::Success(),
1644 ImportKeyJwkFromDict(dict
, algorithm
, false, usage_mask
, &key
));
1645 RestoreJwkRsaDictionary(&dict
);
1647 // Fail on empty parameter.
1648 dict
.SetString(kKtyParmName
[idx
], "");
1649 EXPECT_NE(Status::Success(),
1650 ImportKeyJwkFromDict(dict
, algorithm
, false, usage_mask
, &key
));
1651 RestoreJwkRsaDictionary(&dict
);
1655 TEST_F(SharedCryptoTest
, MAYBE(ImportJwkInputConsistency
)) {
1656 // The Web Crypto spec says that if a JWK value is present, but is
1657 // inconsistent with the input value, the operation must fail.
1659 // Consistency rules when JWK value is not present: Inputs should be used.
1660 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
1661 bool extractable
= false;
1662 blink::WebCryptoAlgorithm algorithm
=
1663 CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha256
);
1664 blink::WebCryptoKeyUsageMask usage_mask
= blink::WebCryptoKeyUsageVerify
;
1665 base::DictionaryValue dict
;
1666 dict
.SetString("kty", "oct");
1667 dict
.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg");
1668 std::vector
<uint8
> json_vec
= MakeJsonVector(dict
);
1672 CryptoData(json_vec
), algorithm
, extractable
, usage_mask
, &key
));
1673 EXPECT_TRUE(key
.handle());
1674 EXPECT_EQ(blink::WebCryptoKeyTypeSecret
, key
.type());
1675 EXPECT_EQ(extractable
, key
.extractable());
1676 EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac
, key
.algorithm().id());
1677 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256
,
1678 key
.algorithm().hmacParams()->hash().id());
1679 EXPECT_EQ(320u, key
.algorithm().hmacParams()->lengthBits());
1680 EXPECT_EQ(blink::WebCryptoKeyUsageVerify
, key
.usages());
1681 key
= blink::WebCryptoKey::createNull();
1683 // Consistency rules when JWK value exists: Fail if inconsistency is found.
1685 // Pass: All input values are consistent with the JWK values.
1687 dict
.SetString("kty", "oct");
1688 dict
.SetString("alg", "HS256");
1689 dict
.SetString("use", "sig");
1690 dict
.SetBoolean("ext", false);
1691 dict
.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg");
1692 json_vec
= MakeJsonVector(dict
);
1696 CryptoData(json_vec
), algorithm
, extractable
, usage_mask
, &key
));
1698 // Extractable cases:
1699 // 1. input=T, JWK=F ==> fail (inconsistent)
1700 // 4. input=F, JWK=F ==> pass, result extractable is F
1701 // 2. input=T, JWK=T ==> pass, result extractable is T
1702 // 3. input=F, JWK=T ==> pass, result extractable is F
1704 Status::ErrorJwkExtInconsistent(),
1705 ImportKeyJwk(CryptoData(json_vec
), algorithm
, true, usage_mask
, &key
));
1708 ImportKeyJwk(CryptoData(json_vec
), algorithm
, false, usage_mask
, &key
));
1709 EXPECT_FALSE(key
.extractable());
1710 dict
.SetBoolean("ext", true);
1711 EXPECT_EQ(Status::Success(),
1712 ImportKeyJwkFromDict(dict
, algorithm
, true, usage_mask
, &key
));
1713 EXPECT_TRUE(key
.extractable());
1714 EXPECT_EQ(Status::Success(),
1715 ImportKeyJwkFromDict(dict
, algorithm
, false, usage_mask
, &key
));
1716 EXPECT_FALSE(key
.extractable());
1717 dict
.SetBoolean("ext", true); // restore previous value
1719 // Fail: Input algorithm (AES-CBC) is inconsistent with JWK value
1721 EXPECT_EQ(Status::ErrorJwkAlgorithmInconsistent(),
1722 ImportKeyJwk(CryptoData(json_vec
),
1723 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
1725 blink::WebCryptoKeyUsageEncrypt
,
1728 // Fail: Input algorithm (HMAC SHA1) is inconsistent with JWK value
1731 Status::ErrorJwkAlgorithmInconsistent(),
1732 ImportKeyJwk(CryptoData(json_vec
),
1733 CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha1
),
1738 // Pass: JWK alg missing but input algorithm specified: use input value
1739 dict
.Remove("alg", NULL
);
1740 EXPECT_EQ(Status::Success(),
1741 ImportKeyJwkFromDict(
1743 CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha256
),
1747 EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac
, algorithm
.id());
1748 dict
.SetString("alg", "HS256");
1750 // Fail: Input usage_mask (encrypt) is not a subset of the JWK value
1751 // (sign|verify). Moreover "encrypt" is not a valid usage for HMAC.
1752 EXPECT_EQ(Status::ErrorCreateKeyBadUsages(),
1753 ImportKeyJwk(CryptoData(json_vec
),
1756 blink::WebCryptoKeyUsageEncrypt
,
1759 // Fail: Input usage_mask (encrypt|sign|verify) is not a subset of the JWK
1760 // value (sign|verify). Moreover "encrypt" is not a valid usage for HMAC.
1761 usage_mask
= blink::WebCryptoKeyUsageEncrypt
| blink::WebCryptoKeyUsageSign
|
1762 blink::WebCryptoKeyUsageVerify
;
1764 Status::ErrorCreateKeyBadUsages(),
1766 CryptoData(json_vec
), algorithm
, extractable
, usage_mask
, &key
));
1768 // TODO(padolph): kty vs alg consistency tests: Depending on the kty value,
1769 // only certain alg values are permitted. For example, when kty = "RSA" alg
1770 // must be of the RSA family, or when kty = "oct" alg must be symmetric
1773 // TODO(padolph): key_ops consistency tests
1776 TEST_F(SharedCryptoTest
, MAYBE(ImportJwkHappy
)) {
1777 // This test verifies the happy path of JWK import, including the application
1778 // of the imported key material.
1780 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
1781 bool extractable
= false;
1782 blink::WebCryptoAlgorithm algorithm
=
1783 CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha256
);
1784 blink::WebCryptoKeyUsageMask usage_mask
= blink::WebCryptoKeyUsageSign
;
1786 // Import a symmetric key JWK and HMAC-SHA256 sign()
1787 // Uses the first SHA256 test vector from the HMAC sample set above.
1789 base::DictionaryValue dict
;
1790 dict
.SetString("kty", "oct");
1791 dict
.SetString("alg", "HS256");
1792 dict
.SetString("use", "sig");
1793 dict
.SetBoolean("ext", false);
1794 dict
.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg");
1798 ImportKeyJwkFromDict(dict
, algorithm
, extractable
, usage_mask
, &key
));
1800 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256
,
1801 key
.algorithm().hmacParams()->hash().id());
1803 const std::vector
<uint8
> message_raw
= HexStringToBytes(
1804 "b1689c2591eaf3c9e66070f8a77954ffb81749f1b00346f9dfe0b2ee905dcc288baf4a"
1805 "92de3f4001dd9f44c468c3d07d6c6ee82faceafc97c2fc0fc0601719d2dcd0aa2aec92"
1806 "d1b0ae933c65eb06a03c9c935c2bad0459810241347ab87e9f11adb30415424c6c7f5f"
1807 "22a003b8ab8de54f6ded0e3ab9245fa79568451dfa258e");
1809 std::vector
<uint8
> output
;
1811 ASSERT_EQ(Status::Success(),
1812 Sign(CreateAlgorithm(blink::WebCryptoAlgorithmIdHmac
),
1814 CryptoData(message_raw
),
1817 const std::string mac_raw
=
1818 "769f00d3e6a6cc1fb426a14a4f76c6462e6149726e0dee0ec0cf97a16605ac8b";
1820 EXPECT_BYTES_EQ_HEX(mac_raw
, output
);
1822 // TODO(padolph): Import an RSA public key JWK and use it
1825 TEST_F(SharedCryptoTest
, MAYBE(ImportExportJwkSymmetricKey
)) {
1826 // Raw keys are generated by openssl:
1827 // % openssl rand -hex <key length bytes>
1828 const char* const key_hex_128
= "3f1e7cd4f6f8543f6b1e16002e688623";
1829 const char* const key_hex_192
=
1830 "ed91f916dc034eba68a0f9e7f34ddd48b98bd2848109e243";
1831 const char* const key_hex_256
=
1832 "bd08286b81a74783fd1ccf46b7e05af84ee25ae021210074159e0c4d9d907692";
1833 const char* const key_hex_384
=
1834 "a22c5441c8b185602283d64c7221de1d0951e706bfc09539435ec0e0ed614e1d406623f2"
1835 "b31d31819fec30993380dd82";
1836 const char* const key_hex_512
=
1837 "5834f639000d4cf82de124fbfd26fb88d463e99f839a76ba41ac88967c80a3f61e1239a4"
1838 "52e573dba0750e988152988576efd75b8d0229b7aca2ada2afd392ee";
1839 const blink::WebCryptoAlgorithm aes_cbc_alg
=
1840 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
);
1841 const blink::WebCryptoAlgorithm aes_gcm_alg
=
1842 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesGcm
);
1843 const blink::WebCryptoAlgorithm aes_kw_alg
=
1844 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw
);
1845 const blink::WebCryptoAlgorithm hmac_sha_1_alg
=
1846 webcrypto::CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha1
);
1847 const blink::WebCryptoAlgorithm hmac_sha_256_alg
=
1848 webcrypto::CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha256
);
1849 const blink::WebCryptoAlgorithm hmac_sha_384_alg
=
1850 webcrypto::CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha384
);
1851 const blink::WebCryptoAlgorithm hmac_sha_512_alg
=
1852 webcrypto::CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha512
);
1855 const char* const key_hex
;
1856 const blink::WebCryptoAlgorithm algorithm
;
1857 const blink::WebCryptoKeyUsageMask usage
;
1858 const char* const jwk_alg
;
1861 // TODO(padolph): Test AES-CTR JWK export, once AES-CTR import works.
1862 const TestCase kTests
[] = {
1864 {key_hex_128
, aes_cbc_alg
,
1865 blink::WebCryptoKeyUsageEncrypt
| blink::WebCryptoKeyUsageDecrypt
,
1868 {key_hex_192
, aes_cbc_alg
, blink::WebCryptoKeyUsageEncrypt
, "A192CBC"},
1870 {key_hex_256
, aes_cbc_alg
, blink::WebCryptoKeyUsageDecrypt
, "A256CBC"},
1872 {key_hex_128
, aes_gcm_alg
,
1873 blink::WebCryptoKeyUsageEncrypt
| blink::WebCryptoKeyUsageDecrypt
,
1876 {key_hex_192
, aes_gcm_alg
, blink::WebCryptoKeyUsageEncrypt
, "A192GCM"},
1878 {key_hex_256
, aes_gcm_alg
, blink::WebCryptoKeyUsageDecrypt
, "A256GCM"},
1880 {key_hex_128
, aes_kw_alg
,
1881 blink::WebCryptoKeyUsageWrapKey
| blink::WebCryptoKeyUsageUnwrapKey
,
1884 {key_hex_192
, aes_kw_alg
,
1885 blink::WebCryptoKeyUsageWrapKey
| blink::WebCryptoKeyUsageUnwrapKey
,
1888 {key_hex_256
, aes_kw_alg
,
1889 blink::WebCryptoKeyUsageWrapKey
| blink::WebCryptoKeyUsageUnwrapKey
,
1892 {key_hex_256
, hmac_sha_1_alg
,
1893 blink::WebCryptoKeyUsageSign
| blink::WebCryptoKeyUsageVerify
, "HS1"},
1895 {key_hex_384
, hmac_sha_384_alg
, blink::WebCryptoKeyUsageSign
, "HS384"},
1897 {key_hex_512
, hmac_sha_512_alg
, blink::WebCryptoKeyUsageVerify
, "HS512"},
1898 // Large usage value
1899 {key_hex_256
, aes_cbc_alg
,
1900 blink::WebCryptoKeyUsageEncrypt
| blink::WebCryptoKeyUsageDecrypt
|
1901 blink::WebCryptoKeyUsageWrapKey
| blink::WebCryptoKeyUsageUnwrapKey
,
1904 {key_hex_512
, hmac_sha_512_alg
, 0, "HS512"},
1907 // Round-trip import/export each key.
1909 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
1910 std::vector
<uint8
> json
;
1911 for (size_t test_index
= 0; test_index
< ARRAYSIZE_UNSAFE(kTests
);
1913 SCOPED_TRACE(test_index
);
1914 const TestCase
& test
= kTests
[test_index
];
1916 // Skip AES-GCM tests where not supported.
1917 if (test
.algorithm
.id() == blink::WebCryptoAlgorithmIdAesGcm
&&
1918 !SupportsAesGcm()) {
1922 // Import a raw key.
1923 key
= ImportSecretKeyFromRaw(
1924 HexStringToBytes(test
.key_hex
), test
.algorithm
, test
.usage
);
1926 // Export the key in JWK format and validate.
1927 ASSERT_EQ(Status::Success(),
1928 ExportKey(blink::WebCryptoKeyFormatJwk
, key
, &json
));
1929 EXPECT_TRUE(VerifySecretJwk(json
, test
.jwk_alg
, test
.key_hex
, test
.usage
));
1931 // Import the JWK-formatted key.
1934 ImportKeyJwk(CryptoData(json
), test
.algorithm
, true, test
.usage
, &key
));
1935 EXPECT_TRUE(key
.handle());
1936 EXPECT_EQ(blink::WebCryptoKeyTypeSecret
, key
.type());
1937 EXPECT_EQ(test
.algorithm
.id(), key
.algorithm().id());
1938 EXPECT_EQ(true, key
.extractable());
1939 EXPECT_EQ(test
.usage
, key
.usages());
1941 // Export the key in raw format and compare to the original.
1942 std::vector
<uint8
> key_raw_out
;
1943 ASSERT_EQ(Status::Success(),
1944 ExportKey(blink::WebCryptoKeyFormatRaw
, key
, &key_raw_out
));
1945 EXPECT_BYTES_EQ_HEX(test
.key_hex
, key_raw_out
);
1949 TEST_F(SharedCryptoTest
, MAYBE(ExportJwkEmptySymmetricKey
)) {
1950 const blink::WebCryptoAlgorithm import_algorithm
=
1951 webcrypto::CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha1
);
1953 blink::WebCryptoKeyUsageMask usages
= blink::WebCryptoKeyUsageSign
;
1954 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
1956 // Import a zero-byte HMAC key.
1957 const char key_data_hex
[] = "";
1958 key
= ImportSecretKeyFromRaw(
1959 HexStringToBytes(key_data_hex
), import_algorithm
, usages
);
1960 EXPECT_EQ(0u, key
.algorithm().hmacParams()->lengthBits());
1962 // Export the key in JWK format and validate.
1963 std::vector
<uint8
> json
;
1964 ASSERT_EQ(Status::Success(),
1965 ExportKey(blink::WebCryptoKeyFormatJwk
, key
, &json
));
1966 EXPECT_TRUE(VerifySecretJwk(json
, "HS1", key_data_hex
, usages
));
1968 // Now try re-importing the JWK key.
1969 key
= blink::WebCryptoKey::createNull();
1970 EXPECT_EQ(Status::Success(),
1971 ImportKey(blink::WebCryptoKeyFormatJwk
,
1978 EXPECT_EQ(blink::WebCryptoKeyTypeSecret
, key
.type());
1979 EXPECT_EQ(0u, key
.algorithm().hmacParams()->lengthBits());
1981 std::vector
<uint8
> exported_key_data
;
1982 EXPECT_EQ(Status::Success(),
1983 ExportKey(blink::WebCryptoKeyFormatRaw
, key
, &exported_key_data
));
1985 EXPECT_EQ(0u, exported_key_data
.size());
1988 TEST_F(SharedCryptoTest
, MAYBE(ImportExportSpki
)) {
1989 // Passing case: Import a valid RSA key in SPKI format.
1990 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
1991 ASSERT_EQ(Status::Success(),
1992 ImportKey(blink::WebCryptoKeyFormatSpki
,
1993 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex
)),
1994 CreateRsaHashedImportAlgorithm(
1995 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
1996 blink::WebCryptoAlgorithmIdSha256
),
1998 blink::WebCryptoKeyUsageVerify
,
2000 EXPECT_TRUE(key
.handle());
2001 EXPECT_EQ(blink::WebCryptoKeyTypePublic
, key
.type());
2002 EXPECT_TRUE(key
.extractable());
2003 EXPECT_EQ(blink::WebCryptoKeyUsageVerify
, key
.usages());
2004 EXPECT_EQ(kModulusLengthBits
,
2005 key
.algorithm().rsaHashedParams()->modulusLengthBits());
2006 EXPECT_BYTES_EQ_HEX(
2008 CryptoData(key
.algorithm().rsaHashedParams()->publicExponent()));
2010 // Failing case: Empty SPKI data
2012 Status::ErrorImportEmptyKeyData(),
2013 ImportKey(blink::WebCryptoKeyFormatSpki
,
2014 CryptoData(std::vector
<uint8
>()),
2015 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
),
2017 blink::WebCryptoKeyUsageVerify
,
2020 // Failing case: Bad DER encoding.
2022 Status::DataError(),
2023 ImportKey(blink::WebCryptoKeyFormatSpki
,
2024 CryptoData(HexStringToBytes("618333c4cb")),
2025 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
),
2027 blink::WebCryptoKeyUsageVerify
,
2030 // Failing case: Import RSA key but provide an inconsistent input algorithm.
2031 EXPECT_EQ(Status::DataError(),
2032 ImportKey(blink::WebCryptoKeyFormatSpki
,
2033 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex
)),
2034 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
2036 blink::WebCryptoKeyUsageEncrypt
,
2039 // Passing case: Export a previously imported RSA public key in SPKI format
2040 // and compare to original data.
2041 std::vector
<uint8
> output
;
2042 ASSERT_EQ(Status::Success(),
2043 ExportKey(blink::WebCryptoKeyFormatSpki
, key
, &output
));
2044 EXPECT_BYTES_EQ_HEX(kPublicKeySpkiDerHex
, output
);
2046 // Failing case: Try to export a previously imported RSA public key in raw
2047 // format (not allowed for a public key).
2048 EXPECT_EQ(Status::ErrorUnexpectedKeyType(),
2049 ExportKey(blink::WebCryptoKeyFormatRaw
, key
, &output
));
2051 // Failing case: Try to export a non-extractable key
2052 ASSERT_EQ(Status::Success(),
2053 ImportKey(blink::WebCryptoKeyFormatSpki
,
2054 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex
)),
2055 CreateRsaHashedImportAlgorithm(
2056 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
2057 blink::WebCryptoAlgorithmIdSha256
),
2059 blink::WebCryptoKeyUsageVerify
,
2061 EXPECT_TRUE(key
.handle());
2062 EXPECT_FALSE(key
.extractable());
2063 EXPECT_EQ(Status::ErrorKeyNotExtractable(),
2064 ExportKey(blink::WebCryptoKeyFormatSpki
, key
, &output
));
2066 // TODO(eroman): Failing test: Import a SPKI with an unrecognized hash OID
2067 // TODO(eroman): Failing test: Import a SPKI with invalid algorithm params
2068 // TODO(eroman): Failing test: Import a SPKI with inconsistent parameters
2069 // (e.g. SHA-1 in OID, SHA-256 in params)
2070 // TODO(eroman): Failing test: Import a SPKI for RSA-SSA, but with params
2074 TEST_F(SharedCryptoTest
, MAYBE(ImportExportPkcs8
)) {
2075 // Passing case: Import a valid RSA key in PKCS#8 format.
2076 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
2077 ASSERT_EQ(Status::Success(),
2078 ImportKey(blink::WebCryptoKeyFormatPkcs8
,
2079 CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex
)),
2080 CreateRsaHashedImportAlgorithm(
2081 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
2082 blink::WebCryptoAlgorithmIdSha1
),
2084 blink::WebCryptoKeyUsageSign
,
2086 EXPECT_TRUE(key
.handle());
2087 EXPECT_EQ(blink::WebCryptoKeyTypePrivate
, key
.type());
2088 EXPECT_TRUE(key
.extractable());
2089 EXPECT_EQ(blink::WebCryptoKeyUsageSign
, key
.usages());
2090 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1
,
2091 key
.algorithm().rsaHashedParams()->hash().id());
2092 EXPECT_EQ(kModulusLengthBits
,
2093 key
.algorithm().rsaHashedParams()->modulusLengthBits());
2094 EXPECT_BYTES_EQ_HEX(
2096 CryptoData(key
.algorithm().rsaHashedParams()->publicExponent()));
2098 std::vector
<uint8
> exported_key
;
2099 ASSERT_EQ(Status::Success(),
2100 ExportKey(blink::WebCryptoKeyFormatPkcs8
, key
, &exported_key
));
2101 EXPECT_BYTES_EQ_HEX(kPrivateKeyPkcs8DerHex
, exported_key
);
2103 // Failing case: Empty PKCS#8 data
2104 EXPECT_EQ(Status::ErrorImportEmptyKeyData(),
2105 ImportKey(blink::WebCryptoKeyFormatPkcs8
,
2106 CryptoData(std::vector
<uint8
>()),
2107 CreateRsaHashedImportAlgorithm(
2108 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
2109 blink::WebCryptoAlgorithmIdSha1
),
2111 blink::WebCryptoKeyUsageSign
,
2114 // Failing case: Bad DER encoding.
2116 Status::DataError(),
2117 ImportKey(blink::WebCryptoKeyFormatPkcs8
,
2118 CryptoData(HexStringToBytes("618333c4cb")),
2119 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
),
2121 blink::WebCryptoKeyUsageSign
,
2124 // Failing case: Import RSA key but provide an inconsistent input algorithm
2125 // and usage. Several issues here:
2126 // * AES-CBC doesn't support PKCS8 key format
2127 // * AES-CBC doesn't support "sign" usage
2128 EXPECT_EQ(Status::ErrorCreateKeyBadUsages(),
2129 ImportKey(blink::WebCryptoKeyFormatPkcs8
,
2130 CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex
)),
2131 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
2133 blink::WebCryptoKeyUsageSign
,
2137 // Tests JWK import and export by doing a roundtrip key conversion and ensuring
2140 // PKCS8 --> JWK --> PKCS8
2141 TEST_F(SharedCryptoTest
, MAYBE(ImportRsaPrivateKeyJwkToPkcs8RoundTrip
)) {
2142 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
2143 ASSERT_EQ(Status::Success(),
2144 ImportKey(blink::WebCryptoKeyFormatPkcs8
,
2145 CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex
)),
2146 CreateRsaHashedImportAlgorithm(
2147 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
2148 blink::WebCryptoAlgorithmIdSha1
),
2150 blink::WebCryptoKeyUsageSign
,
2153 std::vector
<uint8
> exported_key_jwk
;
2154 ASSERT_EQ(Status::Success(),
2155 ExportKey(blink::WebCryptoKeyFormatJwk
, key
, &exported_key_jwk
));
2157 // All of the optional parameters (p, q, dp, dq, qi) should be present in the
2159 const char* expected_jwk
=
2160 "{\"alg\":\"RS1\",\"d\":\"M6UEKpCyfU9UUcqbu9C0R3GhAa-IQ0Cu-YhfKku-"
2161 "kuiUpySsPFaMj5eFOtB8AmbIxqPKCSnx6PESMYhEKfxNmuVf7olqEM5wfD7X5zTkRyejlXRQ"
2162 "GlMmgxCcKrrKuig8MbS9L1PD7jfjUs7jT55QO9gMBiKtecbc7og1R8ajsyU\",\"dp\":"
2164 "KFZy6ylpy6hkMMAieGc0nSlVvNsT24Z9VSzTAd3kEJ7vdjdPt4kSDKPOF2Bsw6OQ7L_-"
2165 "gJ4YZeQ\",\"dq\":\"Gos485j6cSBJiY1_t57gp3ZoeRKZzfoJ78DlB6yyHtdDAe9b_Ui-"
2166 "RV6utuFnglWCdYCo5OjhQVHRUQqCo_LnKQ\",\"e\":\"AQAB\",\"ext\":true,\"key_"
2167 "ops\":[\"sign\"],\"kty\":\"RSA\",\"n\":"
2168 "\"pW5KDnAQF1iaUYfcfqhB0Vby7A42rVKkTf6x5h962ZHYxRBW_-2xYrTA8oOhKoijlN_"
2169 "1JqtykcuzB86r_OCx39XNlQgJbVsri2311nHvY3fAkhyyPCcKcOJZjm_4nRnxBazC0_"
2170 "DLNfKSgOE4a29kxO8i4eHyDQzoz_siSb2aITc\",\"p\":\"5-"
2171 "iUJyCod1Fyc6NWBT6iobwMlKpy1VxuhilrLfyWeUjApyy8zKfqyzVwbgmh31WhU1vZs8w0Fg"
2172 "s7bc0-2o5kQw\",\"q\":\"tp3KHPfU1-yB51uQ_MqHSrzeEj_"
2173 "ScAGAqpBHm25I3o1n7ST58Z2FuidYdPVCzSDccj5pYzZKH5QlRSsmmmeZ_Q\",\"qi\":"
2174 "\"JxVqukEm0kqB86Uoy_sn9WiG-"
2175 "ECp9uhuF6RLlP6TGVhLjiL93h5aLjvYqluo2FhBlOshkKz4MrhH8To9JKefTQ\"}";
2177 ASSERT_EQ(CryptoData(std::string(expected_jwk
)),
2178 CryptoData(exported_key_jwk
));
2180 ASSERT_EQ(Status::Success(),
2181 ImportKey(blink::WebCryptoKeyFormatJwk
,
2182 CryptoData(exported_key_jwk
),
2183 CreateRsaHashedImportAlgorithm(
2184 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
2185 blink::WebCryptoAlgorithmIdSha1
),
2187 blink::WebCryptoKeyUsageSign
,
2190 std::vector
<uint8
> exported_key_pkcs8
;
2193 ExportKey(blink::WebCryptoKeyFormatPkcs8
, key
, &exported_key_pkcs8
));
2195 ASSERT_EQ(CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex
)),
2196 CryptoData(exported_key_pkcs8
));
2199 // Tests importing multiple RSA private keys from JWK, and then exporting to
2202 // This is a regression test for http://crbug.com/378315, for which importing
2203 // a sequence of keys from JWK could yield the wrong key. The first key would
2204 // be imported correctly, however every key after that would actually import
2206 TEST_F(SharedCryptoTest
, MAYBE(ImportMultipleRSAPrivateKeysJwk
)) {
2207 scoped_ptr
<base::ListValue
> key_list
;
2208 ASSERT_TRUE(ReadJsonTestFileToList("rsa_private_keys.json", &key_list
));
2210 // For this test to be meaningful the keys MUST be kept alive before importing
2212 std::vector
<blink::WebCryptoKey
> live_keys
;
2214 for (size_t key_index
= 0; key_index
< key_list
->GetSize(); ++key_index
) {
2215 SCOPED_TRACE(key_index
);
2217 base::DictionaryValue
* key_values
;
2218 ASSERT_TRUE(key_list
->GetDictionary(key_index
, &key_values
));
2220 // Get the JWK representation of the key.
2221 base::DictionaryValue
* key_jwk
;
2222 ASSERT_TRUE(key_values
->GetDictionary("jwk", &key_jwk
));
2224 // Get the PKCS8 representation of the key.
2225 std::string pkcs8_hex_string
;
2226 ASSERT_TRUE(key_values
->GetString("pkcs8", &pkcs8_hex_string
));
2227 std::vector
<uint8
> pkcs8_bytes
= HexStringToBytes(pkcs8_hex_string
);
2229 // Get the modulus length for the key.
2230 int modulus_length_bits
= 0;
2231 ASSERT_TRUE(key_values
->GetInteger("modulusLength", &modulus_length_bits
));
2233 blink::WebCryptoKey private_key
= blink::WebCryptoKey::createNull();
2235 // Import the key from JWK.
2238 ImportKeyJwkFromDict(*key_jwk
,
2239 CreateRsaHashedImportAlgorithm(
2240 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
2241 blink::WebCryptoAlgorithmIdSha256
),
2243 blink::WebCryptoKeyUsageSign
,
2246 live_keys
.push_back(private_key
);
2249 modulus_length_bits
,
2251 private_key
.algorithm().rsaHashedParams()->modulusLengthBits()));
2253 // Export to PKCS8 and verify that it matches expectation.
2254 std::vector
<uint8
> exported_key_pkcs8
;
2258 blink::WebCryptoKeyFormatPkcs8
, private_key
, &exported_key_pkcs8
));
2260 EXPECT_BYTES_EQ(pkcs8_bytes
, exported_key_pkcs8
);
2264 // Import an RSA private key using JWK. Next import a JWK containing the same
2265 // modulus, but mismatched parameters for the rest. It should NOT be possible
2266 // that the second import retrieves the first key. See http://crbug.com/378315
2267 // for how that could happen.
2268 TEST_F(SharedCryptoTest
, MAYBE(ImportJwkExistingModulusAndInvalid
)) {
2269 #if defined(USE_NSS)
2270 if (!NSS_VersionCheck("3.16.2")) {
2271 LOG(WARNING
) << "Skipping test because lacks NSS support";
2276 scoped_ptr
<base::ListValue
> key_list
;
2277 ASSERT_TRUE(ReadJsonTestFileToList("rsa_private_keys.json", &key_list
));
2279 // Import a 1024-bit private key.
2280 base::DictionaryValue
* key1_props
;
2281 ASSERT_TRUE(key_list
->GetDictionary(1, &key1_props
));
2282 base::DictionaryValue
* key1_jwk
;
2283 ASSERT_TRUE(key1_props
->GetDictionary("jwk", &key1_jwk
));
2285 blink::WebCryptoKey key1
= blink::WebCryptoKey::createNull();
2286 ASSERT_EQ(Status::Success(),
2287 ImportKeyJwkFromDict(*key1_jwk
,
2288 CreateRsaHashedImportAlgorithm(
2289 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
2290 blink::WebCryptoAlgorithmIdSha256
),
2292 blink::WebCryptoKeyUsageSign
,
2295 ASSERT_EQ(1024u, key1
.algorithm().rsaHashedParams()->modulusLengthBits());
2297 // Construct a JWK using the modulus of key1, but all the other fields from
2298 // another key (also a 1024-bit private key).
2299 base::DictionaryValue
* key2_props
;
2300 ASSERT_TRUE(key_list
->GetDictionary(5, &key2_props
));
2301 base::DictionaryValue
* key2_jwk
;
2302 ASSERT_TRUE(key2_props
->GetDictionary("jwk", &key2_jwk
));
2303 std::string modulus
;
2304 key1_jwk
->GetString("n", &modulus
);
2305 key2_jwk
->SetString("n", modulus
);
2307 // This should fail, as the n,e,d parameters are not consistent. It MUST NOT
2308 // somehow return the key created earlier.
2309 blink::WebCryptoKey key2
= blink::WebCryptoKey::createNull();
2310 ASSERT_EQ(Status::OperationError(),
2311 ImportKeyJwkFromDict(*key2_jwk
,
2312 CreateRsaHashedImportAlgorithm(
2313 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
2314 blink::WebCryptoAlgorithmIdSha256
),
2316 blink::WebCryptoKeyUsageSign
,
2320 // Import a JWK RSA private key with some optional parameters missing (q, dp,
2323 // The only optional parameter included is "p".
2325 // This fails because JWA says that producers must include either ALL optional
2326 // parameters or NONE.
2327 TEST_F(SharedCryptoTest
, MAYBE(ImportRsaPrivateKeyJwkMissingOptionalParams
)) {
2328 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
2330 base::DictionaryValue dict
;
2331 dict
.SetString("kty", "RSA");
2332 dict
.SetString("alg", "RS1");
2336 "pW5KDnAQF1iaUYfcfqhB0Vby7A42rVKkTf6x5h962ZHYxRBW_-2xYrTA8oOhKoijlN_"
2337 "1JqtykcuzB86r_OCx39XNlQgJbVsri2311nHvY3fAkhyyPCcKcOJZjm_4nRnxBazC0_"
2338 "DLNfKSgOE4a29kxO8i4eHyDQzoz_siSb2aITc");
2339 dict
.SetString("e", "AQAB");
2342 "M6UEKpCyfU9UUcqbu9C0R3GhAa-IQ0Cu-YhfKku-"
2343 "kuiUpySsPFaMj5eFOtB8AmbIxqPKCSnx6PESMYhEKfxNmuVf7olqEM5wfD7X5zTkRyejlXRQ"
2344 "GlMmgxCcKrrKuig8MbS9L1PD7jfjUs7jT55QO9gMBiKtecbc7og1R8ajsyU");
2348 "iUJyCod1Fyc6NWBT6iobwMlKpy1VxuhilrLfyWeUjApyy8zKfqyzVwbgmh31W"
2349 "hU1vZs8w0Fgs7bc0-2o5kQw");
2351 ASSERT_EQ(Status::ErrorJwkIncompleteOptionalRsaPrivateKey(),
2352 ImportKeyJwkFromDict(dict
,
2353 CreateRsaHashedImportAlgorithm(
2354 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
2355 blink::WebCryptoAlgorithmIdSha1
),
2357 blink::WebCryptoKeyUsageSign
,
2361 // Import a JWK RSA private key, without any of the optional parameters.
2363 // This is expected to work, however based on the current NSS implementation it
2366 // TODO(eroman): http://crbug/com/374927
2367 TEST_F(SharedCryptoTest
, MAYBE(ImportRsaPrivateKeyJwkIncorrectOptionalEmpty
)) {
2368 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
2370 base::DictionaryValue dict
;
2371 dict
.SetString("kty", "RSA");
2372 dict
.SetString("alg", "RS1");
2376 "pW5KDnAQF1iaUYfcfqhB0Vby7A42rVKkTf6x5h962ZHYxRBW_-2xYrTA8oOhKoijlN_"
2377 "1JqtykcuzB86r_OCx39XNlQgJbVsri2311nHvY3fAkhyyPCcKcOJZjm_4nRnxBazC0_"
2378 "DLNfKSgOE4a29kxO8i4eHyDQzoz_siSb2aITc");
2379 dict
.SetString("e", "AQAB");
2382 "M6UEKpCyfU9UUcqbu9C0R3GhAa-IQ0Cu-YhfKku-"
2383 "kuiUpySsPFaMj5eFOtB8AmbIxqPKCSnx6PESMYhEKfxNmuVf7olqEM5wfD7X5zTkRyejlXRQ"
2384 "GlMmgxCcKrrKuig8MbS9L1PD7jfjUs7jT55QO9gMBiKtecbc7og1R8ajsyU");
2386 // TODO(eroman): This should pass, see: http://crbug/com/374927
2388 // Technically it is OK to fail since JWA says that consumer are not required
2389 // to support lack of the optional parameters.
2390 ASSERT_EQ(Status::OperationError(),
2391 ImportKeyJwkFromDict(dict
,
2392 CreateRsaHashedImportAlgorithm(
2393 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
2394 blink::WebCryptoAlgorithmIdSha1
),
2396 blink::WebCryptoKeyUsageSign
,
2401 TEST_F(SharedCryptoTest
, MAYBE(GenerateKeyPairRsa
)) {
2402 // Note: using unrealistic short key lengths here to avoid bogging down tests.
2404 // Successful WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 key generation (sha256)
2405 const unsigned int modulus_length
= 256;
2406 const std::vector
<uint8
> public_exponent
= HexStringToBytes("010001");
2407 blink::WebCryptoAlgorithm algorithm
=
2408 CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
2409 blink::WebCryptoAlgorithmIdSha256
,
2412 bool extractable
= true;
2413 const blink::WebCryptoKeyUsageMask usage_mask
= 0;
2414 blink::WebCryptoKey public_key
= blink::WebCryptoKey::createNull();
2415 blink::WebCryptoKey private_key
= blink::WebCryptoKey::createNull();
2417 EXPECT_EQ(Status::Success(),
2419 algorithm
, extractable
, usage_mask
, &public_key
, &private_key
));
2420 EXPECT_FALSE(public_key
.isNull());
2421 EXPECT_FALSE(private_key
.isNull());
2422 EXPECT_EQ(blink::WebCryptoKeyTypePublic
, public_key
.type());
2423 EXPECT_EQ(blink::WebCryptoKeyTypePrivate
, private_key
.type());
2424 EXPECT_EQ(modulus_length
,
2425 public_key
.algorithm().rsaHashedParams()->modulusLengthBits());
2426 EXPECT_EQ(modulus_length
,
2427 private_key
.algorithm().rsaHashedParams()->modulusLengthBits());
2428 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256
,
2429 public_key
.algorithm().rsaHashedParams()->hash().id());
2430 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256
,
2431 private_key
.algorithm().rsaHashedParams()->hash().id());
2432 EXPECT_TRUE(public_key
.extractable());
2433 EXPECT_EQ(extractable
, private_key
.extractable());
2434 EXPECT_EQ(usage_mask
, public_key
.usages());
2435 EXPECT_EQ(usage_mask
, private_key
.usages());
2437 // Try exporting the generated key pair, and then re-importing to verify that
2438 // the exported data was valid.
2439 std::vector
<uint8
> public_key_spki
;
2442 ExportKey(blink::WebCryptoKeyFormatSpki
, public_key
, &public_key_spki
));
2443 public_key
= blink::WebCryptoKey::createNull();
2444 EXPECT_EQ(Status::Success(),
2445 ImportKey(blink::WebCryptoKeyFormatSpki
,
2446 CryptoData(public_key_spki
),
2447 CreateRsaHashedImportAlgorithm(
2448 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
2449 blink::WebCryptoAlgorithmIdSha256
),
2453 EXPECT_EQ(modulus_length
,
2454 public_key
.algorithm().rsaHashedParams()->modulusLengthBits());
2456 std::vector
<uint8
> private_key_pkcs8
;
2460 blink::WebCryptoKeyFormatPkcs8
, private_key
, &private_key_pkcs8
));
2461 private_key
= blink::WebCryptoKey::createNull();
2462 EXPECT_EQ(Status::Success(),
2463 ImportKey(blink::WebCryptoKeyFormatPkcs8
,
2464 CryptoData(private_key_pkcs8
),
2465 CreateRsaHashedImportAlgorithm(
2466 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
2467 blink::WebCryptoAlgorithmIdSha256
),
2471 EXPECT_EQ(modulus_length
,
2472 private_key
.algorithm().rsaHashedParams()->modulusLengthBits());
2474 // Fail with bad modulus.
2476 CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
2477 blink::WebCryptoAlgorithmIdSha256
,
2480 EXPECT_EQ(Status::ErrorGenerateRsaZeroModulus(),
2482 algorithm
, extractable
, usage_mask
, &public_key
, &private_key
));
2484 // Fail with bad exponent: larger than unsigned long.
2485 unsigned int exponent_length
= sizeof(unsigned long) + 1; // NOLINT
2486 const std::vector
<uint8
> long_exponent(exponent_length
, 0x01);
2488 CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
2489 blink::WebCryptoAlgorithmIdSha256
,
2492 EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
2494 algorithm
, extractable
, usage_mask
, &public_key
, &private_key
));
2496 // Fail with bad exponent: empty.
2497 const std::vector
<uint8
> empty_exponent
;
2499 CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
2500 blink::WebCryptoAlgorithmIdSha256
,
2503 EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
2505 algorithm
, extractable
, usage_mask
, &public_key
, &private_key
));
2507 // Fail with bad exponent: all zeros.
2508 std::vector
<uint8
> exponent_with_leading_zeros(15, 0x00);
2510 CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
2511 blink::WebCryptoAlgorithmIdSha256
,
2513 exponent_with_leading_zeros
);
2514 EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
2516 algorithm
, extractable
, usage_mask
, &public_key
, &private_key
));
2518 // Key generation success using exponent with leading zeros.
2519 exponent_with_leading_zeros
.insert(exponent_with_leading_zeros
.end(),
2520 public_exponent
.begin(),
2521 public_exponent
.end());
2523 CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
2524 blink::WebCryptoAlgorithmIdSha256
,
2526 exponent_with_leading_zeros
);
2527 EXPECT_EQ(Status::Success(),
2529 algorithm
, extractable
, usage_mask
, &public_key
, &private_key
));
2530 EXPECT_FALSE(public_key
.isNull());
2531 EXPECT_FALSE(private_key
.isNull());
2532 EXPECT_EQ(blink::WebCryptoKeyTypePublic
, public_key
.type());
2533 EXPECT_EQ(blink::WebCryptoKeyTypePrivate
, private_key
.type());
2534 EXPECT_TRUE(public_key
.extractable());
2535 EXPECT_EQ(extractable
, private_key
.extractable());
2536 EXPECT_EQ(usage_mask
, public_key
.usages());
2537 EXPECT_EQ(usage_mask
, private_key
.usages());
2539 // Successful WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 key generation (sha1)
2541 CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
2542 blink::WebCryptoAlgorithmIdSha1
,
2547 GenerateKeyPair(algorithm
, false, usage_mask
, &public_key
, &private_key
));
2548 EXPECT_FALSE(public_key
.isNull());
2549 EXPECT_FALSE(private_key
.isNull());
2550 EXPECT_EQ(blink::WebCryptoKeyTypePublic
, public_key
.type());
2551 EXPECT_EQ(blink::WebCryptoKeyTypePrivate
, private_key
.type());
2552 EXPECT_EQ(modulus_length
,
2553 public_key
.algorithm().rsaHashedParams()->modulusLengthBits());
2554 EXPECT_EQ(modulus_length
,
2555 private_key
.algorithm().rsaHashedParams()->modulusLengthBits());
2556 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1
,
2557 public_key
.algorithm().rsaHashedParams()->hash().id());
2558 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1
,
2559 private_key
.algorithm().rsaHashedParams()->hash().id());
2560 // Even though "extractable" was set to false, the public key remains
2562 EXPECT_TRUE(public_key
.extractable());
2563 EXPECT_FALSE(private_key
.extractable());
2564 EXPECT_EQ(usage_mask
, public_key
.usages());
2565 EXPECT_EQ(usage_mask
, private_key
.usages());
2567 // Exporting a private key as SPKI format doesn't make sense. However this
2568 // will first fail because the key is not extractable.
2569 std::vector
<uint8
> output
;
2570 EXPECT_EQ(Status::ErrorKeyNotExtractable(),
2571 ExportKey(blink::WebCryptoKeyFormatSpki
, private_key
, &output
));
2573 // Re-generate an extractable private_key and try to export it as SPKI format.
2574 // This should fail since spki is for public keys.
2577 GenerateKeyPair(algorithm
, true, usage_mask
, &public_key
, &private_key
));
2578 EXPECT_EQ(Status::ErrorUnexpectedKeyType(),
2579 ExportKey(blink::WebCryptoKeyFormatSpki
, private_key
, &output
));
2582 TEST_F(SharedCryptoTest
, MAYBE(RsaSsaSignVerifyFailures
)) {
2583 // Import a key pair.
2584 blink::WebCryptoAlgorithm import_algorithm
=
2585 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
2586 blink::WebCryptoAlgorithmIdSha1
);
2587 blink::WebCryptoKey public_key
= blink::WebCryptoKey::createNull();
2588 blink::WebCryptoKey private_key
= blink::WebCryptoKey::createNull();
2589 ASSERT_NO_FATAL_FAILURE(
2590 ImportRsaKeyPair(HexStringToBytes(kPublicKeySpkiDerHex
),
2591 HexStringToBytes(kPrivateKeyPkcs8DerHex
),
2594 blink::WebCryptoKeyUsageVerify
,
2595 blink::WebCryptoKeyUsageSign
,
2599 blink::WebCryptoAlgorithm algorithm
=
2600 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
);
2602 std::vector
<uint8
> signature
;
2603 bool signature_match
;
2605 // Compute a signature.
2606 const std::vector
<uint8
> data
= HexStringToBytes("010203040506070809");
2607 ASSERT_EQ(Status::Success(),
2608 Sign(algorithm
, private_key
, CryptoData(data
), &signature
));
2610 // Ensure truncated signature does not verify by passing one less byte.
2611 EXPECT_EQ(Status::Success(),
2615 CryptoData(Uint8VectorStart(signature
), signature
.size() - 1),
2618 EXPECT_FALSE(signature_match
);
2620 // Ensure truncated signature does not verify by passing no bytes.
2621 EXPECT_EQ(Status::Success(),
2622 VerifySignature(algorithm
,
2627 EXPECT_FALSE(signature_match
);
2629 // Ensure corrupted signature does not verify.
2630 std::vector
<uint8
> corrupt_sig
= signature
;
2631 corrupt_sig
[corrupt_sig
.size() / 2] ^= 0x1;
2632 EXPECT_EQ(Status::Success(),
2633 VerifySignature(algorithm
,
2635 CryptoData(corrupt_sig
),
2638 EXPECT_FALSE(signature_match
);
2640 // Ensure signatures that are greater than the modulus size fail.
2641 const unsigned int long_message_size_bytes
= 1024;
2642 DCHECK_GT(long_message_size_bytes
, kModulusLengthBits
/ 8);
2643 const unsigned char kLongSignature
[long_message_size_bytes
] = {0};
2644 EXPECT_EQ(Status::Success(),
2645 VerifySignature(algorithm
,
2647 CryptoData(kLongSignature
, sizeof(kLongSignature
)),
2650 EXPECT_FALSE(signature_match
);
2652 // Ensure that signing and verifying with an incompatible algorithm fails.
2653 algorithm
= CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaOaep
);
2655 EXPECT_EQ(Status::ErrorUnexpected(),
2656 Sign(algorithm
, private_key
, CryptoData(data
), &signature
));
2657 EXPECT_EQ(Status::ErrorUnexpected(),
2658 VerifySignature(algorithm
,
2660 CryptoData(signature
),
2664 // Some crypto libraries (NSS) can automatically select the RSA SSA inner hash
2665 // based solely on the contents of the input signature data. In the Web Crypto
2666 // implementation, the inner hash should be specified uniquely by the key
2667 // algorithm parameter. To validate this behavior, call Verify with a computed
2668 // signature that used one hash type (SHA-1), but pass in a key with a
2669 // different inner hash type (SHA-256). If the hash type is determined by the
2670 // signature itself (undesired), the verify will pass, while if the hash type
2671 // is specified by the key algorithm (desired), the verify will fail.
2673 // Compute a signature using SHA-1 as the inner hash.
2674 EXPECT_EQ(Status::Success(),
2675 Sign(CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
),
2680 blink::WebCryptoKey public_key_256
= blink::WebCryptoKey::createNull();
2681 EXPECT_EQ(Status::Success(),
2682 ImportKey(blink::WebCryptoKeyFormatSpki
,
2683 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex
)),
2684 CreateRsaHashedImportAlgorithm(
2685 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
2686 blink::WebCryptoAlgorithmIdSha256
),
2688 blink::WebCryptoKeyUsageVerify
,
2691 // Now verify using an algorithm whose inner hash is SHA-256, not SHA-1. The
2692 // signature should not verify.
2693 // NOTE: public_key was produced by generateKey, and so its associated
2694 // algorithm has WebCryptoRsaKeyGenParams and not WebCryptoRsaSsaParams. Thus
2695 // it has no inner hash to conflict with the input algorithm.
2696 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1
,
2697 private_key
.algorithm().rsaHashedParams()->hash().id());
2698 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256
,
2699 public_key_256
.algorithm().rsaHashedParams()->hash().id());
2702 EXPECT_EQ(Status::Success(),
2704 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
),
2706 CryptoData(signature
),
2709 EXPECT_FALSE(is_match
);
2712 TEST_F(SharedCryptoTest
, MAYBE(RsaSignVerifyKnownAnswer
)) {
2713 scoped_ptr
<base::ListValue
> tests
;
2714 ASSERT_TRUE(ReadJsonTestFileToList("pkcs1v15_sign.json", &tests
));
2716 // Import the key pair.
2717 blink::WebCryptoAlgorithm import_algorithm
=
2718 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
2719 blink::WebCryptoAlgorithmIdSha1
);
2720 blink::WebCryptoKey public_key
= blink::WebCryptoKey::createNull();
2721 blink::WebCryptoKey private_key
= blink::WebCryptoKey::createNull();
2722 ASSERT_NO_FATAL_FAILURE(
2723 ImportRsaKeyPair(HexStringToBytes(kPublicKeySpkiDerHex
),
2724 HexStringToBytes(kPrivateKeyPkcs8DerHex
),
2727 blink::WebCryptoKeyUsageVerify
,
2728 blink::WebCryptoKeyUsageSign
,
2732 blink::WebCryptoAlgorithm algorithm
=
2733 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
);
2735 // Validate the signatures are computed and verified as expected.
2736 std::vector
<uint8
> signature
;
2737 for (size_t test_index
= 0; test_index
< tests
->GetSize(); ++test_index
) {
2738 SCOPED_TRACE(test_index
);
2740 base::DictionaryValue
* test
;
2741 ASSERT_TRUE(tests
->GetDictionary(test_index
, &test
));
2743 std::vector
<uint8
> test_message
=
2744 GetBytesFromHexString(test
, "message_hex");
2745 std::vector
<uint8
> test_signature
=
2746 GetBytesFromHexString(test
, "signature_hex");
2751 Sign(algorithm
, private_key
, CryptoData(test_message
), &signature
));
2752 EXPECT_BYTES_EQ(test_signature
, signature
);
2754 bool is_match
= false;
2755 ASSERT_EQ(Status::Success(),
2756 VerifySignature(algorithm
,
2758 CryptoData(test_signature
),
2759 CryptoData(test_message
),
2761 EXPECT_TRUE(is_match
);
2765 TEST_F(SharedCryptoTest
, MAYBE(AesKwKeyImport
)) {
2766 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
2767 blink::WebCryptoAlgorithm algorithm
=
2768 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw
);
2770 // Import a 128-bit Key Encryption Key (KEK)
2771 std::string key_raw_hex_in
= "025a8cf3f08b4f6c5f33bbc76a471939";
2772 ASSERT_EQ(Status::Success(),
2773 ImportKey(blink::WebCryptoKeyFormatRaw
,
2774 CryptoData(HexStringToBytes(key_raw_hex_in
)),
2777 blink::WebCryptoKeyUsageWrapKey
,
2779 std::vector
<uint8
> key_raw_out
;
2780 EXPECT_EQ(Status::Success(),
2781 ExportKey(blink::WebCryptoKeyFormatRaw
, key
, &key_raw_out
));
2782 EXPECT_BYTES_EQ_HEX(key_raw_hex_in
, key_raw_out
);
2784 // Import a 192-bit KEK
2785 key_raw_hex_in
= "c0192c6466b2370decbb62b2cfef4384544ffeb4d2fbc103";
2786 ASSERT_EQ(Status::Success(),
2787 ImportKey(blink::WebCryptoKeyFormatRaw
,
2788 CryptoData(HexStringToBytes(key_raw_hex_in
)),
2791 blink::WebCryptoKeyUsageWrapKey
,
2793 EXPECT_EQ(Status::Success(),
2794 ExportKey(blink::WebCryptoKeyFormatRaw
, key
, &key_raw_out
));
2795 EXPECT_BYTES_EQ_HEX(key_raw_hex_in
, key_raw_out
);
2797 // Import a 256-bit Key Encryption Key (KEK)
2799 "e11fe66380d90fa9ebefb74e0478e78f95664d0c67ca20ce4a0b5842863ac46f";
2800 ASSERT_EQ(Status::Success(),
2801 ImportKey(blink::WebCryptoKeyFormatRaw
,
2802 CryptoData(HexStringToBytes(key_raw_hex_in
)),
2805 blink::WebCryptoKeyUsageWrapKey
,
2807 EXPECT_EQ(Status::Success(),
2808 ExportKey(blink::WebCryptoKeyFormatRaw
, key
, &key_raw_out
));
2809 EXPECT_BYTES_EQ_HEX(key_raw_hex_in
, key_raw_out
);
2811 // Fail import of 0 length key
2812 EXPECT_EQ(Status::ErrorImportAesKeyLength(),
2813 ImportKey(blink::WebCryptoKeyFormatRaw
,
2814 CryptoData(HexStringToBytes("")),
2817 blink::WebCryptoKeyUsageWrapKey
,
2820 // Fail import of 124-bit KEK
2821 key_raw_hex_in
= "3e4566a2bdaa10cb68134fa66c15ddb";
2822 EXPECT_EQ(Status::ErrorImportAesKeyLength(),
2823 ImportKey(blink::WebCryptoKeyFormatRaw
,
2824 CryptoData(HexStringToBytes(key_raw_hex_in
)),
2827 blink::WebCryptoKeyUsageWrapKey
,
2830 // Fail import of 200-bit KEK
2831 key_raw_hex_in
= "0a1d88608a5ad9fec64f1ada269ebab4baa2feeb8d95638c0e";
2832 EXPECT_EQ(Status::ErrorImportAesKeyLength(),
2833 ImportKey(blink::WebCryptoKeyFormatRaw
,
2834 CryptoData(HexStringToBytes(key_raw_hex_in
)),
2837 blink::WebCryptoKeyUsageWrapKey
,
2840 // Fail import of 260-bit KEK
2842 "72d4e475ff34215416c9ad9c8281247a4d730c5f275ac23f376e73e3bce8d7d5a";
2843 EXPECT_EQ(Status::ErrorImportAesKeyLength(),
2844 ImportKey(blink::WebCryptoKeyFormatRaw
,
2845 CryptoData(HexStringToBytes(key_raw_hex_in
)),
2848 blink::WebCryptoKeyUsageWrapKey
,
2852 TEST_F(SharedCryptoTest
, MAYBE(UnwrapFailures
)) {
2853 // This test exercises the code path common to all unwrap operations.
2854 scoped_ptr
<base::ListValue
> tests
;
2855 ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests
));
2856 base::DictionaryValue
* test
;
2857 ASSERT_TRUE(tests
->GetDictionary(0, &test
));
2858 const std::vector
<uint8
> test_kek
= GetBytesFromHexString(test
, "kek");
2859 const std::vector
<uint8
> test_ciphertext
=
2860 GetBytesFromHexString(test
, "ciphertext");
2862 blink::WebCryptoKey unwrapped_key
= blink::WebCryptoKey::createNull();
2864 // Using a wrapping algorithm that does not match the wrapping key algorithm
2866 blink::WebCryptoKey wrapping_key
= ImportSecretKeyFromRaw(
2868 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw
),
2869 blink::WebCryptoKeyUsageUnwrapKey
);
2871 Status::ErrorUnexpected(),
2872 UnwrapKey(blink::WebCryptoKeyFormatRaw
,
2873 CryptoData(test_ciphertext
),
2875 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
2876 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
2878 blink::WebCryptoKeyUsageEncrypt
,
2882 TEST_F(SharedCryptoTest
, MAYBE(AesKwRawSymkeyWrapUnwrapKnownAnswer
)) {
2883 scoped_ptr
<base::ListValue
> tests
;
2884 ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests
));
2886 for (size_t test_index
= 0; test_index
< tests
->GetSize(); ++test_index
) {
2887 SCOPED_TRACE(test_index
);
2888 base::DictionaryValue
* test
;
2889 ASSERT_TRUE(tests
->GetDictionary(test_index
, &test
));
2890 const std::vector
<uint8
> test_kek
= GetBytesFromHexString(test
, "kek");
2891 const std::vector
<uint8
> test_key
= GetBytesFromHexString(test
, "key");
2892 const std::vector
<uint8
> test_ciphertext
=
2893 GetBytesFromHexString(test
, "ciphertext");
2894 const blink::WebCryptoAlgorithm wrapping_algorithm
=
2895 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw
);
2897 // Import the wrapping key.
2898 blink::WebCryptoKey wrapping_key
= ImportSecretKeyFromRaw(
2901 blink::WebCryptoKeyUsageWrapKey
| blink::WebCryptoKeyUsageUnwrapKey
);
2903 // Import the key to be wrapped.
2904 blink::WebCryptoKey key
= ImportSecretKeyFromRaw(
2906 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
2907 blink::WebCryptoKeyUsageEncrypt
);
2909 // Wrap the key and verify the ciphertext result against the known answer.
2910 std::vector
<uint8
> wrapped_key
;
2911 ASSERT_EQ(Status::Success(),
2912 WrapKey(blink::WebCryptoKeyFormatRaw
,
2917 EXPECT_BYTES_EQ(test_ciphertext
, wrapped_key
);
2919 // Unwrap the known ciphertext to get a new test_key.
2920 blink::WebCryptoKey unwrapped_key
= blink::WebCryptoKey::createNull();
2923 UnwrapKey(blink::WebCryptoKeyFormatRaw
,
2924 CryptoData(test_ciphertext
),
2927 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
2929 blink::WebCryptoKeyUsageEncrypt
,
2931 EXPECT_FALSE(key
.isNull());
2932 EXPECT_TRUE(key
.handle());
2933 EXPECT_EQ(blink::WebCryptoKeyTypeSecret
, key
.type());
2934 EXPECT_EQ(blink::WebCryptoAlgorithmIdAesCbc
, key
.algorithm().id());
2935 EXPECT_EQ(true, key
.extractable());
2936 EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt
, key
.usages());
2938 // Export the new key and compare its raw bytes with the original known key.
2939 std::vector
<uint8
> raw_key
;
2940 EXPECT_EQ(Status::Success(),
2941 ExportKey(blink::WebCryptoKeyFormatRaw
, unwrapped_key
, &raw_key
));
2942 EXPECT_BYTES_EQ(test_key
, raw_key
);
2946 // Unwrap a HMAC key using AES-KW, and then try doing a sign/verify with the
2948 TEST_F(SharedCryptoTest
, MAYBE(AesKwRawSymkeyUnwrapSignVerifyHmac
)) {
2949 scoped_ptr
<base::ListValue
> tests
;
2950 ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests
));
2952 base::DictionaryValue
* test
;
2953 ASSERT_TRUE(tests
->GetDictionary(0, &test
));
2954 const std::vector
<uint8
> test_kek
= GetBytesFromHexString(test
, "kek");
2955 const std::vector
<uint8
> test_ciphertext
=
2956 GetBytesFromHexString(test
, "ciphertext");
2957 const blink::WebCryptoAlgorithm wrapping_algorithm
=
2958 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw
);
2960 // Import the wrapping key.
2961 blink::WebCryptoKey wrapping_key
= ImportSecretKeyFromRaw(
2962 test_kek
, wrapping_algorithm
, blink::WebCryptoKeyUsageUnwrapKey
);
2964 // Unwrap the known ciphertext.
2965 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
2968 UnwrapKey(blink::WebCryptoKeyFormatRaw
,
2969 CryptoData(test_ciphertext
),
2972 CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha1
),
2974 blink::WebCryptoKeyUsageSign
| blink::WebCryptoKeyUsageVerify
,
2977 EXPECT_EQ(blink::WebCryptoKeyTypeSecret
, key
.type());
2978 EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac
, key
.algorithm().id());
2979 EXPECT_FALSE(key
.extractable());
2980 EXPECT_EQ(blink::WebCryptoKeyUsageSign
| blink::WebCryptoKeyUsageVerify
,
2983 // Sign an empty message and ensure it is verified.
2984 std::vector
<uint8
> test_message
;
2985 std::vector
<uint8
> signature
;
2987 ASSERT_EQ(Status::Success(),
2988 Sign(CreateAlgorithm(blink::WebCryptoAlgorithmIdHmac
),
2990 CryptoData(test_message
),
2993 EXPECT_GT(signature
.size(), 0u);
2996 ASSERT_EQ(Status::Success(),
2997 VerifySignature(CreateAlgorithm(blink::WebCryptoAlgorithmIdHmac
),
2999 CryptoData(signature
),
3000 CryptoData(test_message
),
3004 TEST_F(SharedCryptoTest
, MAYBE(AesKwRawSymkeyWrapUnwrapErrors
)) {
3005 scoped_ptr
<base::ListValue
> tests
;
3006 ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests
));
3007 base::DictionaryValue
* test
;
3008 // Use 256 bits of data with a 256-bit KEK
3009 ASSERT_TRUE(tests
->GetDictionary(5, &test
));
3010 const std::vector
<uint8
> test_kek
= GetBytesFromHexString(test
, "kek");
3011 const std::vector
<uint8
> test_key
= GetBytesFromHexString(test
, "key");
3012 const std::vector
<uint8
> test_ciphertext
=
3013 GetBytesFromHexString(test
, "ciphertext");
3014 const blink::WebCryptoAlgorithm wrapping_algorithm
=
3015 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw
);
3016 const blink::WebCryptoAlgorithm key_algorithm
=
3017 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
);
3018 // Import the wrapping key.
3019 blink::WebCryptoKey wrapping_key
= ImportSecretKeyFromRaw(
3022 blink::WebCryptoKeyUsageWrapKey
| blink::WebCryptoKeyUsageUnwrapKey
);
3023 // Import the key to be wrapped.
3024 blink::WebCryptoKey key
= ImportSecretKeyFromRaw(
3026 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
3027 blink::WebCryptoKeyUsageEncrypt
);
3029 // Unwrap with wrapped data too small must fail.
3030 const std::vector
<uint8
> small_data(test_ciphertext
.begin(),
3031 test_ciphertext
.begin() + 23);
3032 blink::WebCryptoKey unwrapped_key
= blink::WebCryptoKey::createNull();
3033 EXPECT_EQ(Status::ErrorDataTooSmall(),
3034 UnwrapKey(blink::WebCryptoKeyFormatRaw
,
3035 CryptoData(small_data
),
3040 blink::WebCryptoKeyUsageEncrypt
,
3043 // Unwrap with wrapped data size not a multiple of 8 bytes must fail.
3044 const std::vector
<uint8
> unaligned_data(test_ciphertext
.begin(),
3045 test_ciphertext
.end() - 2);
3046 EXPECT_EQ(Status::ErrorInvalidAesKwDataLength(),
3047 UnwrapKey(blink::WebCryptoKeyFormatRaw
,
3048 CryptoData(unaligned_data
),
3053 blink::WebCryptoKeyUsageEncrypt
,
3057 TEST_F(SharedCryptoTest
, MAYBE(AesKwRawSymkeyUnwrapCorruptData
)) {
3058 scoped_ptr
<base::ListValue
> tests
;
3059 ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests
));
3060 base::DictionaryValue
* test
;
3061 // Use 256 bits of data with a 256-bit KEK
3062 ASSERT_TRUE(tests
->GetDictionary(5, &test
));
3063 const std::vector
<uint8
> test_kek
= GetBytesFromHexString(test
, "kek");
3064 const std::vector
<uint8
> test_key
= GetBytesFromHexString(test
, "key");
3065 const std::vector
<uint8
> test_ciphertext
=
3066 GetBytesFromHexString(test
, "ciphertext");
3067 const blink::WebCryptoAlgorithm wrapping_algorithm
=
3068 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw
);
3070 // Import the wrapping key.
3071 blink::WebCryptoKey wrapping_key
= ImportSecretKeyFromRaw(
3074 blink::WebCryptoKeyUsageWrapKey
| blink::WebCryptoKeyUsageUnwrapKey
);
3076 // Unwrap of a corrupted version of the known ciphertext should fail, due to
3077 // AES-KW's built-in integrity check.
3078 blink::WebCryptoKey unwrapped_key
= blink::WebCryptoKey::createNull();
3080 Status::OperationError(),
3081 UnwrapKey(blink::WebCryptoKeyFormatRaw
,
3082 CryptoData(Corrupted(test_ciphertext
)),
3085 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
3087 blink::WebCryptoKeyUsageEncrypt
,
3091 TEST_F(SharedCryptoTest
, MAYBE(AesKwJwkSymkeyUnwrapKnownData
)) {
3092 // The following data lists a known HMAC SHA-256 key, then a JWK
3093 // representation of this key which was encrypted ("wrapped") using AES-KW and
3094 // the following wrapping key.
3095 // For reference, the intermediate clear JWK is
3096 // {"alg":"HS256","ext":true,"k":<b64urlKey>,"key_ops":["verify"],"kty":"oct"}
3097 // (Not shown is space padding to ensure the cleartext meets the size
3098 // requirements of the AES-KW algorithm.)
3099 const std::vector
<uint8
> key_data
= HexStringToBytes(
3100 "000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F");
3101 const std::vector
<uint8
> wrapped_key_data
= HexStringToBytes(
3102 "14E6380B35FDC5B72E1994764B6CB7BFDD64E7832894356AAEE6C3768FC3D0F115E6B0"
3103 "6729756225F999AA99FDF81FD6A359F1576D3D23DE6CB69C3937054EB497AC1E8C38D5"
3104 "5E01B9783A20C8D930020932CF25926103002213D0FC37279888154FEBCEDF31832158"
3105 "97938C5CFE5B10B4254D0C399F39D0");
3106 const std::vector
<uint8
> wrapping_key_data
=
3107 HexStringToBytes("000102030405060708090A0B0C0D0E0F");
3108 const blink::WebCryptoAlgorithm wrapping_algorithm
=
3109 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw
);
3111 // Import the wrapping key.
3112 blink::WebCryptoKey wrapping_key
= ImportSecretKeyFromRaw(
3113 wrapping_key_data
, wrapping_algorithm
, blink::WebCryptoKeyUsageUnwrapKey
);
3115 // Unwrap the known wrapped key data to produce a new key
3116 blink::WebCryptoKey unwrapped_key
= blink::WebCryptoKey::createNull();
3119 UnwrapKey(blink::WebCryptoKeyFormatJwk
,
3120 CryptoData(wrapped_key_data
),
3123 CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha256
),
3125 blink::WebCryptoKeyUsageVerify
,
3128 // Validate the new key's attributes.
3129 EXPECT_FALSE(unwrapped_key
.isNull());
3130 EXPECT_TRUE(unwrapped_key
.handle());
3131 EXPECT_EQ(blink::WebCryptoKeyTypeSecret
, unwrapped_key
.type());
3132 EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac
, unwrapped_key
.algorithm().id());
3133 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256
,
3134 unwrapped_key
.algorithm().hmacParams()->hash().id());
3135 EXPECT_EQ(256u, unwrapped_key
.algorithm().hmacParams()->lengthBits());
3136 EXPECT_EQ(true, unwrapped_key
.extractable());
3137 EXPECT_EQ(blink::WebCryptoKeyUsageVerify
, unwrapped_key
.usages());
3139 // Export the new key's raw data and compare to the known original.
3140 std::vector
<uint8
> raw_key
;
3141 EXPECT_EQ(Status::Success(),
3142 ExportKey(blink::WebCryptoKeyFormatRaw
, unwrapped_key
, &raw_key
));
3143 EXPECT_BYTES_EQ(key_data
, raw_key
);
3147 // * Test decryption when the tag length exceeds input size
3148 // * Test decryption with empty input
3149 // * Test decryption with tag length of 0.
3150 TEST_F(SharedCryptoTest
, MAYBE(AesGcmSampleSets
)) {
3151 // Some Linux test runners may not have a new enough version of NSS.
3152 if (!SupportsAesGcm()) {
3153 LOG(WARNING
) << "AES GCM not supported, skipping tests";
3157 scoped_ptr
<base::ListValue
> tests
;
3158 ASSERT_TRUE(ReadJsonTestFileToList("aes_gcm.json", &tests
));
3160 // Note that WebCrypto appends the authentication tag to the ciphertext.
3161 for (size_t test_index
= 0; test_index
< tests
->GetSize(); ++test_index
) {
3162 SCOPED_TRACE(test_index
);
3163 base::DictionaryValue
* test
;
3164 ASSERT_TRUE(tests
->GetDictionary(test_index
, &test
));
3166 const std::vector
<uint8
> test_key
= GetBytesFromHexString(test
, "key");
3167 const std::vector
<uint8
> test_iv
= GetBytesFromHexString(test
, "iv");
3168 const std::vector
<uint8
> test_additional_data
=
3169 GetBytesFromHexString(test
, "additional_data");
3170 const std::vector
<uint8
> test_plain_text
=
3171 GetBytesFromHexString(test
, "plain_text");
3172 const std::vector
<uint8
> test_authentication_tag
=
3173 GetBytesFromHexString(test
, "authentication_tag");
3174 const unsigned int test_tag_size_bits
= test_authentication_tag
.size() * 8;
3175 const std::vector
<uint8
> test_cipher_text
=
3176 GetBytesFromHexString(test
, "cipher_text");
3178 blink::WebCryptoKey key
= ImportSecretKeyFromRaw(
3180 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesGcm
),
3181 blink::WebCryptoKeyUsageEncrypt
| blink::WebCryptoKeyUsageDecrypt
);
3183 // Verify exported raw key is identical to the imported data
3184 std::vector
<uint8
> raw_key
;
3185 EXPECT_EQ(Status::Success(),
3186 ExportKey(blink::WebCryptoKeyFormatRaw
, key
, &raw_key
));
3188 EXPECT_BYTES_EQ(test_key
, raw_key
);
3191 std::vector
<uint8
> cipher_text
;
3192 std::vector
<uint8
> authentication_tag
;
3193 EXPECT_EQ(Status::Success(),
3196 test_additional_data
,
3200 &authentication_tag
));
3202 EXPECT_BYTES_EQ(test_cipher_text
, cipher_text
);
3203 EXPECT_BYTES_EQ(test_authentication_tag
, authentication_tag
);
3206 std::vector
<uint8
> plain_text
;
3207 EXPECT_EQ(Status::Success(),
3210 test_additional_data
,
3213 test_authentication_tag
,
3215 EXPECT_BYTES_EQ(test_plain_text
, plain_text
);
3217 // Decryption should fail if any of the inputs are tampered with.
3218 EXPECT_EQ(Status::OperationError(),
3221 test_additional_data
,
3224 test_authentication_tag
,
3226 EXPECT_EQ(Status::OperationError(),
3229 Corrupted(test_additional_data
),
3232 test_authentication_tag
,
3234 EXPECT_EQ(Status::OperationError(),
3237 test_additional_data
,
3239 Corrupted(test_cipher_text
),
3240 test_authentication_tag
,
3242 EXPECT_EQ(Status::OperationError(),
3245 test_additional_data
,
3248 Corrupted(test_authentication_tag
),
3251 // Try different incorrect tag lengths
3252 uint8 kAlternateTagLengths
[] = {0, 8, 96, 120, 128, 160, 255};
3253 for (size_t tag_i
= 0; tag_i
< arraysize(kAlternateTagLengths
); ++tag_i
) {
3254 unsigned int wrong_tag_size_bits
= kAlternateTagLengths
[tag_i
];
3255 if (test_tag_size_bits
== wrong_tag_size_bits
)
3257 EXPECT_NE(Status::Success(),
3260 test_additional_data
,
3261 wrong_tag_size_bits
,
3263 test_authentication_tag
,
3269 class SharedCryptoRsaOaepTest
: public ::testing::Test
{
3271 SharedCryptoRsaOaepTest() { Init(); }
3273 scoped_ptr
<base::DictionaryValue
> CreatePublicKeyJwkDict() {
3274 scoped_ptr
<base::DictionaryValue
> jwk(new base::DictionaryValue());
3275 jwk
->SetString("kty", "RSA");
3277 Base64EncodeUrlSafe(HexStringToBytes(kPublicKeyModulusHex
)));
3279 "e", Base64EncodeUrlSafe(HexStringToBytes(kPublicKeyExponentHex
)));
3284 // Import a PKCS#8 private key that uses RSAPrivateKey with the
3285 // id-rsaEncryption OID.
3286 TEST_F(SharedCryptoRsaOaepTest
, ImportPkcs8WithRsaEncryption
) {
3287 if (!SupportsRsaOaep()) {
3288 LOG(WARNING
) << "RSA-OAEP support not present; skipping.";
3292 blink::WebCryptoKey private_key
= blink::WebCryptoKey::createNull();
3293 ASSERT_EQ(Status::Success(),
3294 ImportKey(blink::WebCryptoKeyFormatPkcs8
,
3295 CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex
)),
3296 CreateRsaHashedImportAlgorithm(
3297 blink::WebCryptoAlgorithmIdRsaOaep
,
3298 blink::WebCryptoAlgorithmIdSha1
),
3300 blink::WebCryptoKeyUsageDecrypt
,
3304 TEST_F(SharedCryptoRsaOaepTest
, ImportPublicJwkWithNoAlg
) {
3305 if (!SupportsRsaOaep()) {
3306 LOG(WARNING
) << "RSA-OAEP support not present; skipping.";
3310 scoped_ptr
<base::DictionaryValue
> jwk(CreatePublicKeyJwkDict());
3312 blink::WebCryptoKey public_key
= blink::WebCryptoKey::createNull();
3313 ASSERT_EQ(Status::Success(),
3314 ImportKeyJwkFromDict(*jwk
.get(),
3315 CreateRsaHashedImportAlgorithm(
3316 blink::WebCryptoAlgorithmIdRsaOaep
,
3317 blink::WebCryptoAlgorithmIdSha1
),
3319 blink::WebCryptoKeyUsageEncrypt
,
3323 TEST_F(SharedCryptoRsaOaepTest
, ImportPublicJwkWithMatchingAlg
) {
3324 if (!SupportsRsaOaep()) {
3325 LOG(WARNING
) << "RSA-OAEP support not present; skipping.";
3329 scoped_ptr
<base::DictionaryValue
> jwk(CreatePublicKeyJwkDict());
3330 jwk
->SetString("alg", "RSA-OAEP");
3332 blink::WebCryptoKey public_key
= blink::WebCryptoKey::createNull();
3333 ASSERT_EQ(Status::Success(),
3334 ImportKeyJwkFromDict(*jwk
.get(),
3335 CreateRsaHashedImportAlgorithm(
3336 blink::WebCryptoAlgorithmIdRsaOaep
,
3337 blink::WebCryptoAlgorithmIdSha1
),
3339 blink::WebCryptoKeyUsageEncrypt
,
3343 TEST_F(SharedCryptoRsaOaepTest
, ImportPublicJwkWithMismatchedAlgFails
) {
3344 if (!SupportsRsaOaep()) {
3345 LOG(WARNING
) << "RSA-OAEP support not present; skipping.";
3349 scoped_ptr
<base::DictionaryValue
> jwk(CreatePublicKeyJwkDict());
3350 jwk
->SetString("alg", "RSA-OAEP-512");
3352 blink::WebCryptoKey public_key
= blink::WebCryptoKey::createNull();
3353 ASSERT_EQ(Status::ErrorJwkAlgorithmInconsistent(),
3354 ImportKeyJwkFromDict(*jwk
.get(),
3355 CreateRsaHashedImportAlgorithm(
3356 blink::WebCryptoAlgorithmIdRsaOaep
,
3357 blink::WebCryptoAlgorithmIdSha1
),
3359 blink::WebCryptoKeyUsageEncrypt
,
3363 TEST_F(SharedCryptoRsaOaepTest
, ImportPublicJwkWithMismatchedTypeFails
) {
3364 if (!SupportsRsaOaep()) {
3365 LOG(WARNING
) << "RSA-OAEP support not present; skipping.";
3369 scoped_ptr
<base::DictionaryValue
> jwk(CreatePublicKeyJwkDict());
3370 jwk
->SetString("kty", "oct");
3371 jwk
->SetString("alg", "RSA-OAEP");
3373 blink::WebCryptoKey public_key
= blink::WebCryptoKey::createNull();
3374 ASSERT_EQ(Status::ErrorJwkPropertyMissing("k"),
3375 ImportKeyJwkFromDict(*jwk
.get(),
3376 CreateRsaHashedImportAlgorithm(
3377 blink::WebCryptoAlgorithmIdRsaOaep
,
3378 blink::WebCryptoAlgorithmIdSha1
),
3380 blink::WebCryptoKeyUsageEncrypt
,
3384 TEST_F(SharedCryptoRsaOaepTest
, ExportPublicJwk
) {
3385 if (!SupportsRsaOaep()) {
3386 LOG(WARNING
) << "RSA-OAEP support not present; skipping.";
3391 blink::WebCryptoAlgorithmId hash_alg
;
3392 const char* expected_jwk_alg
;
3393 } kTestData
[] = {{blink::WebCryptoAlgorithmIdSha1
, "RSA-OAEP"},
3394 {blink::WebCryptoAlgorithmIdSha256
, "RSA-OAEP-256"},
3395 {blink::WebCryptoAlgorithmIdSha384
, "RSA-OAEP-384"},
3396 {blink::WebCryptoAlgorithmIdSha512
, "RSA-OAEP-512"}};
3397 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(kTestData
); ++i
) {
3398 const TestData
& test_data
= kTestData
[i
];
3399 SCOPED_TRACE(test_data
.expected_jwk_alg
);
3401 scoped_ptr
<base::DictionaryValue
> jwk(CreatePublicKeyJwkDict());
3402 jwk
->SetString("alg", test_data
.expected_jwk_alg
);
3404 // Import the key in a known-good format
3405 blink::WebCryptoKey public_key
= blink::WebCryptoKey::createNull();
3406 ASSERT_EQ(Status::Success(),
3407 ImportKeyJwkFromDict(
3409 CreateRsaHashedImportAlgorithm(
3410 blink::WebCryptoAlgorithmIdRsaOaep
, test_data
.hash_alg
),
3412 blink::WebCryptoKeyUsageEncrypt
,
3415 // Now export the key as JWK and verify its contents
3416 std::vector
<uint8
> jwk_data
;
3417 ASSERT_EQ(Status::Success(),
3418 ExportKey(blink::WebCryptoKeyFormatJwk
, public_key
, &jwk_data
));
3419 EXPECT_TRUE(VerifyPublicJwk(jwk_data
,
3420 test_data
.expected_jwk_alg
,
3421 kPublicKeyModulusHex
,
3422 kPublicKeyExponentHex
,
3423 blink::WebCryptoKeyUsageEncrypt
));
3427 TEST_F(SharedCryptoRsaOaepTest
, EncryptDecryptKnownAnswerTest
) {
3428 if (!SupportsRsaOaep()) {
3429 LOG(WARNING
) << "RSA-OAEP support not present; skipping.";
3433 scoped_ptr
<base::ListValue
> tests
;
3434 ASSERT_TRUE(ReadJsonTestFileToList("rsa_oaep.json", &tests
));
3436 for (size_t test_index
= 0; test_index
< tests
->GetSize(); ++test_index
) {
3437 SCOPED_TRACE(test_index
);
3439 base::DictionaryValue
* test
= NULL
;
3440 ASSERT_TRUE(tests
->GetDictionary(test_index
, &test
));
3442 blink::WebCryptoAlgorithm digest_algorithm
=
3443 GetDigestAlgorithm(test
, "hash");
3444 ASSERT_FALSE(digest_algorithm
.isNull());
3445 std::vector
<uint8
> public_key_der
=
3446 GetBytesFromHexString(test
, "public_key");
3447 std::vector
<uint8
> private_key_der
=
3448 GetBytesFromHexString(test
, "private_key");
3449 std::vector
<uint8
> ciphertext
= GetBytesFromHexString(test
, "ciphertext");
3450 std::vector
<uint8
> plaintext
= GetBytesFromHexString(test
, "plaintext");
3451 std::vector
<uint8
> label
= GetBytesFromHexString(test
, "label");
3453 blink::WebCryptoAlgorithm import_algorithm
= CreateRsaHashedImportAlgorithm(
3454 blink::WebCryptoAlgorithmIdRsaOaep
, digest_algorithm
.id());
3455 blink::WebCryptoKey public_key
= blink::WebCryptoKey::createNull();
3456 blink::WebCryptoKey private_key
= blink::WebCryptoKey::createNull();
3458 ASSERT_NO_FATAL_FAILURE(ImportRsaKeyPair(public_key_der
,
3462 blink::WebCryptoKeyUsageEncrypt
,
3463 blink::WebCryptoKeyUsageDecrypt
,
3467 blink::WebCryptoAlgorithm op_algorithm
= CreateRsaOaepAlgorithm(label
);
3468 std::vector
<uint8
> decrypted_data
;
3469 ASSERT_EQ(Status::Success(),
3470 Decrypt(op_algorithm
,
3472 CryptoData(ciphertext
),
3474 EXPECT_BYTES_EQ(plaintext
, decrypted_data
);
3475 std::vector
<uint8
> encrypted_data
;
3479 op_algorithm
, public_key
, CryptoData(plaintext
), &encrypted_data
));
3480 std::vector
<uint8
> redecrypted_data
;
3481 ASSERT_EQ(Status::Success(),
3482 Decrypt(op_algorithm
,
3484 CryptoData(encrypted_data
),
3485 &redecrypted_data
));
3486 EXPECT_BYTES_EQ(plaintext
, redecrypted_data
);
3490 TEST_F(SharedCryptoRsaOaepTest
, EncryptWithLargeMessageFails
) {
3491 if (!SupportsRsaOaep()) {
3492 LOG(WARNING
) << "RSA-OAEP support not present; skipping.";
3496 const blink::WebCryptoAlgorithmId kHash
= blink::WebCryptoAlgorithmIdSha1
;
3497 const size_t kHashSize
= 20;
3499 scoped_ptr
<base::DictionaryValue
> jwk(CreatePublicKeyJwkDict());
3501 blink::WebCryptoKey public_key
= blink::WebCryptoKey::createNull();
3502 ASSERT_EQ(Status::Success(),
3503 ImportKeyJwkFromDict(*jwk
.get(),
3504 CreateRsaHashedImportAlgorithm(
3505 blink::WebCryptoAlgorithmIdRsaOaep
, kHash
),
3507 blink::WebCryptoKeyUsageEncrypt
,
3510 // The maximum size of an encrypted message is:
3512 // - 1 (leading octet)
3513 // - hash size (maskedSeed)
3514 // - hash size (lHash portion of maskedDB)
3515 // - 1 (at least one octet for the padding string)
3516 size_t kMaxMessageSize
= (kModulusLengthBits
/ 8) - 2 - (2 * kHashSize
);
3518 // The label has no influence on the maximum message size. For simplicity,
3519 // use the empty string.
3520 std::vector
<uint8
> label
;
3521 blink::WebCryptoAlgorithm op_algorithm
= CreateRsaOaepAlgorithm(label
);
3523 // Test that a message just before the boundary succeeds.
3524 std::string large_message
;
3525 large_message
.resize(kMaxMessageSize
- 1, 'A');
3527 std::vector
<uint8
> ciphertext
;
3531 op_algorithm
, public_key
, CryptoData(large_message
), &ciphertext
));
3533 // Test that a message at the boundary succeeds.
3534 large_message
.resize(kMaxMessageSize
, 'A');
3540 op_algorithm
, public_key
, CryptoData(large_message
), &ciphertext
));
3542 // Test that a message greater than the largest size fails.
3543 large_message
.resize(kMaxMessageSize
+ 1, 'A');
3547 Status::OperationError(),
3549 op_algorithm
, public_key
, CryptoData(large_message
), &ciphertext
));
3552 // Ensures that if the selected hash algorithm for the RSA-OAEP message is too
3553 // large, then it is rejected, independent of the actual message to be
3555 // For example, a 1024-bit RSA key is too small to accomodate a message that
3556 // uses OAEP with SHA-512, since it requires 1040 bits to encode
3557 // (2 * hash size + 2 padding bytes).
3558 TEST_F(SharedCryptoRsaOaepTest
, EncryptWithLargeDigestFails
) {
3559 if (!SupportsRsaOaep()) {
3560 LOG(WARNING
) << "RSA-OAEP support not present; skipping.";
3564 const blink::WebCryptoAlgorithmId kHash
= blink::WebCryptoAlgorithmIdSha512
;
3566 scoped_ptr
<base::DictionaryValue
> jwk(CreatePublicKeyJwkDict());
3568 blink::WebCryptoKey public_key
= blink::WebCryptoKey::createNull();
3569 ASSERT_EQ(Status::Success(),
3570 ImportKeyJwkFromDict(*jwk
.get(),
3571 CreateRsaHashedImportAlgorithm(
3572 blink::WebCryptoAlgorithmIdRsaOaep
, kHash
),
3574 blink::WebCryptoKeyUsageEncrypt
,
3577 // The label has no influence on the maximum message size. For simplicity,
3578 // use the empty string.
3579 std::vector
<uint8
> label
;
3580 blink::WebCryptoAlgorithm op_algorithm
= CreateRsaOaepAlgorithm(label
);
3582 std::string
small_message("A");
3583 std::vector
<uint8
> ciphertext
;
3584 // This is an operation error, as the internal consistency checking of the
3585 // algorithm parameters is up to the implementation.
3587 Status::OperationError(),
3589 op_algorithm
, public_key
, CryptoData(small_message
), &ciphertext
));
3592 TEST_F(SharedCryptoRsaOaepTest
, DecryptWithLargeMessageFails
) {
3593 if (!SupportsRsaOaep()) {
3594 LOG(WARNING
) << "RSA-OAEP support not present; skipping.";
3598 blink::WebCryptoKey private_key
= blink::WebCryptoKey::createNull();
3599 ASSERT_EQ(Status::Success(),
3600 ImportKey(blink::WebCryptoKeyFormatPkcs8
,
3601 CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex
)),
3602 CreateRsaHashedImportAlgorithm(
3603 blink::WebCryptoAlgorithmIdRsaOaep
,
3604 blink::WebCryptoAlgorithmIdSha1
),
3606 blink::WebCryptoKeyUsageDecrypt
,
3609 // The label has no influence on the maximum message size. For simplicity,
3610 // use the empty string.
3611 std::vector
<uint8
> label
;
3612 blink::WebCryptoAlgorithm op_algorithm
= CreateRsaOaepAlgorithm(label
);
3614 std::string
large_dummy_message(kModulusLengthBits
/ 8, 'A');
3615 std::vector
<uint8
> plaintext
;
3617 ASSERT_EQ(Status::OperationError(),
3618 Decrypt(op_algorithm
,
3620 CryptoData(large_dummy_message
),
3624 TEST_F(SharedCryptoRsaOaepTest
, WrapUnwrapRawKey
) {
3625 if (!SupportsRsaOaep()) {
3626 LOG(WARNING
) << "RSA-OAEP support not present; skipping.";
3630 blink::WebCryptoAlgorithm import_algorithm
= CreateRsaHashedImportAlgorithm(
3631 blink::WebCryptoAlgorithmIdRsaOaep
, blink::WebCryptoAlgorithmIdSha1
);
3632 blink::WebCryptoKey public_key
= blink::WebCryptoKey::createNull();
3633 blink::WebCryptoKey private_key
= blink::WebCryptoKey::createNull();
3635 ASSERT_NO_FATAL_FAILURE(ImportRsaKeyPair(
3636 HexStringToBytes(kPublicKeySpkiDerHex
),
3637 HexStringToBytes(kPrivateKeyPkcs8DerHex
),
3640 blink::WebCryptoKeyUsageEncrypt
| blink::WebCryptoKeyUsageWrapKey
,
3641 blink::WebCryptoKeyUsageDecrypt
| blink::WebCryptoKeyUsageUnwrapKey
,
3645 std::vector
<uint8
> label
;
3646 blink::WebCryptoAlgorithm wrapping_algorithm
= CreateRsaOaepAlgorithm(label
);
3648 const std::string key_hex
= "000102030405060708090A0B0C0D0E0F";
3649 const blink::WebCryptoAlgorithm key_algorithm
=
3650 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
);
3652 blink::WebCryptoKey key
=
3653 ImportSecretKeyFromRaw(HexStringToBytes(key_hex
),
3655 blink::WebCryptoKeyUsageEncrypt
);
3656 ASSERT_FALSE(key
.isNull());
3658 std::vector
<uint8
> wrapped_key
;
3659 ASSERT_EQ(Status::Success(),
3660 WrapKey(blink::WebCryptoKeyFormatRaw
,
3666 // Verify that |wrapped_key| can be decrypted and yields the key data.
3667 // Because |private_key| supports both decrypt and unwrap, this is valid.
3668 std::vector
<uint8
> decrypted_key
;
3669 ASSERT_EQ(Status::Success(),
3670 Decrypt(wrapping_algorithm
,
3672 CryptoData(wrapped_key
),
3674 EXPECT_BYTES_EQ_HEX(key_hex
, decrypted_key
);
3676 // Now attempt to unwrap the key, which should also decrypt the data.
3677 blink::WebCryptoKey unwrapped_key
= blink::WebCryptoKey::createNull();
3678 ASSERT_EQ(Status::Success(),
3679 UnwrapKey(blink::WebCryptoKeyFormatRaw
,
3680 CryptoData(wrapped_key
),
3685 blink::WebCryptoKeyUsageEncrypt
,
3687 ASSERT_FALSE(unwrapped_key
.isNull());
3689 std::vector
<uint8
> raw_key
;
3690 ASSERT_EQ(Status::Success(),
3691 ExportKey(blink::WebCryptoKeyFormatRaw
, unwrapped_key
, &raw_key
));
3692 EXPECT_BYTES_EQ_HEX(key_hex
, raw_key
);
3695 TEST_F(SharedCryptoRsaOaepTest
, WrapUnwrapJwkSymKey
) {
3696 if (!SupportsRsaOaep()) {
3697 LOG(WARNING
) << "RSA-OAEP support not present; skipping.";
3701 // The public and private portions of a 2048-bit RSA key with the
3702 // id-rsaEncryption OID
3703 const char kPublicKey2048SpkiDerHex
[] =
3704 "30820122300d06092a864886f70d01010105000382010f003082010a0282010100c5d8ce"
3705 "137a38168c8ab70229cfa5accc640567159750a312ce2e7d54b6e2fdd59b300c6a6c9764"
3706 "f8de6f00519cdb90111453d273a967462786480621f9e7cee5b73d63358448e7183a3a68"
3707 "e991186359f26aa88fbca5f53e673e502e4c5a2ba5068aeba60c9d0c44d872458d1b1e2f"
3708 "7f339f986076d516e93dc750f0b7680b6f5f02bc0d5590495be04c4ae59d34ba17bc5d08"
3709 "a93c75cfda2828f4a55b153af912038438276cb4a14f8116ca94db0ea9893652d02fc606"
3710 "36f19975e3d79a4d8ea8bfed6f8e0a24b63d243b08ea70a086ad56dd6341d733711c89ca"
3711 "749d4a80b3e6ecd2f8e53731eadeac2ea77788ee55d7b4b47c0f2523fbd61b557c16615d"
3713 const char kPrivateKey2048Pkcs8DerHex
[] =
3714 "308204bd020100300d06092a864886f70d0101010500048204a7308204a3020100028201"
3715 "0100c5d8ce137a38168c8ab70229cfa5accc640567159750a312ce2e7d54b6e2fdd59b30"
3716 "0c6a6c9764f8de6f00519cdb90111453d273a967462786480621f9e7cee5b73d63358448"
3717 "e7183a3a68e991186359f26aa88fbca5f53e673e502e4c5a2ba5068aeba60c9d0c44d872"
3718 "458d1b1e2f7f339f986076d516e93dc750f0b7680b6f5f02bc0d5590495be04c4ae59d34"
3719 "ba17bc5d08a93c75cfda2828f4a55b153af912038438276cb4a14f8116ca94db0ea98936"
3720 "52d02fc60636f19975e3d79a4d8ea8bfed6f8e0a24b63d243b08ea70a086ad56dd6341d7"
3721 "33711c89ca749d4a80b3e6ecd2f8e53731eadeac2ea77788ee55d7b4b47c0f2523fbd61b"
3722 "557c16615d5d02030100010282010074b70feb41a0b0fcbc207670400556c9450042ede3"
3723 "d4383fb1ce8f3558a6d4641d26dd4c333fa4db842d2b9cf9d2354d3e16ad027a9f682d8c"
3724 "f4145a1ad97b9edcd8a41c402bd9d8db10f62f43df854cdccbbb2100834f083f53ed6d42"
3725 "b1b729a59072b004a4e945fc027db15e9c121d1251464d320d4774d5732df6b3dbf751f4"
3726 "9b19c9db201e19989c883bbaad5333db47f64f6f7a95b8d4936b10d945aa3f794cfaab62"
3727 "e7d47686129358914f3b8085f03698a650ab5b8c7e45813f2b0515ec05b6e5195b6a7c2a"
3728 "0d36969745f431ded4fd059f6aa361a4649541016d356297362b778e90f077d48815b339"
3729 "ec6f43aba345df93e67fcb6c2cb5b4544e9be902818100e9c90abe5f9f32468c5b6d630c"
3730 "54a4d7d75e29a72cf792f21e242aac78fd7995c42dfd4ae871d2619ff7096cb05baa78e3"
3731 "23ecab338401a8059adf7a0d8be3b21edc9a9c82c5605634a2ec81ec053271721351868a"
3732 "4c2e50c689d7cef94e31ff23658af5843366e2b289c5bf81d72756a7b93487dd8770d69c"
3733 "1f4e089d6d89f302818100d8a58a727c4e209132afd9933b98c89aca862a01cc0be74133"
3734 "bee517909e5c379e526895ac4af11780c1fe91194c777c9670b6423f0f5a32fd7691a622"
3735 "113eef4bed2ef863363a335fd55b0e75088c582437237d7f3ed3f0a643950237bc6e6277"
3736 "ccd0d0a1b4170aa1047aa7ffa7c8c54be10e8c7327ae2e0885663963817f6f02818100e5"
3737 "aed9ba4d71b7502e6748a1ce247ecb7bd10c352d6d9256031cdf3c11a65e44b0b7ca2945"
3738 "134671195af84c6b3bb3d10ebf65ae916f38bd5dbc59a0ad1c69b8beaf57cb3a8335f19b"
3739 "c7117b576987b48331cd9fd3d1a293436b7bb5e1a35c6560de4b5688ea834367cb0997eb"
3740 "b578f59ed4cb724c47dba94d3b484c1876dcd70281807f15bc7d2406007cac2b138a96af"
3741 "2d1e00276b84da593132c253fcb73212732dfd25824c2a615bc3d9b7f2c8d2fa542d3562"
3742 "b0c7738e61eeff580a6056239fb367ea9e5efe73d4f846033602e90c36a78db6fa8ea792"
3743 "0769675ec58e237bd994d189c8045a96f5dd3a4f12547257ce224e3c9af830a4da3c0eab"
3744 "9227a0035ae9028180067caea877e0b23090fc689322b71fbcce63d6596e66ab5fcdbaa0"
3745 "0d49e93aba8effb4518c2da637f209028401a68f344865b4956b032c69acde51d29177ca"
3746 "3db99fdbf5e74848ed4fa7bdfc2ebb60e2aaa5354770a763e1399ab7a2099762d525fea0"
3747 "37f3e1972c45a477e66db95c9609bb27f862700ef93379930786cf751b";
3748 blink::WebCryptoAlgorithm import_algorithm
= CreateRsaHashedImportAlgorithm(
3749 blink::WebCryptoAlgorithmIdRsaOaep
, blink::WebCryptoAlgorithmIdSha1
);
3750 blink::WebCryptoKey public_key
= blink::WebCryptoKey::createNull();
3751 blink::WebCryptoKey private_key
= blink::WebCryptoKey::createNull();
3753 ASSERT_NO_FATAL_FAILURE(ImportRsaKeyPair(
3754 HexStringToBytes(kPublicKey2048SpkiDerHex
),
3755 HexStringToBytes(kPrivateKey2048Pkcs8DerHex
),
3758 blink::WebCryptoKeyUsageEncrypt
| blink::WebCryptoKeyUsageWrapKey
,
3759 blink::WebCryptoKeyUsageDecrypt
| blink::WebCryptoKeyUsageUnwrapKey
,
3763 std::vector
<uint8
> label
;
3764 blink::WebCryptoAlgorithm wrapping_algorithm
= CreateRsaOaepAlgorithm(label
);
3766 const std::string key_hex
= "000102030405060708090a0b0c0d0e0f";
3767 const blink::WebCryptoAlgorithm key_algorithm
=
3768 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
);
3770 blink::WebCryptoKey key
=
3771 ImportSecretKeyFromRaw(HexStringToBytes(key_hex
),
3773 blink::WebCryptoKeyUsageEncrypt
);
3774 ASSERT_FALSE(key
.isNull());
3776 std::vector
<uint8
> wrapped_key
;
3777 ASSERT_EQ(Status::Success(),
3778 WrapKey(blink::WebCryptoKeyFormatJwk
,
3784 // Verify that |wrapped_key| can be decrypted and yields a valid JWK object.
3785 // Because |private_key| supports both decrypt and unwrap, this is valid.
3786 std::vector
<uint8
> decrypted_jwk
;
3787 ASSERT_EQ(Status::Success(),
3788 Decrypt(wrapping_algorithm
,
3790 CryptoData(wrapped_key
),
3792 EXPECT_TRUE(VerifySecretJwk(
3793 decrypted_jwk
, "A128CBC", key_hex
, blink::WebCryptoKeyUsageEncrypt
));
3795 // Now attempt to unwrap the key, which should also decrypt the data.
3796 blink::WebCryptoKey unwrapped_key
= blink::WebCryptoKey::createNull();
3797 ASSERT_EQ(Status::Success(),
3798 UnwrapKey(blink::WebCryptoKeyFormatJwk
,
3799 CryptoData(wrapped_key
),
3804 blink::WebCryptoKeyUsageEncrypt
,
3806 ASSERT_FALSE(unwrapped_key
.isNull());
3808 std::vector
<uint8
> raw_key
;
3809 ASSERT_EQ(Status::Success(),
3810 ExportKey(blink::WebCryptoKeyFormatRaw
, unwrapped_key
, &raw_key
));
3811 EXPECT_BYTES_EQ_HEX(key_hex
, raw_key
);
3814 // Try importing an RSA-SSA public key with unsupported key usages using SPKI
3815 // format. RSA-SSA public keys only support the 'verify' usage.
3816 TEST_F(SharedCryptoTest
, MAYBE(ImportRsaSsaPublicKeyBadUsage_SPKI
)) {
3817 const blink::WebCryptoAlgorithm algorithm
=
3818 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
3819 blink::WebCryptoAlgorithmIdSha256
);
3821 blink::WebCryptoKeyUsageMask bad_usages
[] = {
3822 blink::WebCryptoKeyUsageSign
,
3823 blink::WebCryptoKeyUsageSign
| blink::WebCryptoKeyUsageVerify
,
3824 blink::WebCryptoKeyUsageEncrypt
,
3825 blink::WebCryptoKeyUsageEncrypt
| blink::WebCryptoKeyUsageDecrypt
,
3828 for (size_t i
= 0; i
< arraysize(bad_usages
); ++i
) {
3831 blink::WebCryptoKey public_key
= blink::WebCryptoKey::createNull();
3832 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
3833 ImportKey(blink::WebCryptoKeyFormatSpki
,
3834 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex
)),
3842 // Try importing an RSA-SSA public key with unsupported key usages using JWK
3843 // format. RSA-SSA public keys only support the 'verify' usage.
3844 TEST_F(SharedCryptoTest
, MAYBE(ImportRsaSsaPublicKeyBadUsage_JWK
)) {
3845 const blink::WebCryptoAlgorithm algorithm
=
3846 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
3847 blink::WebCryptoAlgorithmIdSha256
);
3849 blink::WebCryptoKeyUsageMask bad_usages
[] = {
3850 blink::WebCryptoKeyUsageSign
,
3851 blink::WebCryptoKeyUsageSign
| blink::WebCryptoKeyUsageVerify
,
3852 blink::WebCryptoKeyUsageEncrypt
,
3853 blink::WebCryptoKeyUsageEncrypt
| blink::WebCryptoKeyUsageDecrypt
,
3856 base::DictionaryValue dict
;
3857 RestoreJwkRsaDictionary(&dict
);
3858 dict
.Remove("use", NULL
);
3859 dict
.SetString("alg", "RS256");
3861 for (size_t i
= 0; i
< arraysize(bad_usages
); ++i
) {
3864 blink::WebCryptoKey public_key
= blink::WebCryptoKey::createNull();
3865 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
3866 ImportKeyJwkFromDict(
3867 dict
, algorithm
, false, bad_usages
[i
], &public_key
));
3871 // Try importing an AES-CBC key with unsupported key usages using raw
3872 // format. AES-CBC keys support the following usages:
3873 // 'encrypt', 'decrypt', 'wrapKey', 'unwrapKey'
3874 TEST_F(SharedCryptoTest
, MAYBE(ImportAesCbcKeyBadUsage_Raw
)) {
3875 const blink::WebCryptoAlgorithm algorithm
=
3876 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
);
3878 blink::WebCryptoKeyUsageMask bad_usages
[] = {
3879 blink::WebCryptoKeyUsageSign
,
3880 blink::WebCryptoKeyUsageSign
| blink::WebCryptoKeyUsageDecrypt
,
3881 blink::WebCryptoKeyUsageDeriveBits
,
3882 blink::WebCryptoKeyUsageUnwrapKey
| blink::WebCryptoKeyUsageVerify
,
3885 std::vector
<uint8
> key_bytes(16);
3887 for (size_t i
= 0; i
< arraysize(bad_usages
); ++i
) {
3890 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
3891 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
3892 ImportKey(blink::WebCryptoKeyFormatRaw
,
3893 CryptoData(key_bytes
),
3901 // Try importing an AES-KW key with unsupported key usages using raw
3902 // format. AES-KW keys support the following usages:
3903 // 'wrapKey', 'unwrapKey'
3904 TEST_F(SharedCryptoTest
, MAYBE(ImportAesKwKeyBadUsage_Raw
)) {
3905 const blink::WebCryptoAlgorithm algorithm
=
3906 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw
);
3908 blink::WebCryptoKeyUsageMask bad_usages
[] = {
3909 blink::WebCryptoKeyUsageEncrypt
,
3910 blink::WebCryptoKeyUsageDecrypt
,
3911 blink::WebCryptoKeyUsageSign
,
3912 blink::WebCryptoKeyUsageSign
| blink::WebCryptoKeyUsageUnwrapKey
,
3913 blink::WebCryptoKeyUsageDeriveBits
,
3914 blink::WebCryptoKeyUsageUnwrapKey
| blink::WebCryptoKeyUsageVerify
,
3917 std::vector
<uint8
> key_bytes(16);
3919 for (size_t i
= 0; i
< arraysize(bad_usages
); ++i
) {
3922 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
3923 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
3924 ImportKey(blink::WebCryptoKeyFormatRaw
,
3925 CryptoData(key_bytes
),
3933 // Try unwrapping an HMAC key with unsupported usages using JWK format and
3934 // AES-KW. HMAC keys support the following usages:
3936 TEST_F(SharedCryptoTest
, MAYBE(UnwrapHmacKeyBadUsage_JWK
)) {
3937 const blink::WebCryptoAlgorithm unwrap_algorithm
=
3938 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw
);
3940 blink::WebCryptoKeyUsageMask bad_usages
[] = {
3941 blink::WebCryptoKeyUsageEncrypt
,
3942 blink::WebCryptoKeyUsageDecrypt
,
3943 blink::WebCryptoKeyUsageWrapKey
,
3944 blink::WebCryptoKeyUsageSign
| blink::WebCryptoKeyUsageWrapKey
,
3945 blink::WebCryptoKeyUsageVerify
| blink::WebCryptoKeyUsageDeriveKey
,
3948 // Import the wrapping key.
3949 blink::WebCryptoKey wrapping_key
= blink::WebCryptoKey::createNull();
3950 ASSERT_EQ(Status::Success(),
3951 ImportKey(blink::WebCryptoKeyFormatRaw
,
3952 CryptoData(std::vector
<uint8
>(16)),
3955 blink::WebCryptoKeyUsageUnwrapKey
,
3958 // The JWK plain text is:
3959 // { "kty": "oct","alg": "HS256","k": "GADWrMRHwQfoNaXU5fZvTg=="}
3960 const char* kWrappedJwk
=
3961 "0AA245F17064FFB2A7A094436A39BEBFC962C627303D1327EA750CE9F917688C2782A943"
3962 "7AE7586547AC490E8AE7D5B02D63868D5C3BB57D36C4C8C5BF3962ACEC6F42E767E5706"
3965 for (size_t i
= 0; i
< arraysize(bad_usages
); ++i
) {
3968 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
3970 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
3971 UnwrapKey(blink::WebCryptoKeyFormatJwk
,
3972 CryptoData(HexStringToBytes(kWrappedJwk
)),
3975 webcrypto::CreateHmacImportAlgorithm(
3976 blink::WebCryptoAlgorithmIdSha256
),
3983 // Try unwrapping an RSA-SSA public key with unsupported usages using JWK format
3984 // and AES-KW. RSA-SSA public keys support the following usages:
3986 TEST_F(SharedCryptoTest
, MAYBE(UnwrapRsaSsaPublicKeyBadUsage_JWK
)) {
3987 const blink::WebCryptoAlgorithm unwrap_algorithm
=
3988 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw
);
3990 blink::WebCryptoKeyUsageMask bad_usages
[] = {
3991 blink::WebCryptoKeyUsageEncrypt
,
3992 blink::WebCryptoKeyUsageSign
,
3993 blink::WebCryptoKeyUsageDecrypt
,
3994 blink::WebCryptoKeyUsageWrapKey
,
3995 blink::WebCryptoKeyUsageSign
| blink::WebCryptoKeyUsageWrapKey
,
3998 // Import the wrapping key.
3999 blink::WebCryptoKey wrapping_key
= blink::WebCryptoKey::createNull();
4000 ASSERT_EQ(Status::Success(),
4001 ImportKey(blink::WebCryptoKeyFormatRaw
,
4002 CryptoData(std::vector
<uint8
>(16)),
4005 blink::WebCryptoKeyUsageUnwrapKey
,
4008 // The JWK plaintext is:
4009 // { "kty": "RSA","alg": "RS256","n": "...","e": "AQAB"}
4011 const char* kWrappedJwk
=
4012 "CE8DAEF99E977EE58958B8C4494755C846E883B2ECA575C5366622839AF71AB30875F152"
4013 "E8E33E15A7817A3A2874EB53EFE05C774D98BC936BA9BA29BEB8BB3F3C3CE2323CB3359D"
4014 "E3F426605CF95CCF0E01E870ABD7E35F62E030B5FB6E520A5885514D1D850FB64B57806D"
4015 "1ADA57C6E27DF345D8292D80F6B074F1BE51C4CF3D76ECC8886218551308681B44FAC60B"
4016 "8CF6EA439BC63239103D0AE81ADB96F908680586C6169284E32EB7DD09D31103EBDAC0C2"
4017 "40C72DCF0AEA454113CC47457B13305B25507CBEAB9BDC8D8E0F867F9167F9DCEF0D9F9B"
4018 "30F2EE83CEDFD51136852C8A5939B768";
4020 for (size_t i
= 0; i
< arraysize(bad_usages
); ++i
) {
4023 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
4025 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
4026 UnwrapKey(blink::WebCryptoKeyFormatJwk
,
4027 CryptoData(HexStringToBytes(kWrappedJwk
)),
4030 webcrypto::CreateRsaHashedImportAlgorithm(
4031 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
4032 blink::WebCryptoAlgorithmIdSha256
),
4039 // Generate an AES-CBC key with invalid usages. AES-CBC supports:
4040 // 'encrypt', 'decrypt', 'wrapKey', 'unwrapKey'
4041 TEST_F(SharedCryptoTest
, MAYBE(GenerateAesKeyBadUsages
)) {
4042 blink::WebCryptoKeyUsageMask bad_usages
[] = {
4043 blink::WebCryptoKeyUsageSign
, blink::WebCryptoKeyUsageVerify
,
4044 blink::WebCryptoKeyUsageDecrypt
| blink::WebCryptoKeyUsageVerify
,
4047 for (size_t i
= 0; i
< arraysize(bad_usages
); ++i
) {
4050 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
4052 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
4054 CreateAesCbcKeyGenAlgorithm(128), true, bad_usages
[i
], &key
));
4058 // Generate an RSA-SSA key pair with invalid usages. RSA-SSA supports:
4060 TEST_F(SharedCryptoTest
, MAYBE(GenerateRsaSsaBadUsages
)) {
4061 blink::WebCryptoKeyUsageMask bad_usages
[] = {
4062 blink::WebCryptoKeyUsageDecrypt
,
4063 blink::WebCryptoKeyUsageVerify
| blink::WebCryptoKeyUsageDecrypt
,
4064 blink::WebCryptoKeyUsageWrapKey
,
4067 const unsigned int modulus_length
= 256;
4068 const std::vector
<uint8
> public_exponent
= HexStringToBytes("010001");
4070 for (size_t i
= 0; i
< arraysize(bad_usages
); ++i
) {
4073 blink::WebCryptoKey public_key
= blink::WebCryptoKey::createNull();
4074 blink::WebCryptoKey private_key
= blink::WebCryptoKey::createNull();
4076 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
4077 GenerateKeyPair(CreateRsaHashedKeyGenAlgorithm(
4078 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
4079 blink::WebCryptoAlgorithmIdSha256
,
4089 // Generate an RSA-SSA key pair. The public and private keys should select the
4090 // key usages which are applicable, and not have the exact same usages as was
4091 // specified to GenerateKey
4092 TEST_F(SharedCryptoTest
, MAYBE(GenerateRsaSsaKeyPairIntersectUsages
)) {
4093 const unsigned int modulus_length
= 256;
4094 const std::vector
<uint8
> public_exponent
= HexStringToBytes("010001");
4096 blink::WebCryptoKey public_key
= blink::WebCryptoKey::createNull();
4097 blink::WebCryptoKey private_key
= blink::WebCryptoKey::createNull();
4099 ASSERT_EQ(Status::Success(),
4101 CreateRsaHashedKeyGenAlgorithm(
4102 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
4103 blink::WebCryptoAlgorithmIdSha256
,
4107 blink::WebCryptoKeyUsageSign
| blink::WebCryptoKeyUsageVerify
,
4111 EXPECT_EQ(blink::WebCryptoKeyUsageVerify
, public_key
.usages());
4112 EXPECT_EQ(blink::WebCryptoKeyUsageSign
, private_key
.usages());
4114 // Try again but this time without the Verify usages.
4115 ASSERT_EQ(Status::Success(),
4116 GenerateKeyPair(CreateRsaHashedKeyGenAlgorithm(
4117 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
4118 blink::WebCryptoAlgorithmIdSha256
,
4122 blink::WebCryptoKeyUsageSign
,
4126 EXPECT_EQ(0, public_key
.usages());
4127 EXPECT_EQ(blink::WebCryptoKeyUsageSign
, private_key
.usages());
4130 // Generate an AES-CBC key and an RSA key pair. Use the AES-CBC key to wrap the
4131 // key pair (using SPKI format for public key, PKCS8 format for private key).
4132 // Then unwrap the wrapped key pair and verify that the key data is the same.
4133 TEST_F(SharedCryptoTest
, MAYBE(WrapUnwrapRoundtripSpkiPkcs8UsingAesCbc
)) {
4134 // Generate the wrapping key.
4135 blink::WebCryptoKey wrapping_key
= blink::WebCryptoKey::createNull();
4136 ASSERT_EQ(Status::Success(),
4137 GenerateSecretKey(CreateAesCbcKeyGenAlgorithm(128),
4139 blink::WebCryptoKeyUsageWrapKey
|
4140 blink::WebCryptoKeyUsageUnwrapKey
,
4143 // Generate an RSA key pair to be wrapped.
4144 const unsigned int modulus_length
= 256;
4145 const std::vector
<uint8
> public_exponent
= HexStringToBytes("010001");
4147 blink::WebCryptoKey public_key
= blink::WebCryptoKey::createNull();
4148 blink::WebCryptoKey private_key
= blink::WebCryptoKey::createNull();
4149 ASSERT_EQ(Status::Success(),
4150 GenerateKeyPair(CreateRsaHashedKeyGenAlgorithm(
4151 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
4152 blink::WebCryptoAlgorithmIdSha256
,
4160 // Export key pair as SPKI + PKCS8
4161 std::vector
<uint8
> public_key_spki
;
4164 ExportKey(blink::WebCryptoKeyFormatSpki
, public_key
, &public_key_spki
));
4166 std::vector
<uint8
> private_key_pkcs8
;
4170 blink::WebCryptoKeyFormatPkcs8
, private_key
, &private_key_pkcs8
));
4172 // Wrap the key pair.
4173 blink::WebCryptoAlgorithm wrap_algorithm
=
4174 CreateAesCbcAlgorithm(std::vector
<uint8
>(16, 0));
4176 std::vector
<uint8
> wrapped_public_key
;
4177 ASSERT_EQ(Status::Success(),
4178 WrapKey(blink::WebCryptoKeyFormatSpki
,
4182 &wrapped_public_key
));
4184 std::vector
<uint8
> wrapped_private_key
;
4185 ASSERT_EQ(Status::Success(),
4186 WrapKey(blink::WebCryptoKeyFormatPkcs8
,
4190 &wrapped_private_key
));
4192 // Unwrap the key pair.
4193 blink::WebCryptoAlgorithm rsa_import_algorithm
=
4194 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
4195 blink::WebCryptoAlgorithmIdSha256
);
4197 blink::WebCryptoKey unwrapped_public_key
= blink::WebCryptoKey::createNull();
4199 ASSERT_EQ(Status::Success(),
4200 UnwrapKey(blink::WebCryptoKeyFormatSpki
,
4201 CryptoData(wrapped_public_key
),
4204 rsa_import_algorithm
,
4207 &unwrapped_public_key
));
4209 blink::WebCryptoKey unwrapped_private_key
= blink::WebCryptoKey::createNull();
4211 ASSERT_EQ(Status::Success(),
4212 UnwrapKey(blink::WebCryptoKeyFormatPkcs8
,
4213 CryptoData(wrapped_private_key
),
4216 rsa_import_algorithm
,
4219 &unwrapped_private_key
));
4221 // Export unwrapped key pair as SPKI + PKCS8
4222 std::vector
<uint8
> unwrapped_public_key_spki
;
4223 ASSERT_EQ(Status::Success(),
4224 ExportKey(blink::WebCryptoKeyFormatSpki
,
4225 unwrapped_public_key
,
4226 &unwrapped_public_key_spki
));
4228 std::vector
<uint8
> unwrapped_private_key_pkcs8
;
4229 ASSERT_EQ(Status::Success(),
4230 ExportKey(blink::WebCryptoKeyFormatPkcs8
,
4231 unwrapped_private_key
,
4232 &unwrapped_private_key_pkcs8
));
4234 EXPECT_EQ(public_key_spki
, unwrapped_public_key_spki
);
4235 EXPECT_EQ(private_key_pkcs8
, unwrapped_private_key_pkcs8
);
4237 EXPECT_NE(public_key_spki
, wrapped_public_key
);
4238 EXPECT_NE(private_key_pkcs8
, wrapped_private_key
);
4241 } // namespace webcrypto
4243 } // namespace content