summaryrefslogtreecommitdiff
path: root/ext/node/ops
diff options
context:
space:
mode:
authorDivy Srivastava <dj.srivastava23@gmail.com>2024-08-28 20:33:02 +0530
committerGitHub <noreply@github.com>2024-08-28 15:03:02 +0000
commitb9c144df6fdee9b5e89f6f7787463b366164d622 (patch)
treeeab3c285e67fa0d37ed85792abea9b9e1184ce60 /ext/node/ops
parent044e7c4e63484387ea9066085aeb65142a6b1430 (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.rs78
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,