summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
Diffstat (limited to 'ext')
-rw-r--r--ext/node/Cargo.toml1
-rw-r--r--ext/node/crypto/mod.rs58
-rw-r--r--ext/node/lib.rs2
-rw-r--r--ext/node/polyfills/internal/crypto/hkdf.ts28
4 files changed, 81 insertions, 8 deletions
diff --git a/ext/node/Cargo.toml b/ext/node/Cargo.toml
index 4dbc79b9e..e74cf3805 100644
--- a/ext/node/Cargo.toml
+++ b/ext/node/Cargo.toml
@@ -20,6 +20,7 @@ deno_core.workspace = true
digest = { version = "0.10.5", features = ["core-api", "std"] }
ecb.workspace = true
hex.workspace = true
+hkdf.workspace = true
idna = "0.3.0"
indexmap.workspace = true
libz-sys = { version = "1.1.8", features = ["static"] }
diff --git a/ext/node/crypto/mod.rs b/ext/node/crypto/mod.rs
index 499e99fea..adacdf6d6 100644
--- a/ext/node/crypto/mod.rs
+++ b/ext/node/crypto/mod.rs
@@ -7,6 +7,7 @@ use deno_core::OpState;
use deno_core::ResourceId;
use deno_core::StringOrBuffer;
use deno_core::ZeroCopyBuf;
+use hkdf::Hkdf;
use num_bigint::BigInt;
use rand::Rng;
use std::future::Future;
@@ -419,3 +420,60 @@ pub async fn op_node_generate_secret_async(len: i32) -> ZeroCopyBuf {
.await
.unwrap()
}
+
+fn hkdf_sync(
+ hash: &str,
+ ikm: &[u8],
+ salt: &[u8],
+ info: &[u8],
+ okm: &mut [u8],
+) -> Result<(), AnyError> {
+ macro_rules! hkdf {
+ ($hash:ty) => {{
+ let hk = Hkdf::<$hash>::new(Some(salt), ikm);
+ hk.expand(info, okm)
+ .map_err(|_| type_error("HKDF-Expand failed"))?;
+ }};
+ }
+
+ match hash {
+ "md4" => hkdf!(md4::Md4),
+ "md5" => hkdf!(md5::Md5),
+ "ripemd160" => hkdf!(ripemd::Ripemd160),
+ "sha1" => hkdf!(sha1::Sha1),
+ "sha224" => hkdf!(sha2::Sha224),
+ "sha256" => hkdf!(sha2::Sha256),
+ "sha384" => hkdf!(sha2::Sha384),
+ "sha512" => hkdf!(sha2::Sha512),
+ _ => return Err(type_error("Unknown digest")),
+ }
+
+ Ok(())
+}
+
+#[op]
+pub fn op_node_hkdf(
+ hash: &str,
+ ikm: &[u8],
+ salt: &[u8],
+ info: &[u8],
+ okm: &mut [u8],
+) -> Result<(), AnyError> {
+ hkdf_sync(hash, ikm, salt, info, okm)
+}
+
+#[op]
+pub async fn op_node_hkdf_async(
+ hash: String,
+ ikm: ZeroCopyBuf,
+ salt: ZeroCopyBuf,
+ info: ZeroCopyBuf,
+ okm_len: usize,
+) -> Result<ZeroCopyBuf, AnyError> {
+ tokio::task::spawn_blocking(move || {
+ let mut okm = vec![0u8; okm_len];
+ hkdf_sync(&hash, &ikm, &salt, &info, &mut okm)?;
+ Ok(okm.into())
+ })
+ .await?
+}
diff --git a/ext/node/lib.rs b/ext/node/lib.rs
index 478efaf27..bf947f5e8 100644
--- a/ext/node/lib.rs
+++ b/ext/node/lib.rs
@@ -189,6 +189,8 @@ deno_core::extension!(deno_node,
crypto::op_node_check_prime_bytes_async,
crypto::op_node_pbkdf2,
crypto::op_node_pbkdf2_async,
+ crypto::op_node_hkdf,
+ crypto::op_node_hkdf_async,
crypto::op_node_generate_secret,
crypto::op_node_generate_secret_async,
crypto::op_node_sign,
diff --git a/ext/node/polyfills/internal/crypto/hkdf.ts b/ext/node/polyfills/internal/crypto/hkdf.ts
index deeba102f..fb26053df 100644
--- a/ext/node/polyfills/internal/crypto/hkdf.ts
+++ b/ext/node/polyfills/internal/crypto/hkdf.ts
@@ -7,6 +7,7 @@ import {
validateString,
} from "ext:deno_node/internal/validators.mjs";
import {
+ ERR_CRYPTO_INVALID_DIGEST,
ERR_INVALID_ARG_TYPE,
ERR_OUT_OF_RANGE,
hideStackFrames,
@@ -26,17 +27,19 @@ import {
isAnyArrayBuffer,
isArrayBufferView,
} from "ext:deno_node/internal/util/types.ts";
-import { notImplemented } from "ext:deno_node/_utils.ts";
-const validateParameters = hideStackFrames((hash, key, salt, info, length) => {
- key = prepareKey(key);
- salt = toBuf(salt);
- info = toBuf(info);
+const { core } = globalThis.__bootstrap;
+const { ops } = core;
+const validateParameters = hideStackFrames((hash, key, salt, info, length) => {
validateString(hash, "digest");
+ key = new Uint8Array(prepareKey(key));
validateByteSource(salt, "salt");
validateByteSource(info, "info");
+ salt = new Uint8Array(toBuf(salt));
+ info = new Uint8Array(toBuf(info));
+
validateInteger(length, "length", 0, kMaxLength);
if (info.byteLength > 1024) {
@@ -91,7 +94,7 @@ export function hkdf(
salt: BinaryLike,
info: BinaryLike,
length: number,
- callback: (err: Error | null, derivedKey: ArrayBuffer) => void,
+ callback: (err: Error | null, derivedKey: ArrayBuffer | undefined) => void,
) {
({ hash, key, salt, info, length } = validateParameters(
hash,
@@ -103,7 +106,9 @@ export function hkdf(
validateFunction(callback, "callback");
- notImplemented("crypto.hkdf");
+ core.opAsync("op_node_hkdf_async", hash, key, salt, info, length)
+ .then((okm) => callback(null, okm.buffer))
+ .catch((err) => callback(new ERR_CRYPTO_INVALID_DIGEST(err), undefined));
}
export function hkdfSync(
@@ -121,7 +126,14 @@ export function hkdfSync(
length,
));
- notImplemented("crypto.hkdfSync");
+ const okm = new Uint8Array(length);
+ try {
+ ops.op_node_hkdf(hash, key, salt, info, okm);
+ } catch (e) {
+ throw new ERR_CRYPTO_INVALID_DIGEST(e);
+ }
+
+ return okm.buffer;
}
export default {