diff options
author | Divy Srivastava <dj.srivastava23@gmail.com> | 2024-08-28 20:33:02 +0530 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-08-28 15:03:02 +0000 |
commit | b9c144df6fdee9b5e89f6f7787463b366164d622 (patch) | |
tree | eab3c285e67fa0d37ed85792abea9b9e1184ce60 /ext/node/ops | |
parent | 044e7c4e63484387ea9066085aeb65142a6b1430 (diff) |
fix(ext/node): export JWK public key (#25239)
Fixes https://github.com/denoland/deno/issues/18928
Signed-off-by: Divy Srivastava <dj.srivastava23@gmail.com>
Diffstat (limited to 'ext/node/ops')
-rw-r--r-- | ext/node/ops/crypto/keys.rs | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/ext/node/ops/crypto/keys.rs b/ext/node/ops/crypto/keys.rs index eccd08564..7334fb8eb 100644 --- a/ext/node/ops/crypto/keys.rs +++ b/ext/node/ops/crypto/keys.rs @@ -235,6 +235,16 @@ impl RsaPssPrivateKey { } } +impl EcPublicKey { + pub fn to_jwk(&self) -> Result<elliptic_curve::JwkEcKey, AnyError> { + match self { + EcPublicKey::P224(_) => Err(type_error("Unsupported JWK EC curve: P224")), + EcPublicKey::P256(key) => Ok(key.to_jwk()), + EcPublicKey::P384(key) => Ok(key.to_jwk()), + } + } +} + impl EcPrivateKey { /// Derives the public key from the private key. pub fn to_public_key(&self) -> EcPublicKey { @@ -848,7 +858,63 @@ fn parse_rsa_pss_params( Ok(details) } +use base64::prelude::BASE64_URL_SAFE_NO_PAD; + +fn bytes_to_b64(bytes: &[u8]) -> String { + BASE64_URL_SAFE_NO_PAD.encode(bytes) +} + impl AsymmetricPublicKey { + fn export_jwk(&self) -> Result<deno_core::serde_json::Value, AnyError> { + match self { + AsymmetricPublicKey::Ec(key) => { + let jwk = key.to_jwk()?; + Ok(deno_core::serde_json::json!(jwk)) + } + AsymmetricPublicKey::X25519(key) => { + let bytes = key.as_bytes(); + let jwk = deno_core::serde_json::json!({ + "kty": "OKP", + "crv": "X25519", + "x": bytes_to_b64(bytes), + }); + Ok(jwk) + } + AsymmetricPublicKey::Ed25519(key) => { + let bytes = key.to_bytes(); + let jwk = deno_core::serde_json::json!({ + "kty": "OKP", + "crv": "Ed25519", + "x": bytes_to_b64(&bytes), + }); + Ok(jwk) + } + AsymmetricPublicKey::Rsa(key) => { + let n = key.n(); + let e = key.e(); + + let jwk = deno_core::serde_json::json!({ + "kty": "RSA", + "n": bytes_to_b64(&n.to_bytes_be()), + "e": bytes_to_b64(&e.to_bytes_be()), + }); + Ok(jwk) + } + AsymmetricPublicKey::RsaPss(key) => { + let n = key.key.n(); + let e = key.key.e(); + + let jwk = deno_core::serde_json::json!({ + "kty": "RSA", + "n": bytes_to_b64(&n.to_bytes_be()), + "e": bytes_to_b64(&e.to_bytes_be()), + }); + Ok(jwk) + } + _ => Err(type_error("jwk export not implemented for this key type")), + } + } + fn export_der(&self, typ: &str) -> Result<Box<[u8]>, AnyError> { match typ { "pkcs1" => match self { @@ -1849,6 +1915,18 @@ pub fn op_node_export_secret_key_b64url( } #[op2] +#[serde] +pub fn op_node_export_public_key_jwk( + #[cppgc] handle: &KeyObjectHandle, +) -> Result<deno_core::serde_json::Value, AnyError> { + let public_key = handle + .as_public_key() + .ok_or_else(|| type_error("key is not an asymmetric public key"))?; + + public_key.export_jwk() +} + +#[op2] #[string] pub fn op_node_export_public_key_pem( #[cppgc] handle: &KeyObjectHandle, |