Skip to content

node:crypto: sign and verify with sha512-224 and sha512-256 - #34927

Closed
robobun wants to merge 4 commits into
mainfrom
farm/7bae10aa/sha512t-sign-verify
Closed

robobun wants to merge 4 commits into
mainfrom
farm/7bae10aa/sha512t-sign-verify

Conversation

@robobun

@robobun robobun commented Jul 21, 2026 •

Copy link
Copy Markdown
Collaborator

What does this PR do?

crypto.getHashes() lists sha512-224 and sha512-256 and createHash/createHmac compute them correctly, but every signing entry point rejected them. Node.js signs and verifies both with RSA and EC keys.

import crypto from "node:crypto";
const { privateKey, publicKey } = crypto.generateKeyPairSync("rsa", { modulusLength: 2048 });
crypto.sign("sha512-256", Buffer.from("hello"), privateKey);
// Before: Error: error:0e00009d:RSA routines:OPENSSL_internal:UNKNOWN_ALGORITHM_TYPE
// After:  <Buffer ...> (256 bytes, matches Node byte-for-byte)

Before this change:

  • RSA crypto.sign() threw ERR_OSSL_UNKNOWN_ALGORITHM_TYPE
  • EC crypto.sign() threw ERR_OSSL_INVALID_DIGEST_TYPE
  • createSign(alg).sign() threw a code-less TypeError: Failed to create signature
  • RSA crypto.verify() / createVerify().verify() returned false for every signature instead of throwing
  • The RSA-SHA512/224 and RSA-SHA512/256 aliases threw ERR_CRYPTO_INVALID_DIGEST

Root cause

BoringSSL exposes EVP_sha512_224 / EVP_sha512_256 and recognises the names in EVP_get_digestbyname, so Bun's digest lookup already succeeds. The rejection comes from inside BoringSSL:

  • kPKCS1SigPrefixes in crypto/fipsmodule/rsa/rsa.cc.inc has no entries for NID_sha512_224/NID_sha512_256, so RSA_sign/RSA_verify raise RSA_R_UNKNOWN_ALGORITHM_TYPE for PKCS#1 v1.5 padding. EVP_DigestVerify maps that to a plain 0, which Bun returns as false.
  • pkey_ec_ctrl's EVP_PKEY_CTRL_MD whitelist in crypto/evp/p_ec.cc only admits sha1/224/256/384/512, so EVP_DigestSignInit with an EC key raises EVP_R_INVALID_DIGEST_TYPE.

RSA-PSS already worked because RSA_sign_pss_mgf1 never consults the PKCS#1 prefix table.

Fix

patches/boringssl/sha512t-sign.patch adds both NIDs to the two tables, with the id-sha512-224 / id-sha512-256 DigestInfo prefixes from RFC 8017 (NIST CSOR OIDs 2.16.840.1.101.3.4.2.5 and .6, NULL parameters). The prefixes were verified byte-exact against what Node/OpenSSL emit by raw-RSA-decrypting a Node signature.

ncrypto.cpp getDigestByName gains the RSA-SHA512/224 and RSA-SHA512/256 aliases so the OpenSSL long names Node advertises resolve (BoringSSL's nid_to_digest_mapping only carries RSA-SHA1 through RSA-SHA512).

How did you verify your code works?

test/js/node/crypto/crypto-oneshot.test.ts adds coverage for both digests across one-shot/streaming sign and verify, with RSA PKCS#1 v1.5, RSA-PSS, and ECDSA. The PKCS#1 fixtures are deterministic signatures generated by Node, so the tests also pin byte-exact interop with OpenSSL rather than only proving self-consistency.

This is the third member of the advertised-but-unsignable digest census after #33518 (sha3-*) and #34348 (ripemd160/md4 silent-false verify). Whichever of #33518 and this PR merges second will need a trivial rebase of the shared p_ec.cc whitelist and kPKCS1SigPrefixes hunks.


[review] gate passed · iteration 1 · 5 files touched

fails on main (without fix)
ASAN without fix: 6 FAILED
$ BUN_DEBUG_QUIET_LOGS=1 bun scripts/build.ts --profile=debug --quiet test "--reporter=junit" "--reporter-outfile=/tmp/mechgate.xml" test/js/node/crypto/crypto-oneshot.test.ts test/js/node/crypto/node-crypto.test.js
bun test v1.4.0 (7444609df)

test/js/node/crypto/node-crypto.test.js:
(pass) crypto.randomBytes should return a Buffer [4.03ms]
(pass) crypto.randomInt should return a number [2.25ms]
(pass) crypto.randomInt with no arguments [3.50ms]
(pass) crypto.randomInt with one argument [2.32ms]
(pass) crypto.randomInt with a callback [35.84ms]
(pass) createHash > rsa-md5 - "Hello World" [7.89ms]
(pass) createHash > rsa-md5 - "Hello World" -> binary [4.25ms]
(pass) createHash > rsa-ripemd160 - "Hello World" [1.15ms]
(pass) createHash > rsa-ripemd160 - "Hello World" -> binary [0.98ms]
(pass) createHash > rsa-sha1 - "Hello World" [8.37ms]
(pass) createHash > rsa-sha1 - "Hello World" -> binary [1.17ms]
(pass) createHash > rsa-sha1-2 - "Hello World" [0.77ms]
(pass) createHash > rsa-sha1-2 - "Hello World" -> binary [0.81ms]
(pass) createHash > rsa-sha224 - "Hello World" [2.86ms]
(pass) createHash > rsa-sha224 - "Hello World" -> binary [0.97ms]
(pass) createHash > rsa-sh
... (truncated)

release without fix: all passed
bun test v1.4.0-canary.1 (a2949b9eb)

test/js/node/crypto/node-crypto.test.js:
(pass) crypto.randomBytes should return a Buffer [4.26ms]
(pass) crypto.randomInt should return a number [0.06ms]
(pass) crypto.randomInt with no arguments [0.90ms]
(pass) crypto.randomInt with one argument [0.03ms]
(pass) crypto.randomInt with a callback [0.55ms]
(pass) createHash > rsa-md5 - "Hello World" [1.53ms]
(pass) createHash > rsa-md5 - "Hello World" -> binary [0.06ms]
(pass) createHash > rsa-ripemd160 - "Hello World"
(pass) createHash > rsa-ripemd160 - "Hello World" -> binary
(pass) createHash > rsa-sha1 - "Hello World" [0.08ms]
(pass) createHash > rsa-sha1 - "Hello World" -> binary [0.02ms]
(pass) createHash > rsa-sha1-2 - "Hello World"
(pass) createHash > rsa-sha1-2 - "Hello World" -> binary
(pass) createHash > rsa-sha224 - "Hello World" [0.03ms]
(pass) createHash > rsa-sha224 - "Hello World" -> binary [0.01ms]
(pass) createHash > rsa-sha256 - "Hello World" [0.01ms]
(pass) createHash > rsa-sha256 - "Hello World" -> binary
(pass) createHash > rsa-sha3-224 - "Hello World"
(pass) createHash > rsa-sha3-224 - "Hello World" -> binary
(pass) createHash > rsa-sha3-256 - "Hello World"

... (truncated)
passes on PR (with fix)
ASAN with fix: all passed
$ BUN_DEBUG_QUIET_LOGS=1 bun scripts/build.ts --profile=debug --quiet test "--reporter=junit" "--reporter-outfile=/tmp/mechgate.xml" test/js/node/crypto/crypto-oneshot.test.ts test/js/node/crypto/node-crypto.test.js
bun test v1.4.0 (7444609df)

test/js/node/crypto/node-crypto.test.js:
(pass) crypto.randomBytes should return a Buffer [4.16ms]
(pass) crypto.randomInt should return a number [2.24ms]
(pass) crypto.randomInt with no arguments [3.54ms]
(pass) crypto.randomInt with one argument [2.73ms]
(pass) crypto.randomInt with a callback [39.08ms]
(pass) createHash > rsa-md5 - "Hello World" [7.93ms]
(pass) createHash > rsa-md5 - "Hello World" -> binary [4.13ms]
(pass) createHash > rsa-ripemd160 - "Hello World" [1.14ms]
(pass) createHash > rsa-ripemd160 - "Hello World" -> binary [0.94ms]
(pass) createHash > rsa-sha1 - "Hello World" [8.11ms]
(pass) createHash > rsa-sha1 - "Hello World" -> binary [1.20ms]
(pass) createHash > rsa-sha1-2 - "Hello World" [0.81ms]
(pass) createHash > rsa-sha1-2 - "Hello World" -> binary [0.82ms]
(pass) createHash > rsa-sha224 - "Hello World" [2.88ms]
(pass) createHash > rsa-sha224 - "Hello World" -> binary [0.99ms]
(pass) createHash > rsa-sh
... (truncated)

release with fix: all passed
$ bun scripts/build.ts --profile=release
[configured] bun-profile → bun (stripped) in 656ms (unchanged)
ninja: Entering directory `/workspace/bun/build/release'
[1/7] gen cpp.rs (cppbind)
[1/7] cargo bun_bin → libbun_rust.a (--target x86_64-unknown-linux-gnu)

  nightly-2026-07-20-x86_64-unknown-linux-gnu unchanged - rustc 1.99.0-nightly (9f36de775 2026-07-19)

�[1m�[92m   Compiling�[0m bun_core v0.0.0 (/workspace/bun/src/bun_core)
�[1m�[92m   Compiling�[0m bun_errno v0.0.0 (/workspace/bun/src/errno)
�[1m�[92m   Compiling�[0m bun_ptr v0.0.0 (/workspace/bun/src/ptr)
�[1m�[92m   Compiling�[0m bun_boringssl_sys v0.0.0 (/workspace/bun/src/boringssl_sys)
�[1m�[92m   Compiling�[0m bun_safety v0.0.0 (/workspace/bun/src/safety)
�[1m�[92m   Compiling�[0m bun_zlib_sys v0.0.0 (/workspace/bun/src/zlib_sys)
�[1m�[92m   Compiling�[0m bun_cares_sys v0.0.0 (/workspace/bun/src/cares_sys)
�[1m�[92m   Compiling�[0m bun_zstd v0.0.0 (/workspace/bun/src/zstd)
�[1m�[92m   Compiling�[0m bun_picohttp v0.0.0 (/workspace/bun/src/picohttp)
�[1m�[92m   Compiling�[0m bun_output v0.0.0 (/workspace/bun/src/output)
�[1m�[92m   Compiling�[0m bun_clap v0.0.0 (/workspace/bun/src/clap)
�[1m�[92m   
... (truncated)
diff hotspot
patches/boringssl/sha512t-sign.patch       |  41 +++++++++++
 scripts/build/deps/boringssl.ts            |   6 +-
 src/jsc/bindings/ncrypto.cpp               |   6 ++
 test/js/node/crypto/crypto-oneshot.test.ts | 106 +++++++++++++++++++++++++++++
 test/js/node/crypto/node-crypto.test.js    |   2 -
 5 files changed, 158 insertions(+), 3 deletions(-)

gate history · 3 passed · 0 rejected · iteration 1

evidence per changed file
file                                        reads  edits  tests
patches/boringssl/sha512t-sign.patch            0      3      0
scripts/build/deps/boringssl.ts                 1      2      0
src/jsc/bindings/ncrypto.cpp                    1      1      0
test/js/node/crypto/crypto-oneshot.test.ts      2      2      0
test/js/node/crypto/node-crypto.test.js         1      1      0

getHashes() lists both and createHash/createHmac compute them, but every
sign/verify entry point rejected them: crypto.sign with an RSA key threw
ERR_OSSL_UNKNOWN_ALGORITHM_TYPE, EC keys threw ERR_OSSL_INVALID_DIGEST_TYPE,
createSign().sign() threw a code-less TypeError, the RSA-SHA512/224 and
RSA-SHA512/256 aliases threw ERR_CRYPTO_INVALID_DIGEST, and verify() with an
RSA key returned false for every signature instead of throwing.

BoringSSL exposes EVP_sha512_224/256 but omits NID_sha512_224/256 from
kPKCS1SigPrefixes (so RSA_sign/RSA_verify raise RSA_R_UNKNOWN_ALGORITHM_TYPE)
and from pkey_ec_ctrl's EVP_PKEY_CTRL_MD whitelist (EVP_R_INVALID_DIGEST_TYPE).
Patch both tables with the id-sha512-224/256 DigestInfo prefixes from RFC 8017,
and add the RSA-SHA512/224 and RSA-SHA512/256 aliases to getDigestByName so the
OpenSSL long names Node advertises resolve.

RSA-PSS already worked because RSA_sign_pss_mgf1 never consults the PKCS#1
prefix table.
@robobun

robobun commented Jul 21, 2026 •

Copy link
Copy Markdown
Collaborator Author

Status: diff is green; CI is red on unrelated known-flaky tests. Ready for a maintainer to merge.

Two consecutive runs (#76850, #76879) passed every crypto test on every lane, including the 14 new sha512-224/256 cases in crypto-oneshot.test.ts and the updated node-crypto.test.js. The remaining red lanes are all tagged flaky-on-main and touch nothing this PR changes: no-orphans.test.ts (darwin), bun-server.test.ts (darwin), spawn.test.ts (windows timeout), net-mongodb-pattern-leak.test.ts, complex-workspace.test.ts, webview-chrome.test.ts, test-fs-promises-file-handle-readFile.js, test-http-server-connections-checking-leak.js, es-module-lexer.test.ts, test-repl-close.js, 20144.test.ts.

Review threads all resolved through a2949b9:

  • e46665a: trimmed the boringssl.ts comment to three lines, added an RSA-PSS sign/verify round-trip test
  • a2949b9: dropped the redundant SHA512_224_DIGEST_LENGTH define (sha2.h already has it at line 201); removed rsa-sha512/224 and rsa-sha512/256 from node-crypto.test.js's unsupported list now that getDigestByName resolves them

Related to #20592 (makes the RSA-SHA512/224 and RSA-SHA512/256 aliases resolve) but does not close it: that issue is about getHashes() omitting aliases, which is a separate change.

Repro before/after
$ bun repro.mjs   # before
sha512-224 in getHashes: true createHash: 4634270f707b
  sign THREW ERR_OSSL_UNKNOWN_ALGORITHM_TYPE
  verify = false
sha512-256 in getHashes: true createHash: 53048e268194
  sign THREW ERR_OSSL_UNKNOWN_ALGORITHM_TYPE
  verify = false
EC sha512-224 sign THREW ERR_OSSL_INVALID_DIGEST_TYPE
EC sha512-256 sign THREW ERR_OSSL_INVALID_DIGEST_TYPE
createSign sha512-224 THREW TypeError
createSign sha512-256 THREW TypeError
RSA-SHA512/224 sign THREW ERR_CRYPTO_INVALID_DIGEST
RSA-SHA512/256 sign THREW ERR_CRYPTO_INVALID_DIGEST

$ bun-debug repro.mjs   # after
sha512-224 in getHashes: true createHash: 4634270f707b
  sign ok 256
  verify = true
sha512-256 in getHashes: true createHash: 53048e268194
  sign ok 256
  verify = true
EC sha512-224 sign ok 72 verify = true
EC sha512-256 sign ok 71 verify = true
createSign sha512-224 ok 256
createSign sha512-256 ok 256
RSA-SHA512/224 sign ok 256
RSA-SHA512/256 sign ok 256

@robobun

robobun commented Jul 21, 2026 •

Copy link
Copy Markdown
Collaborator Author
Updated 7:43 AM PT - Jul 21st, 2026

❌ @robobun, your commit 7444609 has some failures in Build #76879 (All Failures)


🧪   To try this PR locally:

bunx bun-pr 34927

That installs a local version of the PR into your bun-34927 executable, so you can run:

bun-34927 --bun

@coderabbitai

coderabbitai Bot commented Jul 21, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Changes

SHA-512/224 and SHA-512/256 support was added to BoringSSL signing internals, ncrypto digest-name mapping, and crypto sign/verify tests covering RSA, RSA-PSS, and ECDSA.

SHA-512 truncated signing

Layer / File(s) Summary
BoringSSL digest and signature support
patches/boringssl/sha512t-sign.patch, scripts/build/deps/boringssl.ts
BoringSSL gains PKCS#1 prefixes and EC digest validation for SHA-512/224 and SHA-512/256, and the build applies the patch.
Digest alias mapping
src/jsc/bindings/ncrypto.cpp
RSA-SHA512/224 and RSA-SHA512/256 names map to the corresponding OpenSSL digest implementations.
Signing and verification coverage
test/js/node/crypto/crypto-oneshot.test.ts
Tests cover one-shot and streaming APIs, RSA PKCS#1, RSA-PSS, ECDSA, aliases, and invalid signatures for both digest variants.

Suggested reviewers: jarred-sumner

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly states the main change: adding sha512-224 and sha512-256 sign/verify support in node:crypto.
Description check ✅ Passed The description follows the template and includes what changed plus detailed verification steps and results.

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/build/deps/boringssl.ts`:
- Around line 42-46: Shorten the dependency note comment near the sha512t-sign
explanation to three content lines or fewer by combining its wording, while
preserving the explanation of the BoringSSL limitation and the condition for
removing the workaround.

In `@test/js/node/crypto/crypto-oneshot.test.ts`:
- Around line 159-176: Extend the crypto tests around the existing
crypto.verify() and createVerify() coverage to include RSA-PSS round trips for
both one-shot and streaming APIs. Generate or use randomized messages, sign with
RSA_PKCS1_PSS_PADDING, then verify through crypto.sign/crypto.verify and
createSign/createVerify, preserving the complete supported variant matrix and
asserting successful verification.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: abdf95a4-602f-45e8-bf62-35173897e09c

📥 Commits

Reviewing files that changed from the base of the PR and between e550f2c and 7c4ab94.

📒 Files selected for processing (4)
  • patches/boringssl/sha512t-sign.patch
  • scripts/build/deps/boringssl.ts
  • src/jsc/bindings/ncrypto.cpp
  • test/js/node/crypto/crypto-oneshot.test.ts

Comment thread scripts/build/deps/boringssl.ts Outdated
Comment thread test/js/node/crypto/crypto-oneshot.test.ts
@github-actions

Copy link
Copy Markdown
Contributor

Found 1 issue this PR may fix:

  1. getHashes function does not report all available hashes #20592 - PR adds RSA-SHA512/224 and RSA-SHA512/256 alias resolution in getDigestByName(), directly related to completing hash algorithm coverage that this issue reports as missing

If this is helpful, copy the block below into the PR description to auto-close this issue on merge.

Fixes #20592

🤖 Generated with Claude Code

Comment thread src/jsc/bindings/ncrypto.cpp
Comment thread patches/boringssl/sha512t-sign.patch Outdated
…12/* out of node-crypto.test.js unsupported list

sha2.h at the pinned fork commit already defines SHA512_224_DIGEST_LENGTH at
line 201, so the patch's own define was a benign identical redefinition with a
misleading comment.

node-crypto.test.js still listed rsa-sha512/224 and rsa-sha512/256 in its
unsupported array, asserting createHash() throws for them. getDigestByName now
resolves both, so the test expectation was inverted.

@claude claude Bot left a comment

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.

Both earlier findings (the redundant SHA512_224_DIGEST_LENGTH define and the stale unsupported entries in node-crypto.test.js) are addressed in a2949b9. I don't see anything else wrong — the RFC 8017 DigestInfo prefixes check out byte-for-byte and the tests pin against Node/OpenSSL fixtures — but this patches vendored BoringSSL crypto internals, so leaving the sign-off to a maintainer.

What was reviewed

  • DigestInfo prefixes: verified the DER encoding for OIDs 2.16.840.1.101.3.4.2.{5,6} with NULL params — outer SEQUENCE lengths (0x2d/0x31), 19-byte prefix, and trailing OCTET STRING lengths (0x1c/0x20) all match RFC 8017 §9.2 note 1.
  • getDigestByName alias placement sits inside the existing rsa-sha prefix branch and can't shadow the plain "512" case above it.
  • Test fixtures rsa_{private,public}_2048.pem / ec_p256_{private,public}.pem exist; PKCS#1 fixtures are deterministic so they pin interop, not just self-round-trip.
Extended reasoning...

Overview

Enables crypto.sign/crypto.verify/createSign/createVerify for sha512-224 and sha512-256, which were already advertised by getHashes() and accepted by createHash but rejected at the signing layer. Three moving parts: a 41-line BoringSSL patch adding the two NIDs to kPKCS1SigPrefixes (rsa.cc.inc) and the EC EVP_PKEY_CTRL_MD whitelist (p_ec.cc); two new alias arms in ncrypto::getDigestByName for the RSA-SHA512/224 / RSA-SHA512/256 OpenSSL long names; and ~100 lines of tests covering one-shot + streaming across RSA PKCS#1 v1.5, RSA-PSS, and ECDSA with Node-generated known-answer fixtures. The two entries removed from node-crypto.test.js's unsupported list were the fix for my prior finding.

Security risks

This is signature crypto. The risk surface is a wrong DigestInfo prefix producing signatures that verify against Bun but not OpenSSL (or vice versa), or the EC whitelist relaxation letting through something it shouldn't. I hand-decoded both DER prefixes against RFC 8017 Appendix B.1 and they're correct. The EC change only adds two NIDs to an existing conjunctive whitelist; the comment in the patch is accurate that pkey_ec_sign hands the digest bytes straight to ECDSA_sign without consulting dctx->md. The tests cross-verify against OpenSSL-generated fixtures, so a prefix mismatch would fail loudly. No new attack surface — this makes previously-rejected inputs succeed with the standard encoding.

Level of scrutiny

High. This is a hand-written patch to a vendored TLS/crypto library. The change itself is small, mechanical, and mirrors two recently-merged siblings (#33518 for sha3-*, #34348 for ripemd160/md4 verify), and REVIEW.md-style test coverage is present including negative cases and known-answer vectors. But vendor crypto patches are exactly where a maintainer should be in the loop regardless of how clean the diff looks — both to sanity-check the DER bytes independently and to confirm the patch-file approach (vs. landing upstream in the fork) is what's wanted here.

Other factors

All prior review threads are resolved: the CodeRabbit comment-length nit and RSA-PSS coverage ask were handled in e46665a; my two findings (stale unsupported list, redundant macro define) were handled in a2949b9. The PR description flags a known trivial rebase conflict with #33518 in the shared p_ec.cc and kPKCS1SigPrefixes hunks depending on merge order — worth the merger being aware of.

@claude claude Bot left a comment

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.

Both earlier findings are addressed in a2949b9 — the redundant SHA512_224_DIGEST_LENGTH define is gone from the patch and rsa-sha512/224/256 are removed from node-crypto.test.js's unsupported list. No new issues found this pass, but leaving the BoringSSL patch for a human sign-off since it touches signing internals.

What was reviewed:

  • DigestInfo prefix bytes for both NIDs check out against RFC 8017 §9.2 (OIDs 2.16.840.1.101.3.4.2.{5,6}, NULL params, outer SEQUENCE lengths 0x2d/0x31, OCTET STRING lengths 0x1c/0x20, prefix len 19).
  • p_ec.cc whitelist addition is gate-only; pkey_ec_sign hands the digest straight to ECDSA_sign, so no other EC-side change is needed.
  • New rsa-sha alias arms in getDigestByName sit after the exact-"512" match, so RSA-SHA512 still resolves to EVP_sha512().
  • Fixture PEMs referenced by the new tests exist on disk.
Extended reasoning...

Overview

Enables sha512-224 / sha512-256 for crypto.sign/verify/createSign/createVerify by (1) a two-hunk BoringSSL patch adding both NIDs to kPKCS1SigPrefixes (RSA PKCS#1 v1.5) and pkey_ec_ctrl's EVP_PKEY_CTRL_MD whitelist, (2) two alias arms in ncrypto.cpp getDigestByName for RSA-SHA512/224 and RSA-SHA512/256, and (3) test coverage pinning byte-exact deterministic PKCS#1 signatures generated by Node/OpenSSL plus PSS/ECDSA round-trips and negative cases. The two entries removed from node-crypto.test.js's unsupported array are the follow-through I flagged last pass.

Security risks

The DigestInfo prefix bytes are the security-load-bearing part: a wrong encoding would produce signatures Node/OpenSSL reject (caught by the deterministic fixture test) or, worse, accept malformed structures on verify. I hand-decoded both 19-byte prefixes and they match RFC 8017 exactly — correct OIDs, NULL parameters, and length fields consistent with 28- and 32-byte digests. The EC change is a pure whitelist extension. The alias additions only widen name resolution to existing EVP_sha512_224/256 digests. No new parsing of untrusted input.

Level of scrutiny

High — this is a patch to vendored BoringSSL's RSA and EC signing paths. The change is small, mechanical, and mirrors the shape of the existing NID_sha224…NID_sha512 entries in the same tables, and it follows two prior merged PRs (#33518 sha3-*, #34348 ripemd160/md4) doing the same class of extension. The deterministic fixture test is strong evidence of interop correctness. Still, patching a crypto library's signing tables is exactly where a maintainer should look before merge.

Other factors

All prior review threads (CodeRabbit's comment-length and PSS-coverage nits, and my two findings) are resolved and reflected in the current diff. CI build #76879 is in flight. The PR description flags a trivial rebase interaction with #33518 on the shared p_ec.cc and kPKCS1SigPrefixes hunks — worth noting for whoever merges second.

@robobun

robobun commented Sep 13, 2026

Copy link
Copy Markdown
Collaborator Author

Closing as part of a cleanup of stale pull requests. This PR has had no new commits since 2026-07-21, it conflicts with main, and its last CI run failed. This is not a judgment on the fix itself. If the problem still reproduces on a current build, reopen this PR after a rebase or open a new one against main.

@robobun robobun closed this Sep 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant