diff options
Diffstat (limited to 'ext/node')
-rw-r--r-- | ext/node/lib.rs | 1 | ||||
-rw-r--r-- | ext/node/ops/crypto/keys.rs | 78 | ||||
-rw-r--r-- | ext/node/polyfills/internal/crypto/keys.ts | 4 |
3 files changed, 82 insertions, 1 deletions
diff --git a/ext/node/lib.rs b/ext/node/lib.rs index 1023fced3..bf7db1475 100644 --- a/ext/node/lib.rs +++ b/ext/node/lib.rs @@ -242,6 +242,7 @@ deno_core::extension!(deno_node, ops::crypto::keys::op_node_export_private_key_pem, ops::crypto::keys::op_node_export_public_key_der, ops::crypto::keys::op_node_export_public_key_pem, + ops::crypto::keys::op_node_export_public_key_jwk, ops::crypto::keys::op_node_export_secret_key_b64url, ops::crypto::keys::op_node_export_secret_key, ops::crypto::keys::op_node_generate_dh_group_key_async, 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, diff --git a/ext/node/polyfills/internal/crypto/keys.ts b/ext/node/polyfills/internal/crypto/keys.ts index c2e9d95ee..49a618b65 100644 --- a/ext/node/polyfills/internal/crypto/keys.ts +++ b/ext/node/polyfills/internal/crypto/keys.ts @@ -21,6 +21,7 @@ import { op_node_export_private_key_der, op_node_export_private_key_pem, op_node_export_public_key_der, + op_node_export_public_key_jwk, op_node_export_public_key_pem, op_node_export_secret_key, op_node_export_secret_key_b64url, @@ -786,8 +787,9 @@ export class PublicKeyObject extends AsymmetricKeyObject { export(options: JwkKeyExportOptions | KeyExportOptions<KeyFormat>) { if (options && options.format === "jwk") { - notImplemented("jwk public key export not implemented"); + return op_node_export_public_key_jwk(this[kHandle]); } + const { format, type, |