Index: content/renderer/webcrypto/webcrypto_impl.cc |
diff --git a/content/renderer/webcrypto/webcrypto_impl.cc b/content/renderer/webcrypto/webcrypto_impl.cc |
index c70a42386f20bbac688bdc74a6a3dc6611c99b1d..a977b94602cc74bb9c1ba36af382328703cb9adc 100644 |
--- a/content/renderer/webcrypto/webcrypto_impl.cc |
+++ b/content/renderer/webcrypto/webcrypto_impl.cc |
@@ -148,6 +148,19 @@ bool WebCryptoAlgorithmsConsistent(const blink::WebCryptoAlgorithm& alg1, |
return false; |
} |
+bool GetDecodedUrl64ValueByKey( |
+ const base::DictionaryValue& dict, |
+ const std::string& key, |
+ std::string* decoded) { |
+ std::string value_url64; |
+ if (!dict.GetString(key, &value_url64) || |
+ !webcrypto::Base64DecodeUrlSafe(value_url64, decoded) || |
+ !decoded->size()) { |
+ return false; |
+ } |
+ return true; |
+} |
+ |
} // namespace |
WebCryptoImpl::WebCryptoImpl() { |
@@ -511,6 +524,10 @@ bool WebCryptoImpl::ImportKeyJwk( |
std::string jwk_alg_value; |
if (dict_value->GetString("alg", &jwk_alg_value)) { |
// JWK alg present |
+ |
+ // TODO(padolph): Validate alg vs kty. For example kty="RSA" implies alg can |
+ // only be from the RSA family. |
+ |
const blink::WebCryptoAlgorithm jwk_algorithm = |
jwk_alg_factory.Get().CreateAlgorithmFromName(jwk_alg_value); |
if (jwk_algorithm.isNull()) { |
@@ -559,14 +576,10 @@ bool WebCryptoImpl::ImportKeyJwk( |
// JWK keying material --> ImportKeyInternal() |
if (jwk_kty_value == "oct") { |
- std::string jwk_k_value_url64; |
- if (!dict_value->GetString("k", &jwk_k_value_url64)) |
- return false; |
+ |
std::string jwk_k_value; |
- if (!webcrypto::Base64DecodeUrlSafe(jwk_k_value_url64, &jwk_k_value) || |
- !jwk_k_value.size()) { |
+ if (!GetDecodedUrl64ValueByKey(*dict_value, "k", &jwk_k_value)) |
return false; |
- } |
// TODO(padolph): Some JWK alg ID's embed information about the key length |
// in the alg ID string. For example "A128" implies the JWK carries 128 bits |
@@ -582,8 +595,36 @@ bool WebCryptoImpl::ImportKeyJwk( |
usage_mask, |
key); |
} else if (jwk_kty_value == "RSA") { |
- // TODO(padolph): JWK import RSA public key |
- return false; |
+ |
+ // An RSA public key must have an "n" (modulus) and an "e" (exponent) entry |
+ // in the JWK, while an RSA private key must have those, plus at least a "d" |
+ // (private exponent) entry. |
+ // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18, |
+ // section 6.3. |
+ |
+ // RSA private key import is not currently supported, so fail here if a "d" |
+ // entry is found. |
+ // TODO(padolph): Support RSA private key import. |
+ if (dict_value->HasKey("d")) |
+ return false; |
+ |
+ std::string jwk_n_value; |
+ if (!GetDecodedUrl64ValueByKey(*dict_value, "n", &jwk_n_value)) |
+ return false; |
+ std::string jwk_e_value; |
+ if (!GetDecodedUrl64ValueByKey(*dict_value, "e", &jwk_e_value)) |
+ return false; |
+ |
+ return ImportRsaPublicKeyInternal( |
+ reinterpret_cast<const uint8*>(jwk_n_value.data()), |
+ jwk_n_value.size(), |
+ reinterpret_cast<const uint8*>(jwk_e_value.data()), |
+ jwk_e_value.size(), |
+ algorithm, |
+ extractable, |
+ usage_mask, |
+ key); |
+ |
} else { |
return false; |
} |