| Index: content/child/webcrypto/shared_crypto_unittest.cc
|
| diff --git a/content/child/webcrypto/shared_crypto_unittest.cc b/content/child/webcrypto/shared_crypto_unittest.cc
|
| index 7613194c61ffae55c300d7809718b11436e44a81..2fdb271575d798273cc5c27d58c17117f5aeafeb 100644
|
| --- a/content/child/webcrypto/shared_crypto_unittest.cc
|
| +++ b/content/child/webcrypto/shared_crypto_unittest.cc
|
| @@ -29,6 +29,13 @@
|
| #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
|
| #include "third_party/re2/re2/re2.h"
|
|
|
| +#if !defined(USE_OPENSSL)
|
| +#include <nss.h>
|
| +#include <pk11pub.h>
|
| +
|
| +#include "crypto/scoped_nss_types.h"
|
| +#endif
|
| +
|
| // The OpenSSL implementation of WebCrypto is less complete, so don't run all of
|
| // the tests: http://crbug.com/267888
|
| #if defined(USE_OPENSSL)
|
| @@ -106,6 +113,17 @@ bool SupportsAesGcm() {
|
| return status.IsSuccess();
|
| }
|
|
|
| +bool SupportsRsaOaep() {
|
| +#if defined(USE_OPENSSL)
|
| + return false;
|
| +#else
|
| + if (!NSS_VersionCheck("3.16.2"))
|
| + return false;
|
| + crypto::ScopedPK11Slot slot(PK11_GetInternalKeySlot());
|
| + return !!PK11_DoesMechanism(slot.get(), CKM_RSA_PKCS_OAEP);
|
| +#endif
|
| +}
|
| +
|
| blink::WebCryptoAlgorithm CreateRsaKeyGenAlgorithm(
|
| blink::WebCryptoAlgorithmId algorithm_id,
|
| unsigned int modulus_length,
|
| @@ -136,6 +154,15 @@ blink::WebCryptoAlgorithm CreateRsaHashedKeyGenAlgorithm(
|
| public_exponent.size()));
|
| }
|
|
|
| +// Creates an RSA-OAEP algorithm
|
| +blink::WebCryptoAlgorithm CreateRsaOaepAlgorithm(
|
| + const std::vector<uint8>& label) {
|
| + return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
|
| + blink::WebCryptoAlgorithmIdRsaOaep,
|
| + new blink::WebCryptoRsaOaepParams(
|
| + !label.empty(), Uint8VectorStart(label), label.size()));
|
| +}
|
| +
|
| // Creates an AES-CBC algorithm.
|
| blink::WebCryptoAlgorithm CreateAesCbcAlgorithm(const std::vector<uint8>& iv) {
|
| return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
|
| @@ -403,6 +430,13 @@ const char* const kPrivateKeyPkcs8DerHex =
|
| "156aba4126d24a81f3a528cbfb27f56886f840a9f6e86e17a44b94fe9319"
|
| "584b8e22fdde1e5a2e3bd8aa5ba8d8584194eb2190acf832b847f13a3d24"
|
| "a79f4d";
|
| +// The modulus and exponent (in hex) of kPublicKeySpkiDerHex
|
| +const char* const kPublicKeyModulusHex =
|
| + "A56E4A0E701017589A5187DC7EA841D156F2EC0E36AD52A44DFEB1E61F7AD991D8C51056"
|
| + "FFEDB162B4C0F283A12A88A394DFF526AB7291CBB307CEABFCE0B1DFD5CD9508096D5B2B"
|
| + "8B6DF5D671EF6377C0921CB23C270A70E2598E6FF89D19F105ACC2D3F0CB35F29280E138"
|
| + "6B6F64C4EF22E1E1F20D0CE8CFFB2249BD9A2137";
|
| +const char* const kPublicKeyExponentHex = "010001";
|
|
|
| class SharedCryptoTest : public testing::Test {
|
| protected:
|
| @@ -439,7 +473,7 @@ void ImportRsaKeyPair(const std::vector<uint8>& spki_der,
|
| blink::WebCryptoKeyUsageMask usage_mask,
|
| blink::WebCryptoKey* public_key,
|
| blink::WebCryptoKey* private_key) {
|
| - EXPECT_EQ(Status::Success(),
|
| + ASSERT_EQ(Status::Success(),
|
| ImportKey(blink::WebCryptoKeyFormatSpki,
|
| CryptoData(spki_der),
|
| algorithm,
|
| @@ -453,7 +487,7 @@ void ImportRsaKeyPair(const std::vector<uint8>& spki_der,
|
| EXPECT_EQ(extractable, extractable);
|
| EXPECT_EQ(usage_mask, public_key->usages());
|
|
|
| - EXPECT_EQ(Status::Success(),
|
| + ASSERT_EQ(Status::Success(),
|
| ImportKey(blink::WebCryptoKeyFormatPkcs8,
|
| CryptoData(pkcs8_der),
|
| algorithm,
|
| @@ -1439,15 +1473,11 @@ TEST_F(SharedCryptoTest, ImportJwkOctFailures) {
|
| }
|
|
|
| TEST_F(SharedCryptoTest, MAYBE(ImportExportJwkRsaPublicKey)) {
|
| - // This test uses kPublicKeySpkiDerHex as the RSA key. The data below
|
| - // represents the modulus and public exponent extracted from this SPKI blob.
|
| - // These values appear explicitly in the JWK rendering of the key.
|
| - const std::string n_hex =
|
| - "A56E4A0E701017589A5187DC7EA841D156F2EC0E36AD52A44DFEB1E61F7AD991D8C51056"
|
| - "FFEDB162B4C0F283A12A88A394DFF526AB7291CBB307CEABFCE0B1DFD5CD9508096D5B2B"
|
| - "8B6DF5D671EF6377C0921CB23C270A70E2598E6FF89D19F105ACC2D3F0CB35F29280E138"
|
| - "6B6F64C4EF22E1E1F20D0CE8CFFB2249BD9A2137";
|
| - const std::string e_hex = "010001";
|
| + const bool supports_rsa_oaep = SupportsRsaOaep();
|
| + if (!supports_rsa_oaep) {
|
| + LOG(WARNING) << "RSA-OAEP not supported on this platform. Skipping some"
|
| + << "tests.";
|
| + }
|
|
|
| struct TestCase {
|
| const blink::WebCryptoAlgorithm algorithm;
|
| @@ -1477,12 +1507,32 @@ TEST_F(SharedCryptoTest, MAYBE(ImportExportJwkRsaPublicKey)) {
|
| {CreateRsaHashedImportAlgorithm(
|
| blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
|
| blink::WebCryptoAlgorithmIdSha512),
|
| - blink::WebCryptoKeyUsageSign, "RS512"}};
|
| + blink::WebCryptoKeyUsageSign, "RS512"},
|
| + // RSA-OAEP with SHA-1 and MGF-1 / SHA-1
|
| + {CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaOaep,
|
| + blink::WebCryptoAlgorithmIdSha1),
|
| + blink::WebCryptoKeyUsageEncrypt, "RSA-OAEP"},
|
| + // RSA-OAEP with SHA-256 and MGF-1 / SHA-256
|
| + {CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaOaep,
|
| + blink::WebCryptoAlgorithmIdSha256),
|
| + blink::WebCryptoKeyUsageEncrypt, "RSA-OAEP-256"},
|
| + // RSA-OAEP with SHA-384 and MGF-1 / SHA-384
|
| + {CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaOaep,
|
| + blink::WebCryptoAlgorithmIdSha384),
|
| + blink::WebCryptoKeyUsageEncrypt, "RSA-OAEP-384"},
|
| + // RSA-OAEP with SHA-512 and MGF-1 / SHA-512
|
| + {CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaOaep,
|
| + blink::WebCryptoAlgorithmIdSha512),
|
| + blink::WebCryptoKeyUsageEncrypt, "RSA-OAEP-512"}};
|
|
|
| for (size_t test_index = 0; test_index < ARRAYSIZE_UNSAFE(kTests);
|
| ++test_index) {
|
| SCOPED_TRACE(test_index);
|
| const TestCase& test = kTests[test_index];
|
| + if (!supports_rsa_oaep &&
|
| + test.algorithm.id() == blink::WebCryptoAlgorithmIdRsaOaep) {
|
| + continue;
|
| + }
|
|
|
| // Import the spki to create a public key
|
| blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
|
| @@ -1498,24 +1548,33 @@ TEST_F(SharedCryptoTest, MAYBE(ImportExportJwkRsaPublicKey)) {
|
| std::vector<uint8> jwk;
|
| ASSERT_EQ(Status::Success(),
|
| ExportKey(blink::WebCryptoKeyFormatJwk, public_key, &jwk));
|
| - EXPECT_TRUE(VerifyPublicJwk(jwk, test.jwk_alg, n_hex, e_hex, test.usage));
|
| + EXPECT_TRUE(VerifyPublicJwk(jwk,
|
| + test.jwk_alg,
|
| + kPublicKeyModulusHex,
|
| + kPublicKeyExponentHex,
|
| + test.usage));
|
|
|
| // Import the JWK back in to create a new key
|
| blink::WebCryptoKey public_key2 = blink::WebCryptoKey::createNull();
|
| - EXPECT_EQ(
|
| + ASSERT_EQ(
|
| Status::Success(),
|
| ImportKeyJwk(
|
| CryptoData(jwk), test.algorithm, true, test.usage, &public_key2));
|
| - EXPECT_TRUE(public_key2.handle());
|
| + ASSERT_TRUE(public_key2.handle());
|
| EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key2.type());
|
| EXPECT_EQ(true, public_key2.extractable());
|
| EXPECT_EQ(test.algorithm.id(), public_key2.algorithm().id());
|
|
|
| - // Export the new key as spki and compare to the original.
|
| - std::vector<uint8> spki;
|
| - ASSERT_EQ(Status::Success(),
|
| - ExportKey(blink::WebCryptoKeyFormatSpki, public_key2, &spki));
|
| - EXPECT_BYTES_EQ_HEX(kPublicKeySpkiDerHex, CryptoData(spki));
|
| + // Only perform SPKI consistency test for RSA-ES and RSA-SSA, as their
|
| + // export format is the same as kPublicKeySpkiDerHex
|
| + if (test.algorithm.id() == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 ||
|
| + test.algorithm.id() == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5) {
|
| + // Export the new key as spki and compare to the original.
|
| + std::vector<uint8> spki;
|
| + ASSERT_EQ(Status::Success(),
|
| + ExportKey(blink::WebCryptoKeyFormatSpki, public_key2, &spki));
|
| + EXPECT_BYTES_EQ_HEX(kPublicKeySpkiDerHex, CryptoData(spki));
|
| + }
|
| }
|
| }
|
|
|
| @@ -1980,6 +2039,13 @@ TEST_F(SharedCryptoTest, MAYBE(ImportExportSpki)) {
|
| EXPECT_FALSE(key.extractable());
|
| EXPECT_EQ(Status::ErrorKeyNotExtractable(),
|
| ExportKey(blink::WebCryptoKeyFormatSpki, key, &output));
|
| +
|
| + // TODO(eroman): Failing test: Import a SPKI with an unrecognized hash OID
|
| + // TODO(eroman): Failing test: Import a SPKI with invalid algorithm params
|
| + // TODO(eroman): Failing test: Import a SPKI with inconsistent parameters
|
| + // (e.g. SHA-1 in OID, SHA-256 in params)
|
| + // TODO(eroman): Failing test: Import a SPKI for RSA-SSA, but with params
|
| + // as OAEP/PSS
|
| }
|
|
|
| TEST_F(SharedCryptoTest, MAYBE(ImportExportPkcs8)) {
|
| @@ -2234,14 +2300,14 @@ TEST_F(SharedCryptoTest, MAYBE(RsaEsRoundTrip)) {
|
| CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5);
|
| blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
|
| blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
|
| - ImportRsaKeyPair(
|
| + ASSERT_NO_FATAL_FAILURE(ImportRsaKeyPair(
|
| HexStringToBytes(kPublicKeySpkiDerHex),
|
| HexStringToBytes(kPrivateKeyPkcs8DerHex),
|
| algorithm,
|
| false,
|
| blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt,
|
| &public_key,
|
| - &private_key);
|
| + &private_key));
|
|
|
| // Make a maximum-length data message. RSAES can operate on messages up to
|
| // length of k - 11 bytes, where k is the octet length of the RSA modulus.
|
| @@ -2302,14 +2368,14 @@ TEST_F(SharedCryptoTest, MAYBE(RsaEsKnownAnswer)) {
|
| CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5);
|
| blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
|
| blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
|
| - ImportRsaKeyPair(
|
| + ASSERT_NO_FATAL_FAILURE(ImportRsaKeyPair(
|
| rsa_spki_der,
|
| rsa_pkcs8_der,
|
| algorithm,
|
| false,
|
| blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt,
|
| &public_key,
|
| - &private_key);
|
| + &private_key));
|
|
|
| // Decrypt the known-good ciphertext with the private key. As a check we must
|
| // get the known original cleartext.
|
| @@ -2343,14 +2409,14 @@ TEST_F(SharedCryptoTest, MAYBE(RsaEsFailures)) {
|
| CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5);
|
| blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
|
| blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
|
| - ImportRsaKeyPair(
|
| + ASSERT_NO_FATAL_FAILURE(ImportRsaKeyPair(
|
| HexStringToBytes(kPublicKeySpkiDerHex),
|
| HexStringToBytes(kPrivateKeyPkcs8DerHex),
|
| algorithm,
|
| false,
|
| blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt,
|
| &public_key,
|
| - &private_key);
|
| + &private_key));
|
|
|
| // Fail encrypt with a private key.
|
| std::vector<uint8> encrypted_data;
|
| @@ -2416,13 +2482,14 @@ TEST_F(SharedCryptoTest, MAYBE(RsaSsaSignVerifyFailures)) {
|
| blink::WebCryptoAlgorithmIdSha1);
|
| blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
|
| blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
|
| - ImportRsaKeyPair(HexStringToBytes(kPublicKeySpkiDerHex),
|
| - HexStringToBytes(kPrivateKeyPkcs8DerHex),
|
| - importAlgorithm,
|
| - false,
|
| - usage_mask,
|
| - &public_key,
|
| - &private_key);
|
| + ASSERT_NO_FATAL_FAILURE(
|
| + ImportRsaKeyPair(HexStringToBytes(kPublicKeySpkiDerHex),
|
| + HexStringToBytes(kPrivateKeyPkcs8DerHex),
|
| + importAlgorithm,
|
| + false,
|
| + usage_mask,
|
| + &public_key,
|
| + &private_key));
|
|
|
| blink::WebCryptoAlgorithm algorithm =
|
| CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5);
|
| @@ -2559,14 +2626,14 @@ TEST_F(SharedCryptoTest, MAYBE(RsaSignVerifyKnownAnswer)) {
|
| blink::WebCryptoAlgorithmIdSha1);
|
| blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
|
| blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
|
| - ImportRsaKeyPair(
|
| + ASSERT_NO_FATAL_FAILURE(ImportRsaKeyPair(
|
| HexStringToBytes(kPublicKeySpkiDerHex),
|
| HexStringToBytes(kPrivateKeyPkcs8DerHex),
|
| importAlgorithm,
|
| false,
|
| blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify,
|
| &public_key,
|
| - &private_key);
|
| + &private_key));
|
|
|
| blink::WebCryptoAlgorithm algorithm =
|
| CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5);
|
| @@ -3140,14 +3207,14 @@ TEST_F(SharedCryptoTest, MAYBE(RsaEsRawSymkeyWrapUnwrapKnownAnswer)) {
|
| CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5);
|
| blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
|
| blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
|
| - ImportRsaKeyPair(
|
| + ASSERT_NO_FATAL_FAILURE(ImportRsaKeyPair(
|
| rsa_spki_der,
|
| rsa_pkcs8_der,
|
| algorithm,
|
| false,
|
| blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey,
|
| &public_key,
|
| - &private_key);
|
| + &private_key));
|
|
|
| // Import the symmetric key.
|
| blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
|
| @@ -3217,14 +3284,14 @@ TEST_F(SharedCryptoTest, MAYBE(RsaEsRawSymkeyWrapUnwrapErrors)) {
|
| CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5);
|
| blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
|
| blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
|
| - ImportRsaKeyPair(
|
| + ASSERT_NO_FATAL_FAILURE(ImportRsaKeyPair(
|
| HexStringToBytes(kPublicKeySpkiDerHex),
|
| HexStringToBytes(kPrivateKeyPkcs8DerHex),
|
| wrapping_algorithm,
|
| false,
|
| blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey,
|
| &public_key,
|
| - &private_key);
|
| + &private_key));
|
|
|
| // Import the symmetric key.
|
| blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
|
| @@ -3370,14 +3437,14 @@ TEST_F(SharedCryptoTest, MAYBE(RsaEsJwkSymkeyWrapUnwrapRoundTrip)) {
|
| CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5);
|
| blink::WebCryptoKey public_wrapping_key = blink::WebCryptoKey::createNull();
|
| blink::WebCryptoKey private_wrapping_key = blink::WebCryptoKey::createNull();
|
| - ImportRsaKeyPair(
|
| + ASSERT_NO_FATAL_FAILURE(ImportRsaKeyPair(
|
| HexStringToBytes(kPublicKeySpkiDerHex),
|
| HexStringToBytes(kPrivateKeyPkcs8DerHex),
|
| wrapping_algorithm,
|
| false,
|
| blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey,
|
| &public_wrapping_key,
|
| - &private_wrapping_key);
|
| + &private_wrapping_key));
|
|
|
| // Wrap the symkey in JWK format, using the public wrapping key.
|
| std::vector<uint8> wrapped_data;
|
| @@ -3479,6 +3546,551 @@ TEST_F(SharedCryptoTest, MAYBE(RsaEsJwkSymkeyWrapUnwrapErrors)) {
|
| &unwrapped_key));
|
| }
|
|
|
| +class SharedCryptoRsaOaepTest : public ::testing::Test {
|
| + public:
|
| + SharedCryptoRsaOaepTest() { Init(); }
|
| +
|
| + scoped_ptr<base::DictionaryValue> CreatePublicKeyJwkDict() {
|
| + scoped_ptr<base::DictionaryValue> jwk(new base::DictionaryValue());
|
| + jwk->SetString("kty", "RSA");
|
| + jwk->SetString("n",
|
| + Base64EncodeUrlSafe(HexStringToBytes(kPublicKeyModulusHex)));
|
| + jwk->SetString(
|
| + "e", Base64EncodeUrlSafe(HexStringToBytes(kPublicKeyExponentHex)));
|
| + return jwk.Pass();
|
| + }
|
| +};
|
| +
|
| +// Import a PKCS#8 private key that uses RSAPrivateKey with the
|
| +// id-rsaEncryption OID.
|
| +TEST_F(SharedCryptoRsaOaepTest, ImportPkcs8WithRsaEncryption) {
|
| + if (!SupportsRsaOaep()) {
|
| + LOG(WARNING) << "RSA-OAEP support not present; skipping.";
|
| + return;
|
| + }
|
| +
|
| + blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
|
| + ASSERT_EQ(Status::Success(),
|
| + ImportKey(blink::WebCryptoKeyFormatPkcs8,
|
| + CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
|
| + CreateRsaHashedImportAlgorithm(
|
| + blink::WebCryptoAlgorithmIdRsaOaep,
|
| + blink::WebCryptoAlgorithmIdSha1),
|
| + true,
|
| + blink::WebCryptoKeyUsageDecrypt,
|
| + &private_key));
|
| +}
|
| +
|
| +TEST_F(SharedCryptoRsaOaepTest, ImportPublicJwkWithNoAlg) {
|
| + if (!SupportsRsaOaep()) {
|
| + LOG(WARNING) << "RSA-OAEP support not present; skipping.";
|
| + return;
|
| + }
|
| +
|
| + scoped_ptr<base::DictionaryValue> jwk(CreatePublicKeyJwkDict());
|
| +
|
| + blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
|
| + ASSERT_EQ(Status::Success(),
|
| + ImportKeyJwkFromDict(*jwk.get(),
|
| + CreateRsaHashedImportAlgorithm(
|
| + blink::WebCryptoAlgorithmIdRsaOaep,
|
| + blink::WebCryptoAlgorithmIdSha1),
|
| + true,
|
| + blink::WebCryptoKeyUsageEncrypt,
|
| + &public_key));
|
| +}
|
| +
|
| +TEST_F(SharedCryptoRsaOaepTest, ImportPublicJwkWithMatchingAlg) {
|
| + if (!SupportsRsaOaep()) {
|
| + LOG(WARNING) << "RSA-OAEP support not present; skipping.";
|
| + return;
|
| + }
|
| +
|
| + scoped_ptr<base::DictionaryValue> jwk(CreatePublicKeyJwkDict());
|
| + jwk->SetString("alg", "RSA-OAEP");
|
| +
|
| + blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
|
| + ASSERT_EQ(Status::Success(),
|
| + ImportKeyJwkFromDict(*jwk.get(),
|
| + CreateRsaHashedImportAlgorithm(
|
| + blink::WebCryptoAlgorithmIdRsaOaep,
|
| + blink::WebCryptoAlgorithmIdSha1),
|
| + true,
|
| + blink::WebCryptoKeyUsageEncrypt,
|
| + &public_key));
|
| +}
|
| +
|
| +TEST_F(SharedCryptoRsaOaepTest, ImportPublicJwkWithMismatchedAlgFails) {
|
| + if (!SupportsRsaOaep()) {
|
| + LOG(WARNING) << "RSA-OAEP support not present; skipping.";
|
| + return;
|
| + }
|
| +
|
| + scoped_ptr<base::DictionaryValue> jwk(CreatePublicKeyJwkDict());
|
| + jwk->SetString("alg", "RSA-OAEP-512");
|
| +
|
| + blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
|
| + ASSERT_EQ(Status::ErrorJwkAlgorithmInconsistent(),
|
| + ImportKeyJwkFromDict(*jwk.get(),
|
| + CreateRsaHashedImportAlgorithm(
|
| + blink::WebCryptoAlgorithmIdRsaOaep,
|
| + blink::WebCryptoAlgorithmIdSha1),
|
| + true,
|
| + blink::WebCryptoKeyUsageEncrypt,
|
| + &public_key));
|
| +}
|
| +
|
| +TEST_F(SharedCryptoRsaOaepTest, ImportPublicJwkWithMismatchedTypFails) {
|
| + if (!SupportsRsaOaep()) {
|
| + LOG(WARNING) << "RSA-OAEP support not present; skipping.";
|
| + return;
|
| + }
|
| +
|
| + scoped_ptr<base::DictionaryValue> jwk(CreatePublicKeyJwkDict());
|
| + jwk->SetString("kty", "oct");
|
| + jwk->SetString("alg", "RSA-OAEP");
|
| +
|
| + blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
|
| + ASSERT_EQ(Status::ErrorJwkPropertyMissing("k"),
|
| + ImportKeyJwkFromDict(*jwk.get(),
|
| + CreateRsaHashedImportAlgorithm(
|
| + blink::WebCryptoAlgorithmIdRsaOaep,
|
| + blink::WebCryptoAlgorithmIdSha1),
|
| + true,
|
| + blink::WebCryptoKeyUsageEncrypt,
|
| + &public_key));
|
| +}
|
| +
|
| +TEST_F(SharedCryptoRsaOaepTest, ExportPublicJwk) {
|
| + if (!SupportsRsaOaep()) {
|
| + LOG(WARNING) << "RSA-OAEP support not present; skipping.";
|
| + return;
|
| + }
|
| +
|
| + struct TestData {
|
| + blink::WebCryptoAlgorithmId hash_alg;
|
| + const char* expected_jwk_alg;
|
| + } kTestData[] = {{blink::WebCryptoAlgorithmIdSha1, "RSA-OAEP"},
|
| + {blink::WebCryptoAlgorithmIdSha256, "RSA-OAEP-256"},
|
| + {blink::WebCryptoAlgorithmIdSha384, "RSA-OAEP-384"},
|
| + {blink::WebCryptoAlgorithmIdSha512, "RSA-OAEP-512"}};
|
| + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestData); ++i) {
|
| + const TestData& test_data = kTestData[i];
|
| + SCOPED_TRACE(test_data.expected_jwk_alg);
|
| +
|
| + scoped_ptr<base::DictionaryValue> jwk(CreatePublicKeyJwkDict());
|
| + jwk->SetString("alg", test_data.expected_jwk_alg);
|
| +
|
| + // Import the key in a known-good format
|
| + blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
|
| + ASSERT_EQ(Status::Success(),
|
| + ImportKeyJwkFromDict(
|
| + *jwk.get(),
|
| + CreateRsaHashedImportAlgorithm(
|
| + blink::WebCryptoAlgorithmIdRsaOaep, test_data.hash_alg),
|
| + true,
|
| + blink::WebCryptoKeyUsageEncrypt,
|
| + &public_key));
|
| +
|
| + // Now export the key as JWK and verify its contents
|
| + std::vector<uint8> jwk_data;
|
| + ASSERT_EQ(Status::Success(),
|
| + ExportKey(blink::WebCryptoKeyFormatJwk, public_key, &jwk_data));
|
| + EXPECT_TRUE(VerifyPublicJwk(jwk_data,
|
| + test_data.expected_jwk_alg,
|
| + kPublicKeyModulusHex,
|
| + kPublicKeyExponentHex,
|
| + blink::WebCryptoKeyUsageEncrypt));
|
| + }
|
| +}
|
| +
|
| +TEST_F(SharedCryptoRsaOaepTest, EncryptDecryptKnownAnswerTest) {
|
| + if (!SupportsRsaOaep()) {
|
| + LOG(WARNING) << "RSA-OAEP support not present; skipping.";
|
| + return;
|
| + }
|
| +
|
| + scoped_ptr<base::ListValue> tests;
|
| + ASSERT_TRUE(ReadJsonTestFileToList("rsa_oaep.json", &tests));
|
| +
|
| + for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
|
| + SCOPED_TRACE(test_index);
|
| +
|
| + base::DictionaryValue* test = NULL;
|
| + ASSERT_TRUE(tests->GetDictionary(test_index, &test));
|
| +
|
| + blink::WebCryptoAlgorithm digest_algorithm =
|
| + GetDigestAlgorithm(test, "hash");
|
| + ASSERT_FALSE(digest_algorithm.isNull());
|
| + std::vector<uint8> public_key_der =
|
| + GetBytesFromHexString(test, "public_key");
|
| + std::vector<uint8> private_key_der =
|
| + GetBytesFromHexString(test, "private_key");
|
| + std::vector<uint8> ciphertext = GetBytesFromHexString(test, "ciphertext");
|
| + std::vector<uint8> plaintext = GetBytesFromHexString(test, "plaintext");
|
| + std::vector<uint8> label = GetBytesFromHexString(test, "label");
|
| +
|
| + blink::WebCryptoAlgorithm import_algorithm = CreateRsaHashedImportAlgorithm(
|
| + blink::WebCryptoAlgorithmIdRsaOaep, digest_algorithm.id());
|
| + blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
|
| + blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
|
| +
|
| + ASSERT_NO_FATAL_FAILURE(ImportRsaKeyPair(
|
| + public_key_der,
|
| + private_key_der,
|
| + import_algorithm,
|
| + false,
|
| + blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt,
|
| + &public_key,
|
| + &private_key));
|
| +
|
| + blink::WebCryptoAlgorithm op_algorithm = CreateRsaOaepAlgorithm(label);
|
| + std::vector<uint8> decrypted_data;
|
| + ASSERT_EQ(Status::Success(),
|
| + Decrypt(op_algorithm,
|
| + private_key,
|
| + CryptoData(ciphertext),
|
| + &decrypted_data));
|
| + EXPECT_BYTES_EQ(plaintext, decrypted_data);
|
| + std::vector<uint8> encrypted_data;
|
| + ASSERT_EQ(
|
| + Status::Success(),
|
| + Encrypt(
|
| + op_algorithm, public_key, CryptoData(plaintext), &encrypted_data));
|
| + std::vector<uint8> redecrypted_data;
|
| + ASSERT_EQ(Status::Success(),
|
| + Decrypt(op_algorithm,
|
| + private_key,
|
| + CryptoData(encrypted_data),
|
| + &redecrypted_data));
|
| + EXPECT_BYTES_EQ(plaintext, redecrypted_data);
|
| + }
|
| +}
|
| +
|
| +TEST_F(SharedCryptoRsaOaepTest, EncryptWithLargeMessageFails) {
|
| + if (!SupportsRsaOaep()) {
|
| + LOG(WARNING) << "RSA-OAEP support not present; skipping.";
|
| + return;
|
| + }
|
| +
|
| + const blink::WebCryptoAlgorithmId kHash = blink::WebCryptoAlgorithmIdSha1;
|
| + const size_t kHashSize = 20;
|
| +
|
| + scoped_ptr<base::DictionaryValue> jwk(CreatePublicKeyJwkDict());
|
| +
|
| + blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
|
| + ASSERT_EQ(Status::Success(),
|
| + ImportKeyJwkFromDict(*jwk.get(),
|
| + CreateRsaHashedImportAlgorithm(
|
| + blink::WebCryptoAlgorithmIdRsaOaep, kHash),
|
| + true,
|
| + blink::WebCryptoKeyUsageEncrypt,
|
| + &public_key));
|
| +
|
| + // The maximum size of an encrypted message is:
|
| + // modulus length
|
| + // - 1 (leading octet)
|
| + // - hash size (maskedSeed)
|
| + // - hash size (lHash portion of maskedDB)
|
| + // - 1 (at least one octet for the padding string)
|
| + size_t kMaxMessageSize = (kModulusLengthBits / 8) - 2 - (2 * kHashSize);
|
| +
|
| + // The label has no influence on the maximum message size. For simplicity,
|
| + // use the empty string.
|
| + std::vector<uint8> label;
|
| + blink::WebCryptoAlgorithm op_algorithm = CreateRsaOaepAlgorithm(label);
|
| +
|
| + // Test that a message just before the boundary succeeds.
|
| + std::string large_message;
|
| + large_message.resize(kMaxMessageSize - 1, 'A');
|
| +
|
| + std::vector<uint8> ciphertext;
|
| + ASSERT_EQ(
|
| + Status::Success(),
|
| + Encrypt(
|
| + op_algorithm, public_key, CryptoData(large_message), &ciphertext));
|
| +
|
| + // Test that a message at the boundary succeeds.
|
| + large_message.resize(kMaxMessageSize, 'A');
|
| + ciphertext.clear();
|
| +
|
| + ASSERT_EQ(
|
| + Status::Success(),
|
| + Encrypt(
|
| + op_algorithm, public_key, CryptoData(large_message), &ciphertext));
|
| +
|
| + // Test that a message greater than the largest size fails.
|
| + large_message.resize(kMaxMessageSize + 1, 'A');
|
| + ciphertext.clear();
|
| +
|
| + ASSERT_EQ(
|
| + Status::OperationError(),
|
| + Encrypt(
|
| + op_algorithm, public_key, CryptoData(large_message), &ciphertext));
|
| +}
|
| +
|
| +// Ensures that if the selected hash algorithm for the RSA-OAEP message is too
|
| +// large, then it is rejected, independent of the actual message to be
|
| +// encrypted.
|
| +// For example, a 1024-bit RSA key is too small to accomodate a message that
|
| +// uses OAEP with SHA-512, since it requires 1040 bits to encode
|
| +// (2 * hash size + 2 padding bytes).
|
| +TEST_F(SharedCryptoRsaOaepTest, EncryptWithLargeDigestFails) {
|
| + if (!SupportsRsaOaep()) {
|
| + LOG(WARNING) << "RSA-OAEP support not present; skipping.";
|
| + return;
|
| + }
|
| +
|
| + const blink::WebCryptoAlgorithmId kHash = blink::WebCryptoAlgorithmIdSha512;
|
| +
|
| + scoped_ptr<base::DictionaryValue> jwk(CreatePublicKeyJwkDict());
|
| +
|
| + blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
|
| + ASSERT_EQ(Status::Success(),
|
| + ImportKeyJwkFromDict(*jwk.get(),
|
| + CreateRsaHashedImportAlgorithm(
|
| + blink::WebCryptoAlgorithmIdRsaOaep, kHash),
|
| + true,
|
| + blink::WebCryptoKeyUsageEncrypt,
|
| + &public_key));
|
| +
|
| + // The label has no influence on the maximum message size. For simplicity,
|
| + // use the empty string.
|
| + std::vector<uint8> label;
|
| + blink::WebCryptoAlgorithm op_algorithm = CreateRsaOaepAlgorithm(label);
|
| +
|
| + std::string small_message("A");
|
| + std::vector<uint8> ciphertext;
|
| + // This is an operation error, as the internal consistency checking of the
|
| + // algorithm parameters is up to the implementation.
|
| + ASSERT_EQ(
|
| + Status::OperationError(),
|
| + Encrypt(
|
| + op_algorithm, public_key, CryptoData(small_message), &ciphertext));
|
| +}
|
| +
|
| +TEST_F(SharedCryptoRsaOaepTest, DecryptWithLargeMessageFails) {
|
| + if (!SupportsRsaOaep()) {
|
| + LOG(WARNING) << "RSA-OAEP support not present; skipping.";
|
| + return;
|
| + }
|
| +
|
| + blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
|
| + ASSERT_EQ(Status::Success(),
|
| + ImportKey(blink::WebCryptoKeyFormatPkcs8,
|
| + CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
|
| + CreateRsaHashedImportAlgorithm(
|
| + blink::WebCryptoAlgorithmIdRsaOaep,
|
| + blink::WebCryptoAlgorithmIdSha1),
|
| + true,
|
| + blink::WebCryptoKeyUsageDecrypt,
|
| + &private_key));
|
| +
|
| + // The label has no influence on the maximum message size. For simplicity,
|
| + // use the empty string.
|
| + std::vector<uint8> label;
|
| + blink::WebCryptoAlgorithm op_algorithm = CreateRsaOaepAlgorithm(label);
|
| +
|
| + std::string large_dummy_message(kModulusLengthBits / 8, 'A');
|
| + std::vector<uint8> plaintext;
|
| +
|
| + ASSERT_EQ(Status::OperationError(),
|
| + Decrypt(op_algorithm,
|
| + private_key,
|
| + CryptoData(large_dummy_message),
|
| + &plaintext));
|
| +}
|
| +
|
| +TEST_F(SharedCryptoRsaOaepTest, WrapUnwrapRawKey) {
|
| + if (!SupportsRsaOaep()) {
|
| + LOG(WARNING) << "RSA-OAEP support not present; skipping.";
|
| + return;
|
| + }
|
| +
|
| + blink::WebCryptoAlgorithm import_algorithm = CreateRsaHashedImportAlgorithm(
|
| + blink::WebCryptoAlgorithmIdRsaOaep, blink::WebCryptoAlgorithmIdSha1);
|
| + blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
|
| + blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
|
| +
|
| + ASSERT_NO_FATAL_FAILURE(ImportRsaKeyPair(
|
| + HexStringToBytes(kPublicKeySpkiDerHex),
|
| + HexStringToBytes(kPrivateKeyPkcs8DerHex),
|
| + import_algorithm,
|
| + false,
|
| + blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt |
|
| + blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey,
|
| + &public_key,
|
| + &private_key));
|
| +
|
| + std::vector<uint8> label;
|
| + blink::WebCryptoAlgorithm wrapping_algorithm = CreateRsaOaepAlgorithm(label);
|
| +
|
| + const std::string key_hex = "000102030405060708090A0B0C0D0E0F";
|
| + const blink::WebCryptoAlgorithm key_algorithm =
|
| + webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
|
| +
|
| + blink::WebCryptoKey key =
|
| + ImportSecretKeyFromRaw(HexStringToBytes(key_hex),
|
| + key_algorithm,
|
| + blink::WebCryptoKeyUsageEncrypt);
|
| + ASSERT_FALSE(key.isNull());
|
| +
|
| + std::vector<uint8> wrapped_key;
|
| + ASSERT_EQ(Status::Success(),
|
| + WrapKey(blink::WebCryptoKeyFormatRaw,
|
| + key,
|
| + public_key,
|
| + wrapping_algorithm,
|
| + &wrapped_key));
|
| +
|
| + // Verify that |wrapped_key| can be decrypted and yields the key data.
|
| + // Because |private_key| supports both decrypt and unwrap, this is valid.
|
| + std::vector<uint8> decrypted_key;
|
| + ASSERT_EQ(Status::Success(),
|
| + Decrypt(wrapping_algorithm,
|
| + private_key,
|
| + CryptoData(wrapped_key),
|
| + &decrypted_key));
|
| + EXPECT_BYTES_EQ_HEX(key_hex, decrypted_key);
|
| +
|
| + // Now attempt to unwrap the key, which should also decrypt the data.
|
| + blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull();
|
| + ASSERT_EQ(Status::Success(),
|
| + UnwrapKey(blink::WebCryptoKeyFormatRaw,
|
| + CryptoData(wrapped_key),
|
| + private_key,
|
| + wrapping_algorithm,
|
| + key_algorithm,
|
| + true,
|
| + blink::WebCryptoKeyUsageEncrypt,
|
| + &unwrapped_key));
|
| + ASSERT_FALSE(unwrapped_key.isNull());
|
| +
|
| + std::vector<uint8> raw_key;
|
| + ASSERT_EQ(Status::Success(),
|
| + ExportKey(blink::WebCryptoKeyFormatRaw, unwrapped_key, &raw_key));
|
| + EXPECT_BYTES_EQ_HEX(key_hex, raw_key);
|
| +}
|
| +
|
| +TEST_F(SharedCryptoRsaOaepTest, WrapUnwrapJwkSymKey) {
|
| + if (!SupportsRsaOaep()) {
|
| + LOG(WARNING) << "RSA-OAEP support not present; skipping.";
|
| + return;
|
| + }
|
| +
|
| + // The public and private portions of a 2048-bit RSA key with the
|
| + // id-rsaEncryption OID
|
| + const char kPublicKey2048SpkiDerHex[] =
|
| + "30820122300d06092a864886f70d01010105000382010f003082010a0282010100c5d8ce"
|
| + "137a38168c8ab70229cfa5accc640567159750a312ce2e7d54b6e2fdd59b300c6a6c9764"
|
| + "f8de6f00519cdb90111453d273a967462786480621f9e7cee5b73d63358448e7183a3a68"
|
| + "e991186359f26aa88fbca5f53e673e502e4c5a2ba5068aeba60c9d0c44d872458d1b1e2f"
|
| + "7f339f986076d516e93dc750f0b7680b6f5f02bc0d5590495be04c4ae59d34ba17bc5d08"
|
| + "a93c75cfda2828f4a55b153af912038438276cb4a14f8116ca94db0ea9893652d02fc606"
|
| + "36f19975e3d79a4d8ea8bfed6f8e0a24b63d243b08ea70a086ad56dd6341d733711c89ca"
|
| + "749d4a80b3e6ecd2f8e53731eadeac2ea77788ee55d7b4b47c0f2523fbd61b557c16615d"
|
| + "5d0203010001";
|
| + const char kPrivateKey2048Pkcs8DerHex[] =
|
| + "308204bd020100300d06092a864886f70d0101010500048204a7308204a3020100028201"
|
| + "0100c5d8ce137a38168c8ab70229cfa5accc640567159750a312ce2e7d54b6e2fdd59b30"
|
| + "0c6a6c9764f8de6f00519cdb90111453d273a967462786480621f9e7cee5b73d63358448"
|
| + "e7183a3a68e991186359f26aa88fbca5f53e673e502e4c5a2ba5068aeba60c9d0c44d872"
|
| + "458d1b1e2f7f339f986076d516e93dc750f0b7680b6f5f02bc0d5590495be04c4ae59d34"
|
| + "ba17bc5d08a93c75cfda2828f4a55b153af912038438276cb4a14f8116ca94db0ea98936"
|
| + "52d02fc60636f19975e3d79a4d8ea8bfed6f8e0a24b63d243b08ea70a086ad56dd6341d7"
|
| + "33711c89ca749d4a80b3e6ecd2f8e53731eadeac2ea77788ee55d7b4b47c0f2523fbd61b"
|
| + "557c16615d5d02030100010282010074b70feb41a0b0fcbc207670400556c9450042ede3"
|
| + "d4383fb1ce8f3558a6d4641d26dd4c333fa4db842d2b9cf9d2354d3e16ad027a9f682d8c"
|
| + "f4145a1ad97b9edcd8a41c402bd9d8db10f62f43df854cdccbbb2100834f083f53ed6d42"
|
| + "b1b729a59072b004a4e945fc027db15e9c121d1251464d320d4774d5732df6b3dbf751f4"
|
| + "9b19c9db201e19989c883bbaad5333db47f64f6f7a95b8d4936b10d945aa3f794cfaab62"
|
| + "e7d47686129358914f3b8085f03698a650ab5b8c7e45813f2b0515ec05b6e5195b6a7c2a"
|
| + "0d36969745f431ded4fd059f6aa361a4649541016d356297362b778e90f077d48815b339"
|
| + "ec6f43aba345df93e67fcb6c2cb5b4544e9be902818100e9c90abe5f9f32468c5b6d630c"
|
| + "54a4d7d75e29a72cf792f21e242aac78fd7995c42dfd4ae871d2619ff7096cb05baa78e3"
|
| + "23ecab338401a8059adf7a0d8be3b21edc9a9c82c5605634a2ec81ec053271721351868a"
|
| + "4c2e50c689d7cef94e31ff23658af5843366e2b289c5bf81d72756a7b93487dd8770d69c"
|
| + "1f4e089d6d89f302818100d8a58a727c4e209132afd9933b98c89aca862a01cc0be74133"
|
| + "bee517909e5c379e526895ac4af11780c1fe91194c777c9670b6423f0f5a32fd7691a622"
|
| + "113eef4bed2ef863363a335fd55b0e75088c582437237d7f3ed3f0a643950237bc6e6277"
|
| + "ccd0d0a1b4170aa1047aa7ffa7c8c54be10e8c7327ae2e0885663963817f6f02818100e5"
|
| + "aed9ba4d71b7502e6748a1ce247ecb7bd10c352d6d9256031cdf3c11a65e44b0b7ca2945"
|
| + "134671195af84c6b3bb3d10ebf65ae916f38bd5dbc59a0ad1c69b8beaf57cb3a8335f19b"
|
| + "c7117b576987b48331cd9fd3d1a293436b7bb5e1a35c6560de4b5688ea834367cb0997eb"
|
| + "b578f59ed4cb724c47dba94d3b484c1876dcd70281807f15bc7d2406007cac2b138a96af"
|
| + "2d1e00276b84da593132c253fcb73212732dfd25824c2a615bc3d9b7f2c8d2fa542d3562"
|
| + "b0c7738e61eeff580a6056239fb367ea9e5efe73d4f846033602e90c36a78db6fa8ea792"
|
| + "0769675ec58e237bd994d189c8045a96f5dd3a4f12547257ce224e3c9af830a4da3c0eab"
|
| + "9227a0035ae9028180067caea877e0b23090fc689322b71fbcce63d6596e66ab5fcdbaa0"
|
| + "0d49e93aba8effb4518c2da637f209028401a68f344865b4956b032c69acde51d29177ca"
|
| + "3db99fdbf5e74848ed4fa7bdfc2ebb60e2aaa5354770a763e1399ab7a2099762d525fea0"
|
| + "37f3e1972c45a477e66db95c9609bb27f862700ef93379930786cf751b";
|
| + blink::WebCryptoAlgorithm import_algorithm = CreateRsaHashedImportAlgorithm(
|
| + blink::WebCryptoAlgorithmIdRsaOaep, blink::WebCryptoAlgorithmIdSha1);
|
| + blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
|
| + blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
|
| +
|
| + ASSERT_NO_FATAL_FAILURE(ImportRsaKeyPair(
|
| + HexStringToBytes(kPublicKey2048SpkiDerHex),
|
| + HexStringToBytes(kPrivateKey2048Pkcs8DerHex),
|
| + import_algorithm,
|
| + false,
|
| + blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt |
|
| + blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey,
|
| + &public_key,
|
| + &private_key));
|
| +
|
| + std::vector<uint8> label;
|
| + blink::WebCryptoAlgorithm wrapping_algorithm = CreateRsaOaepAlgorithm(label);
|
| +
|
| + const std::string key_hex = "000102030405060708090a0b0c0d0e0f";
|
| + const blink::WebCryptoAlgorithm key_algorithm =
|
| + webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
|
| +
|
| + blink::WebCryptoKey key =
|
| + ImportSecretKeyFromRaw(HexStringToBytes(key_hex),
|
| + key_algorithm,
|
| + blink::WebCryptoKeyUsageEncrypt);
|
| + ASSERT_FALSE(key.isNull());
|
| +
|
| + std::vector<uint8> wrapped_key;
|
| + ASSERT_EQ(Status::Success(),
|
| + WrapKey(blink::WebCryptoKeyFormatJwk,
|
| + key,
|
| + public_key,
|
| + wrapping_algorithm,
|
| + &wrapped_key));
|
| +
|
| + // Verify that |wrapped_key| can be decrypted and yields a valid JWK object.
|
| + // Because |private_key| supports both decrypt and unwrap, this is valid.
|
| + std::vector<uint8> decrypted_jwk;
|
| + ASSERT_EQ(Status::Success(),
|
| + Decrypt(wrapping_algorithm,
|
| + private_key,
|
| + CryptoData(wrapped_key),
|
| + &decrypted_jwk));
|
| + EXPECT_TRUE(VerifySecretJwk(
|
| + decrypted_jwk, "A128CBC", key_hex, blink::WebCryptoKeyUsageEncrypt));
|
| +
|
| + // Now attempt to unwrap the key, which should also decrypt the data.
|
| + blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull();
|
| + ASSERT_EQ(Status::Success(),
|
| + UnwrapKey(blink::WebCryptoKeyFormatJwk,
|
| + CryptoData(wrapped_key),
|
| + private_key,
|
| + wrapping_algorithm,
|
| + key_algorithm,
|
| + true,
|
| + blink::WebCryptoKeyUsageEncrypt,
|
| + &unwrapped_key));
|
| + ASSERT_FALSE(unwrapped_key.isNull());
|
| +
|
| + std::vector<uint8> raw_key;
|
| + ASSERT_EQ(Status::Success(),
|
| + ExportKey(blink::WebCryptoKeyFormatRaw, unwrapped_key, &raw_key));
|
| + EXPECT_BYTES_EQ_HEX(key_hex, raw_key);
|
| +}
|
| +
|
| } // namespace webcrypto
|
|
|
| } // namespace content
|
|
|