summaryrefslogtreecommitdiff
path: root/ext/node
diff options
context:
space:
mode:
Diffstat (limited to 'ext/node')
-rw-r--r--ext/node/crypto/mod.rs54
-rw-r--r--ext/node/lib.rs1
-rw-r--r--ext/node/polyfills/internal/crypto/sig.ts72
3 files changed, 105 insertions, 22 deletions
diff --git a/ext/node/crypto/mod.rs b/ext/node/crypto/mod.rs
index f818b96af..b45f36144 100644
--- a/ext/node/crypto/mod.rs
+++ b/ext/node/crypto/mod.rs
@@ -309,7 +309,7 @@ pub fn op_node_sign(
use signature::hazmat::PrehashSigner;
let key = match key_format {
"pem" => RsaPrivateKey::from_pkcs8_pem((&key).try_into()?)
- .map_err(|_| type_error("Invalid RSA key"))?,
+ .map_err(|_| type_error("Invalid RSA private key"))?,
// TODO(kt3k): Support der and jwk formats
_ => {
return Err(type_error(format!(
@@ -353,6 +353,58 @@ pub fn op_node_sign(
}
}
+#[op]
+fn op_node_verify(
+ digest: &[u8],
+ digest_type: &str,
+ key: StringOrBuffer,
+ key_type: &str,
+ key_format: &str,
+ signature: &[u8],
+) -> Result<bool, AnyError> {
+ match key_type {
+ "rsa" => {
+ use rsa::pkcs1v15::VerifyingKey;
+ use signature::hazmat::PrehashVerifier;
+ let key = match key_format {
+ "pem" => RsaPublicKey::from_public_key_pem((&key).try_into()?)
+ .map_err(|_| type_error("Invalid RSA public key"))?,
+ // TODO(kt3k): Support der and jwk formats
+ _ => {
+ return Err(type_error(format!(
+ "Unsupported key format: {}",
+ key_format
+ )))
+ }
+ };
+ Ok(match digest_type {
+ "sha224" => VerifyingKey::<sha2::Sha224>::new_with_prefix(key)
+ .verify_prehash(digest, &signature.to_vec().try_into()?)
+ .is_ok(),
+ "sha256" => VerifyingKey::<sha2::Sha256>::new_with_prefix(key)
+ .verify_prehash(digest, &signature.to_vec().try_into()?)
+ .is_ok(),
+ "sha384" => VerifyingKey::<sha2::Sha384>::new_with_prefix(key)
+ .verify_prehash(digest, &signature.to_vec().try_into()?)
+ .is_ok(),
+ "sha512" => VerifyingKey::<sha2::Sha512>::new_with_prefix(key)
+ .verify_prehash(digest, &signature.to_vec().try_into()?)
+ .is_ok(),
+ _ => {
+ return Err(type_error(format!(
+ "Unknown digest algorithm: {}",
+ digest_type
+ )))
+ }
+ })
+ }
+ _ => Err(type_error(format!(
+ "Verifying with {} keys is not supported yet",
+ key_type
+ ))),
+ }
+}
+
fn pbkdf2_sync(
password: &[u8],
salt: &[u8],
diff --git a/ext/node/lib.rs b/ext/node/lib.rs
index f4b4d0a39..b09cb1c90 100644
--- a/ext/node/lib.rs
+++ b/ext/node/lib.rs
@@ -194,6 +194,7 @@ deno_core::extension!(deno_node,
crypto::op_node_generate_secret,
crypto::op_node_generate_secret_async,
crypto::op_node_sign,
+ crypto::op_node_verify,
crypto::op_node_random_int,
crypto::x509::op_node_x509_parse,
crypto::x509::op_node_x509_ca,
diff --git a/ext/node/polyfills/internal/crypto/sig.ts b/ext/node/polyfills/internal/crypto/sig.ts
index e49128b1e..2996cb2ca 100644
--- a/ext/node/polyfills/internal/crypto/sig.ts
+++ b/ext/node/polyfills/internal/crypto/sig.ts
@@ -67,7 +67,7 @@ export class Sign extends Writable {
}
sign(
- privateKey: KeyLike | SignKeyObjectInput | SignPrivateKeyInput,
+ privateKey: BinaryLike | SignKeyObjectInput | SignPrivateKeyInput,
encoding?: BinaryToTextEncoding,
): Buffer | string {
let keyData: Uint8Array;
@@ -75,7 +75,8 @@ export class Sign extends Writable {
let keyFormat: KeyFormat;
if (typeof privateKey === "string" || isArrayBufferView(privateKey)) {
// if the key is BinaryLike, interpret it as a PEM encoded RSA key
- keyData = privateKey;
+ // deno-lint-ignore no-explicit-any
+ keyData = privateKey as any;
keyType = "rsa";
keyFormat = "pem";
} else {
@@ -103,35 +104,64 @@ export class Sign extends Writable {
}
export class Verify extends Writable {
+ hash: Hash;
+ #digestType: string;
+
constructor(algorithm: string, _options?: WritableOptions) {
validateString(algorithm, "algorithm");
- super();
+ super({
+ write(chunk, enc, callback) {
+ this.update(chunk, enc);
+ callback();
+ },
+ });
+
+ algorithm = algorithm.toLowerCase();
- notImplemented("crypto.Verify");
+ if (algorithm.startsWith("rsa-")) {
+ // Allows RSA-[digest_algorithm] as a valid algorithm
+ algorithm = algorithm.slice(4);
+ }
+
+ this.#digestType = algorithm;
+ this.hash = createHash(this.#digestType);
}
- update(data: BinaryLike): this;
- update(data: string, inputEncoding: Encoding): this;
- update(_data: BinaryLike, _inputEncoding?: string): this {
- notImplemented("crypto.Sign.prototype.update");
+ update(data: BinaryLike, encoding?: string): this {
+ this.hash.update(data, encoding);
+ return this;
}
verify(
- object: KeyLike | VerifyKeyObjectInput | VerifyPublicKeyInput,
- signature: ArrayBufferView,
- ): boolean;
- verify(
- object: KeyLike | VerifyKeyObjectInput | VerifyPublicKeyInput,
- signature: string,
- signatureEncoding?: BinaryToTextEncoding,
- ): boolean;
- verify(
- _object: KeyLike | VerifyKeyObjectInput | VerifyPublicKeyInput,
- _signature: ArrayBufferView | string,
- _signatureEncoding?: BinaryToTextEncoding,
+ publicKey: BinaryLike | VerifyKeyObjectInput | VerifyPublicKeyInput,
+ signature: BinaryLike,
+ encoding?: BinaryToTextEncoding,
): boolean {
- notImplemented("crypto.Sign.prototype.sign");
+ let keyData: BinaryLike;
+ let keyType: KeyType;
+ let keyFormat: KeyFormat;
+ if (typeof publicKey === "string" || isArrayBufferView(publicKey)) {
+ // if the key is BinaryLike, interpret it as a PEM encoded RSA key
+ // deno-lint-ignore no-explicit-any
+ keyData = publicKey as any;
+ keyType = "rsa";
+ keyFormat = "pem";
+ } else {
+ // TODO(kt3k): Add support for the case when publicKey is a KeyObject,
+ // CryptoKey, etc
+ notImplemented(
+ "crypto.Verify.prototype.verify with non BinaryLike input",
+ );
+ }
+ return ops.op_node_verify(
+ this.hash.digest(),
+ this.#digestType,
+ keyData!,
+ keyType,
+ keyFormat,
+ Buffer.from(signature, encoding),
+ );
}
}