Index: content/child/webcrypto/jwk.cc |
diff --git a/content/child/webcrypto/jwk.cc b/content/child/webcrypto/jwk.cc |
index 8e9e11c5de087f42a44047ba9390692d379640f0..0f5ab6777424881bba41cd90b5d219dae63607e4 100644 |
--- a/content/child/webcrypto/jwk.cc |
+++ b/content/child/webcrypto/jwk.cc |
@@ -92,6 +92,9 @@ class JwkAlgorithmRegistry { |
alg_to_info_["HS512"] = |
JwkAlgorithmInfo(&BindAlgorithmId<CreateHmacImportAlgorithm, |
blink::WebCryptoAlgorithmIdSha512>); |
+ alg_to_info_["RS1"] = |
+ JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaSsaImportAlgorithm, |
+ blink::WebCryptoAlgorithmIdSha1>); |
alg_to_info_["RS256"] = |
JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaSsaImportAlgorithm, |
blink::WebCryptoAlgorithmIdSha256>); |
@@ -295,6 +298,32 @@ void WriteSecretKey(const blink::WebArrayBuffer& raw_key, |
jwk_dict->SetString("k", Base64EncodeUrlSafe(key_str)); |
} |
+// Writes an RSA public key to a JWK dictionary |
+void WriteRsaPublicKey(const blink::WebArrayBuffer& modulus, |
+ const blink::WebArrayBuffer& public_exponent, |
+ base::DictionaryValue* jwk_dict) { |
+ DCHECK(jwk_dict); |
+ jwk_dict->SetString("kty", "RSA"); |
+ |
+ DCHECK(!modulus.isNull()); |
+ DCHECK(modulus.data()); |
+ DCHECK(modulus.byteLength()); |
+ const unsigned int modulus_length_bytes = modulus.byteLength(); |
+ const base::StringPiece modulus_str(static_cast<const char*>(modulus.data()), |
eroman
2014/03/21 02:30:51
There are now 3 places in the code which do this i
padolph
2014/03/24 04:28:28
Done.
|
+ modulus_length_bytes); |
+ jwk_dict->SetString("n", Base64EncodeUrlSafe(modulus_str)); |
+ |
+ DCHECK(!public_exponent.isNull()); |
eroman
2014/03/21 02:30:51
my preference is to put all input dchecks at the t
padolph
2014/03/24 04:28:28
Done.
|
+ DCHECK(public_exponent.data()); |
+ DCHECK(public_exponent.byteLength()); |
+ const unsigned int public_exponent_length_bytes = |
+ public_exponent.byteLength(); |
+ const base::StringPiece public_exponent_str( |
+ static_cast<const char*>(public_exponent.data()), |
+ public_exponent_length_bytes); |
+ jwk_dict->SetString("e", Base64EncodeUrlSafe(public_exponent_str)); |
+} |
+ |
// Writes a Web Crypto usage mask to a JWK dictionary. |
void WriteKeyOps(blink::WebCryptoKeyUsageMask key_usages, |
base::DictionaryValue* jwk_dict) { |
@@ -370,15 +399,61 @@ Status WriteAlg(const blink::WebCryptoKeyAlgorithm& algorithm, |
break; |
} |
case blink::WebCryptoKeyAlgorithmParamsTypeRsa: |
+ switch (algorithm.id()) { |
+ case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: |
+ jwk_dict->SetString("alg", "RSA1_5"); |
+ break; |
+ case blink::WebCryptoAlgorithmIdRsaOaep: |
eroman
2014/03/21 02:30:51
I don't believe this is correct.
In WebCrypto RSA
padolph
2014/03/24 04:28:28
Done.
|
+ jwk_dict->SetString("alg", "RSA-OAEP"); |
+ break; |
+ default: |
+ NOTREACHED(); |
+ return Status::ErrorUnexpected(); |
+ } |
+ break; |
case blink::WebCryptoKeyAlgorithmParamsTypeRsaHashed: |
- // TODO(padolph): Handle RSA key |
- return Status::ErrorUnsupported(); |
+ switch (algorithm.rsaHashedParams()->hash().id()) { |
+ case blink::WebCryptoAlgorithmIdSha1: |
+ jwk_dict->SetString("alg", "RS1"); |
+ break; |
+ case blink::WebCryptoAlgorithmIdSha256: |
+ jwk_dict->SetString("alg", "RS256"); |
+ break; |
+ case blink::WebCryptoAlgorithmIdSha384: |
+ jwk_dict->SetString("alg", "RS384"); |
+ break; |
+ case blink::WebCryptoAlgorithmIdSha512: |
+ jwk_dict->SetString("alg", "RS512"); |
+ break; |
+ default: |
+ NOTREACHED(); |
+ return Status::ErrorUnexpected(); |
+ } |
+ break; |
default: |
return Status::ErrorUnsupported(); |
} |
return Status::Success(); |
} |
+bool IsRsaPublicKey(const blink::WebCryptoKey& key) { |
+ if (key.type() != blink::WebCryptoKeyTypePublic) |
+ return false; |
+ const blink::WebCryptoAlgorithmId algorithm_id = key.algorithm().id(); |
+ return algorithm_id == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 || |
+ algorithm_id == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 || |
+ algorithm_id == blink::WebCryptoAlgorithmIdRsaOaep; |
+} |
+ |
+// TODO(padolph): This function is duplicated in shared_crypto.cc |
+Status ToPlatformPublicKey(const blink::WebCryptoKey& key, |
+ platform::PublicKey** out) { |
+ *out = static_cast<platform::Key*>(key.handle())->AsPublicKey(); |
+ if (!*out) |
+ return Status::ErrorUnexpectedKeyType(); |
+ return Status::Success(); |
+} |
+ |
} // namespace |
Status ImportKeyJwk(const CryptoData& key_data, |
@@ -478,6 +553,7 @@ Status ImportKeyJwk(const CryptoData& key_data, |
// | "HS256" | HMAC using SHA-256 hash algorithm | |
// | "HS384" | HMAC using SHA-384 hash algorithm | |
// | "HS512" | HMAC using SHA-512 hash algorithm | |
+ // | "RS1" | RSASSA using SHA-1 hash algorithm |
// | "RS256" | RSASSA using SHA-256 hash algorithm | |
// | "RS384" | RSASSA using SHA-384 hash algorithm | |
// | "RS512" | RSASSA using SHA-512 hash algorithm | |
@@ -714,23 +790,45 @@ Status ImportKeyJwk(const CryptoData& key_data, |
Status ExportKeyJwk(const blink::WebCryptoKey& key, |
blink::WebArrayBuffer* buffer) { |
+ DCHECK(key.extractable()); |
base::DictionaryValue jwk_dict; |
Status status = Status::Error(); |
- blink::WebArrayBuffer exported_key; |
- if (key.type() == blink::WebCryptoKeyTypeSecret) { |
- status = ExportKey(blink::WebCryptoKeyFormatRaw, key, &exported_key); |
- if (status.IsError()) |
- return status; |
- WriteSecretKey(exported_key, &jwk_dict); |
- } else { |
- // TODO(padolph): Handle asymmetric keys, at least the public key. |
- return Status::ErrorUnsupported(); |
+ unsigned int key_length_bytes = 0; |
+ switch (key.type()) { |
+ case blink::WebCryptoKeyTypeSecret: { |
+ blink::WebArrayBuffer exported_key; |
+ status = ExportKey(blink::WebCryptoKeyFormatRaw, key, &exported_key); |
+ if (status.IsError()) |
+ return status; |
+ key_length_bytes = exported_key.byteLength(); |
+ WriteSecretKey(exported_key, &jwk_dict); |
+ break; |
+ } |
+ case blink::WebCryptoKeyTypePublic: { |
+ // Currently only RSA public key export is supported. |
+ if (!IsRsaPublicKey(key)) |
+ return Status::ErrorUnsupported(); |
+ platform::PublicKey* public_key; |
+ status = ToPlatformPublicKey(key, &public_key); |
+ if (status.IsError()) |
+ return status; |
+ blink::WebArrayBuffer modulus, public_exponent; |
+ status = |
+ platform::ExportRsaPublicKey(public_key, &modulus, &public_exponent); |
+ if (status.IsError()) |
+ return status; |
+ WriteRsaPublicKey(modulus, public_exponent, &jwk_dict); |
+ break; |
+ } |
+ case blink::WebCryptoKeyTypePrivate: // TODO(padolph) |
+ default: |
+ return Status::ErrorUnsupported(); |
} |
WriteKeyOps(key.usages(), &jwk_dict); |
WriteExt(key.extractable(), &jwk_dict); |
- status = WriteAlg(key.algorithm(), exported_key.byteLength(), &jwk_dict); |
+ status = WriteAlg(key.algorithm(), key_length_bytes, &jwk_dict); |
if (status.IsError()) |
return status; |