Repository: denoland/deno
Pull request: fix(ext/node): deprecate Hash and Hmac constructors

This PR deprecates `Hash` and `Hmac` constructors. This enables `parallel/test-crypto-hash.js` test case.

ref:
- https://nodejs.org/api/deprecations.html#DEP0179
- https://nodejs.org/api/deprecations.html#DEP0181

towards #29637 

Changed files:
filename: ext/node/polyfills/crypto.ts
patch: @@ -143,8 +143,8 @@ import type {
 import {
   createHash,
   getHashes,
-  Hash,
-  Hmac,
+  Hash as Hash_,
+  Hmac as Hmac_,
 } from "ext:deno_node/internal/crypto/hash.ts";
 import { X509Certificate } from "ext:deno_node/internal/crypto/x509.ts";
 import type {
@@ -170,10 +170,22 @@ import {
 import { isArrayBufferView } from "ext:deno_node/internal/util/types.ts";
 import { validateString } from "ext:deno_node/internal/validators.mjs";
 import { crypto as webcrypto } from "ext:deno_crypto/00_crypto.js";
+import { deprecate } from "node:util";
 
 const subtle = webcrypto.subtle;
 const fipsForced = getOptionValue("--force-fips");
 
+const Hash = deprecate(
+  Hash_,
+  "crypto.Hash constructor is deprecated.",
+  "DEP0179",
+);
+const Hmac = deprecate(
+  Hmac_,
+  "crypto.Hmac constructor is deprecated.",
+  "DEP0181",
+);
+
 function getRandomValues(typedArray) {
   return webcrypto.getRandomValues(typedArray);
 }

filename: tests/node_compat/config.jsonc
patch: @@ -43,7 +43,6 @@
       "test-console-formatTime.js",
       "test-console-instance.js",
       "test-console-tty-colors.js",
-      "test-crypto-hash.js",
       "test-crypto-hmac.js",
       "test-crypto-keygen-missing-oid.js",
       "test-crypto-no-algorithm.js",

filename: tests/node_compat/test/parallel/test-crypto-hash.js
patch: @@ -2,18 +2,20 @@
 // deno-lint-ignore-file
 
 // Copyright Joyent and Node contributors. All rights reserved. MIT license.
-// Taken from Node 20.11.1
+// Taken from Node 23.9.0
 // This file is automatically generated by `tests/node_compat/runner/setup.ts`. Do not modify this file manually.
 
 'use strict';
 const common = require('../common');
-if (!common.hasCrypto)
+if (!common.hasCrypto) {
   common.skip('missing crypto');
+}
 
 const assert = require('assert');
 const crypto = require('crypto');
 const fs = require('fs');
 
+const { hasOpenSSL } = require('../common/crypto');
 const fixtures = require('../common/fixtures');
 
 let cryptoType;
@@ -46,7 +48,7 @@ a8.write('');
 a8.end();
 a8 = a8.read();
 
-if (!common.hasFipsCrypto) {
+if (!crypto.getFips()) {
   cryptoType = 'md5';
   digest = 'latin1';
   const a0 = crypto.createHash(cryptoType).update('Test123').digest(digest);
@@ -189,19 +191,21 @@ assert.throws(
 
 // Test XOF hash functions and the outputLength option.
 {
-  // Default outputLengths.
-  assert.strictEqual(crypto.createHash('shake128').digest('hex'),
-                     '7f9c2ba4e88f827d616045507605853e');
-  assert.strictEqual(crypto.createHash('shake128', null).digest('hex'),
-                     '7f9c2ba4e88f827d616045507605853e');
-  assert.strictEqual(crypto.createHash('shake256').digest('hex'),
-                     '46b9dd2b0ba88d13233b3feb743eeb24' +
-                     '3fcd52ea62b81b82b50c27646ed5762f');
-  assert.strictEqual(crypto.createHash('shake256', { outputLength: 0 })
-                           .copy()  // Default outputLength.
-                           .digest('hex'),
-                     '46b9dd2b0ba88d13233b3feb743eeb24' +
-                     '3fcd52ea62b81b82b50c27646ed5762f');
+  // Default outputLengths. Since OpenSSL 3.4 an outputLength is mandatory
+  if (!hasOpenSSL(3, 4)) {
+    assert.strictEqual(crypto.createHash('shake128').digest('hex'),
+                       '7f9c2ba4e88f827d616045507605853e');
+    assert.strictEqual(crypto.createHash('shake128', null).digest('hex'),
+                       '7f9c2ba4e88f827d616045507605853e');
+    assert.strictEqual(crypto.createHash('shake256').digest('hex'),
+                       '46b9dd2b0ba88d13233b3feb743eeb24' +
+                       '3fcd52ea62b81b82b50c27646ed5762f');
+    assert.strictEqual(crypto.createHash('shake256', { outputLength: 0 })
+                             .copy()  // Default outputLength.
+                             .digest('hex'),
+                       '46b9dd2b0ba88d13233b3feb743eeb24' +
+                       '3fcd52ea62b81b82b50c27646ed5762f');
+  }
 
   // Short outputLengths.
   assert.strictEqual(crypto.createHash('shake128', { outputLength: 0 })
@@ -283,3 +287,13 @@ assert.throws(
   assert.strictEqual(a.digest('hex'), b.digest('hex'));
   assert.strictEqual(c.digest('hex'), d.digest('hex'));
 }
+
+{
+  crypto.Hash('sha256');
+  common.expectWarning({
+    DeprecationWarning: [
+      ['crypto.Hash constructor is deprecated.',
+       'DEP0179'],
+    ]
+  });
+}