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 6995b48c4b07868b63f7df252dc5f99df9611e5d..556e721d9a3b19a2517cbed583080db5108fa506 100644 |
--- a/content/child/webcrypto/shared_crypto_unittest.cc |
+++ b/content/child/webcrypto/shared_crypto_unittest.cc |
@@ -542,23 +542,20 @@ scoped_ptr<base::DictionaryValue> GetJwkDictionary( |
// Verifies that the JSON in the input ArrayBuffer contains the provided |
eroman
2014/03/24 22:05:51
This comment needs to be updated as well (no longe
padolph
2014/03/25 01:10:28
Done.
|
// expected values. Exact matches are required on the fields examined. |
-::testing::AssertionResult VerifySymmetricJwk( |
- const blink::WebArrayBuffer& json, |
+::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! |
eroman
2014/03/24 22:05:51
Not sure I follow, can you explain this comment? S
padolph
2014/03/25 01:10:28
LowerCaseEqual() did not behave properly in this c
eroman
2014/03/25 01:21:12
I would be very surprised if LowerCaseEqual() was
|
+ |
+ // ---- 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,77 @@ 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 |
+ {CreateRsaSsaImportAlgorithm(blink::WebCryptoAlgorithmIdSha1), |
+ blink::WebCryptoKeyUsageSign, "RS1"}, |
+ // RSASSA-PKCS1-v1_5 SHA-256 |
+ {CreateRsaSsaImportAlgorithm(blink::WebCryptoAlgorithmIdSha256), |
+ blink::WebCryptoKeyUsageSign, "RS256"}, |
+ // RSASSA-PKCS1-v1_5 SHA-384 |
+ {CreateRsaSsaImportAlgorithm(blink::WebCryptoAlgorithmIdSha384), |
+ blink::WebCryptoKeyUsageSign, "RS384"}, |
+ // RSASSA-PKCS1-v1_5 SHA-512 |
+ {CreateRsaSsaImportAlgorithm(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 +1713,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( |