mirror of
https://github.com/oven-sh/bun
synced 2026-02-10 10:58:56 +00:00
## Summary Fixes #11029 - `crypto.verify()` now correctly handles null/undefined algorithm parameter for RSA keys, matching Node.js behavior. ## Problem When calling `crypto.verify()` with a null or undefined algorithm parameter, Bun was throwing an error: ``` error: error:06000077:public key routines:OPENSSL_internal:NO_DEFAULT_DIGEST ``` ## Root Cause The issue stems from the difference between OpenSSL (used by Node.js) and BoringSSL (used by Bun): - **OpenSSL v3**: Automatically provides SHA256 as the default digest for RSA keys when NULL is passed - **BoringSSL**: Returns an error when NULL digest is passed for RSA keys ## Solution This fix explicitly sets SHA256 as the default digest for RSA keys when no algorithm is specified, achieving OpenSSL-compatible behavior. ## OpenSSL v3 Source Code Analysis I traced through the OpenSSL v3 source code to understand exactly how it handles null digests: ### 1. Entry Point (`crypto/evp/m_sigver.c`) When `EVP_DigestSignInit` or `EVP_DigestVerifyInit` is called with NULL digest: ```c // Lines 215-220 in do_sigver_init function if (mdname == NULL && !reinit) { if (evp_keymgmt_util_get_deflt_digest_name(tmp_keymgmt, provkey, locmdname, sizeof(locmdname)) > 0) { mdname = canon_mdname(locmdname); } } ``` ### 2. Default Digest Query (`crypto/evp/keymgmt_lib.c`) ```c // Lines 533-571 in evp_keymgmt_util_get_deflt_digest_name params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_DEFAULT_DIGEST, mddefault, sizeof(mddefault)); if (!evp_keymgmt_get_params(keymgmt, keydata, params)) return 0; ``` ### 3. RSA Provider Implementation (`providers/implementations/keymgmt/rsa_kmgmt.c`) ```c // Line 54: Define the default #define RSA_DEFAULT_MD "SHA256" // Lines 351-355: Return it for RSA keys if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DEFAULT_DIGEST)) != NULL && (rsa_type != RSA_FLAG_TYPE_RSASSAPSS || ossl_rsa_pss_params_30_is_unrestricted(pss_params))) { if (!OSSL_PARAM_set_utf8_string(p, RSA_DEFAULT_MD)) return 0; } ``` ## Implementation Details The fix includes extensive documentation in the source code explaining: - The OpenSSL v3 mechanism with specific file paths and line numbers - Why BoringSSL behaves differently - Why Ed25519/Ed448 keys are handled differently (they don't need a digest) ## Test Plan ✅ Added comprehensive regression test in `test/regression/issue/11029-crypto-verify-null-algorithm.test.ts` ✅ Tests cover: - RSA keys with null/undefined algorithm - Ed25519 keys with null algorithm - Cross-verification between null and explicit SHA256 - `createVerify()` compatibility ✅ All tests pass and behavior matches Node.js ## Verification ```bash # Test with Bun bun test test/regression/issue/11029-crypto-verify-null-algorithm.test.ts # Compare with Node.js behavior node -e "const crypto = require('crypto'); const {publicKey, privateKey} = crypto.generateKeyPairSync('rsa', {modulusLength: 2048}); const data = Buffer.from('test'); const sig = crypto.sign(null, data, privateKey); console.log('Node.js verify with null:', crypto.verify(null, data, publicKey, sig));" ``` 🤖 Generated with [Claude Code](https://claude.ai/code) --------- Co-authored-by: Claude Bot <claude-bot@bun.sh> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
3.9 KiB
3.9 KiB