From c8a78011ff5a94e9f183b00567a82f2b4ff3de9e Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Tue, 28 Apr 2026 16:20:12 +0200 Subject: [PATCH 1/4] ci: refresh workflow action pins Signed-off-by: Filip Skokan --- .github/workflows/bazel.yml | 8 ++++---- .github/workflows/commitlint.yml | 2 +- .github/workflows/linter.yml | 4 ++-- .github/workflows/macos.yml | 6 +++--- .github/workflows/release-please.yml | 2 +- .github/workflows/ubuntu.yml | 16 ++++++++-------- .github/workflows/visual-studio.yml | 4 ++-- 7 files changed, 21 insertions(+), 21 deletions(-) diff --git a/.github/workflows/bazel.yml b/.github/workflows/bazel.yml index 8737917..b7367e6 100644 --- a/.github/workflows/bazel.yml +++ b/.github/workflows/bazel.yml @@ -25,8 +25,8 @@ jobs: macos: runs-on: macos-latest steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: bazel-contrib/setup-bazel@bbf8fe8b219f642c7f8bc673215f28eb1d9dec51 # v0.10.0 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: bazel-contrib/setup-bazel@c5acdfb288317d0b5c0bbd7a396a3dc868bb0f86 # 0.19.0 with: bazelisk-cache: true disk-cache: ${{ github.workflow }} @@ -45,8 +45,8 @@ jobs: cxx: clang++-18 runs-on: ubuntu-latest steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: bazel-contrib/setup-bazel@bbf8fe8b219f642c7f8bc673215f28eb1d9dec51 # v0.10.0 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: bazel-contrib/setup-bazel@c5acdfb288317d0b5c0bbd7a396a3dc868bb0f86 # 0.19.0 with: bazelisk-cache: true disk-cache: ${{ github.workflow }} diff --git a/.github/workflows/commitlint.yml b/.github/workflows/commitlint.yml index f82bae9..1c26323 100644 --- a/.github/workflows/commitlint.yml +++ b/.github/workflows/commitlint.yml @@ -10,7 +10,7 @@ jobs: commitlint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 100 - uses: wagoid/commitlint-github-action@b948419dd99f3fd78a6548d48f94e3df7f6bf3ed # v6.2.1 diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index 5546d0a..3239fe1 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -24,10 +24,10 @@ jobs: lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Run clang-format - uses: jidicula/clang-format-action@6cd220de46c89139a0365edae93eee8eb30ca8fe # v4.16.0 + uses: jidicula/clang-format-action@654a770daa28443dd111d133e4083e21c1075674 # v4.18.0 with: clang-format-version: '21' fallback-style: 'Google' diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index dd49a8f..5f227c3 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -28,9 +28,9 @@ jobs: runs-on: [macos-14, macos-15] runs-on: ${{matrix.runs-on}} steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: ccache - uses: hendrikmuhs/ccache-action@v1.2 + uses: hendrikmuhs/ccache-action@d62db5f07c26379fc4b4e0916f098a92573c3b03 # v1.2.23 with: key: ${{github.job}}-${{matrix.os}} - name: Prepare @@ -40,4 +40,4 @@ jobs: # Ref: https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners run: cmake --build build -j=3 - name: Test - run: ctest --output-on-failure --test-dir build \ No newline at end of file + run: ctest --output-on-failure --test-dir build diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index 57f8a91..7d455ef 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -13,4 +13,4 @@ jobs: release-please: runs-on: ubuntu-latest steps: - - uses: googleapis/release-please-action@16a9c90856f42705d54a6fda1823352bdc62cf38 # v4.4.0 + - uses: googleapis/release-please-action@45996ed1f6d02564a971a2fa1b5860e934307cf7 # v5.0.0 diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index 3b26eb6..f4486ac 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -29,9 +29,9 @@ jobs: cxx: [g++-14] runs-on: ${{matrix.runs-on}} steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: ccache - uses: hendrikmuhs/ccache-action@v1.2 + uses: hendrikmuhs/ccache-action@d62db5f07c26379fc4b4e0916f098a92573c3b03 # v1.2.23 with: key: ${{github.job}}-${{matrix.os}}-{{matrix.shared}} - name: Setup Ninja @@ -52,10 +52,10 @@ jobs: OPENSSL_VERSION: "3.4.1" OPENSSL_DIR: "${{ github.workspace }}/openssl-install" steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Cache OpenSSL id: cache-openssl - uses: actions/cache@v4 + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: ${{ env.OPENSSL_DIR }} key: openssl-${{ env.OPENSSL_VERSION }}-${{ runner.os }} @@ -69,7 +69,7 @@ jobs: make -j$(nproc) make install_sw - name: ccache - uses: hendrikmuhs/ccache-action@v1.2 + uses: hendrikmuhs/ccache-action@d62db5f07c26379fc4b4e0916f098a92573c3b03 # v1.2.23 with: key: ${{github.job}}-openssl - name: Setup dependencies @@ -93,10 +93,10 @@ jobs: OPENSSL_VERSION: "3.4.1" OPENSSL_DIR: "${{ github.workspace }}/openssl-install" steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Cache OpenSSL id: cache-openssl - uses: actions/cache@v4 + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: ${{ env.OPENSSL_DIR }} key: openssl-${{ env.OPENSSL_VERSION }}-${{ runner.os }} @@ -110,7 +110,7 @@ jobs: make -j$(nproc) make install_sw - name: ccache - uses: hendrikmuhs/ccache-action@v1.2 + uses: hendrikmuhs/ccache-action@d62db5f07c26379fc4b4e0916f098a92573c3b03 # v1.2.23 with: key: ${{github.job}}-openssl-no-argon2 - name: Setup dependencies diff --git a/.github/workflows/visual-studio.yml b/.github/workflows/visual-studio.yml index 8e966a6..0eb78f8 100644 --- a/.github/workflows/visual-studio.yml +++ b/.github/workflows/visual-studio.yml @@ -30,9 +30,9 @@ jobs: - {gen: Visual Studio 17 2022, arch: x64, config: Release} - {gen: Visual Studio 17 2022, arch: x64, config: Debug} steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: ccache - uses: hendrikmuhs/ccache-action@v1.2 + uses: hendrikmuhs/ccache-action@d62db5f07c26379fc4b4e0916f098a92573c3b03 # v1.2.23 with: key: ${{github.job}}-${{matrix.os}}-${{matrix.config}} - name: Install Dependencies From 8b978aa7706a132f075d0cc71b66ec7be2e383b8 Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Tue, 28 Apr 2026 16:27:49 +0200 Subject: [PATCH 2/4] ci: add node ncrypto sync workflow Signed-off-by: Filip Skokan --- .github/sync-node-ncrypto.json | 3 + .github/workflows/sync-node-ncrypto.yml | 109 ++++++++++ tools/sync-node-ncrypto.py | 262 ++++++++++++++++++++++++ 3 files changed, 374 insertions(+) create mode 100644 .github/sync-node-ncrypto.json create mode 100644 .github/workflows/sync-node-ncrypto.yml create mode 100644 tools/sync-node-ncrypto.py diff --git a/.github/sync-node-ncrypto.json b/.github/sync-node-ncrypto.json new file mode 100644 index 0000000..484039f --- /dev/null +++ b/.github/sync-node-ncrypto.json @@ -0,0 +1,3 @@ +{ + "node_commit": null +} diff --git a/.github/workflows/sync-node-ncrypto.yml b/.github/workflows/sync-node-ncrypto.yml new file mode 100644 index 0000000..f70119f --- /dev/null +++ b/.github/workflows/sync-node-ncrypto.yml @@ -0,0 +1,109 @@ +name: Sync Node ncrypto + +on: + workflow_dispatch: + inputs: + node_ref: + description: nodejs/node ref to sync from + required: true + default: main + base_node_ref: + description: Optional previous nodejs/node ref for bootstrap or recovery + required: false + default: '' + +permissions: + contents: write + pull-requests: write + +jobs: + sync: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + ref: main + fetch-depth: 0 + + - name: Sync from nodejs/node + id: sync + env: + NODE_REF: ${{ inputs.node_ref }} + BASE_NODE_REF: ${{ inputs.base_node_ref }} + run: | + python3 tools/sync-node-ncrypto.py \ + --node-ref "$NODE_REF" \ + --base-node-ref "$BASE_NODE_REF" + + - name: Stop when there are no changes + if: steps.sync.outputs.has_changes != 'true' + run: echo 'No ncrypto changes to sync.' + + - name: Commit sync branch + id: commit + if: steps.sync.outputs.has_changes == 'true' + run: | + branch='${{ steps.sync.outputs.branch_name }}' + git switch -c "$branch" + git fetch origin "$branch:refs/remotes/origin/$branch" || true + git config user.name 'github-actions[bot]' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + git add \ + .github/sync-node-ncrypto.json \ + include/ncrypto.h \ + src/engine.cpp \ + src/ncrypto.cpp + git commit \ + -m 'chore: sync ncrypto from nodejs/node' \ + -m 'Node-Base-Commit: ${{ steps.sync.outputs.base_sha }}' \ + -m 'Node-Target-Commit: ${{ steps.sync.outputs.target_sha }}' + git push --force-with-lease origin "$branch" + echo "branch=$branch" >> "$GITHUB_OUTPUT" + + - name: Prepare PR body + if: steps.sync.outputs.has_changes == 'true' + run: | + { + echo 'Syncs `deps/ncrypto` from `nodejs/node` into this repository.' + echo + echo '- Base node commit: `${{ steps.sync.outputs.base_sha }}`' + echo '- Target node commit: `${{ steps.sync.outputs.target_sha }}`' + echo '- Conflicts: `${{ steps.sync.outputs.has_conflicts }}`' + if [ '${{ steps.sync.outputs.has_conflicts }}' = 'true' ]; then + echo + echo 'This PR was opened as a draft because the 3-way merge produced conflicts:' + echo + printf '%s\n' '${{ steps.sync.outputs.conflicts }}' | sed 's/^/- `/' | sed 's/$/`/' + fi + } > "$RUNNER_TEMP/pr-body.md" + + - name: Open or update PR + if: steps.sync.outputs.has_changes == 'true' + env: + GH_TOKEN: ${{ github.token }} + run: | + branch='${{ steps.commit.outputs.branch }}' + title='chore: sync ncrypto from nodejs/node' + existing_url="$(gh pr view "$branch" --json url --jq .url 2>/dev/null || true)" + if [ -n "$existing_url" ]; then + gh pr edit "$branch" --title "$title" --body-file "$RUNNER_TEMP/pr-body.md" + if [ '${{ steps.sync.outputs.has_conflicts }}' = 'true' ]; then + gh pr ready "$branch" --undo || true + else + gh pr ready "$branch" || true + fi + echo "$existing_url" + exit 0 + fi + + args=( + pr create + --base main + --head "$branch" + --title "$title" + --body-file "$RUNNER_TEMP/pr-body.md" + ) + if [ '${{ steps.sync.outputs.has_conflicts }}' = 'true' ]; then + args+=(--draft) + fi + gh "${args[@]}" diff --git a/tools/sync-node-ncrypto.py b/tools/sync-node-ncrypto.py new file mode 100644 index 0000000..5a461a3 --- /dev/null +++ b/tools/sync-node-ncrypto.py @@ -0,0 +1,262 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import argparse +import json +import os +import subprocess +import sys +import tempfile +from pathlib import Path +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from collections.abc import Sequence + + +NODE_REPOSITORY = 'https://github.com/nodejs/node.git' +STATE_FILE = Path('.github/sync-node-ncrypto.json') +MAPPINGS = { + 'deps/ncrypto/ncrypto.h': Path('include/ncrypto.h'), + 'deps/ncrypto/ncrypto.cc': Path('src/ncrypto.cpp'), + 'deps/ncrypto/engine.cc': Path('src/engine.cpp'), +} +SOURCE_SUFFIXES = ('.c', '.cc', '.cpp', '.cxx', '.h', '.hh', '.hpp', '.hxx') + + +class SyncError(Exception): + pass + + +def run( + args: Sequence[str], + *, + input_data: bytes | None = None, + check: bool = True, +) -> subprocess.CompletedProcess[bytes]: + result = subprocess.run(args, input=input_data, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=False) + if check and result.returncode != 0: + command = ' '.join(args) + stderr = result.stderr.decode(errors='replace').strip() + raise SyncError(f'{command} failed: {stderr}') + return result + + +def git(args: Sequence[str], *, check: bool = True) -> subprocess.CompletedProcess[bytes]: + return run(('git', *args), check=check) + + +def repo_root() -> Path: + return Path(git(('rev-parse', '--show-toplevel')).stdout.decode().strip()) + + +def fetch_ref(repository: str, ref: str) -> str: + if not ref: + raise SyncError('ref cannot be empty') + + git(('fetch', '--no-tags', '--depth=1', repository, ref)) + return git(('rev-parse', 'FETCH_HEAD^{commit}')).stdout.decode().strip() + + +def load_state(path: Path) -> str | None: + if not path.exists(): + return None + + with path.open(encoding='utf-8') as file: + state = json.load(file) + + node_commit = state.get('node_commit') + if node_commit is not None and not isinstance(node_commit, str): + raise SyncError(f'{path} has an invalid node_commit value') + return node_commit or None + + +def write_state(path: Path, node_commit: str) -> None: + path.parent.mkdir(parents=True, exist_ok=True) + state = {'node_commit': node_commit} + with path.open('w', encoding='utf-8') as file: + json.dump(state, file, indent=2) + file.write('\n') + + +def node_file(commit: str, path: str) -> bytes: + return git(('show', f'{commit}:{path}')).stdout + + +def node_ncrypto_files(commit: str) -> list[str]: + output = git(('ls-tree', '-r', '--name-only', commit, '--', 'deps/ncrypto')).stdout.decode() + return [line for line in output.splitlines() if line] + + +def check_unmapped_files(commit: str) -> None: + mapped = set(MAPPINGS) + unmapped = [ + path + for path in node_ncrypto_files(commit) + if path.endswith(SOURCE_SUFFIXES) and path not in mapped + ] + if unmapped: + files = '\n'.join(f'- {path}' for path in unmapped) + raise SyncError(f'nodejs/node added unmapped deps/ncrypto source/header files:\n{files}') + + +def mapped_files_different_from_node(commit: str) -> list[str]: + return [ + str(destination) + for source, destination in MAPPINGS.items() + if destination.read_bytes() != node_file(commit, source) + ] + + +def write_temp_file(directory: Path, name: str, data: bytes) -> Path: + path = directory / name + path.write_bytes(data) + return path + + +def merge_file( + *, + source: str, + destination: Path, + base_sha: str, + target_sha: str, + temporary_directory: Path, +) -> tuple[bytes, bool]: + base = write_temp_file(temporary_directory, 'base', node_file(base_sha, source)) + theirs = write_temp_file(temporary_directory, 'theirs', node_file(target_sha, source)) + ours = write_temp_file(temporary_directory, 'ours', destination.read_bytes()) + result = git( + ( + 'merge-file', + '-p', + '--diff3', + '-L', + f'nodejs/ncrypto:{destination}', + '-L', + f'nodejs/node:{source}@{base_sha[:12]}', + '-L', + f'nodejs/node:{source}@{target_sha[:12]}', + str(ours), + str(base), + str(theirs), + ), + check=False, + ) + if result.returncode >= 128: + stderr = result.stderr.decode(errors='replace').strip() + raise SyncError(f'failed to merge {source} into {destination}: {stderr}') + return result.stdout, result.returncode != 0 + + +def has_changes(paths: Sequence[Path]) -> bool: + result = git(('status', '--porcelain', '--', *(str(path) for path in paths))) + return bool(result.stdout.strip()) + + +def write_github_output(values: dict[str, str | bool | Sequence[str]]) -> None: + output_path = os.environ.get('GITHUB_OUTPUT') + if not output_path: + return + + with Path(output_path).open('a', encoding='utf-8') as file: + for key, value in values.items(): + if isinstance(value, bool): + file.write(f'{key}={str(value).lower()}\n') + elif isinstance(value, str): + file.write(f'{key}={value}\n') + else: + file.write(f'{key}< int: + root = repo_root() + os.chdir(root) + + state_path = Path(args.state_file) + current_state = load_state(state_path) + base_ref = args.base_node_ref or current_state + if base_ref is None: + raise SyncError(f'{state_path} does not record a node_commit; pass --base-node-ref to bootstrap the sync') + + base_sha = fetch_ref(args.node_repository, base_ref) + target_sha = fetch_ref(args.node_repository, args.node_ref) + + check_unmapped_files(target_sha) + + if current_state is None and base_sha == target_sha: + differing_files = mapped_files_different_from_node(target_sha) + if differing_files: + files = '\n'.join(f'- {path}' for path in differing_files) + raise SyncError( + 'refusing to bootstrap sync state from identical base and target Node commits because the mapped ' + f'standalone files differ from nodejs/node:\n{files}\n' + 'Pass the previous imported nodejs/node commit as --base-node-ref, not the target commit.' + ) + + conflicts: list[str] = [] + would_change = current_state != target_sha + with tempfile.TemporaryDirectory(prefix='sync-node-ncrypto-') as temporary_directory_name: + temporary_directory = Path(temporary_directory_name) + for source, destination in MAPPINGS.items(): + merged, conflicted = merge_file( + source=source, + destination=destination, + base_sha=base_sha, + target_sha=target_sha, + temporary_directory=temporary_directory, + ) + if destination.read_bytes() != merged: + would_change = True + if not args.dry_run: + destination.write_bytes(merged) + if conflicted: + conflicts.append(str(destination)) + + if not args.dry_run: + write_state(state_path, target_sha) + + paths = [*MAPPINGS.values(), state_path] + changed = would_change if args.dry_run else has_changes(paths) + outputs = { + 'base_sha': base_sha, + 'target_sha': target_sha, + 'target_short_sha': target_sha[:12], + 'has_changes': changed, + 'has_conflicts': bool(conflicts), + 'conflicts': conflicts, + 'branch_name': f'sync-node-ncrypto/{target_sha[:12]}', + } + write_github_output(outputs) + + print(f'Base node commit: {base_sha}') + print(f'Target node commit: {target_sha}') + print(f'Changed files: {str(changed).lower()}') + print(f'Conflicts: {str(bool(conflicts)).lower()}') + for path in conflicts: + print(f'Conflict: {path}') + + return 0 + + +def parse_args(argv: Sequence[str]) -> argparse.Namespace: + parser = argparse.ArgumentParser(description='Sync nodejs/node deps/ncrypto into standalone ncrypto.') + parser.add_argument('--node-repository', default=NODE_REPOSITORY) + parser.add_argument('--node-ref', default='main') + parser.add_argument('--base-node-ref', default='') + parser.add_argument('--state-file', default=str(STATE_FILE)) + parser.add_argument('--dry-run', action='store_true') + return parser.parse_args(argv) + + +def main(argv: Sequence[str]) -> int: + try: + return sync(parse_args(argv)) + except SyncError as error: + print(f'error: {error}', file=sys.stderr) + return 1 + + +if __name__ == '__main__': + raise SystemExit(main(sys.argv[1:])) From 0b0eccaec8c18e8cbb7e5e59770e888da2c1283c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2026 14:33:45 +0000 Subject: [PATCH 3/4] chore: sync ncrypto from nodejs/node Node-Base-Commit: 84aaed75978e537ebcfa82b094794fa4bb0ffa79 Node-Target-Commit: 8385efc01343a835e3a0efe05611f44272cbb413 --- .github/sync-node-ncrypto.json | 2 +- include/ncrypto.h | 64 ++++++++++- src/ncrypto.cpp | 199 +++++++++++++++++++++++++++++---- 3 files changed, 238 insertions(+), 27 deletions(-) diff --git a/.github/sync-node-ncrypto.json b/.github/sync-node-ncrypto.json index 484039f..5e32169 100644 --- a/.github/sync-node-ncrypto.json +++ b/.github/sync-node-ncrypto.json @@ -1,3 +1,3 @@ { - "node_commit": null + "node_commit": "8385efc01343a835e3a0efe05611f44272cbb413" } diff --git a/include/ncrypto.h b/include/ncrypto.h index 79b7298..222139c 100644 --- a/include/ncrypto.h +++ b/include/ncrypto.h @@ -899,6 +899,9 @@ class EVPKeyPointer final { DER, PEM, JWK, + RAW_PUBLIC, + RAW_PRIVATE, + RAW_SEED, }; enum class PKParseError { NOT_RECOGNIZED, NEED_PASSPHRASE, FAILED }; @@ -908,6 +911,7 @@ class EVPKeyPointer final { bool output_key_object = false; PKFormatType format = PKFormatType::DER; PKEncodingType type = PKEncodingType::PKCS8; + int ec_point_form = POINT_CONVERSION_UNCOMPRESSED; AsymmetricKeyEncodingConfig() = default; AsymmetricKeyEncodingConfig(bool output_key_object, PKFormatType format, @@ -1622,8 +1626,9 @@ int NoPasswordCallback(char* buf, int size, int rwflag, void* u); int PasswordCallback(char* buf, int size, int rwflag, void* u); -bool SafeX509SubjectAltNamePrint(const BIOPointer& out, X509_EXTENSION* ext); -bool SafeX509InfoAccessPrint(const BIOPointer& out, X509_EXTENSION* ext); +bool SafeX509SubjectAltNamePrint(const BIOPointer& out, + const X509_EXTENSION* ext); +bool SafeX509InfoAccessPrint(const BIOPointer& out, const X509_EXTENSION* ext); // ============================================================================ // SPKAC @@ -1698,6 +1703,7 @@ DataPointer pbkdf2(const Digest& md, uint32_t iterations, size_t length); +<<<<<<< nodejs/ncrypto:include/ncrypto.h #if OPENSSL_VERSION_NUMBER >= 0x30200000L #ifndef OPENSSL_NO_ARGON2 enum class Argon2Type { ARGON2D, ARGON2I, ARGON2ID }; @@ -1715,6 +1721,60 @@ DataPointer argon2(const Buffer& pass, #endif #endif +||||||| nodejs/node:deps/ncrypto/ncrypto.h@84aaed75978e +======= +#if OPENSSL_VERSION_NUMBER >= 0x30200000L +#ifndef OPENSSL_NO_ARGON2 +enum class Argon2Type { ARGON2D, ARGON2I, ARGON2ID }; + +DataPointer argon2(const Buffer& pass, + const Buffer& salt, + uint32_t lanes, + size_t length, + uint32_t memcost, + uint32_t iter, + uint32_t version, + const Buffer& secret, + const Buffer& ad, + Argon2Type type); +#endif +#endif + +// ============================================================================ +// KEM (Key Encapsulation Mechanism) +#if OPENSSL_VERSION_MAJOR >= 3 + +class KEM final { + public: + struct EncapsulateResult { + DataPointer ciphertext; + DataPointer shared_key; + + EncapsulateResult() = default; + EncapsulateResult(DataPointer ct, DataPointer sk) + : ciphertext(std::move(ct)), shared_key(std::move(sk)) {} + }; + + // Encapsulate a shared secret using KEM with a public key. + // Returns both the ciphertext and shared secret. + static std::optional Encapsulate( + const EVPKeyPointer& public_key); + + // Decapsulate a shared secret using KEM with a private key and ciphertext. + // Returns the shared secret. + static DataPointer Decapsulate(const EVPKeyPointer& private_key, + const Buffer& ciphertext); + + private: +#if !OPENSSL_VERSION_PREREQ(3, 5) + static bool SetOperationParameter(EVP_PKEY_CTX* ctx, + const EVPKeyPointer& key); +#endif +}; + +#endif // OPENSSL_VERSION_MAJOR >= 3 + +>>>>>>> nodejs/node:deps/ncrypto/ncrypto.h@8385efc01343 // ============================================================================ // KEM (Key Encapsulation Mechanism) #if OPENSSL_VERSION_MAJOR >= 3 diff --git a/src/ncrypto.cpp b/src/ncrypto.cpp index ee0822a..22f74ea 100644 --- a/src/ncrypto.cpp +++ b/src/ncrypto.cpp @@ -22,12 +22,20 @@ #include #include #include +<<<<<<< nodejs/ncrypto:src/ncrypto.cpp #include #include +||||||| nodejs/node:deps/ncrypto/ncrypto.cc@84aaed75978e +======= +#include +>>>>>>> nodejs/node:deps/ncrypto/ncrypto.cc@8385efc01343 #if OPENSSL_VERSION_MAJOR >= 3 #include #include #include +#if OPENSSL_VERSION_NUMBER >= 0x30200000L +#include +#endif #endif #if OPENSSL_WITH_PQC struct PQCMapping { @@ -819,11 +827,15 @@ bool PrintGeneralName(const BIOPointer& out, const GENERAL_NAME* gen) { // Note that the preferred name syntax (see RFCs 5280 and 1034) with // wildcards is a subset of what we consider "safe", so spec-compliant DNS // names will never need to be escaped. - PrintAltName(out, reinterpret_cast(name->data), name->length); + PrintAltName(out, + reinterpret_cast(ASN1_STRING_get0_data(name)), + ASN1_STRING_length(name)); } else if (gen->type == GEN_EMAIL) { ASN1_IA5STRING* name = gen->d.rfc822Name; BIO_write(out.get(), "email:", 6); - PrintAltName(out, reinterpret_cast(name->data), name->length); + PrintAltName(out, + reinterpret_cast(ASN1_STRING_get0_data(name)), + ASN1_STRING_length(name)); } else if (gen->type == GEN_URI) { ASN1_IA5STRING* name = gen->d.uniformResourceIdentifier; BIO_write(out.get(), "URI:", 4); @@ -831,7 +843,9 @@ bool PrintGeneralName(const BIOPointer& out, const GENERAL_NAME* gen) { // with a few exceptions, most notably URIs that contains commas (see // RFC 2396). In other words, most legitimate URIs will not require // escaping. - PrintAltName(out, reinterpret_cast(name->data), name->length); + PrintAltName(out, + reinterpret_cast(ASN1_STRING_get0_data(name)), + ASN1_STRING_length(name)); } else if (gen->type == GEN_DIRNAME) { // Earlier versions of Node.js used X509_NAME_oneline to print the X509_NAME // object. The format was non standard and should be avoided. The use of @@ -864,17 +878,18 @@ bool PrintGeneralName(const BIOPointer& out, const GENERAL_NAME* gen) { } else if (gen->type == GEN_IPADD) { BIO_printf(out.get(), "IP Address:"); const ASN1_OCTET_STRING* ip = gen->d.ip; - const unsigned char* b = ip->data; - if (ip->length == 4) { + const unsigned char* b = ASN1_STRING_get0_data(ip); + int ip_len = ASN1_STRING_length(ip); + if (ip_len == 4) { BIO_printf(out.get(), "%d.%d.%d.%d", b[0], b[1], b[2], b[3]); - } else if (ip->length == 16) { + } else if (ip_len == 16) { for (unsigned int j = 0; j < 8; j++) { uint16_t pair = (b[2 * j] << 8) | b[2 * j + 1]; BIO_printf(out.get(), (j == 0) ? "%X" : ":%X", pair); } } else { #if OPENSSL_VERSION_MAJOR >= 3 - BIO_printf(out.get(), "", ip->length); + BIO_printf(out.get(), "", ip_len); #else BIO_printf(out.get(), ""); #endif @@ -924,15 +939,15 @@ bool PrintGeneralName(const BIOPointer& out, const GENERAL_NAME* gen) { if (unicode) { auto name = gen->d.otherName->value->value.utf8string; PrintAltName(out, - reinterpret_cast(name->data), - name->length, + reinterpret_cast(ASN1_STRING_get0_data(name)), + ASN1_STRING_length(name), AltNameOption::UTF8, prefix); } else { auto name = gen->d.otherName->value->value.ia5string; PrintAltName(out, - reinterpret_cast(name->data), - name->length, + reinterpret_cast(ASN1_STRING_get0_data(name)), + ASN1_STRING_length(name), AltNameOption::NONE, prefix); } @@ -953,11 +968,14 @@ bool PrintGeneralName(const BIOPointer& out, const GENERAL_NAME* gen) { } } // namespace -bool SafeX509SubjectAltNamePrint(const BIOPointer& out, X509_EXTENSION* ext) { - auto ret = OBJ_obj2nid(X509_EXTENSION_get_object(ext)); +bool SafeX509SubjectAltNamePrint(const BIOPointer& out, + const X509_EXTENSION* ext) { + // const_cast needed for OpenSSL < 4.0 which lacks const-correctness + auto* mext = const_cast(ext); + auto ret = OBJ_obj2nid(X509_EXTENSION_get_object(mext)); if (ret != NID_subject_alt_name) return false; - GENERAL_NAMES* names = static_cast(X509V3_EXT_d2i(ext)); + GENERAL_NAMES* names = static_cast(X509V3_EXT_d2i(mext)); if (names == nullptr) return false; bool ok = true; @@ -976,12 +994,14 @@ bool SafeX509SubjectAltNamePrint(const BIOPointer& out, X509_EXTENSION* ext) { return ok; } -bool SafeX509InfoAccessPrint(const BIOPointer& out, X509_EXTENSION* ext) { - auto ret = OBJ_obj2nid(X509_EXTENSION_get_object(ext)); +bool SafeX509InfoAccessPrint(const BIOPointer& out, const X509_EXTENSION* ext) { + // const_cast needed for OpenSSL < 4.0 which lacks const-correctness + auto* mext = const_cast(ext); + auto ret = OBJ_obj2nid(X509_EXTENSION_get_object(mext)); if (ret != NID_info_access) return false; AUTHORITY_INFO_ACCESS* descs = - static_cast(X509V3_EXT_d2i(ext)); + static_cast(X509V3_EXT_d2i(mext)); if (descs == nullptr) return false; bool ok = true; @@ -1125,7 +1145,7 @@ BIOPointer X509View::getValidFrom() const { if (cert_ == nullptr) return {}; BIOPointer bio(BIO_new(BIO_s_mem())); if (!bio) return {}; - ASN1_TIME_print(bio.get(), X509_get_notBefore(cert_)); + ASN1_TIME_print(bio.get(), X509_get0_notBefore(cert_)); return bio; } @@ -1134,7 +1154,7 @@ BIOPointer X509View::getValidTo() const { if (cert_ == nullptr) return {}; BIOPointer bio(BIO_new(BIO_s_mem())); if (!bio) return {}; - ASN1_TIME_print(bio.get(), X509_get_notAfter(cert_)); + ASN1_TIME_print(bio.get(), X509_get0_notAfter(cert_)); return bio; } @@ -3238,6 +3258,7 @@ const Cipher Cipher::AES_256_GCM = Cipher::FromNid(NID_aes_256_gcm); const Cipher Cipher::AES_128_KW = Cipher::FromNid(NID_id_aes128_wrap); const Cipher Cipher::AES_192_KW = Cipher::FromNid(NID_id_aes192_wrap); const Cipher Cipher::AES_256_KW = Cipher::FromNid(NID_id_aes256_wrap); +<<<<<<< nodejs/ncrypto:src/ncrypto.cpp #ifndef OPENSSL_IS_BORINGSSL const Cipher Cipher::AES_128_OCB = Cipher::FromNid(NID_aes_128_ocb); @@ -3245,6 +3266,12 @@ const Cipher Cipher::AES_192_OCB = Cipher::FromNid(NID_aes_192_ocb); const Cipher Cipher::AES_256_OCB = Cipher::FromNid(NID_aes_256_ocb); #endif +||||||| nodejs/node:deps/ncrypto/ncrypto.cc@84aaed75978e +======= +const Cipher Cipher::AES_128_OCB = Cipher::FromNid(NID_aes_128_ocb); +const Cipher Cipher::AES_192_OCB = Cipher::FromNid(NID_aes_192_ocb); +const Cipher Cipher::AES_256_OCB = Cipher::FromNid(NID_aes_256_ocb); +>>>>>>> nodejs/node:deps/ncrypto/ncrypto.cc@8385efc01343 const Cipher Cipher::CHACHA20_POLY1305 = Cipher::FromNid(NID_chacha20_poly1305); bool Cipher::isGcmMode() const { @@ -3679,8 +3706,38 @@ bool ECKeyPointer::setPublicKey(const ECPointPointer& pub) { bool ECKeyPointer::setPublicKeyRaw(const BignumPointer& x, const BignumPointer& y) { if (!key_) return false; - return EC_KEY_set_public_key_affine_coordinates( - key_.get(), x.get(), y.get()) == 1; + const EC_GROUP* group = EC_KEY_get0_group(key_.get()); + if (group == nullptr) return false; + + // For curves with cofactor h=1, use EC_POINT_oct2point + + // EC_KEY_set_public_key instead of EC_KEY_set_public_key_affine_coordinates. + // The latter internally calls EC_KEY_check_key() which performs a scalar + // multiplication (n*Q) for order validation — redundant when h=1 since every + // on-curve point already has order n. EC_POINT_oct2point validates the point + // is on the curve, which is sufficient. For curves with h!=1, fall back to + // the full check. + auto cofactor = BignumPointer::New(); + if (!cofactor || !EC_GROUP_get_cofactor(group, cofactor.get(), nullptr) || + !cofactor.isOne()) { + return EC_KEY_set_public_key_affine_coordinates( + key_.get(), x.get(), y.get()) == 1; + } + + // Field element byte length: ceil(degree_bits / 8). + size_t field_len = (EC_GROUP_get_degree(group) + 7) / 8; + // Build an uncompressed point: 0x04 || x || y, each padded to field_len. + size_t uncompressed_len = 1 + 2 * field_len; + auto buf = DataPointer::Alloc(uncompressed_len); + if (!buf) return false; + unsigned char* ptr = static_cast(buf.get()); + ptr[0] = POINT_CONVERSION_UNCOMPRESSED; + x.encodePaddedInto(ptr + 1, field_len); + y.encodePaddedInto(ptr + 1 + field_len, field_len); + + auto point = ECPointPointer::New(group); + if (!point) return false; + if (!point.setFromBuffer({ptr, uncompressed_len}, group)) return false; + return EC_KEY_set_public_key(key_.get(), point.get()) == 1; } bool ECKeyPointer::setPrivateKey(const BignumPointer& priv) { @@ -4495,6 +4552,57 @@ std::optional EVPMDCtxPointer::verifyInit( return ctx; } +<<<<<<< nodejs/ncrypto:src/ncrypto.cpp +std::optional EVPMDCtxPointer::signInitWithContext( + const EVPKeyPointer& key, + const Digest& digest, + const Buffer& context_string) { +#ifdef OSSL_SIGNATURE_PARAM_CONTEXT_STRING + EVP_PKEY_CTX* ctx = nullptr; + + const OSSL_PARAM params[] = { + OSSL_PARAM_construct_octet_string( + OSSL_SIGNATURE_PARAM_CONTEXT_STRING, + const_cast(context_string.data), + context_string.len), + OSSL_PARAM_END}; + + if (!EVP_DigestSignInit_ex( + ctx_.get(), &ctx, nullptr, nullptr, nullptr, key.get(), params)) { + return std::nullopt; + } + return ctx; +#else + return std::nullopt; +#endif +} + +std::optional EVPMDCtxPointer::verifyInitWithContext( + const EVPKeyPointer& key, + const Digest& digest, + const Buffer& context_string) { +#ifdef OSSL_SIGNATURE_PARAM_CONTEXT_STRING + EVP_PKEY_CTX* ctx = nullptr; + + const OSSL_PARAM params[] = { + OSSL_PARAM_construct_octet_string( + OSSL_SIGNATURE_PARAM_CONTEXT_STRING, + const_cast(context_string.data), + context_string.len), + OSSL_PARAM_END}; + + if (!EVP_DigestVerifyInit_ex( + ctx_.get(), &ctx, nullptr, nullptr, nullptr, key.get(), params)) { + return std::nullopt; + } + return ctx; +#else + return std::nullopt; +#endif +} + +||||||| nodejs/node:deps/ncrypto/ncrypto.cc@84aaed75978e +======= std::optional EVPMDCtxPointer::signInitWithContext( const EVPKeyPointer& key, const Digest& digest, @@ -4502,6 +4610,27 @@ std::optional EVPMDCtxPointer::signInitWithContext( #ifdef OSSL_SIGNATURE_PARAM_CONTEXT_STRING EVP_PKEY_CTX* ctx = nullptr; +#ifdef OSSL_SIGNATURE_PARAM_INSTANCE + // Ed25519 requires the INSTANCE param to switch into Ed25519ctx mode. + // Without it, OpenSSL silently ignores the context string. + if (key.id() == EVP_PKEY_ED25519) { + const OSSL_PARAM params[] = { + OSSL_PARAM_construct_utf8_string( + OSSL_SIGNATURE_PARAM_INSTANCE, const_cast("Ed25519ctx"), 0), + OSSL_PARAM_construct_octet_string( + OSSL_SIGNATURE_PARAM_CONTEXT_STRING, + const_cast(context_string.data), + context_string.len), + OSSL_PARAM_END}; + + if (!EVP_DigestSignInit_ex( + ctx_.get(), &ctx, nullptr, nullptr, nullptr, key.get(), params)) { + return std::nullopt; + } + return ctx; + } +#endif // OSSL_SIGNATURE_PARAM_INSTANCE + const OSSL_PARAM params[] = { OSSL_PARAM_construct_octet_string( OSSL_SIGNATURE_PARAM_CONTEXT_STRING, @@ -4526,6 +4655,27 @@ std::optional EVPMDCtxPointer::verifyInitWithContext( #ifdef OSSL_SIGNATURE_PARAM_CONTEXT_STRING EVP_PKEY_CTX* ctx = nullptr; +#ifdef OSSL_SIGNATURE_PARAM_INSTANCE + // Ed25519 requires the INSTANCE param to switch into Ed25519ctx mode. + // Without it, OpenSSL silently ignores the context string. + if (key.id() == EVP_PKEY_ED25519) { + const OSSL_PARAM params[] = { + OSSL_PARAM_construct_utf8_string( + OSSL_SIGNATURE_PARAM_INSTANCE, const_cast("Ed25519ctx"), 0), + OSSL_PARAM_construct_octet_string( + OSSL_SIGNATURE_PARAM_CONTEXT_STRING, + const_cast(context_string.data), + context_string.len), + OSSL_PARAM_END}; + + if (!EVP_DigestVerifyInit_ex( + ctx_.get(), &ctx, nullptr, nullptr, nullptr, key.get(), params)) { + return std::nullopt; + } + return ctx; + } +#endif // OSSL_SIGNATURE_PARAM_INSTANCE + const OSSL_PARAM params[] = { OSSL_PARAM_construct_octet_string( OSSL_SIGNATURE_PARAM_CONTEXT_STRING, @@ -4543,6 +4693,7 @@ std::optional EVPMDCtxPointer::verifyInitWithContext( #endif } +>>>>>>> nodejs/node:deps/ncrypto/ncrypto.cc@8385efc01343 DataPointer EVPMDCtxPointer::signOneShot( const Buffer& buf) const { if (!ctx_) return {}; @@ -4824,12 +4975,12 @@ bool X509Name::Iterator::operator!=(const Iterator& other) const { std::pair X509Name::Iterator::operator*() const { if (loc_ == name_.total_) return {{}, {}}; - X509_NAME_ENTRY* entry = X509_NAME_get_entry(name_, loc_); + const X509_NAME_ENTRY* entry = X509_NAME_get_entry(name_, loc_); if (entry == nullptr) [[unlikely]] return {{}, {}}; - ASN1_OBJECT* name = X509_NAME_ENTRY_get_object(entry); - ASN1_STRING* value = X509_NAME_ENTRY_get_data(entry); + const ASN1_OBJECT* name = X509_NAME_ENTRY_get_object(entry); + const ASN1_STRING* value = X509_NAME_ENTRY_get_data(entry); if (name == nullptr || value == nullptr) [[unlikely]] { return {{}, {}}; From ce5b003ab7f293e68ab99820a720fb51fb9e265d Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Tue, 28 Apr 2026 17:07:13 +0200 Subject: [PATCH 4/4] fixup! chore: sync ncrypto from nodejs/node Signed-off-by: Filip Skokan --- include/ncrypto.h | 55 -------------------------------------- src/ncrypto.cpp | 68 ----------------------------------------------- 2 files changed, 123 deletions(-) diff --git a/include/ncrypto.h b/include/ncrypto.h index 222139c..4f499a9 100644 --- a/include/ncrypto.h +++ b/include/ncrypto.h @@ -1703,7 +1703,6 @@ DataPointer pbkdf2(const Digest& md, uint32_t iterations, size_t length); -<<<<<<< nodejs/ncrypto:include/ncrypto.h #if OPENSSL_VERSION_NUMBER >= 0x30200000L #ifndef OPENSSL_NO_ARGON2 enum class Argon2Type { ARGON2D, ARGON2I, ARGON2ID }; @@ -1721,60 +1720,6 @@ DataPointer argon2(const Buffer& pass, #endif #endif -||||||| nodejs/node:deps/ncrypto/ncrypto.h@84aaed75978e -======= -#if OPENSSL_VERSION_NUMBER >= 0x30200000L -#ifndef OPENSSL_NO_ARGON2 -enum class Argon2Type { ARGON2D, ARGON2I, ARGON2ID }; - -DataPointer argon2(const Buffer& pass, - const Buffer& salt, - uint32_t lanes, - size_t length, - uint32_t memcost, - uint32_t iter, - uint32_t version, - const Buffer& secret, - const Buffer& ad, - Argon2Type type); -#endif -#endif - -// ============================================================================ -// KEM (Key Encapsulation Mechanism) -#if OPENSSL_VERSION_MAJOR >= 3 - -class KEM final { - public: - struct EncapsulateResult { - DataPointer ciphertext; - DataPointer shared_key; - - EncapsulateResult() = default; - EncapsulateResult(DataPointer ct, DataPointer sk) - : ciphertext(std::move(ct)), shared_key(std::move(sk)) {} - }; - - // Encapsulate a shared secret using KEM with a public key. - // Returns both the ciphertext and shared secret. - static std::optional Encapsulate( - const EVPKeyPointer& public_key); - - // Decapsulate a shared secret using KEM with a private key and ciphertext. - // Returns the shared secret. - static DataPointer Decapsulate(const EVPKeyPointer& private_key, - const Buffer& ciphertext); - - private: -#if !OPENSSL_VERSION_PREREQ(3, 5) - static bool SetOperationParameter(EVP_PKEY_CTX* ctx, - const EVPKeyPointer& key); -#endif -}; - -#endif // OPENSSL_VERSION_MAJOR >= 3 - ->>>>>>> nodejs/node:deps/ncrypto/ncrypto.h@8385efc01343 // ============================================================================ // KEM (Key Encapsulation Mechanism) #if OPENSSL_VERSION_MAJOR >= 3 diff --git a/src/ncrypto.cpp b/src/ncrypto.cpp index 22f74ea..5e450e2 100644 --- a/src/ncrypto.cpp +++ b/src/ncrypto.cpp @@ -15,20 +15,11 @@ #include #endif -#if OPENSSL_VERSION_NUMBER >= 0x30200000L -#include -#endif - #include #include #include -<<<<<<< nodejs/ncrypto:src/ncrypto.cpp #include #include -||||||| nodejs/node:deps/ncrypto/ncrypto.cc@84aaed75978e -======= -#include ->>>>>>> nodejs/node:deps/ncrypto/ncrypto.cc@8385efc01343 #if OPENSSL_VERSION_MAJOR >= 3 #include #include @@ -3258,7 +3249,6 @@ const Cipher Cipher::AES_256_GCM = Cipher::FromNid(NID_aes_256_gcm); const Cipher Cipher::AES_128_KW = Cipher::FromNid(NID_id_aes128_wrap); const Cipher Cipher::AES_192_KW = Cipher::FromNid(NID_id_aes192_wrap); const Cipher Cipher::AES_256_KW = Cipher::FromNid(NID_id_aes256_wrap); -<<<<<<< nodejs/ncrypto:src/ncrypto.cpp #ifndef OPENSSL_IS_BORINGSSL const Cipher Cipher::AES_128_OCB = Cipher::FromNid(NID_aes_128_ocb); @@ -3266,12 +3256,6 @@ const Cipher Cipher::AES_192_OCB = Cipher::FromNid(NID_aes_192_ocb); const Cipher Cipher::AES_256_OCB = Cipher::FromNid(NID_aes_256_ocb); #endif -||||||| nodejs/node:deps/ncrypto/ncrypto.cc@84aaed75978e -======= -const Cipher Cipher::AES_128_OCB = Cipher::FromNid(NID_aes_128_ocb); -const Cipher Cipher::AES_192_OCB = Cipher::FromNid(NID_aes_192_ocb); -const Cipher Cipher::AES_256_OCB = Cipher::FromNid(NID_aes_256_ocb); ->>>>>>> nodejs/node:deps/ncrypto/ncrypto.cc@8385efc01343 const Cipher Cipher::CHACHA20_POLY1305 = Cipher::FromNid(NID_chacha20_poly1305); bool Cipher::isGcmMode() const { @@ -4552,57 +4536,6 @@ std::optional EVPMDCtxPointer::verifyInit( return ctx; } -<<<<<<< nodejs/ncrypto:src/ncrypto.cpp -std::optional EVPMDCtxPointer::signInitWithContext( - const EVPKeyPointer& key, - const Digest& digest, - const Buffer& context_string) { -#ifdef OSSL_SIGNATURE_PARAM_CONTEXT_STRING - EVP_PKEY_CTX* ctx = nullptr; - - const OSSL_PARAM params[] = { - OSSL_PARAM_construct_octet_string( - OSSL_SIGNATURE_PARAM_CONTEXT_STRING, - const_cast(context_string.data), - context_string.len), - OSSL_PARAM_END}; - - if (!EVP_DigestSignInit_ex( - ctx_.get(), &ctx, nullptr, nullptr, nullptr, key.get(), params)) { - return std::nullopt; - } - return ctx; -#else - return std::nullopt; -#endif -} - -std::optional EVPMDCtxPointer::verifyInitWithContext( - const EVPKeyPointer& key, - const Digest& digest, - const Buffer& context_string) { -#ifdef OSSL_SIGNATURE_PARAM_CONTEXT_STRING - EVP_PKEY_CTX* ctx = nullptr; - - const OSSL_PARAM params[] = { - OSSL_PARAM_construct_octet_string( - OSSL_SIGNATURE_PARAM_CONTEXT_STRING, - const_cast(context_string.data), - context_string.len), - OSSL_PARAM_END}; - - if (!EVP_DigestVerifyInit_ex( - ctx_.get(), &ctx, nullptr, nullptr, nullptr, key.get(), params)) { - return std::nullopt; - } - return ctx; -#else - return std::nullopt; -#endif -} - -||||||| nodejs/node:deps/ncrypto/ncrypto.cc@84aaed75978e -======= std::optional EVPMDCtxPointer::signInitWithContext( const EVPKeyPointer& key, const Digest& digest, @@ -4693,7 +4626,6 @@ std::optional EVPMDCtxPointer::verifyInitWithContext( #endif } ->>>>>>> nodejs/node:deps/ncrypto/ncrypto.cc@8385efc01343 DataPointer EVPMDCtxPointer::signOneShot( const Buffer& buf) const { if (!ctx_) return {};