Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(112)

Unified Diff: content/child/webcrypto/shared_crypto_unittest.cc

Issue 205913002: [webcrypto] Add JWK RSA public key export for NSS. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « content/child/webcrypto/platform_crypto_openssl.cc ('k') | content/child/webcrypto/webcrypto_util.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 821945fb800bb70c7cb84b27d7ae94dc29c70568..f7acd6da5189407e8351292372715a2d2877523a 100644
--- a/content/child/webcrypto/shared_crypto_unittest.cc
+++ b/content/child/webcrypto/shared_crypto_unittest.cc
@@ -540,25 +540,22 @@ scoped_ptr<base::DictionaryValue> GetJwkDictionary(
return scoped_ptr<base::DictionaryValue>(dict_value);
}
-// Verifies that the JSON in the input ArrayBuffer contains the provided
-// expected values. Exact matches are required on the fields examined.
-::testing::AssertionResult VerifySymmetricJwk(
- const blink::WebArrayBuffer& json,
+// Verifies the input dictionary contains the expected values. Exact matches are
+// required on the fields examined.
+::testing::AssertionResult VerifyJwk(
+ const scoped_ptr<base::DictionaryValue>& dict,
+ const std::string& kty_expected,
const std::string& alg_expected,
- const std::string& k_expected_hex,
blink::WebCryptoKeyUsageMask use_mask_expected) {
- scoped_ptr<base::DictionaryValue> dict = GetJwkDictionary(json);
- if (!dict.get() || dict->empty())
- return ::testing::AssertionFailure() << "JSON parsing failed";
-
// ---- kty
std::string value_string;
if (!dict->GetString("kty", &value_string))
return ::testing::AssertionFailure() << "Missing 'kty'";
- if (value_string != "oct")
- return ::testing::AssertionFailure()
- << "Expected 'kty' to be 'oct' but found " << value_string;
+ if (value_string != kty_expected)
+ return ::testing::AssertionFailure() << "Expected 'kty' to be "
+ << kty_expected << "but found "
+ << value_string;
// ---- alg
if (!dict->GetString("alg", &value_string))
@@ -568,18 +565,6 @@ scoped_ptr<base::DictionaryValue> GetJwkDictionary(
<< alg_expected << " but found "
<< value_string;
- // ---- k
- if (!dict->GetString("k", &value_string))
- return ::testing::AssertionFailure() << "Missing 'k'";
- std::string k_value;
- if (!webcrypto::Base64DecodeUrlSafe(value_string, &k_value))
- return ::testing::AssertionFailure() << "Base64DecodeUrlSafe(k) failed";
- if (!LowerCaseEqualsASCII(base::HexEncode(k_value.data(), k_value.size()),
- k_expected_hex.c_str())) {
- return ::testing::AssertionFailure() << "Expected 'k' to be "
- << k_expected_hex
- << " but found something different";
- }
// ---- ext
// always expect ext == true in this case
bool ext_value;
@@ -605,6 +590,75 @@ scoped_ptr<base::DictionaryValue> GetJwkDictionary(
return ::testing::AssertionSuccess();
}
+// Verifies that the JSON in the input ArrayBuffer contains the provided
+// expected values. Exact matches are required on the fields examined.
+::testing::AssertionResult VerifySecretJwk(
+ const blink::WebArrayBuffer& json,
+ const std::string& alg_expected,
+ const std::string& k_expected_hex,
+ blink::WebCryptoKeyUsageMask use_mask_expected) {
+ scoped_ptr<base::DictionaryValue> dict = GetJwkDictionary(json);
+ if (!dict.get() || dict->empty())
+ return ::testing::AssertionFailure() << "JSON parsing failed";
+
+ // ---- k
+ std::string value_string;
+ if (!dict->GetString("k", &value_string))
+ return ::testing::AssertionFailure() << "Missing 'k'";
+ std::string k_value;
+ if (!webcrypto::Base64DecodeUrlSafe(value_string, &k_value))
+ return ::testing::AssertionFailure() << "Base64DecodeUrlSafe(k) failed";
+ if (!LowerCaseEqualsASCII(base::HexEncode(k_value.data(), k_value.size()),
+ k_expected_hex.c_str())) {
+ return ::testing::AssertionFailure() << "Expected 'k' to be "
+ << k_expected_hex
+ << " but found something different";
+ }
+
+ return VerifyJwk(dict, "oct", alg_expected, use_mask_expected);
+}
+
+// Verifies that the JSON in the input ArrayBuffer contains the provided
+// expected values. Exact matches are required on the fields examined.
+::testing::AssertionResult VerifyPublicJwk(
+ const blink::WebArrayBuffer& json,
+ const std::string& alg_expected,
+ const std::string& n_expected_hex,
+ const std::string& e_expected_hex,
+ blink::WebCryptoKeyUsageMask use_mask_expected) {
+ scoped_ptr<base::DictionaryValue> dict = GetJwkDictionary(json);
+ if (!dict.get() || dict->empty())
+ return ::testing::AssertionFailure() << "JSON parsing failed";
+
+ // ---- n
+ std::string value_string;
+ if (!dict->GetString("n", &value_string))
+ return ::testing::AssertionFailure() << "Missing 'n'";
+ std::string n_value;
+ if (!webcrypto::Base64DecodeUrlSafe(value_string, &n_value))
+ return ::testing::AssertionFailure() << "Base64DecodeUrlSafe(n) failed";
+ if (base::HexEncode(n_value.data(), n_value.size()) != n_expected_hex) {
+ return ::testing::AssertionFailure() << "'n' does not match the expected "
+ "value";
+ }
+ // TODO(padolph): LowerCaseEqualsASCII() does not work for above!
+
+ // ---- e
+ if (!dict->GetString("e", &value_string))
+ return ::testing::AssertionFailure() << "Missing 'e'";
+ std::string e_value;
+ if (!webcrypto::Base64DecodeUrlSafe(value_string, &e_value))
+ return ::testing::AssertionFailure() << "Base64DecodeUrlSafe(e) failed";
+ if (!LowerCaseEqualsASCII(base::HexEncode(e_value.data(), e_value.size()),
+ e_expected_hex.c_str())) {
+ return ::testing::AssertionFailure() << "Expected 'e' to be "
+ << e_expected_hex
+ << " but found something different";
+ }
+
+ return VerifyJwk(dict, "RSA", alg_expected, use_mask_expected);
+}
+
} // namespace
TEST_F(SharedCryptoTest, CheckAesGcm) {
@@ -1270,6 +1324,85 @@ TEST_F(SharedCryptoTest, ImportJwkOctFailures) {
RestoreJwkOctDictionary(&dict);
}
+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";
+
+ struct TestCase {
+ const blink::WebCryptoAlgorithm algorithm;
+ const blink::WebCryptoKeyUsageMask usage;
+ const char* const jwk_alg;
+ };
+ const TestCase kTests[] = {
+ // RSAES-PKCS1-v1_5
+ {CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5),
+ blink::WebCryptoKeyUsageEncrypt, "RSA1_5"},
+ // RSASSA-PKCS1-v1_5 SHA-1
+ {CreateRsaHashedImportAlgorithm(
+ blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
+ blink::WebCryptoAlgorithmIdSha1),
+ blink::WebCryptoKeyUsageSign, "RS1"},
+ // RSASSA-PKCS1-v1_5 SHA-256
+ {CreateRsaHashedImportAlgorithm(
+ blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
+ blink::WebCryptoAlgorithmIdSha256),
+ blink::WebCryptoKeyUsageSign, "RS256"},
+ // RSASSA-PKCS1-v1_5 SHA-384
+ {CreateRsaHashedImportAlgorithm(
+ blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
+ blink::WebCryptoAlgorithmIdSha384),
+ blink::WebCryptoKeyUsageSign, "RS384"},
+ // RSASSA-PKCS1-v1_5 SHA-512
+ {CreateRsaHashedImportAlgorithm(
+ blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
+ blink::WebCryptoAlgorithmIdSha512),
+ blink::WebCryptoKeyUsageSign, "RS512"}};
+
+ for (size_t test_index = 0; test_index < ARRAYSIZE_UNSAFE(kTests);
+ ++test_index) {
+ SCOPED_TRACE(test_index);
+ const TestCase& test = kTests[test_index];
+
+ // Import the spki to create a public key
+ blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
+ ASSERT_STATUS_SUCCESS(
+ ImportKey(blink::WebCryptoKeyFormatSpki,
+ CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
+ test.algorithm,
+ true,
+ test.usage,
+ &public_key));
+
+ // Export the public key as JWK and verify its contents
+ blink::WebArrayBuffer jwk;
+ ASSERT_STATUS_SUCCESS(
+ ExportKey(blink::WebCryptoKeyFormatJwk, public_key, &jwk));
+ EXPECT_TRUE(VerifyPublicJwk(jwk, test.jwk_alg, n_hex, e_hex, test.usage));
+
+ // Import the JWK back in to create a new key
+ blink::WebCryptoKey public_key2 = blink::WebCryptoKey::createNull();
+ EXPECT_STATUS_SUCCESS(ImportKeyJwk(
+ CryptoData(jwk), test.algorithm, true, test.usage, &public_key2));
+ EXPECT_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.
+ blink::WebArrayBuffer spki;
+ ASSERT_STATUS_SUCCESS(
+ ExportKey(blink::WebCryptoKeyFormatSpki, public_key2, &spki));
+ ExpectCryptoDataMatchesHex(kPublicKeySpkiDerHex, CryptoData(spki));
+ }
+}
+
TEST_F(SharedCryptoTest, MAYBE(ImportJwkRsaFailures)) {
base::DictionaryValue dict;
RestoreJwkRsaDictionary(&dict);
@@ -1588,8 +1721,7 @@ TEST_F(SharedCryptoTest, MAYBE(ImportExportJwkSymmetricKey)) {
// Export the key in JWK format and validate.
ASSERT_STATUS_SUCCESS(ExportKeyJwk(key, &json));
- EXPECT_TRUE(
- VerifySymmetricJwk(json, test.jwk_alg, test.key_hex, test.usage));
+ EXPECT_TRUE(VerifySecretJwk(json, test.jwk_alg, test.key_hex, test.usage));
// Import the JWK-formatted key.
ASSERT_STATUS_SUCCESS(
« no previous file with comments | « content/child/webcrypto/platform_crypto_openssl.cc ('k') | content/child/webcrypto/webcrypto_util.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698