Skip to content

Implement SHA-3 support for node crypto#6680

Open
guybedford wants to merge 1 commit intomainfrom
sha3
Open

Implement SHA-3 support for node crypto#6680
guybedford wants to merge 1 commit intomainfrom
sha3

Conversation

@guybedford
Copy link
Copy Markdown
Contributor

Summary

  • Adds sha3-224, sha3-256, sha3-384, and sha3-512 support for node:crypto hashes and createHmac().
  • Uses RustCrypto's sha3 crate through the existing Rust CXX bridge because BoringSSL does not provide SHA-3 EVP digests.
  • Lists SHA-3 algorithms in crypto.getHashes() and covers streaming, one-shot, case-insensitive names, copy, and HMAC behavior in node crypto tests.

Implementation

  • Introduces opaque Rust SHA-3 hash and HMAC states in src/rust/api/lib.rs.
  • Routes only SHA-3 algorithm names through the Rust path in HashContext and HmacContext; existing BoringSSL-backed algorithms continue using EVP/HMAC.
  • Preserves Hash.copy() by cloning RustCrypto hash state before finalization.
  • Preserves Node-style repeated digest() behavior by caching the finalized JS-visible digest in the existing context state.

Dependency Security View

  • The implementation uses RustCrypto crates sha3 and hmac, which are widely used Rust cryptography implementations maintained under the RustCrypto organization.
  • sha3 implements the standardized FIPS 202 SHA-3 family and depends on the RustCrypto keccak permutation implementation.
  • The C++ boundary keeps the Rust state opaque and only passes byte slices into Rust and finalized digest bytes back to C++; there is no unsafe Rust added in this change.
  • The dependency is used only for SHA-3 hash/HMAC algorithms that BoringSSL does not expose, limiting new cryptographic surface area to the missing Node-compatible algorithms.
  • Cargo.lock pins exact crate versions and checksums, and Bazel resolves those locked versions for reproducible builds.

Tests

  • bazel build //src/rust/api //src/workerd/api/node:node
  • bazel test //src/workerd/api/node/tests:crypto_hash-test@ //src/workerd/api/node/tests:crypto_hmac-test@ --nocache_test_results
  • bazel test //src/rust/... --nocache_test_results
  • bazel test //src/workerd/api/node/tests:crypto_hash-test@ //src/workerd/api/node/tests:crypto_hash-test@all-compat-flags //src/workerd/api/node/tests:crypto_hash-test@all-autogates //src/workerd/api/node/tests:crypto_hmac-test@ //src/workerd/api/node/tests:crypto_hmac-test@all-compat-flags //src/workerd/api/node/tests:crypto_hmac-test@all-autogates --nocache_test_results
  • just format

@guybedford guybedford requested review from a team as code owners April 27, 2026 23:21
Copy link
Copy Markdown
Contributor

@ask-bonk ask-bonk Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm Bonk, and I've done a quick review of your PR.

This PR adds SHA-3 hash and HMAC support to node:crypto via RustCrypto crates through the existing CXX bridge, cleanly routing only SHA-3 algorithm names through Rust while preserving existing BoringSSL paths.

Issues (ranked by severity):

  1. [LOW] The getHashes() comment says "hashes supported in BoringSSL" but SHA-3 hashes are now backed by RustCrypto, not BoringSSL. The comment should be updated.
  2. [LOW] The INT_MAX checks on the Rust SHA-3 update() paths are unnecessary — Rust &[u8] slices accept any usize length, and the Keccak sponge has no inherent input length limit. The checks are harmless but asymmetric with the Rust side's actual constraints. Not blocking.

This review was generated by an AI assistant and may contain inaccuracies.

Comment thread src/node/crypto.ts
@@ -190,9 +190,9 @@ export function getHashes(): string[] {
// expected to change infrequently based of bssl's stability-focused approach.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[LOW] This comment is now inaccurate — SHA-3 hashes are backed by RustCrypto, not BoringSSL.

Suggested change
// expected to change infrequently based of bssl's stability-focused approach.
// Hardcoded list of supported hashes. Most are backed by BoringSSL; sha3-* variants use
// RustCrypto via the Rust CXX bridge since BoringSSL does not expose SHA-3 EVP digests.

@ask-bonk
Copy link
Copy Markdown
Contributor

ask-bonk Bot commented Apr 27, 2026

Review posted successfully on PR #6680. Here's a summary of the review:

Findings:

  1. [LOW] Stale comment in src/node/crypto.ts:190 — says "hashes supported in BoringSSL" but SHA-3 is now backed by RustCrypto. Posted a suggestion comment with corrected wording.

  2. [LOW] The INT_MAX bounds checks on the Rust SHA-3 update() paths are unnecessary (Rust slices have no such limit, and Keccak has no input length constraint), but they're harmless and maintain consistency with the BoringSSL path — noted in the review body but not blocking.

What looked good (not mentioned in the review per tone guidelines):

  • Clean separation: SHA-3 routing via lookupSha3Algorithm happens before the OpenSSL fallback path
  • No backward compatibility concerns — purely additive (new algorithms in getHashes(), new hash/HMAC support)
  • No compat flag needed since this adds new functionality without changing existing behavior
  • SubtleCrypto paths correctly reject SHA-3 (WebCrypto doesn't standardize SHA-3)
  • Rust code is safe — no unsafe, proper CXX bridge patterns, #[expect] over #[allow]
  • Tests cover correctness vectors, streaming, copy, case-insensitive names, and HMAC
  • Cargo version specifiers follow project convention

github run

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant