summaryrefslogtreecommitdiff
path: root/ext/node/ops/crypto/mod.rs
diff options
context:
space:
mode:
authorLuca Casonato <hello@lcas.dev>2024-08-08 11:35:29 +0200
committerGitHub <noreply@github.com>2024-08-08 15:05:29 +0530
commit93d479252b5a18e6e782c74b808240bd3ef036bd (patch)
tree4c8b83797fb0e30d1ce3fcebad3fbde6cf33ef1d /ext/node/ops/crypto/mod.rs
parent507e5b74ff21161ba8bd947d7d9cee317c0af379 (diff)
fix(ext/node): add crypto.diffieHellman (#24938)
Co-authored-by: Divy Srivastava <dj.srivastava23@gmail.com> Closes #21806
Diffstat (limited to 'ext/node/ops/crypto/mod.rs')
-rw-r--r--ext/node/ops/crypto/mod.rs86
1 files changed, 86 insertions, 0 deletions
diff --git a/ext/node/ops/crypto/mod.rs b/ext/node/ops/crypto/mod.rs
index 07d901cbc..567affd52 100644
--- a/ext/node/ops/crypto/mod.rs
+++ b/ext/node/ops/crypto/mod.rs
@@ -10,6 +10,10 @@ use deno_core::StringOrBuffer;
use deno_core::ToJsBuffer;
use elliptic_curve::sec1::ToEncodedPoint;
use hkdf::Hkdf;
+use keys::AsymmetricPrivateKey;
+use keys::AsymmetricPublicKey;
+use keys::EcPrivateKey;
+use keys::EcPublicKey;
use keys::KeyObjectHandle;
use num_bigint::BigInt;
use num_bigint_dig::BigUint;
@@ -34,6 +38,7 @@ mod dh;
mod digest;
pub mod keys;
mod md5_sha1;
+mod pkcs3;
mod primes;
mod sign;
pub mod x509;
@@ -839,3 +844,84 @@ pub async fn op_node_gen_prime_async(
) -> Result<ToJsBuffer, AnyError> {
Ok(spawn_blocking(move || gen_prime(size)).await?)
}
+
+#[op2]
+#[buffer]
+pub fn op_node_diffie_hellman(
+ #[cppgc] private: &KeyObjectHandle,
+ #[cppgc] public: &KeyObjectHandle,
+) -> Result<Box<[u8]>, AnyError> {
+ let private = private
+ .as_private_key()
+ .ok_or_else(|| type_error("Expected private key"))?;
+ let public = public
+ .as_public_key()
+ .ok_or_else(|| type_error("Expected public key"))?;
+
+ let res = match (private, &*public) {
+ (
+ AsymmetricPrivateKey::Ec(EcPrivateKey::P224(private)),
+ AsymmetricPublicKey::Ec(EcPublicKey::P224(public)),
+ ) => p224::ecdh::diffie_hellman(
+ private.to_nonzero_scalar(),
+ public.as_affine(),
+ )
+ .raw_secret_bytes()
+ .to_vec()
+ .into_boxed_slice(),
+ (
+ AsymmetricPrivateKey::Ec(EcPrivateKey::P256(private)),
+ AsymmetricPublicKey::Ec(EcPublicKey::P256(public)),
+ ) => p256::ecdh::diffie_hellman(
+ private.to_nonzero_scalar(),
+ public.as_affine(),
+ )
+ .raw_secret_bytes()
+ .to_vec()
+ .into_boxed_slice(),
+ (
+ AsymmetricPrivateKey::Ec(EcPrivateKey::P384(private)),
+ AsymmetricPublicKey::Ec(EcPublicKey::P384(public)),
+ ) => p384::ecdh::diffie_hellman(
+ private.to_nonzero_scalar(),
+ public.as_affine(),
+ )
+ .raw_secret_bytes()
+ .to_vec()
+ .into_boxed_slice(),
+ (
+ AsymmetricPrivateKey::X25519(private),
+ AsymmetricPublicKey::X25519(public),
+ ) => private
+ .diffie_hellman(public)
+ .to_bytes()
+ .into_iter()
+ .collect(),
+ (AsymmetricPrivateKey::Dh(private), AsymmetricPublicKey::Dh(public)) => {
+ if private.params.prime != public.params.prime
+ || private.params.base != public.params.base
+ {
+ return Err(type_error("DH parameters mismatch"));
+ }
+
+ // OSIP - Octet-String-to-Integer primitive
+ let public_key = public.key.clone().into_vec();
+ let pubkey = BigUint::from_bytes_be(&public_key);
+
+ // Exponentiation (z = y^x mod p)
+ let prime = BigUint::from_bytes_be(private.params.prime.as_bytes());
+ let private_key = private.key.clone().into_vec();
+ let private_key = BigUint::from_bytes_be(&private_key);
+ let shared_secret = pubkey.modpow(&private_key, &prime);
+
+ shared_secret.to_bytes_be().into()
+ }
+ _ => {
+ return Err(type_error(
+ "Unsupported key type for diffie hellman, or key type mismatch",
+ ))
+ }
+ };
+
+ Ok(res)
+}