From 544a13cd89450e3c636e10e3a4e94c9a4fba756a Mon Sep 17 00:00:00 2001 From: Nicholas Paun Date: Thu, 23 Oct 2025 13:18:31 -0700 Subject: [PATCH 1/3] Provide a copy of EVP_CIPHER_do_all_sorted if required --- BUILD.bazel | 32 +++++++++++++++++++++---- src/ncrypto.cpp | 62 +++++++++++++++++++++++++++++++++++++++++++++++++ tests/basic.cpp | 18 ++++++++++++-- 3 files changed, 106 insertions(+), 6 deletions(-) diff --git a/BUILD.bazel b/BUILD.bazel index c6ea9e2..f476bfe 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -1,12 +1,36 @@ +load("@bazel_skylib//rules:common_settings.bzl", "bool_flag") + +bool_flag( + name = "bssl_libdecrepit_missing", + build_setting_default = False, +) + +config_setting( + name = "cfg_bssl_libdecrepit_missing", + flag_values = { + "bssl_libdecrepit_missing": "True", + }, +) + cc_library( name = "ncrypto", srcs = glob(["src/*.cpp"]), hdrs = glob(["include/*.h"]), includes = ["include"], + local_defines = { + "NCRYPTO_BSSL_LIBDECREPIT_MISSING": select( + { + ":cfg_bssl_libdecrepit_missing": 1, + "//conditions:default": 0, + }, + ), + }, visibility = ["//visibility:public"], deps = [ - "@ssl//:ssl", - "@ssl//:crypto", - "@ssl//:decrepit" - ] + "@ssl", + "@ssl//:crypto", + ] + select({ + ":cfg_bssl_libdecrepit_missing": [], + "//conditions:default": ["@ssl//:decrepit"], + }), ) diff --git a/src/ncrypto.cpp b/src/ncrypto.cpp index 60cfe6e..120bb0b 100644 --- a/src/ncrypto.cpp +++ b/src/ncrypto.cpp @@ -5297,3 +5297,65 @@ BIGNUM* BN_get_rfc3526_prime_8192(BIGNUM* ret) { return get_params(ret, kWords, OPENSSL_ARRAY_SIZE(kWords)); } #endif + +// =========================================================================== +#if NCRYPTO_BSSL_LIBDECREPIT_MISSING +// While BoringSSL implements EVP_CIPHER_do_all_sorted, it includes this +// inplementation in a library called "libdecrepit", which might not be included +// depending on how boringssl was built. In such cases, a copy of the function +// is provided here: + +extern "C" void EVP_CIPHER_do_all_sorted( + void (*callback)(const EVP_CIPHER* cipher, + const char* name, + const char* unused, + void* arg), + void* arg) { + callback(EVP_aes_128_cbc(), "AES-128-CBC", NULL, arg); + callback(EVP_aes_192_cbc(), "AES-192-CBC", NULL, arg); + callback(EVP_aes_256_cbc(), "AES-256-CBC", NULL, arg); + callback(EVP_aes_128_ctr(), "AES-128-CTR", NULL, arg); + callback(EVP_aes_192_ctr(), "AES-192-CTR", NULL, arg); + callback(EVP_aes_256_ctr(), "AES-256-CTR", NULL, arg); + callback(EVP_aes_128_ecb(), "AES-128-ECB", NULL, arg); + callback(EVP_aes_192_ecb(), "AES-192-ECB", NULL, arg); + callback(EVP_aes_256_ecb(), "AES-256-ECB", NULL, arg); + callback(EVP_aes_128_ofb(), "AES-128-OFB", NULL, arg); + callback(EVP_aes_192_ofb(), "AES-192-OFB", NULL, arg); + callback(EVP_aes_256_ofb(), "AES-256-OFB", NULL, arg); + callback(EVP_aes_128_gcm(), "AES-128-GCM", NULL, arg); + callback(EVP_aes_192_gcm(), "AES-192-GCM", NULL, arg); + callback(EVP_aes_256_gcm(), "AES-256-GCM", NULL, arg); + callback(EVP_des_cbc(), "DES-CBC", NULL, arg); + callback(EVP_des_ecb(), "DES-ECB", NULL, arg); + callback(EVP_des_ede(), "DES-EDE", NULL, arg); + callback(EVP_des_ede_cbc(), "DES-EDE-CBC", NULL, arg); + callback(EVP_des_ede3_cbc(), "DES-EDE3-CBC", NULL, arg); + callback(EVP_rc2_cbc(), "RC2-CBC", NULL, arg); + callback(EVP_rc4(), "RC4", NULL, arg); + + // OpenSSL returns everything twice, the second time in lower case. + callback(EVP_aes_128_cbc(), "aes-128-cbc", NULL, arg); + callback(EVP_aes_192_cbc(), "aes-192-cbc", NULL, arg); + callback(EVP_aes_256_cbc(), "aes-256-cbc", NULL, arg); + callback(EVP_aes_128_ctr(), "aes-128-ctr", NULL, arg); + callback(EVP_aes_192_ctr(), "aes-192-ctr", NULL, arg); + callback(EVP_aes_256_ctr(), "aes-256-ctr", NULL, arg); + callback(EVP_aes_128_ecb(), "aes-128-ecb", NULL, arg); + callback(EVP_aes_192_ecb(), "aes-192-ecb", NULL, arg); + callback(EVP_aes_256_ecb(), "aes-256-ecb", NULL, arg); + callback(EVP_aes_128_ofb(), "aes-128-ofb", NULL, arg); + callback(EVP_aes_192_ofb(), "aes-192-ofb", NULL, arg); + callback(EVP_aes_256_ofb(), "aes-256-ofb", NULL, arg); + callback(EVP_aes_128_gcm(), "aes-128-gcm", NULL, arg); + callback(EVP_aes_192_gcm(), "aes-192-gcm", NULL, arg); + callback(EVP_aes_256_gcm(), "aes-256-gcm", NULL, arg); + callback(EVP_des_cbc(), "des-cbc", NULL, arg); + callback(EVP_des_ecb(), "des-ecb", NULL, arg); + callback(EVP_des_ede(), "des-ede", NULL, arg); + callback(EVP_des_ede_cbc(), "des-ede-cbc", NULL, arg); + callback(EVP_des_ede3_cbc(), "des-ede3-cbc", NULL, arg); + callback(EVP_rc2_cbc(), "rc2-cbc", NULL, arg); + callback(EVP_rc4(), "rc4", NULL, arg); +} +#endif diff --git a/tests/basic.cpp b/tests/basic.cpp index ade02cf..29e34bf 100644 --- a/tests/basic.cpp +++ b/tests/basic.cpp @@ -2,6 +2,20 @@ #include -TEST(basic, test_it) { - SUCCEED(); +#include +#include + +using namespace ncrypto; + +TEST(basic, cipher_foreach) { + std::unordered_set foundCiphers; + + Cipher::ForEach([&](const char* name) { foundCiphers.insert(name); }); + + // When testing Cipher::ForEach, we cannot expect a particular list of ciphers + // as that depends on openssl vs boringssl, versions, configuration, etc. + // Instead, we look for a couple of very common ciphers that should always be + // present. + ASSERT_TRUE(foundCiphers.count("AES-128-CTR")); + ASSERT_TRUE(foundCiphers.count("AES-256-CBC")); } From f0f28e29d274c805963807753b89a352a14b45b0 Mon Sep 17 00:00:00 2001 From: Nicholas Paun Date: Fri, 24 Oct 2025 13:44:23 -0700 Subject: [PATCH 2/3] Update cmake config to match bazel config --- CMakeLists.txt | 4 ++-- cmake/ncrypto-flags.cmake | 1 + src/CMakeLists.txt | 7 +++++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 259f136..1704cd3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,9 +15,9 @@ include(cmake/CPM.cmake) CPMAddPackage( NAME boringssl - VERSION 0.20250114.0 + VERSION 0.20250818.0 GITHUB_REPOSITORY google/boringssl - GIT_TAG 0.20250114.0 + GIT_TAG 0.20250818.0 OPTIONS "BUILD_SHARED_LIBS OFF" "BUILD_TESTING OFF" ) add_subdirectory(src) diff --git a/cmake/ncrypto-flags.cmake b/cmake/ncrypto-flags.cmake index bdb1012..3023f0a 100644 --- a/cmake/ncrypto-flags.cmake +++ b/cmake/ncrypto-flags.cmake @@ -1,5 +1,6 @@ option(NCRYPTO_DEVELOPMENT_CHECKS "development checks (useful for debugging)" OFF) option(NCRYPTO_TESTING "Build tests" ON) +option(NCRYPTO_BSSL_LIBDECREPIT_MISSING "enable if boringssl is built without libdecrepit" OFF) set(CMAKE_POSITION_INDEPENDENT_CODE ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cb07cb8..87296cd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,5 +1,12 @@ add_library(ncrypto ncrypto.cpp engine.cpp) target_link_libraries(ncrypto PUBLIC ssl crypto) + +if (NCRYPTO_BSSL_LIBDECREPIT_MISSING) + target_compile_definitions(ncrypto PUBLIC NCRYPTO_BSSL_LIBDECREPIT_MISSING=1) +else() + target_link_libraries(ncrypto PUBLIC decrepit) +endif() + target_include_directories(ncrypto PUBLIC $ From 6cd8355dd0ac1ca37c78304488bf765c126bbdf3 Mon Sep 17 00:00:00 2001 From: Nicholas Paun Date: Mon, 27 Oct 2025 09:42:39 -0700 Subject: [PATCH 3/3] Add README.md to project --- README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..7ae41a1 --- /dev/null +++ b/README.md @@ -0,0 +1,18 @@ +# Node.js crypto (ncrypto) library + +The `ncrypto` library extracts the base internal implementation of Node.js crypto operations +that support both `node:crypto` and Web Crypto implementations and makes them available for +use in other projects that need to emulate Node.js' behavior. + +## Compatibility + +* Build systems: `ncrypto` can be built with either Bazel or CMake. +* SSL libraries: `ncrypto` supports linking to either `boringssl` or `openssl`. + +## Build flags + +* Bazel: `--@ncrypto//:bssl_libdecrepit_missing=True` +* CMake: `-DNCRYPTO_BSSL_LIBDECREPIT_MISSING=1` + +If linking against `boringssl`, libdecrepit is an optional component that isn't always built. If +this option is set, `ncrypto` will use a built-in replacement for the missing functions.