From 43c70afcdbbf8544d8ad561968d11852b2721e4b Mon Sep 17 00:00:00 2001 From: Brad Anderson Date: Wed, 10 Sep 2025 23:06:06 -0400 Subject: [PATCH 1/2] fix: cleanup ncrypto, add modern windsurf rules structure --- .cursorrules | 1 - .windsurf/rules/cpp.md | 9 + .windsurf/rules/local.md | 12 + .rules => .windsurf/rules/project.md | 35 +- .windsurf/rules/typescript.md | 31 + .windsurfrules | 1 - bun.lock | 486 +++-- example/ios/Podfile.lock | 2 +- .../QuickCrypto.podspec | 2 +- .../android/CMakeLists.txt | 4 +- .../deps/ncrypto/.bazelignore | 4 - .../deps/ncrypto/.bazelrc | 2 - .../deps/ncrypto/.bazelversion | 1 - .../deps/ncrypto/.clang-format | 2 - .../deps/ncrypto/.gitignore | 4 - .../deps/ncrypto/.python-version | 1 - .../deps/ncrypto/BUILD.bazel | 10 - .../deps/ncrypto/CMakeLists.txt | 55 - .../deps/ncrypto/LICENSE | 21 - .../deps/ncrypto/MODULE.bazel | 1 - .../deps/ncrypto/MODULE.bazel.lock | 280 --- .../deps/ncrypto/WORKSPACE | 11 - .../deps/ncrypto/cmake/CPM.cmake | 1225 ----------- .../deps/ncrypto/cmake/ncrypto-flags.cmake | 15 - .../deps/ncrypto/include/dh-primes.h | 67 - .../ncrypto/{src/ncrypto.cpp => ncrypto.cc} | 1861 +++++++++++------ .../deps/ncrypto/{include => }/ncrypto.h | 551 +++-- .../deps/ncrypto/pyproject.toml | 38 - .../deps/ncrypto/src/CMakeLists.txt | 8 - .../deps/ncrypto/src/engine.cpp | 91 - .../deps/ncrypto/tests/BUILD.bazel | 9 - .../deps/ncrypto/tests/CMakeLists.txt | 7 - .../deps/ncrypto/tests/basic.cpp | 5 - .../deps/ncrypto/tools/run-clang-format.sh | 42 - scripts/setup_clang_env.sh | 4 +- 35 files changed, 1935 insertions(+), 2963 deletions(-) delete mode 120000 .cursorrules create mode 100644 .windsurf/rules/cpp.md create mode 100644 .windsurf/rules/local.md rename .rules => .windsurf/rules/project.md (51%) create mode 100644 .windsurf/rules/typescript.md delete mode 120000 .windsurfrules delete mode 100644 packages/react-native-quick-crypto/deps/ncrypto/.bazelignore delete mode 100644 packages/react-native-quick-crypto/deps/ncrypto/.bazelrc delete mode 100644 packages/react-native-quick-crypto/deps/ncrypto/.bazelversion delete mode 100644 packages/react-native-quick-crypto/deps/ncrypto/.clang-format delete mode 100644 packages/react-native-quick-crypto/deps/ncrypto/.gitignore delete mode 100644 packages/react-native-quick-crypto/deps/ncrypto/.python-version delete mode 100644 packages/react-native-quick-crypto/deps/ncrypto/BUILD.bazel delete mode 100644 packages/react-native-quick-crypto/deps/ncrypto/CMakeLists.txt delete mode 100644 packages/react-native-quick-crypto/deps/ncrypto/LICENSE delete mode 100644 packages/react-native-quick-crypto/deps/ncrypto/MODULE.bazel delete mode 100644 packages/react-native-quick-crypto/deps/ncrypto/MODULE.bazel.lock delete mode 100644 packages/react-native-quick-crypto/deps/ncrypto/WORKSPACE delete mode 100644 packages/react-native-quick-crypto/deps/ncrypto/cmake/CPM.cmake delete mode 100644 packages/react-native-quick-crypto/deps/ncrypto/cmake/ncrypto-flags.cmake delete mode 100644 packages/react-native-quick-crypto/deps/ncrypto/include/dh-primes.h rename packages/react-native-quick-crypto/deps/ncrypto/{src/ncrypto.cpp => ncrypto.cc} (73%) rename packages/react-native-quick-crypto/deps/ncrypto/{include => }/ncrypto.h (78%) delete mode 100644 packages/react-native-quick-crypto/deps/ncrypto/pyproject.toml delete mode 100644 packages/react-native-quick-crypto/deps/ncrypto/src/CMakeLists.txt delete mode 100644 packages/react-native-quick-crypto/deps/ncrypto/src/engine.cpp delete mode 100644 packages/react-native-quick-crypto/deps/ncrypto/tests/BUILD.bazel delete mode 100644 packages/react-native-quick-crypto/deps/ncrypto/tests/CMakeLists.txt delete mode 100644 packages/react-native-quick-crypto/deps/ncrypto/tests/basic.cpp delete mode 100755 packages/react-native-quick-crypto/deps/ncrypto/tools/run-clang-format.sh diff --git a/.cursorrules b/.cursorrules deleted file mode 120000 index 8a63b64b..00000000 --- a/.cursorrules +++ /dev/null @@ -1 +0,0 @@ -.rules \ No newline at end of file diff --git a/.windsurf/rules/cpp.md b/.windsurf/rules/cpp.md new file mode 100644 index 00000000..161296ec --- /dev/null +++ b/.windsurf/rules/cpp.md @@ -0,0 +1,9 @@ +--- +trigger: glob +globs: *.cpp,*.hpp +--- + +## C++ +- Use smart pointers in C++. +- Use modern C++ features. +- Set up builds for C++ 20, no lower diff --git a/.windsurf/rules/local.md b/.windsurf/rules/local.md new file mode 100644 index 00000000..9879bc9f --- /dev/null +++ b/.windsurf/rules/local.md @@ -0,0 +1,12 @@ +--- +trigger: always_on +--- + +# Local Codebases + +Use these instead of web searches for Node and 0.x branch: + +- NodeJS code is located at `$HOME/dev/node` + - use its `deps/ncrypto` code as a bible for crypto operations, and update this library's copy occasionally when we're implementing new features + +- The old 0.x branch codebase is located at `$HOME/dev/rnqc/0.x` diff --git a/.rules b/.windsurf/rules/project.md similarity index 51% rename from .rules rename to .windsurf/rules/project.md index 58960cc8..1bffbe90 100644 --- a/.rules +++ b/.windsurf/rules/project.md @@ -1,3 +1,7 @@ +--- +trigger: always_on +--- + # React Native Quick Crypto Every time you choose to apply a rule(s), explicitly state the rule(s) in the output. You can abbreviate the rule description to a single word or phrase. @@ -10,6 +14,7 @@ Every time you choose to apply a rule(s), explicitly state the rule(s) in the ou - Part of the API strives to be a polyfill of the Node.js `{crypto}` module. - When in doubt, favor in order: WebCrypto API, NodeJS implementation, 0.x implementation - The goal is to migrate 0.x of this library that uses OpenSSL 1.1.1 to now use OpenSSL 3.3 and modern C++ with Nitro Modules. +- NodeJS code has the `deps/ncrypto` library where they are externalizing cryptography code using OpenSSL from the main guts of Node. Try to use this before anything else when adding new features and/or troubleshooting. It may still need upgrading to OpenSSL 3.3+ ## Tech Stack @@ -19,39 +24,11 @@ Every time you choose to apply a rule(s), explicitly state the rule(s) in the ou - C++ 20 and higher, modern - OpenSSL 3.3 and higher - TypeScript package manager is `bun` 1.2 or higher -- Don't ask to run tests. They have to be run in an example React Native app. ## Rules -- Use smart pointers in C++. -- Use modern C++ features. - Attempt to reduce the amount of code rather than add more. - Prefer iteration and modularization over code duplication. - Do not add comments unless explicitly told to do so, or the code is sufficiently complex to warrant comments. +- Don't ask to run tests. They have to be run in an example React Native app. -## TypeScript Best Practices - -- Use TypeScript for all code; prefer interfaces over types. -- Use lowercase with dashes for directories (e.g., `components/auth-wizard`). -- Favor named exports for components. -- Avoid `any` and enums; use explicit types and maps instead. -- Do not cast to `unknown` and then another type. -- Use functional components with TypeScript interfaces. -- Enable strict mode in TypeScript for better type safety. -- Suggest the optimal implementation considering: - - Performance impact - - Maintenance overhead - - Testing strategy -- Code examples should follow TypeScript best practices. - -## React Best Practices - -- Minimize the use of `useEffect`. They should be a last resort. -- Use named functions for `useEffect`s with a meaningful function name. Avoid adding unnecessary comments on effect behavior. - -## Syntax & Formatting - -- Use the `function` keyword for pure functions. -- Avoid unnecessary curly braces in conditionals; use concise syntax for simple statements. -- Use declarative JSX. -- Use Prettier for consistent code formatting. diff --git a/.windsurf/rules/typescript.md b/.windsurf/rules/typescript.md new file mode 100644 index 00000000..ec37a353 --- /dev/null +++ b/.windsurf/rules/typescript.md @@ -0,0 +1,31 @@ +--- +trigger: glob +globs: *.ts,*.tsx +--- + +## TypeScript Best Practices + +- Use TypeScript for all code; prefer interfaces over types. +- Use lowercase with dashes for directories (e.g., `components/auth-wizard`). +- Favor named exports for components. +- Avoid `any` and enums; use explicit types and maps instead. +- Do not cast to `unknown` and then another type. +- Use functional components with TypeScript interfaces. +- Enable strict mode in TypeScript for better type safety. +- Suggest the optimal implementation considering: + - Performance impact + - Maintenance overhead + - Testing strategy +- Code examples should follow TypeScript best practices. + +## React Best Practices + +- Minimize the use of `useEffect`. They should be a last resort. +- Use named functions for `useEffect`s with a meaningful function name. Avoid adding unnecessary comments on effect behavior. + +## Syntax & Formatting + +- Use the `function` keyword for pure functions. +- Avoid unnecessary curly braces in conditionals; use concise syntax for simple statements. +- Use declarative JSX. +- Use Prettier for consistent code formatting. \ No newline at end of file diff --git a/.windsurfrules b/.windsurfrules deleted file mode 120000 index 8a63b64b..00000000 --- a/.windsurfrules +++ /dev/null @@ -1 +0,0 @@ -.rules \ No newline at end of file diff --git a/bun.lock b/bun.lock index a9ec51ae..7a2fb40e 100644 --- a/bun.lock +++ b/bun.lock @@ -1869,25 +1869,25 @@ "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], - "metro": ["metro@0.83.1", "", { "dependencies": { "@babel/code-frame": "^7.24.7", "@babel/core": "^7.25.2", "@babel/generator": "^7.25.0", "@babel/parser": "^7.25.3", "@babel/template": "^7.25.0", "@babel/traverse": "^7.25.3", "@babel/types": "^7.25.2", "accepts": "^1.3.7", "chalk": "^4.0.0", "ci-info": "^2.0.0", "connect": "^3.6.5", "debug": "^4.4.0", "error-stack-parser": "^2.0.6", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "hermes-parser": "0.29.1", "image-size": "^1.0.2", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "jsc-safe-url": "^0.2.2", "lodash.throttle": "^4.1.1", "metro-babel-transformer": "0.83.1", "metro-cache": "0.83.1", "metro-cache-key": "0.83.1", "metro-config": "0.83.1", "metro-core": "0.83.1", "metro-file-map": "0.83.1", "metro-resolver": "0.83.1", "metro-runtime": "0.83.1", "metro-source-map": "0.83.1", "metro-symbolicate": "0.83.1", "metro-transform-plugins": "0.83.1", "metro-transform-worker": "0.83.1", "mime-types": "^2.1.27", "nullthrows": "^1.1.1", "serialize-error": "^2.1.0", "source-map": "^0.5.6", "throat": "^5.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" }, "bin": { "metro": "src/cli.js" } }, "sha512-UGKepmTxoGD4HkQV8YWvpvwef7fUujNtTgG4Ygf7m/M0qjvb9VuDmAsEU+UdriRX7F61pnVK/opz89hjKlYTXA=="], + "metro": ["metro@0.80.10", "", { "dependencies": { "@babel/code-frame": "^7.0.0", "@babel/core": "^7.20.0", "@babel/generator": "^7.20.0", "@babel/parser": "^7.20.0", "@babel/template": "^7.0.0", "@babel/traverse": "^7.20.0", "@babel/types": "^7.20.0", "accepts": "^1.3.7", "chalk": "^4.0.0", "ci-info": "^2.0.0", "connect": "^3.6.5", "debug": "^2.2.0", "denodeify": "^1.2.1", "error-stack-parser": "^2.0.6", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "hermes-parser": "0.23.0", "image-size": "^1.0.2", "invariant": "^2.2.4", "jest-worker": "^29.6.3", "jsc-safe-url": "^0.2.2", "lodash.throttle": "^4.1.1", "metro-babel-transformer": "0.80.10", "metro-cache": "0.80.10", "metro-cache-key": "0.80.10", "metro-config": "0.80.10", "metro-core": "0.80.10", "metro-file-map": "0.80.10", "metro-resolver": "0.80.10", "metro-runtime": "0.80.10", "metro-source-map": "0.80.10", "metro-symbolicate": "0.80.10", "metro-transform-plugins": "0.80.10", "metro-transform-worker": "0.80.10", "mime-types": "^2.1.27", "node-fetch": "^2.2.0", "nullthrows": "^1.1.1", "serialize-error": "^2.1.0", "source-map": "^0.5.6", "strip-ansi": "^6.0.0", "throat": "^5.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" }, "bin": { "metro": "src/cli.js" } }, "sha512-FDPi0X7wpafmDREXe1lgg3WzETxtXh6Kpq8+IwsG35R2tMyp2kFIqDdshdohuvDt1J/qDARcEPq7V/jElTb1kA=="], - "metro-babel-transformer": ["metro-babel-transformer@0.83.1", "", { "dependencies": { "@babel/core": "^7.25.2", "flow-enums-runtime": "^0.0.6", "hermes-parser": "0.29.1", "nullthrows": "^1.1.1" } }, "sha512-r3xAD3964E8dwDBaZNSO2aIIvWXjIK80uO2xo0/pi3WI8XWT9h5SCjtGWtMtE5PRWw+t20TN0q1WMRsjvhC1rQ=="], + "metro-babel-transformer": ["metro-babel-transformer@0.80.10", "", { "dependencies": { "@babel/core": "^7.20.0", "flow-enums-runtime": "^0.0.6", "hermes-parser": "0.23.0", "nullthrows": "^1.1.1" } }, "sha512-GXHueUzgzcazfzORDxDzWS9jVVRV6u+cR6TGvHOfGdfLzJCj7/D0PretLfyq+MwN20twHxLW+BUXkoaB8sCQBg=="], "metro-cache": ["metro-cache@0.80.10", "", { "dependencies": { "exponential-backoff": "^3.1.1", "flow-enums-runtime": "^0.0.6", "metro-core": "0.80.10" } }, "sha512-8CBtDJwMguIE5RvV3PU1QtxUG8oSSX54mIuAbRZmcQ0MYiOl9JdrMd4JCBvIyhiZLoSStph425SMyCSnjtJsdA=="], - "metro-cache-key": ["metro-cache-key@0.83.1", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-ZUs+GD5CNeDLxx5UUWmfg26IL+Dnbryd+TLqTlZnDEgehkIa11kUSvgF92OFfJhONeXzV4rZDRGNXoo6JT+8Gg=="], + "metro-cache-key": ["metro-cache-key@0.80.10", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-57qBhO3zQfoU/hP4ZlLW5hVej2jVfBX6B4NcSfMj4LgDPL3YknWg80IJBxzQfjQY/m+fmMLmPy8aUMHzUp/guA=="], "metro-config": ["metro-config@0.80.10", "", { "dependencies": { "connect": "^3.6.5", "cosmiconfig": "^5.0.5", "flow-enums-runtime": "^0.0.6", "jest-validate": "^29.6.3", "metro": "0.80.10", "metro-cache": "0.80.10", "metro-core": "0.80.10", "metro-runtime": "0.80.10" } }, "sha512-0GYAw0LkmGbmA81FepKQepL1KU/85Cyv7sAiWm6QWeV6AcVCpsKg6jGLqGHJ0LLPL60rWzA4TV1DQAlzdJAEtA=="], - "metro-core": ["metro-core@0.83.1", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "lodash.throttle": "^4.1.1", "metro-resolver": "0.83.1" } }, "sha512-uVL1eAJcMFd2o2Q7dsbpg8COaxjZBBGaXqO2OHnivpCdfanraVL8dPmY6It9ZeqWLOihUKZ2yHW4b6soVCzH/Q=="], + "metro-core": ["metro-core@0.80.10", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "lodash.throttle": "^4.1.1", "metro-resolver": "0.80.10" } }, "sha512-nwBB6HbpGlNsZMuzxVqxqGIOsn5F3JKpsp8PziS7Z4mV8a/jA1d44mVOgYmDa2q5WlH5iJfRIIhdz24XRNDlLA=="], - "metro-file-map": ["metro-file-map@0.83.1", "", { "dependencies": { "debug": "^4.4.0", "fb-watchman": "^2.0.0", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "micromatch": "^4.0.4", "nullthrows": "^1.1.1", "walker": "^1.0.7" } }, "sha512-Yu429lnexKl44PttKw3nhqgmpBR+6UQ/tRaYcxPeEShtcza9DWakCn7cjqDTQZtWR2A8xSNv139izJMyQ4CG+w=="], + "metro-file-map": ["metro-file-map@0.80.10", "", { "dependencies": { "anymatch": "^3.0.3", "debug": "^2.2.0", "fb-watchman": "^2.0.0", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "invariant": "^2.2.4", "jest-worker": "^29.6.3", "micromatch": "^4.0.4", "node-abort-controller": "^3.1.1", "nullthrows": "^1.1.1", "walker": "^1.0.7" }, "optionalDependencies": { "fsevents": "^2.3.2" } }, "sha512-ytsUq8coneaN7ZCVk1IogojcGhLIbzWyiI2dNmw2nnBgV/0A+M5WaTTgZ6dJEz3dzjObPryDnkqWPvIGLCPtiw=="], - "metro-minify-terser": ["metro-minify-terser@0.83.1", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "terser": "^5.15.0" } }, "sha512-kmooOxXLvKVxkh80IVSYO4weBdJDhCpg5NSPkjzzAnPJP43u6+usGXobkTWxxrAlq900bhzqKek4pBsUchlX6A=="], + "metro-minify-terser": ["metro-minify-terser@0.80.10", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "terser": "^5.15.0" } }, "sha512-Xyv9pEYpOsAerrld7cSLIcnCCpv8ItwysOmTA+AKf1q4KyE9cxrH2O2SA0FzMCkPzwxzBWmXwHUr+A89BpEM6g=="], "metro-react-native-babel-preset": ["metro-react-native-babel-preset@0.72.3", "", { "dependencies": { "@babel/core": "^7.14.0", "@babel/plugin-proposal-async-generator-functions": "^7.0.0", "@babel/plugin-proposal-class-properties": "^7.0.0", "@babel/plugin-proposal-export-default-from": "^7.0.0", "@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0", "@babel/plugin-proposal-object-rest-spread": "^7.0.0", "@babel/plugin-proposal-optional-catch-binding": "^7.0.0", "@babel/plugin-proposal-optional-chaining": "^7.0.0", "@babel/plugin-syntax-dynamic-import": "^7.0.0", "@babel/plugin-syntax-export-default-from": "^7.0.0", "@babel/plugin-syntax-flow": "^7.2.0", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.0.0", "@babel/plugin-syntax-optional-chaining": "^7.0.0", "@babel/plugin-transform-arrow-functions": "^7.0.0", "@babel/plugin-transform-async-to-generator": "^7.0.0", "@babel/plugin-transform-block-scoping": "^7.0.0", "@babel/plugin-transform-classes": "^7.0.0", "@babel/plugin-transform-computed-properties": "^7.0.0", "@babel/plugin-transform-destructuring": "^7.0.0", "@babel/plugin-transform-exponentiation-operator": "^7.0.0", "@babel/plugin-transform-flow-strip-types": "^7.0.0", "@babel/plugin-transform-function-name": "^7.0.0", "@babel/plugin-transform-literals": "^7.0.0", "@babel/plugin-transform-modules-commonjs": "^7.0.0", "@babel/plugin-transform-named-capturing-groups-regex": "^7.0.0", "@babel/plugin-transform-parameters": "^7.0.0", "@babel/plugin-transform-react-display-name": "^7.0.0", "@babel/plugin-transform-react-jsx": "^7.0.0", "@babel/plugin-transform-react-jsx-self": "^7.0.0", "@babel/plugin-transform-react-jsx-source": "^7.0.0", "@babel/plugin-transform-runtime": "^7.0.0", "@babel/plugin-transform-shorthand-properties": "^7.0.0", "@babel/plugin-transform-spread": "^7.0.0", "@babel/plugin-transform-sticky-regex": "^7.0.0", "@babel/plugin-transform-template-literals": "^7.0.0", "@babel/plugin-transform-typescript": "^7.5.0", "@babel/plugin-transform-unicode-regex": "^7.0.0", "@babel/template": "^7.0.0", "react-refresh": "^0.4.0" } }, "sha512-uJx9y/1NIqoYTp6ZW1osJ7U5ZrXGAJbOQ/Qzl05BdGYvN1S7Qmbzid6xOirgK0EIT0pJKEEh1s8qbassYZe4cw=="], - "metro-resolver": ["metro-resolver@0.83.1", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-t8j46kiILAqqFS5RNa+xpQyVjULxRxlvMidqUswPEk5nQVNdlJslqizDm/Et3v/JKwOtQGkYAQCHxP1zGStR/g=="], + "metro-resolver": ["metro-resolver@0.80.10", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-EYC5CL7f+bSzrqdk1bylKqFNGabfiI5PDctxoPx70jFt89Jz+ThcOscENog8Jb4LEQFG6GkOYlwmPpsi7kx3QA=="], "metro-runtime": ["metro-runtime@0.83.1", "", { "dependencies": { "@babel/runtime": "^7.25.0", "flow-enums-runtime": "^0.0.6" } }, "sha512-3Ag8ZS4IwafL/JUKlaeM6/CbkooY+WcVeqdNlBG0m4S0Qz0om3rdFdy1y6fYBpl6AwXJwWeMuXrvZdMuByTcRA=="], @@ -1895,9 +1895,9 @@ "metro-symbolicate": ["metro-symbolicate@0.83.1", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-source-map": "0.83.1", "nullthrows": "^1.1.1", "source-map": "^0.5.6", "vlq": "^1.0.0" }, "bin": { "metro-symbolicate": "src/index.js" } }, "sha512-wPxYkONlq/Sv8Ji7vHEx5OzFouXAMQJjpcPW41ySKMLP/Ir18SsiJK2h4YkdKpYrTS1+0xf8oqF6nxCsT3uWtg=="], - "metro-transform-plugins": ["metro-transform-plugins@0.83.1", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/generator": "^7.25.0", "@babel/template": "^7.25.0", "@babel/traverse": "^7.25.3", "flow-enums-runtime": "^0.0.6", "nullthrows": "^1.1.1" } }, "sha512-1Y+I8oozXwhuS0qwC+ezaHXBf0jXW4oeYn4X39XWbZt9X2HfjodqY9bH9r6RUTsoiK7S4j8Ni2C91bUC+sktJQ=="], + "metro-transform-plugins": ["metro-transform-plugins@0.80.10", "", { "dependencies": { "@babel/core": "^7.20.0", "@babel/generator": "^7.20.0", "@babel/template": "^7.0.0", "@babel/traverse": "^7.20.0", "flow-enums-runtime": "^0.0.6", "nullthrows": "^1.1.1" } }, "sha512-leAx9gtA+2MHLsCeWK6XTLBbv2fBnNFu/QiYhWzMq8HsOAP4u1xQAU0tSgPs8+1vYO34Plyn79xTLUtQCRSSUQ=="], - "metro-transform-worker": ["metro-transform-worker@0.83.1", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/generator": "^7.25.0", "@babel/parser": "^7.25.3", "@babel/types": "^7.25.2", "flow-enums-runtime": "^0.0.6", "metro": "0.83.1", "metro-babel-transformer": "0.83.1", "metro-cache": "0.83.1", "metro-cache-key": "0.83.1", "metro-minify-terser": "0.83.1", "metro-source-map": "0.83.1", "metro-transform-plugins": "0.83.1", "nullthrows": "^1.1.1" } }, "sha512-owCrhPyUxdLgXEEEAL2b14GWTPZ2zYuab1VQXcfEy0sJE71iciD7fuMcrngoufh7e7UHDZ56q4ktXg8wgiYA1Q=="], + "metro-transform-worker": ["metro-transform-worker@0.80.10", "", { "dependencies": { "@babel/core": "^7.20.0", "@babel/generator": "^7.20.0", "@babel/parser": "^7.20.0", "@babel/types": "^7.20.0", "flow-enums-runtime": "^0.0.6", "metro": "0.80.10", "metro-babel-transformer": "0.80.10", "metro-cache": "0.80.10", "metro-cache-key": "0.80.10", "metro-minify-terser": "0.80.10", "metro-source-map": "0.80.10", "metro-transform-plugins": "0.80.10", "nullthrows": "^1.1.1" } }, "sha512-zNfNLD8Rz99U+JdOTqtF2o7iTjcDMMYdVS90z6+81Tzd2D0lDWVpls7R1hadS6xwM+ymgXFQTjM6V6wFoZaC0g=="], "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], @@ -2305,7 +2305,7 @@ "send": ["send@0.18.0", "", { "dependencies": { "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", "http-errors": "2.0.0", "mime": "1.6.0", "ms": "2.1.3", "on-finished": "2.4.1", "range-parser": "~1.2.1", "statuses": "2.0.1" } }, "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg=="], - "serialize-error": ["serialize-error@2.1.0", "", {}, "sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw=="], + "serialize-error": ["serialize-error@6.0.0", "", { "dependencies": { "type-fest": "^0.12.0" } }, "sha512-3vmBkMZLQO+BR4RPHcyRGdE09XCF6cvxzk2N2qn8Er3F91cy8Qt7VvEbZBOpaL53qsBbe2cFOefU6tRY6WDelA=="], "serve-static": ["serve-static@1.15.0", "", { "dependencies": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "parseurl": "~1.3.3", "send": "0.18.0" } }, "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g=="], @@ -2959,8 +2959,6 @@ "@expo/dev-server/semver": ["semver@7.3.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ=="], - "@expo/dev-server/serialize-error": ["serialize-error@6.0.0", "", { "dependencies": { "type-fest": "^0.12.0" } }, "sha512-3vmBkMZLQO+BR4RPHcyRGdE09XCF6cvxzk2N2qn8Er3F91cy8Qt7VvEbZBOpaL53qsBbe2cFOefU6tRY6WDelA=="], - "@expo/devcert/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="], "@expo/devcert/glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="], @@ -3077,8 +3075,12 @@ "@react-native/community-cli-plugin/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], + "@react-native/community-cli-plugin/metro": ["metro@0.83.1", "", { "dependencies": { "@babel/code-frame": "^7.24.7", "@babel/core": "^7.25.2", "@babel/generator": "^7.25.0", "@babel/parser": "^7.25.3", "@babel/template": "^7.25.0", "@babel/traverse": "^7.25.3", "@babel/types": "^7.25.2", "accepts": "^1.3.7", "chalk": "^4.0.0", "ci-info": "^2.0.0", "connect": "^3.6.5", "debug": "^4.4.0", "error-stack-parser": "^2.0.6", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "hermes-parser": "0.29.1", "image-size": "^1.0.2", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "jsc-safe-url": "^0.2.2", "lodash.throttle": "^4.1.1", "metro-babel-transformer": "0.83.1", "metro-cache": "0.83.1", "metro-cache-key": "0.83.1", "metro-config": "0.83.1", "metro-core": "0.83.1", "metro-file-map": "0.83.1", "metro-resolver": "0.83.1", "metro-runtime": "0.83.1", "metro-source-map": "0.83.1", "metro-symbolicate": "0.83.1", "metro-transform-plugins": "0.83.1", "metro-transform-worker": "0.83.1", "mime-types": "^2.1.27", "nullthrows": "^1.1.1", "serialize-error": "^2.1.0", "source-map": "^0.5.6", "throat": "^5.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" }, "bin": { "metro": "src/cli.js" } }, "sha512-UGKepmTxoGD4HkQV8YWvpvwef7fUujNtTgG4Ygf7m/M0qjvb9VuDmAsEU+UdriRX7F61pnVK/opz89hjKlYTXA=="], + "@react-native/community-cli-plugin/metro-config": ["metro-config@0.83.1", "", { "dependencies": { "connect": "^3.6.5", "cosmiconfig": "^5.0.5", "flow-enums-runtime": "^0.0.6", "jest-validate": "^29.7.0", "metro": "0.83.1", "metro-cache": "0.83.1", "metro-core": "0.83.1", "metro-runtime": "0.83.1" } }, "sha512-HJhpZx3wyOkux/jeF1o7akFJzZFdbn6Zf7UQqWrvp7gqFqNulQ8Mju09raBgPmmSxKDl4LbbNeigkX0/nKY1QA=="], + "@react-native/community-cli-plugin/metro-core": ["metro-core@0.83.1", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "lodash.throttle": "^4.1.1", "metro-resolver": "0.83.1" } }, "sha512-uVL1eAJcMFd2o2Q7dsbpg8COaxjZBBGaXqO2OHnivpCdfanraVL8dPmY6It9ZeqWLOihUKZ2yHW4b6soVCzH/Q=="], + "@react-native/dev-middleware/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], "@react-native/dev-middleware/open": ["open@7.4.2", "", { "dependencies": { "is-docker": "^2.0.0", "is-wsl": "^2.1.1" } }, "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q=="], @@ -3423,41 +3425,49 @@ "md5.js/safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], - "metro/@babel/code-frame": ["@babel/code-frame@7.27.1", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg=="], + "metro/@babel/code-frame": ["@babel/code-frame@7.24.7", "", { "dependencies": { "@babel/highlight": "^7.24.7", "picocolors": "^1.0.0" } }, "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA=="], - "metro/@babel/generator": ["@babel/generator@7.27.3", "", { "dependencies": { "@babel/parser": "^7.27.3", "@babel/types": "^7.27.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q=="], + "metro/@babel/core": ["@babel/core@7.25.2", "", { "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.7", "@babel/generator": "^7.25.0", "@babel/helper-compilation-targets": "^7.25.2", "@babel/helper-module-transforms": "^7.25.2", "@babel/helpers": "^7.25.0", "@babel/parser": "^7.25.0", "@babel/template": "^7.25.0", "@babel/traverse": "^7.25.2", "@babel/types": "^7.25.2", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA=="], - "metro/@babel/parser": ["@babel/parser@7.27.4", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-BRmLHGwpUqLFR2jzx9orBuX/ABDkj2jLKOXrHDTN2aOKL+jFDDKaRNo9nyYsIl9h/UE/7lMKdDjKQQyxKKDZ7g=="], + "metro/@babel/generator": ["@babel/generator@7.25.5", "", { "dependencies": { "@babel/types": "^7.25.4", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" } }, "sha512-abd43wyLfbWoxC6ahM8xTkqLpGB2iWBVyuKC9/srhFunCd1SDNrV1s72bBpK4hLj8KLzHBBcOblvLQZBNw9r3w=="], - "metro/@babel/template": ["@babel/template@7.27.2", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/parser": "^7.27.2", "@babel/types": "^7.27.1" } }, "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw=="], + "metro/@babel/parser": ["@babel/parser@7.25.4", "", { "dependencies": { "@babel/types": "^7.25.4" }, "bin": "./bin/babel-parser.js" }, "sha512-nq+eWrOgdtu3jG5Os4TQP3x3cLA8hR8TvJNjD8vnPa20WGycimcparWnLK4jJhElTK6SDyuJo1weMKO/5LpmLA=="], - "metro/@babel/traverse": ["@babel/traverse@7.27.4", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.27.3", "@babel/parser": "^7.27.4", "@babel/template": "^7.27.2", "@babel/types": "^7.27.3", "debug": "^4.3.1", "globals": "^11.1.0" } }, "sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA=="], + "metro/@babel/template": ["@babel/template@7.25.0", "", { "dependencies": { "@babel/code-frame": "^7.24.7", "@babel/parser": "^7.25.0", "@babel/types": "^7.25.0" } }, "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q=="], - "metro/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="], + "metro/@babel/traverse": ["@babel/traverse@7.25.4", "", { "dependencies": { "@babel/code-frame": "^7.24.7", "@babel/generator": "^7.25.4", "@babel/parser": "^7.25.4", "@babel/template": "^7.25.0", "@babel/types": "^7.25.4", "debug": "^4.3.1", "globals": "^11.1.0" } }, "sha512-VJ4XsrD+nOvlXyLzmLzUs/0qjFS4sK30te5yEFlvbbUNEgKaVb2BHZUpAL+ttLPQAHNrsI3zZisbfha5Cvr8vg=="], + + "metro/@babel/types": ["@babel/types@7.25.4", "", { "dependencies": { "@babel/helper-string-parser": "^7.24.8", "@babel/helper-validator-identifier": "^7.24.7", "to-fast-properties": "^2.0.0" } }, "sha512-zQ1ijeeCXVEh+aNL0RlmkPkG8HUiDcU2pzQQFjtbntgAczRASFzj4H+6+bV+dy1ntKR14I/DypeuRG1uma98iQ=="], "metro/ci-info": ["ci-info@2.0.0", "", {}, "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ=="], - "metro/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], + "metro/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], + + "metro/hermes-parser": ["hermes-parser@0.23.0", "", { "dependencies": { "hermes-estree": "0.23.0" } }, "sha512-xLwM4ylfHGwrm+2qXfO1JT/fnqEDGSnpS/9hQ4VLtqTexSviu2ZpBgz07U8jVtndq67qdb/ps0qvaWDZ3fkTyg=="], - "metro/metro-cache": ["metro-cache@0.83.1", "", { "dependencies": { "exponential-backoff": "^3.1.1", "flow-enums-runtime": "^0.0.6", "https-proxy-agent": "^7.0.5", "metro-core": "0.83.1" } }, "sha512-7N/Ad1PHa1YMWDNiyynTPq34Op2qIE68NWryGEQ4TSE3Zy6a8GpsYnEEZE4Qi6aHgsE+yZHKkRczeBgxhnFIxQ=="], + "metro/metro-runtime": ["metro-runtime@0.80.10", "", { "dependencies": { "@babel/runtime": "^7.0.0", "flow-enums-runtime": "^0.0.6" } }, "sha512-Xh0N589ZmSIgJYAM+oYwlzTXEHfASZac9TYPCNbvjNTn0EHKqpoJ/+Im5G3MZT4oZzYv4YnvzRtjqS5k0tK94A=="], - "metro/metro-config": ["metro-config@0.83.1", "", { "dependencies": { "connect": "^3.6.5", "cosmiconfig": "^5.0.5", "flow-enums-runtime": "^0.0.6", "jest-validate": "^29.7.0", "metro": "0.83.1", "metro-cache": "0.83.1", "metro-core": "0.83.1", "metro-runtime": "0.83.1" } }, "sha512-HJhpZx3wyOkux/jeF1o7akFJzZFdbn6Zf7UQqWrvp7gqFqNulQ8Mju09raBgPmmSxKDl4LbbNeigkX0/nKY1QA=="], + "metro/metro-source-map": ["metro-source-map@0.80.10", "", { "dependencies": { "@babel/traverse": "^7.20.0", "@babel/types": "^7.20.0", "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-symbolicate": "0.80.10", "nullthrows": "^1.1.1", "ob1": "0.80.10", "source-map": "^0.5.6", "vlq": "^1.0.0" } }, "sha512-EyZswqJW8Uukv/HcQr6K19vkMXW1nzHAZPWJSEyJFKIbgp708QfRZ6vnZGmrtFxeJEaFdNup4bGnu8/mIOYlyA=="], + + "metro/metro-symbolicate": ["metro-symbolicate@0.80.10", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-source-map": "0.80.10", "nullthrows": "^1.1.1", "source-map": "^0.5.6", "through2": "^2.0.1", "vlq": "^1.0.0" }, "bin": { "metro-symbolicate": "src/index.js" } }, "sha512-qAoVUoSxpfZ2DwZV7IdnQGXCSsf2cAUExUcZyuCqGlY5kaWBb0mx2BL/xbMFDJ4wBp3sVvSBPtK/rt4J7a0xBA=="], + + "metro/serialize-error": ["serialize-error@2.1.0", "", {}, "sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw=="], + + "metro/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], "metro/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="], "metro/yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], - "metro-cache/metro-core": ["metro-core@0.80.10", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "lodash.throttle": "^4.1.1", "metro-resolver": "0.80.10" } }, "sha512-nwBB6HbpGlNsZMuzxVqxqGIOsn5F3JKpsp8PziS7Z4mV8a/jA1d44mVOgYmDa2q5WlH5iJfRIIhdz24XRNDlLA=="], - - "metro-config/cosmiconfig": ["cosmiconfig@5.2.1", "", { "dependencies": { "import-fresh": "^2.0.0", "is-directory": "^0.3.1", "js-yaml": "^3.13.1", "parse-json": "^4.0.0" } }, "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA=="], + "metro-babel-transformer/@babel/core": ["@babel/core@7.25.2", "", { "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.7", "@babel/generator": "^7.25.0", "@babel/helper-compilation-targets": "^7.25.2", "@babel/helper-module-transforms": "^7.25.2", "@babel/helpers": "^7.25.0", "@babel/parser": "^7.25.0", "@babel/template": "^7.25.0", "@babel/traverse": "^7.25.2", "@babel/types": "^7.25.2", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA=="], - "metro-config/metro": ["metro@0.80.10", "", { "dependencies": { "@babel/code-frame": "^7.0.0", "@babel/core": "^7.20.0", "@babel/generator": "^7.20.0", "@babel/parser": "^7.20.0", "@babel/template": "^7.0.0", "@babel/traverse": "^7.20.0", "@babel/types": "^7.20.0", "accepts": "^1.3.7", "chalk": "^4.0.0", "ci-info": "^2.0.0", "connect": "^3.6.5", "debug": "^2.2.0", "denodeify": "^1.2.1", "error-stack-parser": "^2.0.6", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "hermes-parser": "0.23.0", "image-size": "^1.0.2", "invariant": "^2.2.4", "jest-worker": "^29.6.3", "jsc-safe-url": "^0.2.2", "lodash.throttle": "^4.1.1", "metro-babel-transformer": "0.80.10", "metro-cache": "0.80.10", "metro-cache-key": "0.80.10", "metro-config": "0.80.10", "metro-core": "0.80.10", "metro-file-map": "0.80.10", "metro-resolver": "0.80.10", "metro-runtime": "0.80.10", "metro-source-map": "0.80.10", "metro-symbolicate": "0.80.10", "metro-transform-plugins": "0.80.10", "metro-transform-worker": "0.80.10", "mime-types": "^2.1.27", "node-fetch": "^2.2.0", "nullthrows": "^1.1.1", "serialize-error": "^2.1.0", "source-map": "^0.5.6", "strip-ansi": "^6.0.0", "throat": "^5.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" }, "bin": { "metro": "src/cli.js" } }, "sha512-FDPi0X7wpafmDREXe1lgg3WzETxtXh6Kpq8+IwsG35R2tMyp2kFIqDdshdohuvDt1J/qDARcEPq7V/jElTb1kA=="], + "metro-babel-transformer/hermes-parser": ["hermes-parser@0.23.0", "", { "dependencies": { "hermes-estree": "0.23.0" } }, "sha512-xLwM4ylfHGwrm+2qXfO1JT/fnqEDGSnpS/9hQ4VLtqTexSviu2ZpBgz07U8jVtndq67qdb/ps0qvaWDZ3fkTyg=="], - "metro-config/metro-core": ["metro-core@0.80.10", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "lodash.throttle": "^4.1.1", "metro-resolver": "0.80.10" } }, "sha512-nwBB6HbpGlNsZMuzxVqxqGIOsn5F3JKpsp8PziS7Z4mV8a/jA1d44mVOgYmDa2q5WlH5iJfRIIhdz24XRNDlLA=="], + "metro-config/cosmiconfig": ["cosmiconfig@5.2.1", "", { "dependencies": { "import-fresh": "^2.0.0", "is-directory": "^0.3.1", "js-yaml": "^3.13.1", "parse-json": "^4.0.0" } }, "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA=="], "metro-config/metro-runtime": ["metro-runtime@0.80.10", "", { "dependencies": { "@babel/runtime": "^7.0.0", "flow-enums-runtime": "^0.0.6" } }, "sha512-Xh0N589ZmSIgJYAM+oYwlzTXEHfASZac9TYPCNbvjNTn0EHKqpoJ/+Im5G3MZT4oZzYv4YnvzRtjqS5k0tK94A=="], - "metro-file-map/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], + "metro-file-map/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], "metro-react-native-babel-preset/@babel/template": ["@babel/template@7.27.2", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/parser": "^7.27.2", "@babel/types": "^7.27.1" } }, "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw=="], @@ -3467,19 +3477,23 @@ "metro-source-map/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="], - "metro-transform-plugins/@babel/generator": ["@babel/generator@7.27.3", "", { "dependencies": { "@babel/parser": "^7.27.3", "@babel/types": "^7.27.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q=="], + "metro-transform-plugins/@babel/core": ["@babel/core@7.25.2", "", { "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.7", "@babel/generator": "^7.25.0", "@babel/helper-compilation-targets": "^7.25.2", "@babel/helper-module-transforms": "^7.25.2", "@babel/helpers": "^7.25.0", "@babel/parser": "^7.25.0", "@babel/template": "^7.25.0", "@babel/traverse": "^7.25.2", "@babel/types": "^7.25.2", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA=="], + + "metro-transform-plugins/@babel/generator": ["@babel/generator@7.25.5", "", { "dependencies": { "@babel/types": "^7.25.4", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" } }, "sha512-abd43wyLfbWoxC6ahM8xTkqLpGB2iWBVyuKC9/srhFunCd1SDNrV1s72bBpK4hLj8KLzHBBcOblvLQZBNw9r3w=="], + + "metro-transform-plugins/@babel/template": ["@babel/template@7.25.0", "", { "dependencies": { "@babel/code-frame": "^7.24.7", "@babel/parser": "^7.25.0", "@babel/types": "^7.25.0" } }, "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q=="], - "metro-transform-plugins/@babel/template": ["@babel/template@7.27.2", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/parser": "^7.27.2", "@babel/types": "^7.27.1" } }, "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw=="], + "metro-transform-plugins/@babel/traverse": ["@babel/traverse@7.25.4", "", { "dependencies": { "@babel/code-frame": "^7.24.7", "@babel/generator": "^7.25.4", "@babel/parser": "^7.25.4", "@babel/template": "^7.25.0", "@babel/types": "^7.25.4", "debug": "^4.3.1", "globals": "^11.1.0" } }, "sha512-VJ4XsrD+nOvlXyLzmLzUs/0qjFS4sK30te5yEFlvbbUNEgKaVb2BHZUpAL+ttLPQAHNrsI3zZisbfha5Cvr8vg=="], - "metro-transform-plugins/@babel/traverse": ["@babel/traverse@7.27.4", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.27.3", "@babel/parser": "^7.27.4", "@babel/template": "^7.27.2", "@babel/types": "^7.27.3", "debug": "^4.3.1", "globals": "^11.1.0" } }, "sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA=="], + "metro-transform-worker/@babel/core": ["@babel/core@7.25.2", "", { "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.7", "@babel/generator": "^7.25.0", "@babel/helper-compilation-targets": "^7.25.2", "@babel/helper-module-transforms": "^7.25.2", "@babel/helpers": "^7.25.0", "@babel/parser": "^7.25.0", "@babel/template": "^7.25.0", "@babel/traverse": "^7.25.2", "@babel/types": "^7.25.2", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA=="], - "metro-transform-worker/@babel/generator": ["@babel/generator@7.27.3", "", { "dependencies": { "@babel/parser": "^7.27.3", "@babel/types": "^7.27.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q=="], + "metro-transform-worker/@babel/generator": ["@babel/generator@7.25.5", "", { "dependencies": { "@babel/types": "^7.25.4", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" } }, "sha512-abd43wyLfbWoxC6ahM8xTkqLpGB2iWBVyuKC9/srhFunCd1SDNrV1s72bBpK4hLj8KLzHBBcOblvLQZBNw9r3w=="], - "metro-transform-worker/@babel/parser": ["@babel/parser@7.27.4", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-BRmLHGwpUqLFR2jzx9orBuX/ABDkj2jLKOXrHDTN2aOKL+jFDDKaRNo9nyYsIl9h/UE/7lMKdDjKQQyxKKDZ7g=="], + "metro-transform-worker/@babel/parser": ["@babel/parser@7.25.4", "", { "dependencies": { "@babel/types": "^7.25.4" }, "bin": "./bin/babel-parser.js" }, "sha512-nq+eWrOgdtu3jG5Os4TQP3x3cLA8hR8TvJNjD8vnPa20WGycimcparWnLK4jJhElTK6SDyuJo1weMKO/5LpmLA=="], - "metro-transform-worker/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="], + "metro-transform-worker/@babel/types": ["@babel/types@7.25.4", "", { "dependencies": { "@babel/helper-string-parser": "^7.24.8", "@babel/helper-validator-identifier": "^7.24.7", "to-fast-properties": "^2.0.0" } }, "sha512-zQ1ijeeCXVEh+aNL0RlmkPkG8HUiDcU2pzQQFjtbntgAczRASFzj4H+6+bV+dy1ntKR14I/DypeuRG1uma98iQ=="], - "metro-transform-worker/metro-cache": ["metro-cache@0.83.1", "", { "dependencies": { "exponential-backoff": "^3.1.1", "flow-enums-runtime": "^0.0.6", "https-proxy-agent": "^7.0.5", "metro-core": "0.83.1" } }, "sha512-7N/Ad1PHa1YMWDNiyynTPq34Op2qIE68NWryGEQ4TSE3Zy6a8GpsYnEEZE4Qi6aHgsE+yZHKkRczeBgxhnFIxQ=="], + "metro-transform-worker/metro-source-map": ["metro-source-map@0.80.10", "", { "dependencies": { "@babel/traverse": "^7.20.0", "@babel/types": "^7.20.0", "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-symbolicate": "0.80.10", "nullthrows": "^1.1.1", "ob1": "0.80.10", "source-map": "^0.5.6", "vlq": "^1.0.0" } }, "sha512-EyZswqJW8Uukv/HcQr6K19vkMXW1nzHAZPWJSEyJFKIbgp708QfRZ6vnZGmrtFxeJEaFdNup4bGnu8/mIOYlyA=="], "miller-rabin/bn.js": ["bn.js@4.12.0", "", {}, "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="], @@ -3599,6 +3613,8 @@ "send/ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + "serialize-error/type-fest": ["type-fest@0.12.0", "", {}, "sha512-53RyidyjvkGpnWPMF9bQgFtWp+Sl8O2Rp13VavmJgfAP9WWG6q6TkrKU8iyJdnwnfgHI6k2hTlgqH4aSdjoTbg=="], + "set-proto/es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="], "sha.js/safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], @@ -4031,8 +4047,6 @@ "@expo/dev-server/open/define-lazy-prop": ["define-lazy-prop@2.0.0", "", {}, "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og=="], - "@expo/dev-server/serialize-error/type-fest": ["type-fest@0.12.0", "", {}, "sha512-53RyidyjvkGpnWPMF9bQgFtWp+Sl8O2Rp13VavmJgfAP9WWG6q6TkrKU8iyJdnwnfgHI6k2hTlgqH4aSdjoTbg=="], - "@expo/devcert/debug/ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], "@expo/devcert/glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], @@ -4299,10 +4313,46 @@ "@react-native/community-cli-plugin/debug/ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + "@react-native/community-cli-plugin/metro/@babel/code-frame": ["@babel/code-frame@7.27.1", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg=="], + + "@react-native/community-cli-plugin/metro/@babel/generator": ["@babel/generator@7.27.3", "", { "dependencies": { "@babel/parser": "^7.27.3", "@babel/types": "^7.27.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q=="], + + "@react-native/community-cli-plugin/metro/@babel/parser": ["@babel/parser@7.27.4", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-BRmLHGwpUqLFR2jzx9orBuX/ABDkj2jLKOXrHDTN2aOKL+jFDDKaRNo9nyYsIl9h/UE/7lMKdDjKQQyxKKDZ7g=="], + + "@react-native/community-cli-plugin/metro/@babel/template": ["@babel/template@7.27.2", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/parser": "^7.27.2", "@babel/types": "^7.27.1" } }, "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw=="], + + "@react-native/community-cli-plugin/metro/@babel/traverse": ["@babel/traverse@7.27.4", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.27.3", "@babel/parser": "^7.27.4", "@babel/template": "^7.27.2", "@babel/types": "^7.27.3", "debug": "^4.3.1", "globals": "^11.1.0" } }, "sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA=="], + + "@react-native/community-cli-plugin/metro/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="], + + "@react-native/community-cli-plugin/metro/ci-info": ["ci-info@2.0.0", "", {}, "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ=="], + + "@react-native/community-cli-plugin/metro/metro-babel-transformer": ["metro-babel-transformer@0.83.1", "", { "dependencies": { "@babel/core": "^7.25.2", "flow-enums-runtime": "^0.0.6", "hermes-parser": "0.29.1", "nullthrows": "^1.1.1" } }, "sha512-r3xAD3964E8dwDBaZNSO2aIIvWXjIK80uO2xo0/pi3WI8XWT9h5SCjtGWtMtE5PRWw+t20TN0q1WMRsjvhC1rQ=="], + + "@react-native/community-cli-plugin/metro/metro-cache": ["metro-cache@0.83.1", "", { "dependencies": { "exponential-backoff": "^3.1.1", "flow-enums-runtime": "^0.0.6", "https-proxy-agent": "^7.0.5", "metro-core": "0.83.1" } }, "sha512-7N/Ad1PHa1YMWDNiyynTPq34Op2qIE68NWryGEQ4TSE3Zy6a8GpsYnEEZE4Qi6aHgsE+yZHKkRczeBgxhnFIxQ=="], + + "@react-native/community-cli-plugin/metro/metro-cache-key": ["metro-cache-key@0.83.1", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-ZUs+GD5CNeDLxx5UUWmfg26IL+Dnbryd+TLqTlZnDEgehkIa11kUSvgF92OFfJhONeXzV4rZDRGNXoo6JT+8Gg=="], + + "@react-native/community-cli-plugin/metro/metro-file-map": ["metro-file-map@0.83.1", "", { "dependencies": { "debug": "^4.4.0", "fb-watchman": "^2.0.0", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "micromatch": "^4.0.4", "nullthrows": "^1.1.1", "walker": "^1.0.7" } }, "sha512-Yu429lnexKl44PttKw3nhqgmpBR+6UQ/tRaYcxPeEShtcza9DWakCn7cjqDTQZtWR2A8xSNv139izJMyQ4CG+w=="], + + "@react-native/community-cli-plugin/metro/metro-resolver": ["metro-resolver@0.83.1", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-t8j46kiILAqqFS5RNa+xpQyVjULxRxlvMidqUswPEk5nQVNdlJslqizDm/Et3v/JKwOtQGkYAQCHxP1zGStR/g=="], + + "@react-native/community-cli-plugin/metro/metro-transform-plugins": ["metro-transform-plugins@0.83.1", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/generator": "^7.25.0", "@babel/template": "^7.25.0", "@babel/traverse": "^7.25.3", "flow-enums-runtime": "^0.0.6", "nullthrows": "^1.1.1" } }, "sha512-1Y+I8oozXwhuS0qwC+ezaHXBf0jXW4oeYn4X39XWbZt9X2HfjodqY9bH9r6RUTsoiK7S4j8Ni2C91bUC+sktJQ=="], + + "@react-native/community-cli-plugin/metro/metro-transform-worker": ["metro-transform-worker@0.83.1", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/generator": "^7.25.0", "@babel/parser": "^7.25.3", "@babel/types": "^7.25.2", "flow-enums-runtime": "^0.0.6", "metro": "0.83.1", "metro-babel-transformer": "0.83.1", "metro-cache": "0.83.1", "metro-cache-key": "0.83.1", "metro-minify-terser": "0.83.1", "metro-source-map": "0.83.1", "metro-transform-plugins": "0.83.1", "nullthrows": "^1.1.1" } }, "sha512-owCrhPyUxdLgXEEEAL2b14GWTPZ2zYuab1VQXcfEy0sJE71iciD7fuMcrngoufh7e7UHDZ56q4ktXg8wgiYA1Q=="], + + "@react-native/community-cli-plugin/metro/serialize-error": ["serialize-error@2.1.0", "", {}, "sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw=="], + + "@react-native/community-cli-plugin/metro/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="], + + "@react-native/community-cli-plugin/metro/yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], + "@react-native/community-cli-plugin/metro-config/cosmiconfig": ["cosmiconfig@5.2.1", "", { "dependencies": { "import-fresh": "^2.0.0", "is-directory": "^0.3.1", "js-yaml": "^3.13.1", "parse-json": "^4.0.0" } }, "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA=="], "@react-native/community-cli-plugin/metro-config/metro-cache": ["metro-cache@0.83.1", "", { "dependencies": { "exponential-backoff": "^3.1.1", "flow-enums-runtime": "^0.0.6", "https-proxy-agent": "^7.0.5", "metro-core": "0.83.1" } }, "sha512-7N/Ad1PHa1YMWDNiyynTPq34Op2qIE68NWryGEQ4TSE3Zy6a8GpsYnEEZE4Qi6aHgsE+yZHKkRczeBgxhnFIxQ=="], + "@react-native/community-cli-plugin/metro-core/metro-resolver": ["metro-resolver@0.83.1", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-t8j46kiILAqqFS5RNa+xpQyVjULxRxlvMidqUswPEk5nQVNdlJslqizDm/Et3v/JKwOtQGkYAQCHxP1zGStR/g=="], + "@react-native/dev-middleware/debug/ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], "@react-native/dev-middleware/open/is-docker": ["is-docker@2.2.1", "", { "bin": { "is-docker": "cli.js" } }, "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="], @@ -4337,8 +4387,12 @@ "@react-native/metro-config/metro-config/cosmiconfig": ["cosmiconfig@5.2.1", "", { "dependencies": { "import-fresh": "^2.0.0", "is-directory": "^0.3.1", "js-yaml": "^3.13.1", "parse-json": "^4.0.0" } }, "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA=="], + "@react-native/metro-config/metro-config/metro": ["metro@0.83.1", "", { "dependencies": { "@babel/code-frame": "^7.24.7", "@babel/core": "^7.25.2", "@babel/generator": "^7.25.0", "@babel/parser": "^7.25.3", "@babel/template": "^7.25.0", "@babel/traverse": "^7.25.3", "@babel/types": "^7.25.2", "accepts": "^1.3.7", "chalk": "^4.0.0", "ci-info": "^2.0.0", "connect": "^3.6.5", "debug": "^4.4.0", "error-stack-parser": "^2.0.6", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "hermes-parser": "0.29.1", "image-size": "^1.0.2", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "jsc-safe-url": "^0.2.2", "lodash.throttle": "^4.1.1", "metro-babel-transformer": "0.83.1", "metro-cache": "0.83.1", "metro-cache-key": "0.83.1", "metro-config": "0.83.1", "metro-core": "0.83.1", "metro-file-map": "0.83.1", "metro-resolver": "0.83.1", "metro-runtime": "0.83.1", "metro-source-map": "0.83.1", "metro-symbolicate": "0.83.1", "metro-transform-plugins": "0.83.1", "metro-transform-worker": "0.83.1", "mime-types": "^2.1.27", "nullthrows": "^1.1.1", "serialize-error": "^2.1.0", "source-map": "^0.5.6", "throat": "^5.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" }, "bin": { "metro": "src/cli.js" } }, "sha512-UGKepmTxoGD4HkQV8YWvpvwef7fUujNtTgG4Ygf7m/M0qjvb9VuDmAsEU+UdriRX7F61pnVK/opz89hjKlYTXA=="], + "@react-native/metro-config/metro-config/metro-cache": ["metro-cache@0.83.1", "", { "dependencies": { "exponential-backoff": "^3.1.1", "flow-enums-runtime": "^0.0.6", "https-proxy-agent": "^7.0.5", "metro-core": "0.83.1" } }, "sha512-7N/Ad1PHa1YMWDNiyynTPq34Op2qIE68NWryGEQ4TSE3Zy6a8GpsYnEEZE4Qi6aHgsE+yZHKkRczeBgxhnFIxQ=="], + "@react-native/metro-config/metro-config/metro-core": ["metro-core@0.83.1", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "lodash.throttle": "^4.1.1", "metro-resolver": "0.83.1" } }, "sha512-uVL1eAJcMFd2o2Q7dsbpg8COaxjZBBGaXqO2OHnivpCdfanraVL8dPmY6It9ZeqWLOihUKZ2yHW4b6soVCzH/Q=="], + "@ts-morph/common/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], "@types/babel__core/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.24.8", "", {}, "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ=="], @@ -4645,7 +4699,27 @@ "logkitty/yargs/yargs-parser": ["yargs-parser@18.1.3", "", { "dependencies": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" } }, "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ=="], - "metro-cache/metro-core/metro-resolver": ["metro-resolver@0.80.10", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-EYC5CL7f+bSzrqdk1bylKqFNGabfiI5PDctxoPx70jFt89Jz+ThcOscENog8Jb4LEQFG6GkOYlwmPpsi7kx3QA=="], + "metro-babel-transformer/@babel/core/@babel/code-frame": ["@babel/code-frame@7.24.7", "", { "dependencies": { "@babel/highlight": "^7.24.7", "picocolors": "^1.0.0" } }, "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA=="], + + "metro-babel-transformer/@babel/core/@babel/generator": ["@babel/generator@7.25.5", "", { "dependencies": { "@babel/types": "^7.25.4", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" } }, "sha512-abd43wyLfbWoxC6ahM8xTkqLpGB2iWBVyuKC9/srhFunCd1SDNrV1s72bBpK4hLj8KLzHBBcOblvLQZBNw9r3w=="], + + "metro-babel-transformer/@babel/core/@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.25.2", "", { "dependencies": { "@babel/compat-data": "^7.25.2", "@babel/helper-validator-option": "^7.24.8", "browserslist": "^4.23.1", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw=="], + + "metro-babel-transformer/@babel/core/@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.25.2", "", { "dependencies": { "@babel/helper-module-imports": "^7.24.7", "@babel/helper-simple-access": "^7.24.7", "@babel/helper-validator-identifier": "^7.24.7", "@babel/traverse": "^7.25.2" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ=="], + + "metro-babel-transformer/@babel/core/@babel/helpers": ["@babel/helpers@7.25.0", "", { "dependencies": { "@babel/template": "^7.25.0", "@babel/types": "^7.25.0" } }, "sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw=="], + + "metro-babel-transformer/@babel/core/@babel/parser": ["@babel/parser@7.25.4", "", { "dependencies": { "@babel/types": "^7.25.4" }, "bin": "./bin/babel-parser.js" }, "sha512-nq+eWrOgdtu3jG5Os4TQP3x3cLA8hR8TvJNjD8vnPa20WGycimcparWnLK4jJhElTK6SDyuJo1weMKO/5LpmLA=="], + + "metro-babel-transformer/@babel/core/@babel/template": ["@babel/template@7.25.0", "", { "dependencies": { "@babel/code-frame": "^7.24.7", "@babel/parser": "^7.25.0", "@babel/types": "^7.25.0" } }, "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q=="], + + "metro-babel-transformer/@babel/core/@babel/traverse": ["@babel/traverse@7.25.4", "", { "dependencies": { "@babel/code-frame": "^7.24.7", "@babel/generator": "^7.25.4", "@babel/parser": "^7.25.4", "@babel/template": "^7.25.0", "@babel/types": "^7.25.4", "debug": "^4.3.1", "globals": "^11.1.0" } }, "sha512-VJ4XsrD+nOvlXyLzmLzUs/0qjFS4sK30te5yEFlvbbUNEgKaVb2BHZUpAL+ttLPQAHNrsI3zZisbfha5Cvr8vg=="], + + "metro-babel-transformer/@babel/core/@babel/types": ["@babel/types@7.25.4", "", { "dependencies": { "@babel/helper-string-parser": "^7.24.8", "@babel/helper-validator-identifier": "^7.24.7", "to-fast-properties": "^2.0.0" } }, "sha512-zQ1ijeeCXVEh+aNL0RlmkPkG8HUiDcU2pzQQFjtbntgAczRASFzj4H+6+bV+dy1ntKR14I/DypeuRG1uma98iQ=="], + + "metro-babel-transformer/@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + + "metro-babel-transformer/hermes-parser/hermes-estree": ["hermes-estree@0.23.0", "", {}, "sha512-Rkp0PNLGpORw4ktsttkVbpYJbrYKS3hAnkxu8D9nvQi6LvSbuPa+tYw/t2u3Gjc35lYd/k95YkjqyTcN4zspag=="], "metro-config/cosmiconfig/import-fresh": ["import-fresh@2.0.0", "", { "dependencies": { "caller-path": "^2.0.0", "resolve-from": "^3.0.0" } }, "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg=="], @@ -4653,111 +4727,115 @@ "metro-config/cosmiconfig/parse-json": ["parse-json@4.0.0", "", { "dependencies": { "error-ex": "^1.3.1", "json-parse-better-errors": "^1.0.1" } }, "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw=="], - "metro-config/metro/@babel/code-frame": ["@babel/code-frame@7.24.7", "", { "dependencies": { "@babel/highlight": "^7.24.7", "picocolors": "^1.0.0" } }, "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA=="], + "metro-config/metro-runtime/@babel/runtime": ["@babel/runtime@7.25.0", "", { "dependencies": { "regenerator-runtime": "^0.14.0" } }, "sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw=="], - "metro-config/metro/@babel/core": ["@babel/core@7.25.2", "", { "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.7", "@babel/generator": "^7.25.0", "@babel/helper-compilation-targets": "^7.25.2", "@babel/helper-module-transforms": "^7.25.2", "@babel/helpers": "^7.25.0", "@babel/parser": "^7.25.0", "@babel/template": "^7.25.0", "@babel/traverse": "^7.25.2", "@babel/types": "^7.25.2", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA=="], + "metro-file-map/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - "metro-config/metro/@babel/generator": ["@babel/generator@7.25.5", "", { "dependencies": { "@babel/types": "^7.25.4", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" } }, "sha512-abd43wyLfbWoxC6ahM8xTkqLpGB2iWBVyuKC9/srhFunCd1SDNrV1s72bBpK4hLj8KLzHBBcOblvLQZBNw9r3w=="], + "metro-react-native-babel-preset/@babel/template/@babel/code-frame": ["@babel/code-frame@7.27.1", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg=="], - "metro-config/metro/@babel/parser": ["@babel/parser@7.25.4", "", { "dependencies": { "@babel/types": "^7.25.4" }, "bin": "./bin/babel-parser.js" }, "sha512-nq+eWrOgdtu3jG5Os4TQP3x3cLA8hR8TvJNjD8vnPa20WGycimcparWnLK4jJhElTK6SDyuJo1weMKO/5LpmLA=="], + "metro-react-native-babel-preset/@babel/template/@babel/parser": ["@babel/parser@7.27.4", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-BRmLHGwpUqLFR2jzx9orBuX/ABDkj2jLKOXrHDTN2aOKL+jFDDKaRNo9nyYsIl9h/UE/7lMKdDjKQQyxKKDZ7g=="], - "metro-config/metro/@babel/template": ["@babel/template@7.25.0", "", { "dependencies": { "@babel/code-frame": "^7.24.7", "@babel/parser": "^7.25.0", "@babel/types": "^7.25.0" } }, "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q=="], + "metro-react-native-babel-preset/@babel/template/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="], - "metro-config/metro/@babel/traverse": ["@babel/traverse@7.25.4", "", { "dependencies": { "@babel/code-frame": "^7.24.7", "@babel/generator": "^7.25.4", "@babel/parser": "^7.25.4", "@babel/template": "^7.25.0", "@babel/types": "^7.25.4", "debug": "^4.3.1", "globals": "^11.1.0" } }, "sha512-VJ4XsrD+nOvlXyLzmLzUs/0qjFS4sK30te5yEFlvbbUNEgKaVb2BHZUpAL+ttLPQAHNrsI3zZisbfha5Cvr8vg=="], + "metro-source-map/@babel/traverse/@babel/code-frame": ["@babel/code-frame@7.27.1", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg=="], - "metro-config/metro/@babel/types": ["@babel/types@7.25.4", "", { "dependencies": { "@babel/helper-string-parser": "^7.24.8", "@babel/helper-validator-identifier": "^7.24.7", "to-fast-properties": "^2.0.0" } }, "sha512-zQ1ijeeCXVEh+aNL0RlmkPkG8HUiDcU2pzQQFjtbntgAczRASFzj4H+6+bV+dy1ntKR14I/DypeuRG1uma98iQ=="], + "metro-source-map/@babel/traverse/@babel/generator": ["@babel/generator@7.27.3", "", { "dependencies": { "@babel/parser": "^7.27.3", "@babel/types": "^7.27.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q=="], - "metro-config/metro/ci-info": ["ci-info@2.0.0", "", {}, "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ=="], + "metro-source-map/@babel/traverse/@babel/parser": ["@babel/parser@7.27.4", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-BRmLHGwpUqLFR2jzx9orBuX/ABDkj2jLKOXrHDTN2aOKL+jFDDKaRNo9nyYsIl9h/UE/7lMKdDjKQQyxKKDZ7g=="], - "metro-config/metro/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], + "metro-source-map/@babel/traverse/@babel/template": ["@babel/template@7.27.2", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/parser": "^7.27.2", "@babel/types": "^7.27.1" } }, "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw=="], - "metro-config/metro/hermes-parser": ["hermes-parser@0.23.0", "", { "dependencies": { "hermes-estree": "0.23.0" } }, "sha512-xLwM4ylfHGwrm+2qXfO1JT/fnqEDGSnpS/9hQ4VLtqTexSviu2ZpBgz07U8jVtndq67qdb/ps0qvaWDZ3fkTyg=="], + "metro-source-map/@babel/traverse/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="], - "metro-config/metro/metro-babel-transformer": ["metro-babel-transformer@0.80.10", "", { "dependencies": { "@babel/core": "^7.20.0", "flow-enums-runtime": "^0.0.6", "hermes-parser": "0.23.0", "nullthrows": "^1.1.1" } }, "sha512-GXHueUzgzcazfzORDxDzWS9jVVRV6u+cR6TGvHOfGdfLzJCj7/D0PretLfyq+MwN20twHxLW+BUXkoaB8sCQBg=="], + "metro-source-map/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], - "metro-config/metro/metro-cache-key": ["metro-cache-key@0.80.10", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-57qBhO3zQfoU/hP4ZlLW5hVej2jVfBX6B4NcSfMj4LgDPL3YknWg80IJBxzQfjQY/m+fmMLmPy8aUMHzUp/guA=="], + "metro-source-map/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="], - "metro-config/metro/metro-file-map": ["metro-file-map@0.80.10", "", { "dependencies": { "anymatch": "^3.0.3", "debug": "^2.2.0", "fb-watchman": "^2.0.0", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "invariant": "^2.2.4", "jest-worker": "^29.6.3", "micromatch": "^4.0.4", "node-abort-controller": "^3.1.1", "nullthrows": "^1.1.1", "walker": "^1.0.7" }, "optionalDependencies": { "fsevents": "^2.3.2" } }, "sha512-ytsUq8coneaN7ZCVk1IogojcGhLIbzWyiI2dNmw2nnBgV/0A+M5WaTTgZ6dJEz3dzjObPryDnkqWPvIGLCPtiw=="], + "metro-transform-plugins/@babel/core/@babel/code-frame": ["@babel/code-frame@7.24.7", "", { "dependencies": { "@babel/highlight": "^7.24.7", "picocolors": "^1.0.0" } }, "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA=="], - "metro-config/metro/metro-resolver": ["metro-resolver@0.80.10", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-EYC5CL7f+bSzrqdk1bylKqFNGabfiI5PDctxoPx70jFt89Jz+ThcOscENog8Jb4LEQFG6GkOYlwmPpsi7kx3QA=="], + "metro-transform-plugins/@babel/core/@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.25.2", "", { "dependencies": { "@babel/compat-data": "^7.25.2", "@babel/helper-validator-option": "^7.24.8", "browserslist": "^4.23.1", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw=="], - "metro-config/metro/metro-source-map": ["metro-source-map@0.80.10", "", { "dependencies": { "@babel/traverse": "^7.20.0", "@babel/types": "^7.20.0", "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-symbolicate": "0.80.10", "nullthrows": "^1.1.1", "ob1": "0.80.10", "source-map": "^0.5.6", "vlq": "^1.0.0" } }, "sha512-EyZswqJW8Uukv/HcQr6K19vkMXW1nzHAZPWJSEyJFKIbgp708QfRZ6vnZGmrtFxeJEaFdNup4bGnu8/mIOYlyA=="], + "metro-transform-plugins/@babel/core/@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.25.2", "", { "dependencies": { "@babel/helper-module-imports": "^7.24.7", "@babel/helper-simple-access": "^7.24.7", "@babel/helper-validator-identifier": "^7.24.7", "@babel/traverse": "^7.25.2" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ=="], - "metro-config/metro/metro-symbolicate": ["metro-symbolicate@0.80.10", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-source-map": "0.80.10", "nullthrows": "^1.1.1", "source-map": "^0.5.6", "through2": "^2.0.1", "vlq": "^1.0.0" }, "bin": { "metro-symbolicate": "src/index.js" } }, "sha512-qAoVUoSxpfZ2DwZV7IdnQGXCSsf2cAUExUcZyuCqGlY5kaWBb0mx2BL/xbMFDJ4wBp3sVvSBPtK/rt4J7a0xBA=="], + "metro-transform-plugins/@babel/core/@babel/helpers": ["@babel/helpers@7.25.0", "", { "dependencies": { "@babel/template": "^7.25.0", "@babel/types": "^7.25.0" } }, "sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw=="], - "metro-config/metro/metro-transform-plugins": ["metro-transform-plugins@0.80.10", "", { "dependencies": { "@babel/core": "^7.20.0", "@babel/generator": "^7.20.0", "@babel/template": "^7.0.0", "@babel/traverse": "^7.20.0", "flow-enums-runtime": "^0.0.6", "nullthrows": "^1.1.1" } }, "sha512-leAx9gtA+2MHLsCeWK6XTLBbv2fBnNFu/QiYhWzMq8HsOAP4u1xQAU0tSgPs8+1vYO34Plyn79xTLUtQCRSSUQ=="], + "metro-transform-plugins/@babel/core/@babel/parser": ["@babel/parser@7.25.4", "", { "dependencies": { "@babel/types": "^7.25.4" }, "bin": "./bin/babel-parser.js" }, "sha512-nq+eWrOgdtu3jG5Os4TQP3x3cLA8hR8TvJNjD8vnPa20WGycimcparWnLK4jJhElTK6SDyuJo1weMKO/5LpmLA=="], - "metro-config/metro/metro-transform-worker": ["metro-transform-worker@0.80.10", "", { "dependencies": { "@babel/core": "^7.20.0", "@babel/generator": "^7.20.0", "@babel/parser": "^7.20.0", "@babel/types": "^7.20.0", "flow-enums-runtime": "^0.0.6", "metro": "0.80.10", "metro-babel-transformer": "0.80.10", "metro-cache": "0.80.10", "metro-cache-key": "0.80.10", "metro-minify-terser": "0.80.10", "metro-source-map": "0.80.10", "metro-transform-plugins": "0.80.10", "nullthrows": "^1.1.1" } }, "sha512-zNfNLD8Rz99U+JdOTqtF2o7iTjcDMMYdVS90z6+81Tzd2D0lDWVpls7R1hadS6xwM+ymgXFQTjM6V6wFoZaC0g=="], + "metro-transform-plugins/@babel/core/@babel/types": ["@babel/types@7.25.4", "", { "dependencies": { "@babel/helper-string-parser": "^7.24.8", "@babel/helper-validator-identifier": "^7.24.7", "to-fast-properties": "^2.0.0" } }, "sha512-zQ1ijeeCXVEh+aNL0RlmkPkG8HUiDcU2pzQQFjtbntgAczRASFzj4H+6+bV+dy1ntKR14I/DypeuRG1uma98iQ=="], - "metro-config/metro/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "metro-transform-plugins/@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - "metro-config/metro/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="], + "metro-transform-plugins/@babel/generator/@babel/types": ["@babel/types@7.25.4", "", { "dependencies": { "@babel/helper-string-parser": "^7.24.8", "@babel/helper-validator-identifier": "^7.24.7", "to-fast-properties": "^2.0.0" } }, "sha512-zQ1ijeeCXVEh+aNL0RlmkPkG8HUiDcU2pzQQFjtbntgAczRASFzj4H+6+bV+dy1ntKR14I/DypeuRG1uma98iQ=="], - "metro-config/metro/yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], + "metro-transform-plugins/@babel/generator/jsesc": ["jsesc@2.5.2", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA=="], - "metro-config/metro-core/metro-resolver": ["metro-resolver@0.80.10", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-EYC5CL7f+bSzrqdk1bylKqFNGabfiI5PDctxoPx70jFt89Jz+ThcOscENog8Jb4LEQFG6GkOYlwmPpsi7kx3QA=="], + "metro-transform-plugins/@babel/template/@babel/code-frame": ["@babel/code-frame@7.24.7", "", { "dependencies": { "@babel/highlight": "^7.24.7", "picocolors": "^1.0.0" } }, "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA=="], - "metro-config/metro-runtime/@babel/runtime": ["@babel/runtime@7.25.0", "", { "dependencies": { "regenerator-runtime": "^0.14.0" } }, "sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw=="], + "metro-transform-plugins/@babel/template/@babel/parser": ["@babel/parser@7.25.4", "", { "dependencies": { "@babel/types": "^7.25.4" }, "bin": "./bin/babel-parser.js" }, "sha512-nq+eWrOgdtu3jG5Os4TQP3x3cLA8hR8TvJNjD8vnPa20WGycimcparWnLK4jJhElTK6SDyuJo1weMKO/5LpmLA=="], - "metro-file-map/debug/ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + "metro-transform-plugins/@babel/template/@babel/types": ["@babel/types@7.25.4", "", { "dependencies": { "@babel/helper-string-parser": "^7.24.8", "@babel/helper-validator-identifier": "^7.24.7", "to-fast-properties": "^2.0.0" } }, "sha512-zQ1ijeeCXVEh+aNL0RlmkPkG8HUiDcU2pzQQFjtbntgAczRASFzj4H+6+bV+dy1ntKR14I/DypeuRG1uma98iQ=="], - "metro-react-native-babel-preset/@babel/template/@babel/code-frame": ["@babel/code-frame@7.27.1", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg=="], + "metro-transform-plugins/@babel/traverse/@babel/code-frame": ["@babel/code-frame@7.24.7", "", { "dependencies": { "@babel/highlight": "^7.24.7", "picocolors": "^1.0.0" } }, "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA=="], - "metro-react-native-babel-preset/@babel/template/@babel/parser": ["@babel/parser@7.27.4", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-BRmLHGwpUqLFR2jzx9orBuX/ABDkj2jLKOXrHDTN2aOKL+jFDDKaRNo9nyYsIl9h/UE/7lMKdDjKQQyxKKDZ7g=="], + "metro-transform-plugins/@babel/traverse/@babel/parser": ["@babel/parser@7.25.4", "", { "dependencies": { "@babel/types": "^7.25.4" }, "bin": "./bin/babel-parser.js" }, "sha512-nq+eWrOgdtu3jG5Os4TQP3x3cLA8hR8TvJNjD8vnPa20WGycimcparWnLK4jJhElTK6SDyuJo1weMKO/5LpmLA=="], - "metro-react-native-babel-preset/@babel/template/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="], + "metro-transform-plugins/@babel/traverse/@babel/types": ["@babel/types@7.25.4", "", { "dependencies": { "@babel/helper-string-parser": "^7.24.8", "@babel/helper-validator-identifier": "^7.24.7", "to-fast-properties": "^2.0.0" } }, "sha512-zQ1ijeeCXVEh+aNL0RlmkPkG8HUiDcU2pzQQFjtbntgAczRASFzj4H+6+bV+dy1ntKR14I/DypeuRG1uma98iQ=="], - "metro-source-map/@babel/traverse/@babel/code-frame": ["@babel/code-frame@7.27.1", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg=="], + "metro-transform-plugins/@babel/traverse/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="], - "metro-source-map/@babel/traverse/@babel/generator": ["@babel/generator@7.27.3", "", { "dependencies": { "@babel/parser": "^7.27.3", "@babel/types": "^7.27.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q=="], + "metro-transform-worker/@babel/core/@babel/code-frame": ["@babel/code-frame@7.24.7", "", { "dependencies": { "@babel/highlight": "^7.24.7", "picocolors": "^1.0.0" } }, "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA=="], - "metro-source-map/@babel/traverse/@babel/parser": ["@babel/parser@7.27.4", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-BRmLHGwpUqLFR2jzx9orBuX/ABDkj2jLKOXrHDTN2aOKL+jFDDKaRNo9nyYsIl9h/UE/7lMKdDjKQQyxKKDZ7g=="], + "metro-transform-worker/@babel/core/@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.25.2", "", { "dependencies": { "@babel/compat-data": "^7.25.2", "@babel/helper-validator-option": "^7.24.8", "browserslist": "^4.23.1", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw=="], - "metro-source-map/@babel/traverse/@babel/template": ["@babel/template@7.27.2", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/parser": "^7.27.2", "@babel/types": "^7.27.1" } }, "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw=="], + "metro-transform-worker/@babel/core/@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.25.2", "", { "dependencies": { "@babel/helper-module-imports": "^7.24.7", "@babel/helper-simple-access": "^7.24.7", "@babel/helper-validator-identifier": "^7.24.7", "@babel/traverse": "^7.25.2" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ=="], - "metro-source-map/@babel/traverse/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="], + "metro-transform-worker/@babel/core/@babel/helpers": ["@babel/helpers@7.25.0", "", { "dependencies": { "@babel/template": "^7.25.0", "@babel/types": "^7.25.0" } }, "sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw=="], - "metro-source-map/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], + "metro-transform-worker/@babel/core/@babel/template": ["@babel/template@7.25.0", "", { "dependencies": { "@babel/code-frame": "^7.24.7", "@babel/parser": "^7.25.0", "@babel/types": "^7.25.0" } }, "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q=="], - "metro-source-map/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="], + "metro-transform-worker/@babel/core/@babel/traverse": ["@babel/traverse@7.25.4", "", { "dependencies": { "@babel/code-frame": "^7.24.7", "@babel/generator": "^7.25.4", "@babel/parser": "^7.25.4", "@babel/template": "^7.25.0", "@babel/types": "^7.25.4", "debug": "^4.3.1", "globals": "^11.1.0" } }, "sha512-VJ4XsrD+nOvlXyLzmLzUs/0qjFS4sK30te5yEFlvbbUNEgKaVb2BHZUpAL+ttLPQAHNrsI3zZisbfha5Cvr8vg=="], - "metro-transform-plugins/@babel/generator/@babel/parser": ["@babel/parser@7.27.4", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-BRmLHGwpUqLFR2jzx9orBuX/ABDkj2jLKOXrHDTN2aOKL+jFDDKaRNo9nyYsIl9h/UE/7lMKdDjKQQyxKKDZ7g=="], + "metro-transform-worker/@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - "metro-transform-plugins/@babel/generator/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="], + "metro-transform-worker/@babel/generator/jsesc": ["jsesc@2.5.2", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA=="], - "metro-transform-plugins/@babel/template/@babel/code-frame": ["@babel/code-frame@7.27.1", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg=="], + "metro-transform-worker/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.24.8", "", {}, "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ=="], - "metro-transform-plugins/@babel/template/@babel/parser": ["@babel/parser@7.27.4", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-BRmLHGwpUqLFR2jzx9orBuX/ABDkj2jLKOXrHDTN2aOKL+jFDDKaRNo9nyYsIl9h/UE/7lMKdDjKQQyxKKDZ7g=="], + "metro-transform-worker/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.24.7", "", {}, "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w=="], - "metro-transform-plugins/@babel/template/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="], + "metro-transform-worker/metro-source-map/@babel/traverse": ["@babel/traverse@7.25.4", "", { "dependencies": { "@babel/code-frame": "^7.24.7", "@babel/generator": "^7.25.4", "@babel/parser": "^7.25.4", "@babel/template": "^7.25.0", "@babel/types": "^7.25.4", "debug": "^4.3.1", "globals": "^11.1.0" } }, "sha512-VJ4XsrD+nOvlXyLzmLzUs/0qjFS4sK30te5yEFlvbbUNEgKaVb2BHZUpAL+ttLPQAHNrsI3zZisbfha5Cvr8vg=="], - "metro-transform-plugins/@babel/traverse/@babel/code-frame": ["@babel/code-frame@7.27.1", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg=="], + "metro-transform-worker/metro-source-map/metro-symbolicate": ["metro-symbolicate@0.80.10", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-source-map": "0.80.10", "nullthrows": "^1.1.1", "source-map": "^0.5.6", "through2": "^2.0.1", "vlq": "^1.0.0" }, "bin": { "metro-symbolicate": "src/index.js" } }, "sha512-qAoVUoSxpfZ2DwZV7IdnQGXCSsf2cAUExUcZyuCqGlY5kaWBb0mx2BL/xbMFDJ4wBp3sVvSBPtK/rt4J7a0xBA=="], - "metro-transform-plugins/@babel/traverse/@babel/parser": ["@babel/parser@7.27.4", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-BRmLHGwpUqLFR2jzx9orBuX/ABDkj2jLKOXrHDTN2aOKL+jFDDKaRNo9nyYsIl9h/UE/7lMKdDjKQQyxKKDZ7g=="], + "metro-transform-worker/metro-source-map/ob1": ["ob1@0.80.10", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-dJHyB0S6JkMorUSfSGcYGkkg9kmq3qDUu3ygZUKIfkr47XOPuG35r2Sk6tbwtHXbdKIXmcMvM8DF2CwgdyaHfQ=="], - "metro-transform-plugins/@babel/traverse/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="], + "metro/@babel/core/@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.25.2", "", { "dependencies": { "@babel/compat-data": "^7.25.2", "@babel/helper-validator-option": "^7.24.8", "browserslist": "^4.23.1", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw=="], - "metro-transform-plugins/@babel/traverse/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="], + "metro/@babel/core/@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.25.2", "", { "dependencies": { "@babel/helper-module-imports": "^7.24.7", "@babel/helper-simple-access": "^7.24.7", "@babel/helper-validator-identifier": "^7.24.7", "@babel/traverse": "^7.25.2" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ=="], - "metro-transform-worker/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], + "metro/@babel/core/@babel/helpers": ["@babel/helpers@7.25.0", "", { "dependencies": { "@babel/template": "^7.25.0", "@babel/types": "^7.25.0" } }, "sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw=="], - "metro-transform-worker/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="], + "metro/@babel/core/debug": ["debug@4.3.6", "", { "dependencies": { "ms": "2.1.2" } }, "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg=="], - "metro/@babel/code-frame/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="], + "metro/@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - "metro/@babel/code-frame/picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], + "metro/@babel/generator/jsesc": ["jsesc@2.5.2", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA=="], "metro/@babel/traverse/debug": ["debug@4.3.6", "", { "dependencies": { "ms": "2.1.2" } }, "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg=="], "metro/@babel/traverse/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="], - "metro/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], + "metro/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.24.8", "", {}, "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ=="], + + "metro/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.24.7", "", {}, "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w=="], - "metro/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="], + "metro/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - "metro/debug/ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + "metro/hermes-parser/hermes-estree": ["hermes-estree@0.23.0", "", {}, "sha512-Rkp0PNLGpORw4ktsttkVbpYJbrYKS3hAnkxu8D9nvQi6LvSbuPa+tYw/t2u3Gjc35lYd/k95YkjqyTcN4zspag=="], - "metro/metro-config/cosmiconfig": ["cosmiconfig@5.2.1", "", { "dependencies": { "import-fresh": "^2.0.0", "is-directory": "^0.3.1", "js-yaml": "^3.13.1", "parse-json": "^4.0.0" } }, "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA=="], + "metro/metro-runtime/@babel/runtime": ["@babel/runtime@7.25.0", "", { "dependencies": { "regenerator-runtime": "^0.14.0" } }, "sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw=="], + + "metro/metro-source-map/ob1": ["ob1@0.80.10", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-dJHyB0S6JkMorUSfSGcYGkkg9kmq3qDUu3ygZUKIfkr47XOPuG35r2Sk6tbwtHXbdKIXmcMvM8DF2CwgdyaHfQ=="], "metro/yargs/cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="], @@ -5255,6 +5333,24 @@ "@react-native/community-cli-plugin/metro-config/cosmiconfig/parse-json": ["parse-json@4.0.0", "", { "dependencies": { "error-ex": "^1.3.1", "json-parse-better-errors": "^1.0.1" } }, "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw=="], + "@react-native/community-cli-plugin/metro/@babel/code-frame/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="], + + "@react-native/community-cli-plugin/metro/@babel/code-frame/picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], + + "@react-native/community-cli-plugin/metro/@babel/traverse/debug": ["debug@4.3.6", "", { "dependencies": { "ms": "2.1.2" } }, "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg=="], + + "@react-native/community-cli-plugin/metro/@babel/traverse/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="], + + "@react-native/community-cli-plugin/metro/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], + + "@react-native/community-cli-plugin/metro/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="], + + "@react-native/community-cli-plugin/metro/metro-transform-worker/metro-minify-terser": ["metro-minify-terser@0.83.1", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "terser": "^5.15.0" } }, "sha512-kmooOxXLvKVxkh80IVSYO4weBdJDhCpg5NSPkjzzAnPJP43u6+usGXobkTWxxrAlq900bhzqKek4pBsUchlX6A=="], + + "@react-native/community-cli-plugin/metro/yargs/cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="], + + "@react-native/community-cli-plugin/metro/yargs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + "@react-native/dev-middleware/serve-static/send/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], "@react-native/dev-middleware/serve-static/send/encodeurl": ["encodeurl@1.0.2", "", {}, "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="], @@ -5291,6 +5387,42 @@ "@react-native/metro-config/metro-config/cosmiconfig/parse-json": ["parse-json@4.0.0", "", { "dependencies": { "error-ex": "^1.3.1", "json-parse-better-errors": "^1.0.1" } }, "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw=="], + "@react-native/metro-config/metro-config/metro/@babel/code-frame": ["@babel/code-frame@7.27.1", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg=="], + + "@react-native/metro-config/metro-config/metro/@babel/generator": ["@babel/generator@7.27.3", "", { "dependencies": { "@babel/parser": "^7.27.3", "@babel/types": "^7.27.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q=="], + + "@react-native/metro-config/metro-config/metro/@babel/parser": ["@babel/parser@7.27.4", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-BRmLHGwpUqLFR2jzx9orBuX/ABDkj2jLKOXrHDTN2aOKL+jFDDKaRNo9nyYsIl9h/UE/7lMKdDjKQQyxKKDZ7g=="], + + "@react-native/metro-config/metro-config/metro/@babel/template": ["@babel/template@7.27.2", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/parser": "^7.27.2", "@babel/types": "^7.27.1" } }, "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw=="], + + "@react-native/metro-config/metro-config/metro/@babel/traverse": ["@babel/traverse@7.27.4", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.27.3", "@babel/parser": "^7.27.4", "@babel/template": "^7.27.2", "@babel/types": "^7.27.3", "debug": "^4.3.1", "globals": "^11.1.0" } }, "sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA=="], + + "@react-native/metro-config/metro-config/metro/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="], + + "@react-native/metro-config/metro-config/metro/ci-info": ["ci-info@2.0.0", "", {}, "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ=="], + + "@react-native/metro-config/metro-config/metro/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], + + "@react-native/metro-config/metro-config/metro/metro-babel-transformer": ["metro-babel-transformer@0.83.1", "", { "dependencies": { "@babel/core": "^7.25.2", "flow-enums-runtime": "^0.0.6", "hermes-parser": "0.29.1", "nullthrows": "^1.1.1" } }, "sha512-r3xAD3964E8dwDBaZNSO2aIIvWXjIK80uO2xo0/pi3WI8XWT9h5SCjtGWtMtE5PRWw+t20TN0q1WMRsjvhC1rQ=="], + + "@react-native/metro-config/metro-config/metro/metro-cache-key": ["metro-cache-key@0.83.1", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-ZUs+GD5CNeDLxx5UUWmfg26IL+Dnbryd+TLqTlZnDEgehkIa11kUSvgF92OFfJhONeXzV4rZDRGNXoo6JT+8Gg=="], + + "@react-native/metro-config/metro-config/metro/metro-file-map": ["metro-file-map@0.83.1", "", { "dependencies": { "debug": "^4.4.0", "fb-watchman": "^2.0.0", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "micromatch": "^4.0.4", "nullthrows": "^1.1.1", "walker": "^1.0.7" } }, "sha512-Yu429lnexKl44PttKw3nhqgmpBR+6UQ/tRaYcxPeEShtcza9DWakCn7cjqDTQZtWR2A8xSNv139izJMyQ4CG+w=="], + + "@react-native/metro-config/metro-config/metro/metro-resolver": ["metro-resolver@0.83.1", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-t8j46kiILAqqFS5RNa+xpQyVjULxRxlvMidqUswPEk5nQVNdlJslqizDm/Et3v/JKwOtQGkYAQCHxP1zGStR/g=="], + + "@react-native/metro-config/metro-config/metro/metro-transform-plugins": ["metro-transform-plugins@0.83.1", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/generator": "^7.25.0", "@babel/template": "^7.25.0", "@babel/traverse": "^7.25.3", "flow-enums-runtime": "^0.0.6", "nullthrows": "^1.1.1" } }, "sha512-1Y+I8oozXwhuS0qwC+ezaHXBf0jXW4oeYn4X39XWbZt9X2HfjodqY9bH9r6RUTsoiK7S4j8Ni2C91bUC+sktJQ=="], + + "@react-native/metro-config/metro-config/metro/metro-transform-worker": ["metro-transform-worker@0.83.1", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/generator": "^7.25.0", "@babel/parser": "^7.25.3", "@babel/types": "^7.25.2", "flow-enums-runtime": "^0.0.6", "metro": "0.83.1", "metro-babel-transformer": "0.83.1", "metro-cache": "0.83.1", "metro-cache-key": "0.83.1", "metro-minify-terser": "0.83.1", "metro-source-map": "0.83.1", "metro-transform-plugins": "0.83.1", "nullthrows": "^1.1.1" } }, "sha512-owCrhPyUxdLgXEEEAL2b14GWTPZ2zYuab1VQXcfEy0sJE71iciD7fuMcrngoufh7e7UHDZ56q4ktXg8wgiYA1Q=="], + + "@react-native/metro-config/metro-config/metro/serialize-error": ["serialize-error@2.1.0", "", {}, "sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw=="], + + "@react-native/metro-config/metro-config/metro/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="], + + "@react-native/metro-config/metro-config/metro/yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], + + "@react-native/metro-config/metro-config/metro-core/metro-resolver": ["metro-resolver@0.83.1", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-t8j46kiILAqqFS5RNa+xpQyVjULxRxlvMidqUswPEk5nQVNdlJslqizDm/Et3v/JKwOtQGkYAQCHxP1zGStR/g=="], + "@typescript-eslint/type-utils/@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], "@typescript-eslint/utils/@typescript-eslint/typescript-estree/debug/ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], @@ -5407,90 +5539,110 @@ "logkitty/yargs/yargs-parser/camelcase": ["camelcase@5.3.1", "", {}, "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="], + "metro-babel-transformer/@babel/core/@babel/generator/jsesc": ["jsesc@2.5.2", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA=="], + + "metro-babel-transformer/@babel/core/@babel/helper-compilation-targets/@babel/compat-data": ["@babel/compat-data@7.25.4", "", {}, "sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ=="], + + "metro-babel-transformer/@babel/core/@babel/helper-compilation-targets/@babel/helper-validator-option": ["@babel/helper-validator-option@7.24.8", "", {}, "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q=="], + + "metro-babel-transformer/@babel/core/@babel/helper-compilation-targets/browserslist": ["browserslist@4.23.3", "", { "dependencies": { "caniuse-lite": "^1.0.30001646", "electron-to-chromium": "^1.5.4", "node-releases": "^2.0.18", "update-browserslist-db": "^1.1.0" }, "bin": { "browserslist": "cli.js" } }, "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA=="], + + "metro-babel-transformer/@babel/core/@babel/helper-compilation-targets/lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], + + "metro-babel-transformer/@babel/core/@babel/helper-module-transforms/@babel/helper-module-imports": ["@babel/helper-module-imports@7.24.7", "", { "dependencies": { "@babel/traverse": "^7.24.7", "@babel/types": "^7.24.7" } }, "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA=="], + + "metro-babel-transformer/@babel/core/@babel/helper-module-transforms/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.24.7", "", {}, "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w=="], + + "metro-babel-transformer/@babel/core/@babel/traverse/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="], + + "metro-babel-transformer/@babel/core/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.24.8", "", {}, "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ=="], + + "metro-babel-transformer/@babel/core/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.24.7", "", {}, "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w=="], + "metro-config/cosmiconfig/import-fresh/resolve-from": ["resolve-from@3.0.0", "", {}, "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw=="], "metro-config/cosmiconfig/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], "metro-config/metro-runtime/@babel/runtime/regenerator-runtime": ["regenerator-runtime@0.14.1", "", {}, "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="], - "metro-config/metro/@babel/core/@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.25.2", "", { "dependencies": { "@babel/compat-data": "^7.25.2", "@babel/helper-validator-option": "^7.24.8", "browserslist": "^4.23.1", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw=="], + "metro-react-native-babel-preset/@babel/template/@babel/code-frame/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="], - "metro-config/metro/@babel/core/@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.25.2", "", { "dependencies": { "@babel/helper-module-imports": "^7.24.7", "@babel/helper-simple-access": "^7.24.7", "@babel/helper-validator-identifier": "^7.24.7", "@babel/traverse": "^7.25.2" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ=="], + "metro-react-native-babel-preset/@babel/template/@babel/code-frame/picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], - "metro-config/metro/@babel/core/@babel/helpers": ["@babel/helpers@7.25.0", "", { "dependencies": { "@babel/template": "^7.25.0", "@babel/types": "^7.25.0" } }, "sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw=="], + "metro-react-native-babel-preset/@babel/template/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], - "metro-config/metro/@babel/core/debug": ["debug@4.3.6", "", { "dependencies": { "ms": "2.1.2" } }, "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg=="], + "metro-react-native-babel-preset/@babel/template/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="], - "metro-config/metro/@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + "metro-source-map/@babel/traverse/@babel/code-frame/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="], - "metro-config/metro/@babel/generator/jsesc": ["jsesc@2.5.2", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA=="], + "metro-source-map/@babel/traverse/@babel/code-frame/picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], - "metro-config/metro/@babel/traverse/debug": ["debug@4.3.6", "", { "dependencies": { "ms": "2.1.2" } }, "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg=="], + "metro-transform-plugins/@babel/core/@babel/helper-compilation-targets/@babel/compat-data": ["@babel/compat-data@7.25.4", "", {}, "sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ=="], - "metro-config/metro/@babel/traverse/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="], + "metro-transform-plugins/@babel/core/@babel/helper-compilation-targets/@babel/helper-validator-option": ["@babel/helper-validator-option@7.24.8", "", {}, "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q=="], - "metro-config/metro/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.24.8", "", {}, "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ=="], + "metro-transform-plugins/@babel/core/@babel/helper-compilation-targets/browserslist": ["browserslist@4.23.3", "", { "dependencies": { "caniuse-lite": "^1.0.30001646", "electron-to-chromium": "^1.5.4", "node-releases": "^2.0.18", "update-browserslist-db": "^1.1.0" }, "bin": { "browserslist": "cli.js" } }, "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA=="], - "metro-config/metro/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.24.7", "", {}, "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w=="], + "metro-transform-plugins/@babel/core/@babel/helper-compilation-targets/lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], - "metro-config/metro/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + "metro-transform-plugins/@babel/core/@babel/helper-module-transforms/@babel/helper-module-imports": ["@babel/helper-module-imports@7.24.7", "", { "dependencies": { "@babel/traverse": "^7.24.7", "@babel/types": "^7.24.7" } }, "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA=="], - "metro-config/metro/hermes-parser/hermes-estree": ["hermes-estree@0.23.0", "", {}, "sha512-Rkp0PNLGpORw4ktsttkVbpYJbrYKS3hAnkxu8D9nvQi6LvSbuPa+tYw/t2u3Gjc35lYd/k95YkjqyTcN4zspag=="], + "metro-transform-plugins/@babel/core/@babel/helper-module-transforms/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.24.7", "", {}, "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w=="], - "metro-config/metro/metro-source-map/ob1": ["ob1@0.80.10", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-dJHyB0S6JkMorUSfSGcYGkkg9kmq3qDUu3ygZUKIfkr47XOPuG35r2Sk6tbwtHXbdKIXmcMvM8DF2CwgdyaHfQ=="], + "metro-transform-plugins/@babel/core/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.24.8", "", {}, "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ=="], - "metro-config/metro/metro-transform-worker/metro-minify-terser": ["metro-minify-terser@0.80.10", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "terser": "^5.15.0" } }, "sha512-Xyv9pEYpOsAerrld7cSLIcnCCpv8ItwysOmTA+AKf1q4KyE9cxrH2O2SA0FzMCkPzwxzBWmXwHUr+A89BpEM6g=="], + "metro-transform-plugins/@babel/core/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.24.7", "", {}, "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w=="], - "metro-config/metro/yargs/cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="], + "metro-transform-plugins/@babel/generator/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.24.8", "", {}, "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ=="], - "metro-config/metro/yargs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + "metro-transform-plugins/@babel/generator/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.24.7", "", {}, "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w=="], - "metro-react-native-babel-preset/@babel/template/@babel/code-frame/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="], + "metro-transform-plugins/@babel/template/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.24.8", "", {}, "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ=="], - "metro-react-native-babel-preset/@babel/template/@babel/code-frame/picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], + "metro-transform-plugins/@babel/template/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.24.7", "", {}, "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w=="], - "metro-react-native-babel-preset/@babel/template/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], + "metro-transform-plugins/@babel/traverse/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.24.8", "", {}, "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ=="], - "metro-react-native-babel-preset/@babel/template/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="], + "metro-transform-plugins/@babel/traverse/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.24.7", "", {}, "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w=="], - "metro-source-map/@babel/traverse/@babel/code-frame/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="], + "metro-transform-worker/@babel/core/@babel/helper-compilation-targets/@babel/compat-data": ["@babel/compat-data@7.25.4", "", {}, "sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ=="], - "metro-source-map/@babel/traverse/@babel/code-frame/picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], + "metro-transform-worker/@babel/core/@babel/helper-compilation-targets/@babel/helper-validator-option": ["@babel/helper-validator-option@7.24.8", "", {}, "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q=="], + + "metro-transform-worker/@babel/core/@babel/helper-compilation-targets/browserslist": ["browserslist@4.23.3", "", { "dependencies": { "caniuse-lite": "^1.0.30001646", "electron-to-chromium": "^1.5.4", "node-releases": "^2.0.18", "update-browserslist-db": "^1.1.0" }, "bin": { "browserslist": "cli.js" } }, "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA=="], - "metro-transform-plugins/@babel/generator/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], + "metro-transform-worker/@babel/core/@babel/helper-compilation-targets/lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], - "metro-transform-plugins/@babel/generator/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="], + "metro-transform-worker/@babel/core/@babel/helper-module-transforms/@babel/helper-module-imports": ["@babel/helper-module-imports@7.24.7", "", { "dependencies": { "@babel/traverse": "^7.24.7", "@babel/types": "^7.24.7" } }, "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA=="], - "metro-transform-plugins/@babel/template/@babel/code-frame/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="], + "metro-transform-worker/@babel/core/@babel/helper-module-transforms/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.24.7", "", {}, "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w=="], - "metro-transform-plugins/@babel/template/@babel/code-frame/picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], + "metro-transform-worker/@babel/core/@babel/traverse/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="], - "metro-transform-plugins/@babel/template/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], + "metro-transform-worker/metro-source-map/@babel/traverse/@babel/code-frame": ["@babel/code-frame@7.24.7", "", { "dependencies": { "@babel/highlight": "^7.24.7", "picocolors": "^1.0.0" } }, "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA=="], - "metro-transform-plugins/@babel/template/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="], + "metro-transform-worker/metro-source-map/@babel/traverse/@babel/template": ["@babel/template@7.25.0", "", { "dependencies": { "@babel/code-frame": "^7.24.7", "@babel/parser": "^7.25.0", "@babel/types": "^7.25.0" } }, "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q=="], - "metro-transform-plugins/@babel/traverse/@babel/code-frame/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="], + "metro-transform-worker/metro-source-map/@babel/traverse/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="], - "metro-transform-plugins/@babel/traverse/@babel/code-frame/picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], + "metro/@babel/core/@babel/helper-compilation-targets/@babel/compat-data": ["@babel/compat-data@7.25.4", "", {}, "sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ=="], - "metro-transform-plugins/@babel/traverse/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], + "metro/@babel/core/@babel/helper-compilation-targets/@babel/helper-validator-option": ["@babel/helper-validator-option@7.24.8", "", {}, "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q=="], - "metro-transform-plugins/@babel/traverse/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="], + "metro/@babel/core/@babel/helper-compilation-targets/browserslist": ["browserslist@4.23.3", "", { "dependencies": { "caniuse-lite": "^1.0.30001646", "electron-to-chromium": "^1.5.4", "node-releases": "^2.0.18", "update-browserslist-db": "^1.1.0" }, "bin": { "browserslist": "cli.js" } }, "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA=="], - "metro/metro-config/cosmiconfig/import-fresh": ["import-fresh@2.0.0", "", { "dependencies": { "caller-path": "^2.0.0", "resolve-from": "^3.0.0" } }, "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg=="], + "metro/@babel/core/@babel/helper-compilation-targets/lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], - "metro/metro-config/cosmiconfig/js-yaml": ["js-yaml@3.14.1", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g=="], + "metro/@babel/core/@babel/helper-module-transforms/@babel/helper-module-imports": ["@babel/helper-module-imports@7.24.7", "", { "dependencies": { "@babel/traverse": "^7.24.7", "@babel/types": "^7.24.7" } }, "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA=="], - "metro/metro-config/cosmiconfig/parse-json": ["parse-json@4.0.0", "", { "dependencies": { "error-ex": "^1.3.1", "json-parse-better-errors": "^1.0.1" } }, "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw=="], + "metro/@babel/core/@babel/helper-module-transforms/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.24.7", "", {}, "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w=="], - "metro/yargs/cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "metro/metro-runtime/@babel/runtime/regenerator-runtime": ["regenerator-runtime@0.14.1", "", {}, "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="], "metro/yargs/cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], "metro/yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], - "metro/yargs/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - "nitro-codegen/yargs/cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], "nitro-codegen/yargs/cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], @@ -5711,6 +5863,14 @@ "@react-native/community-cli-plugin/metro-config/cosmiconfig/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], + "@react-native/community-cli-plugin/metro/yargs/cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "@react-native/community-cli-plugin/metro/yargs/cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], + + "@react-native/community-cli-plugin/metro/yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "@react-native/community-cli-plugin/metro/yargs/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "@react-native/dev-middleware/serve-static/send/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], "@react-native/eslint-config/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils/@typescript-eslint/typescript-estree/@typescript-eslint/types": ["@typescript-eslint/types@7.18.0", "", {}, "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ=="], @@ -5737,6 +5897,26 @@ "@react-native/metro-config/metro-config/cosmiconfig/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], + "@react-native/metro-config/metro-config/metro/@babel/code-frame/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="], + + "@react-native/metro-config/metro-config/metro/@babel/code-frame/picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], + + "@react-native/metro-config/metro-config/metro/@babel/traverse/debug": ["debug@4.3.6", "", { "dependencies": { "ms": "2.1.2" } }, "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg=="], + + "@react-native/metro-config/metro-config/metro/@babel/traverse/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="], + + "@react-native/metro-config/metro-config/metro/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], + + "@react-native/metro-config/metro-config/metro/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="], + + "@react-native/metro-config/metro-config/metro/debug/ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + + "@react-native/metro-config/metro-config/metro/metro-transform-worker/metro-minify-terser": ["metro-minify-terser@0.83.1", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "terser": "^5.15.0" } }, "sha512-kmooOxXLvKVxkh80IVSYO4weBdJDhCpg5NSPkjzzAnPJP43u6+usGXobkTWxxrAlq900bhzqKek4pBsUchlX6A=="], + + "@react-native/metro-config/metro-config/metro/yargs/cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="], + + "@react-native/metro-config/metro-config/metro/yargs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + "ansi-fragments/slice-ansi/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="], "default-gateway/execa/cross-spawn/shebang-command/shebang-regex": ["shebang-regex@1.0.0", "", {}, "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ=="], @@ -5783,25 +5963,45 @@ "logkitty/yargs/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="], - "metro-config/metro/@babel/core/@babel/helper-compilation-targets/@babel/compat-data": ["@babel/compat-data@7.25.4", "", {}, "sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ=="], + "metro-babel-transformer/@babel/core/@babel/helper-compilation-targets/browserslist/caniuse-lite": ["caniuse-lite@1.0.30001653", "", {}, "sha512-XGWQVB8wFQ2+9NZwZ10GxTYC5hk0Fa+q8cSkr0tgvMhYhMHP/QC+WTgrePMDBWiWc/pV+1ik82Al20XOK25Gcw=="], + + "metro-babel-transformer/@babel/core/@babel/helper-compilation-targets/browserslist/electron-to-chromium": ["electron-to-chromium@1.5.13", "", {}, "sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q=="], + + "metro-babel-transformer/@babel/core/@babel/helper-compilation-targets/browserslist/node-releases": ["node-releases@2.0.18", "", {}, "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g=="], + + "metro-babel-transformer/@babel/core/@babel/helper-compilation-targets/browserslist/update-browserslist-db": ["update-browserslist-db@1.1.0", "", { "dependencies": { "escalade": "^3.1.2", "picocolors": "^1.0.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ=="], + + "metro-babel-transformer/@babel/core/@babel/helper-compilation-targets/lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], + + "metro-transform-plugins/@babel/core/@babel/helper-compilation-targets/browserslist/caniuse-lite": ["caniuse-lite@1.0.30001653", "", {}, "sha512-XGWQVB8wFQ2+9NZwZ10GxTYC5hk0Fa+q8cSkr0tgvMhYhMHP/QC+WTgrePMDBWiWc/pV+1ik82Al20XOK25Gcw=="], + + "metro-transform-plugins/@babel/core/@babel/helper-compilation-targets/browserslist/electron-to-chromium": ["electron-to-chromium@1.5.13", "", {}, "sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q=="], - "metro-config/metro/@babel/core/@babel/helper-compilation-targets/@babel/helper-validator-option": ["@babel/helper-validator-option@7.24.8", "", {}, "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q=="], + "metro-transform-plugins/@babel/core/@babel/helper-compilation-targets/browserslist/node-releases": ["node-releases@2.0.18", "", {}, "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g=="], - "metro-config/metro/@babel/core/@babel/helper-compilation-targets/browserslist": ["browserslist@4.23.3", "", { "dependencies": { "caniuse-lite": "^1.0.30001646", "electron-to-chromium": "^1.5.4", "node-releases": "^2.0.18", "update-browserslist-db": "^1.1.0" }, "bin": { "browserslist": "cli.js" } }, "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA=="], + "metro-transform-plugins/@babel/core/@babel/helper-compilation-targets/browserslist/update-browserslist-db": ["update-browserslist-db@1.1.0", "", { "dependencies": { "escalade": "^3.1.2", "picocolors": "^1.0.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ=="], - "metro-config/metro/@babel/core/@babel/helper-compilation-targets/lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], + "metro-transform-plugins/@babel/core/@babel/helper-compilation-targets/lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], - "metro-config/metro/@babel/core/@babel/helper-module-transforms/@babel/helper-module-imports": ["@babel/helper-module-imports@7.24.7", "", { "dependencies": { "@babel/traverse": "^7.24.7", "@babel/types": "^7.24.7" } }, "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA=="], + "metro-transform-worker/@babel/core/@babel/helper-compilation-targets/browserslist/caniuse-lite": ["caniuse-lite@1.0.30001653", "", {}, "sha512-XGWQVB8wFQ2+9NZwZ10GxTYC5hk0Fa+q8cSkr0tgvMhYhMHP/QC+WTgrePMDBWiWc/pV+1ik82Al20XOK25Gcw=="], - "metro-config/metro/@babel/core/@babel/helper-module-transforms/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.24.7", "", {}, "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w=="], + "metro-transform-worker/@babel/core/@babel/helper-compilation-targets/browserslist/electron-to-chromium": ["electron-to-chromium@1.5.13", "", {}, "sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q=="], - "metro-config/metro/yargs/cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], + "metro-transform-worker/@babel/core/@babel/helper-compilation-targets/browserslist/node-releases": ["node-releases@2.0.18", "", {}, "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g=="], - "metro-config/metro/yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + "metro-transform-worker/@babel/core/@babel/helper-compilation-targets/browserslist/update-browserslist-db": ["update-browserslist-db@1.1.0", "", { "dependencies": { "escalade": "^3.1.2", "picocolors": "^1.0.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ=="], - "metro/metro-config/cosmiconfig/import-fresh/resolve-from": ["resolve-from@3.0.0", "", {}, "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw=="], + "metro-transform-worker/@babel/core/@babel/helper-compilation-targets/lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], - "metro/metro-config/cosmiconfig/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], + "metro/@babel/core/@babel/helper-compilation-targets/browserslist/caniuse-lite": ["caniuse-lite@1.0.30001653", "", {}, "sha512-XGWQVB8wFQ2+9NZwZ10GxTYC5hk0Fa+q8cSkr0tgvMhYhMHP/QC+WTgrePMDBWiWc/pV+1ik82Al20XOK25Gcw=="], + + "metro/@babel/core/@babel/helper-compilation-targets/browserslist/electron-to-chromium": ["electron-to-chromium@1.5.13", "", {}, "sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q=="], + + "metro/@babel/core/@babel/helper-compilation-targets/browserslist/node-releases": ["node-releases@2.0.18", "", {}, "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g=="], + + "metro/@babel/core/@babel/helper-compilation-targets/browserslist/update-browserslist-db": ["update-browserslist-db@1.1.0", "", { "dependencies": { "escalade": "^3.1.2", "picocolors": "^1.0.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ=="], + + "metro/@babel/core/@babel/helper-compilation-targets/lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], "pkg-dir/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], @@ -5879,19 +6079,17 @@ "@react-native/eslint-config/@typescript-eslint/parser/@typescript-eslint/typescript-estree/globby/fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], - "eslint-plugin-jest/@typescript-eslint/utils/@typescript-eslint/typescript-estree/globby/fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + "@react-native/metro-config/metro-config/metro/yargs/cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - "logkitty/yargs/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], - - "metro-config/metro/@babel/core/@babel/helper-compilation-targets/browserslist/caniuse-lite": ["caniuse-lite@1.0.30001653", "", {}, "sha512-XGWQVB8wFQ2+9NZwZ10GxTYC5hk0Fa+q8cSkr0tgvMhYhMHP/QC+WTgrePMDBWiWc/pV+1ik82Al20XOK25Gcw=="], + "@react-native/metro-config/metro-config/metro/yargs/cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], - "metro-config/metro/@babel/core/@babel/helper-compilation-targets/browserslist/electron-to-chromium": ["electron-to-chromium@1.5.13", "", {}, "sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q=="], + "@react-native/metro-config/metro-config/metro/yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], - "metro-config/metro/@babel/core/@babel/helper-compilation-targets/browserslist/node-releases": ["node-releases@2.0.18", "", {}, "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g=="], + "@react-native/metro-config/metro-config/metro/yargs/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - "metro-config/metro/@babel/core/@babel/helper-compilation-targets/browserslist/update-browserslist-db": ["update-browserslist-db@1.1.0", "", { "dependencies": { "escalade": "^3.1.2", "picocolors": "^1.0.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ=="], + "eslint-plugin-jest/@typescript-eslint/utils/@typescript-eslint/typescript-estree/globby/fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], - "metro-config/metro/@babel/core/@babel/helper-compilation-targets/lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], + "logkitty/yargs/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], "typedarray.prototype.slice/es-abstract/typed-array-length/reflect.getprototypeof/which-builtin-type/is-date-object": ["is-date-object@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "has-tostringtag": "^1.0.2" } }, "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg=="], diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 62288686..0a9c70a4 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -2057,7 +2057,7 @@ SPEC CHECKSUMS: hermes-engine: 4f8246b1f6d79f625e0d99472d1f3a71da4d28ca NitroModules: e74e119e5c9f75902ef828936f75e4e078f0c4fc OpenSSL-Universal: 6082b0bf950e5636fe0d78def171184e2b3899c2 - QuickCrypto: 55910fe2f97dc24a4e72cc1f1038a4a5b3fb8ebe + QuickCrypto: 4bd633b3a4532e137a53087da836e5c09d26ef62 RCTDeprecation: 24056820c873bf5115c0441651440bfde2b82d51 RCTRequired: d0b6e766be3c17896d92059c917d682433ff8a34 RCTTypeSafety: 1954dcf545fe67e969e11e1b4fe6cf864e1ac632 diff --git a/packages/react-native-quick-crypto/QuickCrypto.podspec b/packages/react-native-quick-crypto/QuickCrypto.podspec index 83e87216..da867c42 100644 --- a/packages/react-native-quick-crypto/QuickCrypto.podspec +++ b/packages/react-native-quick-crypto/QuickCrypto.podspec @@ -93,7 +93,7 @@ Pod::Spec.new do |s| # implementation (C++) "cpp/**/*.{hpp,cpp}", # dependencies (C++) - "deps/**/*.{hpp,cpp}", + "deps/**/*.{h,cc,c}", # dependencies (C) "deps/**/*.{h,c}", ] diff --git a/packages/react-native-quick-crypto/android/CMakeLists.txt b/packages/react-native-quick-crypto/android/CMakeLists.txt index f8f0464a..fe01c172 100644 --- a/packages/react-native-quick-crypto/android/CMakeLists.txt +++ b/packages/react-native-quick-crypto/android/CMakeLists.txt @@ -25,7 +25,7 @@ add_library( ../cpp/random/HybridRandom.cpp ../cpp/rsa/HybridRsaKeyPair.cpp ../deps/fastpbkdf2/fastpbkdf2.c - ../deps/ncrypto/src/ncrypto.cpp + ../deps/ncrypto/ncrypto.cc ) # add Nitrogen specs @@ -45,7 +45,7 @@ include_directories( "../cpp/rsa" "../cpp/utils" "../deps/fastpbkdf2" - "../deps/ncrypto/include" + "../deps/ncrypto" ) # Third party libraries (Prefabs) diff --git a/packages/react-native-quick-crypto/deps/ncrypto/.bazelignore b/packages/react-native-quick-crypto/deps/ncrypto/.bazelignore deleted file mode 100644 index f9420d37..00000000 --- a/packages/react-native-quick-crypto/deps/ncrypto/.bazelignore +++ /dev/null @@ -1,4 +0,0 @@ -build -cmake-build-debug-coverage -cmake-build-debug -cmake-build-release diff --git a/packages/react-native-quick-crypto/deps/ncrypto/.bazelrc b/packages/react-native-quick-crypto/deps/ncrypto/.bazelrc deleted file mode 100644 index 9775957b..00000000 --- a/packages/react-native-quick-crypto/deps/ncrypto/.bazelrc +++ /dev/null @@ -1,2 +0,0 @@ -common --enable_workspace -build --cxxopt="-std=c++20" diff --git a/packages/react-native-quick-crypto/deps/ncrypto/.bazelversion b/packages/react-native-quick-crypto/deps/ncrypto/.bazelversion deleted file mode 100644 index ae9a76b9..00000000 --- a/packages/react-native-quick-crypto/deps/ncrypto/.bazelversion +++ /dev/null @@ -1 +0,0 @@ -8.0.0 diff --git a/packages/react-native-quick-crypto/deps/ncrypto/.clang-format b/packages/react-native-quick-crypto/deps/ncrypto/.clang-format deleted file mode 100644 index 59d0684d..00000000 --- a/packages/react-native-quick-crypto/deps/ncrypto/.clang-format +++ /dev/null @@ -1,2 +0,0 @@ -BasedOnStyle: Google -SortIncludes: Never diff --git a/packages/react-native-quick-crypto/deps/ncrypto/.gitignore b/packages/react-native-quick-crypto/deps/ncrypto/.gitignore deleted file mode 100644 index 03c7786c..00000000 --- a/packages/react-native-quick-crypto/deps/ncrypto/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -cmake-build-debug -build -.idea -bazel-* diff --git a/packages/react-native-quick-crypto/deps/ncrypto/.python-version b/packages/react-native-quick-crypto/deps/ncrypto/.python-version deleted file mode 100644 index e4fba218..00000000 --- a/packages/react-native-quick-crypto/deps/ncrypto/.python-version +++ /dev/null @@ -1 +0,0 @@ -3.12 diff --git a/packages/react-native-quick-crypto/deps/ncrypto/BUILD.bazel b/packages/react-native-quick-crypto/deps/ncrypto/BUILD.bazel deleted file mode 100644 index dfd6c1a0..00000000 --- a/packages/react-native-quick-crypto/deps/ncrypto/BUILD.bazel +++ /dev/null @@ -1,10 +0,0 @@ -cc_library( - name = "ncrypto", - srcs = glob(["src/*.cpp"]), - hdrs = glob(["include/*.h"]), - includes = ["include"], - visibility = ["//visibility:public"], - deps = [ - "@ssl" - ] -) diff --git a/packages/react-native-quick-crypto/deps/ncrypto/CMakeLists.txt b/packages/react-native-quick-crypto/deps/ncrypto/CMakeLists.txt deleted file mode 100644 index 259f1361..00000000 --- a/packages/react-native-quick-crypto/deps/ncrypto/CMakeLists.txt +++ /dev/null @@ -1,55 +0,0 @@ -cmake_minimum_required(VERSION 3.28) -project(ncrypto) - -include(CTest) -include(GNUInstallDirs) -include(FetchContent) -include(cmake/ncrypto-flags.cmake) - -if (NOT CMAKE_BUILD_TYPE) - message(STATUS "No build type selected, default to Release") - set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE) -endif() - -include(cmake/CPM.cmake) - -CPMAddPackage( - NAME boringssl - VERSION 0.20250114.0 - GITHUB_REPOSITORY google/boringssl - GIT_TAG 0.20250114.0 - OPTIONS "BUILD_SHARED_LIBS OFF" "BUILD_TESTING OFF" -) -add_subdirectory(src) -add_library(ncrypto::ncrypto ALIAS ncrypto) - -include_directories(${boringssl_SOURCE_DIR}/include) - -if (NCRYPTO_TESTING) - CPMAddPackage( - NAME GTest - GITHUB_REPOSITORY google/googletest - VERSION 1.15.2 - OPTIONS "BUILD_GMOCK OFF" "INSTALL_GTEST OFF" - ) - # For Windows: Prevent overriding the parent project's compiler/linker settings - set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) - enable_testing() - add_subdirectory(tests) -endif() - -install( - FILES include/ncrypto.h - DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" - COMPONENT ncrypto_development -) - -install( - TARGETS ncrypto - EXPORT ncrypto_targets - RUNTIME COMPONENT ncrypto_runtime - LIBRARY COMPONENT ncrypto_runtime - NAMELINK_COMPONENT ncrypto_development - ARCHIVE COMPONENT ncrypto_development - INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" -) diff --git a/packages/react-native-quick-crypto/deps/ncrypto/LICENSE b/packages/react-native-quick-crypto/deps/ncrypto/LICENSE deleted file mode 100644 index 6da37b65..00000000 --- a/packages/react-native-quick-crypto/deps/ncrypto/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2025 Node.js - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/packages/react-native-quick-crypto/deps/ncrypto/MODULE.bazel b/packages/react-native-quick-crypto/deps/ncrypto/MODULE.bazel deleted file mode 100644 index 9f5819bc..00000000 --- a/packages/react-native-quick-crypto/deps/ncrypto/MODULE.bazel +++ /dev/null @@ -1 +0,0 @@ -bazel_dep(name = "googletest", version = "1.15.2") diff --git a/packages/react-native-quick-crypto/deps/ncrypto/MODULE.bazel.lock b/packages/react-native-quick-crypto/deps/ncrypto/MODULE.bazel.lock deleted file mode 100644 index 04aeff80..00000000 --- a/packages/react-native-quick-crypto/deps/ncrypto/MODULE.bazel.lock +++ /dev/null @@ -1,280 +0,0 @@ -{ - "lockFileVersion": 16, - "registryFileHashes": { - "https://bcr.bazel.build/bazel_registry.json": "8a28e4aff06ee60aed2a8c281907fb8bcbf3b753c91fb5a5c57da3215d5b3497", - "https://bcr.bazel.build/modules/abseil-cpp/20210324.2/MODULE.bazel": "7cd0312e064fde87c8d1cd79ba06c876bd23630c83466e9500321be55c96ace2", - "https://bcr.bazel.build/modules/abseil-cpp/20211102.0/MODULE.bazel": "70390338f7a5106231d20620712f7cccb659cd0e9d073d1991c038eb9fc57589", - "https://bcr.bazel.build/modules/abseil-cpp/20230125.1/MODULE.bazel": "89047429cb0207707b2dface14ba7f8df85273d484c2572755be4bab7ce9c3a0", - "https://bcr.bazel.build/modules/abseil-cpp/20230802.0.bcr.1/MODULE.bazel": "1c8cec495288dccd14fdae6e3f95f772c1c91857047a098fad772034264cc8cb", - "https://bcr.bazel.build/modules/abseil-cpp/20230802.0/MODULE.bazel": "d253ae36a8bd9ee3c5955384096ccb6baf16a1b1e93e858370da0a3b94f77c16", - "https://bcr.bazel.build/modules/abseil-cpp/20230802.1/MODULE.bazel": "fa92e2eb41a04df73cdabeec37107316f7e5272650f81d6cc096418fe647b915", - "https://bcr.bazel.build/modules/abseil-cpp/20240116.1/MODULE.bazel": "37bcdb4440fbb61df6a1c296ae01b327f19e9bb521f9b8e26ec854b6f97309ed", - "https://bcr.bazel.build/modules/abseil-cpp/20240116.2/MODULE.bazel": "73939767a4686cd9a520d16af5ab440071ed75cec1a876bf2fcfaf1f71987a16", - "https://bcr.bazel.build/modules/abseil-cpp/20240116.2/source.json": "750d5e29326fb59cbe61116a7b803c8a1d0a7090a9c8ed89888d188e3c473fc7", - "https://bcr.bazel.build/modules/apple_support/1.15.1/MODULE.bazel": "a0556fefca0b1bb2de8567b8827518f94db6a6e7e7d632b4c48dc5f865bc7c85", - "https://bcr.bazel.build/modules/apple_support/1.15.1/source.json": "517f2b77430084c541bc9be2db63fdcbb7102938c5f64c17ee60ffda2e5cf07b", - "https://bcr.bazel.build/modules/bazel_features/1.1.1/MODULE.bazel": "27b8c79ef57efe08efccbd9dd6ef70d61b4798320b8d3c134fd571f78963dbcd", - "https://bcr.bazel.build/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8", - "https://bcr.bazel.build/modules/bazel_features/1.15.0/MODULE.bazel": "d38ff6e517149dc509406aca0db3ad1efdd890a85e049585b7234d04238e2a4d", - "https://bcr.bazel.build/modules/bazel_features/1.17.0/MODULE.bazel": "039de32d21b816b47bd42c778e0454217e9c9caac4a3cf8e15c7231ee3ddee4d", - "https://bcr.bazel.build/modules/bazel_features/1.18.0/MODULE.bazel": "1be0ae2557ab3a72a57aeb31b29be347bcdc5d2b1eb1e70f39e3851a7e97041a", - "https://bcr.bazel.build/modules/bazel_features/1.19.0/MODULE.bazel": "59adcdf28230d220f0067b1f435b8537dd033bfff8db21335ef9217919c7fb58", - "https://bcr.bazel.build/modules/bazel_features/1.21.0/MODULE.bazel": "675642261665d8eea09989aa3b8afb5c37627f1be178382c320d1b46afba5e3b", - "https://bcr.bazel.build/modules/bazel_features/1.21.0/source.json": "3e8379efaaef53ce35b7b8ba419df829315a880cb0a030e5bb45c96d6d5ecb5f", - "https://bcr.bazel.build/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7", - "https://bcr.bazel.build/modules/bazel_features/1.9.1/MODULE.bazel": "8f679097876a9b609ad1f60249c49d68bfab783dd9be012faf9d82547b14815a", - "https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8", - "https://bcr.bazel.build/modules/bazel_skylib/1.1.1/MODULE.bazel": "1add3e7d93ff2e6998f9e118022c84d163917d912f5afafb3058e3d2f1545b5e", - "https://bcr.bazel.build/modules/bazel_skylib/1.2.0/MODULE.bazel": "44fe84260e454ed94ad326352a698422dbe372b21a1ac9f3eab76eb531223686", - "https://bcr.bazel.build/modules/bazel_skylib/1.2.1/MODULE.bazel": "f35baf9da0efe45fa3da1696ae906eea3d615ad41e2e3def4aeb4e8bc0ef9a7a", - "https://bcr.bazel.build/modules/bazel_skylib/1.3.0/MODULE.bazel": "20228b92868bf5cfc41bda7afc8a8ba2a543201851de39d990ec957b513579c5", - "https://bcr.bazel.build/modules/bazel_skylib/1.4.1/MODULE.bazel": "a0dcb779424be33100dcae821e9e27e4f2901d9dfd5333efe5ac6a8d7ab75e1d", - "https://bcr.bazel.build/modules/bazel_skylib/1.4.2/MODULE.bazel": "3bd40978e7a1fac911d5989e6b09d8f64921865a45822d8b09e815eaa726a651", - "https://bcr.bazel.build/modules/bazel_skylib/1.5.0/MODULE.bazel": "32880f5e2945ce6a03d1fbd588e9198c0a959bb42297b2cfaf1685b7bc32e138", - "https://bcr.bazel.build/modules/bazel_skylib/1.6.1/MODULE.bazel": "8fdee2dbaace6c252131c00e1de4b165dc65af02ea278476187765e1a617b917", - "https://bcr.bazel.build/modules/bazel_skylib/1.7.0/MODULE.bazel": "0db596f4563de7938de764cc8deeabec291f55e8ec15299718b93c4423e9796d", - "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/MODULE.bazel": "3120d80c5861aa616222ec015332e5f8d3171e062e3e804a2a0253e1be26e59b", - "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/source.json": "f121b43eeefc7c29efbd51b83d08631e2347297c95aac9764a701f2a6a2bb953", - "https://bcr.bazel.build/modules/buildozer/7.1.2/MODULE.bazel": "2e8dd40ede9c454042645fd8d8d0cd1527966aa5c919de86661e62953cd73d84", - "https://bcr.bazel.build/modules/buildozer/7.1.2/source.json": "c9028a501d2db85793a6996205c8de120944f50a0d570438fcae0457a5f9d1f8", - "https://bcr.bazel.build/modules/google_benchmark/1.8.2/MODULE.bazel": "a70cf1bba851000ba93b58ae2f6d76490a9feb74192e57ab8e8ff13c34ec50cb", - "https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4", - "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6", - "https://bcr.bazel.build/modules/googletest/1.14.0/MODULE.bazel": "cfbcbf3e6eac06ef9d85900f64424708cc08687d1b527f0ef65aa7517af8118f", - "https://bcr.bazel.build/modules/googletest/1.15.2/MODULE.bazel": "6de1edc1d26cafb0ea1a6ab3f4d4192d91a312fd2d360b63adaa213cd00b2108", - "https://bcr.bazel.build/modules/googletest/1.15.2/source.json": "dbdda654dcb3a0d7a8bc5d0ac5fc7e150b58c2a986025ae5bc634bb2cb61f470", - "https://bcr.bazel.build/modules/jsoncpp/1.9.5/MODULE.bazel": "31271aedc59e815656f5736f282bb7509a97c7ecb43e927ac1a37966e0578075", - "https://bcr.bazel.build/modules/jsoncpp/1.9.5/source.json": "4108ee5085dd2885a341c7fab149429db457b3169b86eb081fa245eadf69169d", - "https://bcr.bazel.build/modules/libpfm/4.11.0/MODULE.bazel": "45061ff025b301940f1e30d2c16bea596c25b176c8b6b3087e92615adbd52902", - "https://bcr.bazel.build/modules/platforms/0.0.10/MODULE.bazel": "8cb8efaf200bdeb2150d93e162c40f388529a25852b332cec879373771e48ed5", - "https://bcr.bazel.build/modules/platforms/0.0.10/source.json": "f22828ff4cf021a6b577f1bf6341cb9dcd7965092a439f64fc1bb3b7a5ae4bd5", - "https://bcr.bazel.build/modules/platforms/0.0.4/MODULE.bazel": "9b328e31ee156f53f3c416a64f8491f7eb731742655a47c9eec4703a71644aee", - "https://bcr.bazel.build/modules/platforms/0.0.5/MODULE.bazel": "5733b54ea419d5eaf7997054bb55f6a1d0b5ff8aedf0176fef9eea44f3acda37", - "https://bcr.bazel.build/modules/platforms/0.0.6/MODULE.bazel": "ad6eeef431dc52aefd2d77ed20a4b353f8ebf0f4ecdd26a807d2da5aa8cd0615", - "https://bcr.bazel.build/modules/platforms/0.0.7/MODULE.bazel": "72fd4a0ede9ee5c021f6a8dd92b503e089f46c227ba2813ff183b71616034814", - "https://bcr.bazel.build/modules/platforms/0.0.8/MODULE.bazel": "9f142c03e348f6d263719f5074b21ef3adf0b139ee4c5133e2aa35664da9eb2d", - "https://bcr.bazel.build/modules/platforms/0.0.9/MODULE.bazel": "4a87a60c927b56ddd67db50c89acaa62f4ce2a1d2149ccb63ffd871d5ce29ebc", - "https://bcr.bazel.build/modules/protobuf/21.7/MODULE.bazel": "a5a29bb89544f9b97edce05642fac225a808b5b7be74038ea3640fae2f8e66a7", - "https://bcr.bazel.build/modules/protobuf/27.0/MODULE.bazel": "7873b60be88844a0a1d8f80b9d5d20cfbd8495a689b8763e76c6372998d3f64c", - "https://bcr.bazel.build/modules/protobuf/27.1/MODULE.bazel": "703a7b614728bb06647f965264967a8ef1c39e09e8f167b3ca0bb1fd80449c0d", - "https://bcr.bazel.build/modules/protobuf/29.0-rc2/MODULE.bazel": "6241d35983510143049943fc0d57937937122baf1b287862f9dc8590fc4c37df", - "https://bcr.bazel.build/modules/protobuf/29.0/MODULE.bazel": "319dc8bf4c679ff87e71b1ccfb5a6e90a6dbc4693501d471f48662ac46d04e4e", - "https://bcr.bazel.build/modules/protobuf/29.0/source.json": "b857f93c796750eef95f0d61ee378f3420d00ee1dd38627b27193aa482f4f981", - "https://bcr.bazel.build/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0", - "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e", - "https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/MODULE.bazel": "e6f4c20442eaa7c90d7190d8dc539d0ab422f95c65a57cc59562170c58ae3d34", - "https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/source.json": "6900fdc8a9e95866b8c0d4ad4aba4d4236317b5c1cd04c502df3f0d33afed680", - "https://bcr.bazel.build/modules/re2/2023-09-01/MODULE.bazel": "cb3d511531b16cfc78a225a9e2136007a48cf8a677e4264baeab57fe78a80206", - "https://bcr.bazel.build/modules/re2/2024-07-02/MODULE.bazel": "0eadc4395959969297cbcf31a249ff457f2f1d456228c67719480205aa306daa", - "https://bcr.bazel.build/modules/re2/2024-07-02/source.json": "547d0111a9d4f362db32196fef805abbf3676e8d6afbe44d395d87816c1130ca", - "https://bcr.bazel.build/modules/rules_android/0.1.1/MODULE.bazel": "48809ab0091b07ad0182defb787c4c5328bd3a278938415c00a7b69b50c4d3a8", - "https://bcr.bazel.build/modules/rules_android/0.1.1/source.json": "e6986b41626ee10bdc864937ffb6d6bf275bb5b9c65120e6137d56e6331f089e", - "https://bcr.bazel.build/modules/rules_cc/0.0.1/MODULE.bazel": "cb2aa0747f84c6c3a78dad4e2049c154f08ab9d166b1273835a8174940365647", - "https://bcr.bazel.build/modules/rules_cc/0.0.10/MODULE.bazel": "ec1705118f7eaedd6e118508d3d26deba2a4e76476ada7e0e3965211be012002", - "https://bcr.bazel.build/modules/rules_cc/0.0.13/MODULE.bazel": "0e8529ed7b323dad0775ff924d2ae5af7640b23553dfcd4d34344c7e7a867191", - "https://bcr.bazel.build/modules/rules_cc/0.0.14/MODULE.bazel": "5e343a3aac88b8d7af3b1b6d2093b55c347b8eefc2e7d1442f7a02dc8fea48ac", - "https://bcr.bazel.build/modules/rules_cc/0.0.15/MODULE.bazel": "6704c35f7b4a72502ee81f61bf88706b54f06b3cbe5558ac17e2e14666cd5dcc", - "https://bcr.bazel.build/modules/rules_cc/0.0.16/MODULE.bazel": "7661303b8fc1b4d7f532e54e9d6565771fea666fbdf839e0a86affcd02defe87", - "https://bcr.bazel.build/modules/rules_cc/0.0.16/source.json": "227e83737046aa4f50015da48e98e0d8ab42fd0ec74d8d653b6cc9f9a357f200", - "https://bcr.bazel.build/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c", - "https://bcr.bazel.build/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f", - "https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e", - "https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5", - "https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6", - "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8", - "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/source.json": "c8b1e2c717646f1702290959a3302a178fb639d987ab61d548105019f11e527e", - "https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74", - "https://bcr.bazel.build/modules/rules_java/5.3.5/MODULE.bazel": "a4ec4f2db570171e3e5eb753276ee4b389bae16b96207e9d3230895c99644b86", - "https://bcr.bazel.build/modules/rules_java/6.0.0/MODULE.bazel": "8a43b7df601a7ec1af61d79345c17b31ea1fedc6711fd4abfd013ea612978e39", - "https://bcr.bazel.build/modules/rules_java/6.4.0/MODULE.bazel": "e986a9fe25aeaa84ac17ca093ef13a4637f6107375f64667a15999f77db6c8f6", - "https://bcr.bazel.build/modules/rules_java/6.5.2/MODULE.bazel": "1d440d262d0e08453fa0c4d8f699ba81609ed0e9a9a0f02cd10b3e7942e61e31", - "https://bcr.bazel.build/modules/rules_java/7.10.0/MODULE.bazel": "530c3beb3067e870561739f1144329a21c851ff771cd752a49e06e3dc9c2e71a", - "https://bcr.bazel.build/modules/rules_java/7.12.2/MODULE.bazel": "579c505165ee757a4280ef83cda0150eea193eed3bef50b1004ba88b99da6de6", - "https://bcr.bazel.build/modules/rules_java/7.2.0/MODULE.bazel": "06c0334c9be61e6cef2c8c84a7800cef502063269a5af25ceb100b192453d4ab", - "https://bcr.bazel.build/modules/rules_java/7.3.2/MODULE.bazel": "50dece891cfdf1741ea230d001aa9c14398062f2b7c066470accace78e412bc2", - "https://bcr.bazel.build/modules/rules_java/7.6.1/MODULE.bazel": "2f14b7e8a1aa2f67ae92bc69d1ec0fa8d9f827c4e17ff5e5f02e91caa3b2d0fe", - "https://bcr.bazel.build/modules/rules_java/8.6.1/MODULE.bazel": "f4808e2ab5b0197f094cabce9f4b006a27766beb6a9975931da07099560ca9c2", - "https://bcr.bazel.build/modules/rules_java/8.6.1/source.json": "f18d9ad3c4c54945bf422ad584fa6c5ca5b3116ff55a5b1bc77e5c1210be5960", - "https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7", - "https://bcr.bazel.build/modules/rules_jvm_external/5.1/MODULE.bazel": "33f6f999e03183f7d088c9be518a63467dfd0be94a11d0055fe2d210f89aa909", - "https://bcr.bazel.build/modules/rules_jvm_external/5.2/MODULE.bazel": "d9351ba35217ad0de03816ef3ed63f89d411349353077348a45348b096615036", - "https://bcr.bazel.build/modules/rules_jvm_external/5.3/MODULE.bazel": "bf93870767689637164657731849fb887ad086739bd5d360d90007a581d5527d", - "https://bcr.bazel.build/modules/rules_jvm_external/6.1/MODULE.bazel": "75b5fec090dbd46cf9b7d8ea08cf84a0472d92ba3585b476f44c326eda8059c4", - "https://bcr.bazel.build/modules/rules_jvm_external/6.3/MODULE.bazel": "c998e060b85f71e00de5ec552019347c8bca255062c990ac02d051bb80a38df0", - "https://bcr.bazel.build/modules/rules_jvm_external/6.3/source.json": "6f5f5a5a4419ae4e37c35a5bb0a6ae657ed40b7abc5a5189111b47fcebe43197", - "https://bcr.bazel.build/modules/rules_kotlin/1.9.0/MODULE.bazel": "ef85697305025e5a61f395d4eaede272a5393cee479ace6686dba707de804d59", - "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/MODULE.bazel": "d269a01a18ee74d0335450b10f62c9ed81f2321d7958a2934e44272fe82dcef3", - "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/source.json": "2faa4794364282db7c06600b7e5e34867a564ae91bda7cae7c29c64e9466b7d5", - "https://bcr.bazel.build/modules/rules_license/0.0.3/MODULE.bazel": "627e9ab0247f7d1e05736b59dbb1b6871373de5ad31c3011880b4133cafd4bd0", - "https://bcr.bazel.build/modules/rules_license/0.0.7/MODULE.bazel": "088fbeb0b6a419005b89cf93fe62d9517c0a2b8bb56af3244af65ecfe37e7d5d", - "https://bcr.bazel.build/modules/rules_license/1.0.0/MODULE.bazel": "a7fda60eefdf3d8c827262ba499957e4df06f659330bbe6cdbdb975b768bb65c", - "https://bcr.bazel.build/modules/rules_license/1.0.0/source.json": "a52c89e54cc311196e478f8382df91c15f7a2bfdf4c6cd0e2675cc2ff0b56efb", - "https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc", - "https://bcr.bazel.build/modules/rules_pkg/1.0.1/MODULE.bazel": "5b1df97dbc29623bccdf2b0dcd0f5cb08e2f2c9050aab1092fd39a41e82686ff", - "https://bcr.bazel.build/modules/rules_pkg/1.0.1/source.json": "bd82e5d7b9ce2d31e380dd9f50c111d678c3bdaca190cb76b0e1c71b05e1ba8a", - "https://bcr.bazel.build/modules/rules_proto/4.0.0/MODULE.bazel": "a7a7b6ce9bee418c1a760b3d84f83a299ad6952f9903c67f19e4edd964894e06", - "https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/MODULE.bazel": "e8dff86b0971688790ae75528fe1813f71809b5afd57facb44dad9e8eca631b7", - "https://bcr.bazel.build/modules/rules_proto/6.0.0-rc1/MODULE.bazel": "1e5b502e2e1a9e825eef74476a5a1ee524a92297085015a052510b09a1a09483", - "https://bcr.bazel.build/modules/rules_proto/6.0.2/MODULE.bazel": "ce916b775a62b90b61888052a416ccdda405212b6aaeb39522f7dc53431a5e73", - "https://bcr.bazel.build/modules/rules_proto/7.0.2/MODULE.bazel": "bf81793bd6d2ad89a37a40693e56c61b0ee30f7a7fdbaf3eabbf5f39de47dea2", - "https://bcr.bazel.build/modules/rules_proto/7.0.2/source.json": "1e5e7260ae32ef4f2b52fd1d0de8d03b606a44c91b694d2f1afb1d3b28a48ce1", - "https://bcr.bazel.build/modules/rules_python/0.10.2/MODULE.bazel": "cc82bc96f2997baa545ab3ce73f196d040ffb8756fd2d66125a530031cd90e5f", - "https://bcr.bazel.build/modules/rules_python/0.23.1/MODULE.bazel": "49ffccf0511cb8414de28321f5fcf2a31312b47c40cc21577144b7447f2bf300", - "https://bcr.bazel.build/modules/rules_python/0.25.0/MODULE.bazel": "72f1506841c920a1afec76975b35312410eea3aa7b63267436bfb1dd91d2d382", - "https://bcr.bazel.build/modules/rules_python/0.28.0/MODULE.bazel": "cba2573d870babc976664a912539b320cbaa7114cd3e8f053c720171cde331ed", - "https://bcr.bazel.build/modules/rules_python/0.31.0/MODULE.bazel": "93a43dc47ee570e6ec9f5779b2e64c1476a6ce921c48cc9a1678a91dd5f8fd58", - "https://bcr.bazel.build/modules/rules_python/0.33.2/MODULE.bazel": "3e036c4ad8d804a4dad897d333d8dce200d943df4827cb849840055be8d2e937", - "https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c", - "https://bcr.bazel.build/modules/rules_python/0.40.0/MODULE.bazel": "9d1a3cd88ed7d8e39583d9ffe56ae8a244f67783ae89b60caafc9f5cf318ada7", - "https://bcr.bazel.build/modules/rules_python/0.40.0/source.json": "939d4bd2e3110f27bfb360292986bb79fd8dcefb874358ccd6cdaa7bda029320", - "https://bcr.bazel.build/modules/rules_shell/0.2.0/MODULE.bazel": "fda8a652ab3c7d8fee214de05e7a9916d8b28082234e8d2c0094505c5268ed3c", - "https://bcr.bazel.build/modules/rules_shell/0.2.0/source.json": "7f27af3c28037d9701487c4744b5448d26537cc66cdef0d8df7ae85411f8de95", - "https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8", - "https://bcr.bazel.build/modules/stardoc/0.5.3/MODULE.bazel": "c7f6948dae6999bf0db32c1858ae345f112cacf98f174c7a8bb707e41b974f1c", - "https://bcr.bazel.build/modules/stardoc/0.5.6/MODULE.bazel": "c43dabc564990eeab55e25ed61c07a1aadafe9ece96a4efabb3f8bf9063b71ef", - "https://bcr.bazel.build/modules/stardoc/0.7.0/MODULE.bazel": "05e3d6d30c099b6770e97da986c53bd31844d7f13d41412480ea265ac9e8079c", - "https://bcr.bazel.build/modules/stardoc/0.7.1/MODULE.bazel": "3548faea4ee5dda5580f9af150e79d0f6aea934fc60c1cc50f4efdd9420759e7", - "https://bcr.bazel.build/modules/stardoc/0.7.1/source.json": "b6500ffcd7b48cd72c29bb67bcac781e12701cc0d6d55d266a652583cfcdab01", - "https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43", - "https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0", - "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/MODULE.bazel": "af322bc08976524477c79d1e45e241b6efbeb918c497e8840b8ab116802dda79", - "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/source.json": "2be409ac3c7601245958cd4fcdff4288be79ed23bd690b4b951f500d54ee6e7d", - "https://bcr.bazel.build/modules/zlib/1.3.1/MODULE.bazel": "751c9940dcfe869f5f7274e1295422a34623555916eb98c174c1e945594bf198" - }, - "selectedYankedVersions": {}, - "moduleExtensions": { - "@@apple_support+//crosstool:setup.bzl%apple_cc_configure_extension": { - "general": { - "bzlTransitiveDigest": "pd/h9zu+PbVBnRwZ3tnvvnAydlf0zxd9Ov95CD7vJIM=", - "usagesDigest": "aYRVMk+1OupIp+5hdBlpzT36qgd6ntgSxYTzMLW5K4U=", - "recordedFileInputs": {}, - "recordedDirentsInputs": {}, - "envVariables": {}, - "generatedRepoSpecs": { - "local_config_apple_cc_toolchains": { - "repoRuleId": "@@apple_support+//crosstool:setup.bzl%_apple_cc_autoconf_toolchains", - "attributes": {} - }, - "local_config_apple_cc": { - "repoRuleId": "@@apple_support+//crosstool:setup.bzl%_apple_cc_autoconf", - "attributes": {} - } - }, - "recordedRepoMappingEntries": [ - [ - "apple_support+", - "bazel_tools", - "bazel_tools" - ], - [ - "bazel_tools", - "rules_cc", - "rules_cc+" - ] - ] - } - }, - "@@platforms//host:extension.bzl%host_platform": { - "general": { - "bzlTransitiveDigest": "xelQcPZH8+tmuOHVjL9vDxMnnQNMlwj0SlvgoqBkm4U=", - "usagesDigest": "SeQiIN/f8/Qt9vYQk7qcXp4I4wJeEC0RnQDiaaJ4tb8=", - "recordedFileInputs": {}, - "recordedDirentsInputs": {}, - "envVariables": {}, - "generatedRepoSpecs": { - "host_platform": { - "repoRuleId": "@@platforms//host:extension.bzl%host_platform_repo", - "attributes": {} - } - }, - "recordedRepoMappingEntries": [] - } - }, - "@@rules_java+//java:rules_java_deps.bzl%compatibility_proxy": { - "general": { - "bzlTransitiveDigest": "84xJEZ1jnXXwo8BXMprvBm++rRt4jsTu9liBxz0ivps=", - "usagesDigest": "jTQDdLDxsS43zuRmg1faAjIEPWdLAbDAowI1pInQSoo=", - "recordedFileInputs": {}, - "recordedDirentsInputs": {}, - "envVariables": {}, - "generatedRepoSpecs": { - "compatibility_proxy": { - "repoRuleId": "@@rules_java+//java:rules_java_deps.bzl%_compatibility_proxy_repo_rule", - "attributes": {} - } - }, - "recordedRepoMappingEntries": [ - [ - "rules_java+", - "bazel_tools", - "bazel_tools" - ] - ] - } - }, - "@@rules_kotlin+//src/main/starlark/core/repositories:bzlmod_setup.bzl%rules_kotlin_extensions": { - "general": { - "bzlTransitiveDigest": "sFhcgPbDQehmbD1EOXzX4H1q/CD5df8zwG4kp4jbvr8=", - "usagesDigest": "QI2z8ZUR+mqtbwsf2fLqYdJAkPOHdOV+tF2yVAUgRzw=", - "recordedFileInputs": {}, - "recordedDirentsInputs": {}, - "envVariables": {}, - "generatedRepoSpecs": { - "com_github_jetbrains_kotlin_git": { - "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:compiler.bzl%kotlin_compiler_git_repository", - "attributes": { - "urls": [ - "https://github.com/JetBrains/kotlin/releases/download/v1.9.23/kotlin-compiler-1.9.23.zip" - ], - "sha256": "93137d3aab9afa9b27cb06a824c2324195c6b6f6179d8a8653f440f5bd58be88" - } - }, - "com_github_jetbrains_kotlin": { - "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:compiler.bzl%kotlin_capabilities_repository", - "attributes": { - "git_repository_name": "com_github_jetbrains_kotlin_git", - "compiler_version": "1.9.23" - } - }, - "com_github_google_ksp": { - "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:ksp.bzl%ksp_compiler_plugin_repository", - "attributes": { - "urls": [ - "https://github.com/google/ksp/releases/download/1.9.23-1.0.20/artifacts.zip" - ], - "sha256": "ee0618755913ef7fd6511288a232e8fad24838b9af6ea73972a76e81053c8c2d", - "strip_version": "1.9.23-1.0.20" - } - }, - "com_github_pinterest_ktlint": { - "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_file", - "attributes": { - "sha256": "01b2e0ef893383a50dbeb13970fe7fa3be36ca3e83259e01649945b09d736985", - "urls": [ - "https://github.com/pinterest/ktlint/releases/download/1.3.0/ktlint" - ], - "executable": true - } - }, - "rules_android": { - "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", - "attributes": { - "sha256": "cd06d15dd8bb59926e4d65f9003bfc20f9da4b2519985c27e190cddc8b7a7806", - "strip_prefix": "rules_android-0.1.1", - "urls": [ - "https://github.com/bazelbuild/rules_android/archive/v0.1.1.zip" - ] - } - } - }, - "recordedRepoMappingEntries": [ - [ - "rules_kotlin+", - "bazel_tools", - "bazel_tools" - ] - ] - } - } - } -} diff --git a/packages/react-native-quick-crypto/deps/ncrypto/WORKSPACE b/packages/react-native-quick-crypto/deps/ncrypto/WORKSPACE deleted file mode 100644 index 52ce7cea..00000000 --- a/packages/react-native-quick-crypto/deps/ncrypto/WORKSPACE +++ /dev/null @@ -1,11 +0,0 @@ -workspace(name = "ncrypto") - -load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") - -http_archive( - name = "ssl", - sha256 = "76962c003a298f405d1a5d273a74a94f58b69f65d64b8574a82d4c21c5e407be", - strip_prefix = "google-boringssl-6abe184", - type = "tgz", - urls = ["https://github.com/google/boringssl/tarball/6abe18402eb2a5e9b00158c6459646a948c53060"], -) diff --git a/packages/react-native-quick-crypto/deps/ncrypto/cmake/CPM.cmake b/packages/react-native-quick-crypto/deps/ncrypto/cmake/CPM.cmake deleted file mode 100644 index 55b883d8..00000000 --- a/packages/react-native-quick-crypto/deps/ncrypto/cmake/CPM.cmake +++ /dev/null @@ -1,1225 +0,0 @@ -# CPM.cmake - CMake's missing package manager -# =========================================== -# See https://github.com/cpm-cmake/CPM.cmake for usage and update instructions. -# -# MIT License -# ----------- -#[[ - Copyright (c) 2019-2023 Lars Melchior and contributors - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -]] - -cmake_minimum_required(VERSION 3.14 FATAL_ERROR) - -# Initialize logging prefix -if(NOT CPM_INDENT) - set(CPM_INDENT - "CPM:" - CACHE INTERNAL "" - ) -endif() - -if(NOT COMMAND cpm_message) - function(cpm_message) - message(${ARGV}) - endfunction() -endif() - -set(CURRENT_CPM_VERSION 0.40.0) - -get_filename_component(CPM_CURRENT_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}" REALPATH) -if(CPM_DIRECTORY) - if(NOT CPM_DIRECTORY STREQUAL CPM_CURRENT_DIRECTORY) - if(CPM_VERSION VERSION_LESS CURRENT_CPM_VERSION) - message( - AUTHOR_WARNING - "${CPM_INDENT} \ -A dependency is using a more recent CPM version (${CURRENT_CPM_VERSION}) than the current project (${CPM_VERSION}). \ -It is recommended to upgrade CPM to the most recent version. \ -See https://github.com/cpm-cmake/CPM.cmake for more information." - ) - endif() - if(${CMAKE_VERSION} VERSION_LESS "3.17.0") - include(FetchContent) - endif() - return() - endif() - - get_property( - CPM_INITIALIZED GLOBAL "" - PROPERTY CPM_INITIALIZED - SET - ) - if(CPM_INITIALIZED) - return() - endif() -endif() - -if(CURRENT_CPM_VERSION MATCHES "development-version") - message( - WARNING "${CPM_INDENT} Your project is using an unstable development version of CPM.cmake. \ -Please update to a recent release if possible. \ -See https://github.com/cpm-cmake/CPM.cmake for details." - ) -endif() - -set_property(GLOBAL PROPERTY CPM_INITIALIZED true) - -macro(cpm_set_policies) - # the policy allows us to change options without caching - cmake_policy(SET CMP0077 NEW) - set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) - - # the policy allows us to change set(CACHE) without caching - if(POLICY CMP0126) - cmake_policy(SET CMP0126 NEW) - set(CMAKE_POLICY_DEFAULT_CMP0126 NEW) - endif() - - # The policy uses the download time for timestamp, instead of the timestamp in the archive. This - # allows for proper rebuilds when a projects url changes - if(POLICY CMP0135) - cmake_policy(SET CMP0135 NEW) - set(CMAKE_POLICY_DEFAULT_CMP0135 NEW) - endif() - - # treat relative git repository paths as being relative to the parent project's remote - if(POLICY CMP0150) - cmake_policy(SET CMP0150 NEW) - set(CMAKE_POLICY_DEFAULT_CMP0150 NEW) - endif() -endmacro() -cpm_set_policies() - -option(CPM_USE_LOCAL_PACKAGES "Always try to use `find_package` to get dependencies" - $ENV{CPM_USE_LOCAL_PACKAGES} -) -option(CPM_LOCAL_PACKAGES_ONLY "Only use `find_package` to get dependencies" - $ENV{CPM_LOCAL_PACKAGES_ONLY} -) -option(CPM_DOWNLOAD_ALL "Always download dependencies from source" $ENV{CPM_DOWNLOAD_ALL}) -option(CPM_DONT_UPDATE_MODULE_PATH "Don't update the module path to allow using find_package" - $ENV{CPM_DONT_UPDATE_MODULE_PATH} -) -option(CPM_DONT_CREATE_PACKAGE_LOCK "Don't create a package lock file in the binary path" - $ENV{CPM_DONT_CREATE_PACKAGE_LOCK} -) -option(CPM_INCLUDE_ALL_IN_PACKAGE_LOCK - "Add all packages added through CPM.cmake to the package lock" - $ENV{CPM_INCLUDE_ALL_IN_PACKAGE_LOCK} -) -option(CPM_USE_NAMED_CACHE_DIRECTORIES - "Use additional directory of package name in cache on the most nested level." - $ENV{CPM_USE_NAMED_CACHE_DIRECTORIES} -) - -set(CPM_VERSION - ${CURRENT_CPM_VERSION} - CACHE INTERNAL "" -) -set(CPM_DIRECTORY - ${CPM_CURRENT_DIRECTORY} - CACHE INTERNAL "" -) -set(CPM_FILE - ${CMAKE_CURRENT_LIST_FILE} - CACHE INTERNAL "" -) -set(CPM_PACKAGES - "" - CACHE INTERNAL "" -) -set(CPM_DRY_RUN - OFF - CACHE INTERNAL "Don't download or configure dependencies (for testing)" -) - -if(DEFINED ENV{CPM_SOURCE_CACHE}) - set(CPM_SOURCE_CACHE_DEFAULT $ENV{CPM_SOURCE_CACHE}) -else() - set(CPM_SOURCE_CACHE_DEFAULT OFF) -endif() - -set(CPM_SOURCE_CACHE - ${CPM_SOURCE_CACHE_DEFAULT} - CACHE PATH "Directory to download CPM dependencies" -) - -if(NOT CPM_DONT_UPDATE_MODULE_PATH) - set(CPM_MODULE_PATH - "${CMAKE_BINARY_DIR}/CPM_modules" - CACHE INTERNAL "" - ) - # remove old modules - file(REMOVE_RECURSE ${CPM_MODULE_PATH}) - file(MAKE_DIRECTORY ${CPM_MODULE_PATH}) - # locally added CPM modules should override global packages - set(CMAKE_MODULE_PATH "${CPM_MODULE_PATH};${CMAKE_MODULE_PATH}") -endif() - -if(NOT CPM_DONT_CREATE_PACKAGE_LOCK) - set(CPM_PACKAGE_LOCK_FILE - "${CMAKE_BINARY_DIR}/cpm-package-lock.cmake" - CACHE INTERNAL "" - ) - file(WRITE ${CPM_PACKAGE_LOCK_FILE} - "# CPM Package Lock\n# This file should be committed to version control\n\n" - ) -endif() - -include(FetchContent) - -# Try to infer package name from git repository uri (path or url) -function(cpm_package_name_from_git_uri URI RESULT) - if("${URI}" MATCHES "([^/:]+)/?.git/?$") - set(${RESULT} - ${CMAKE_MATCH_1} - PARENT_SCOPE - ) - else() - unset(${RESULT} PARENT_SCOPE) - endif() -endfunction() - -# Try to infer package name and version from a url -function(cpm_package_name_and_ver_from_url url outName outVer) - if(url MATCHES "[/\\?]([a-zA-Z0-9_\\.-]+)\\.(tar|tar\\.gz|tar\\.bz2|zip|ZIP)(\\?|/|$)") - # We matched an archive - set(filename "${CMAKE_MATCH_1}") - - if(filename MATCHES "([a-zA-Z0-9_\\.-]+)[_-]v?(([0-9]+\\.)*[0-9]+[a-zA-Z0-9]*)") - # We matched - (ie foo-1.2.3) - set(${outName} - "${CMAKE_MATCH_1}" - PARENT_SCOPE - ) - set(${outVer} - "${CMAKE_MATCH_2}" - PARENT_SCOPE - ) - elseif(filename MATCHES "(([0-9]+\\.)+[0-9]+[a-zA-Z0-9]*)") - # We couldn't find a name, but we found a version - # - # In many cases (which we don't handle here) the url would look something like - # `irrelevant/ACTUAL_PACKAGE_NAME/irrelevant/1.2.3.zip`. In such a case we can't possibly - # distinguish the package name from the irrelevant bits. Moreover if we try to match the - # package name from the filename, we'd get bogus at best. - unset(${outName} PARENT_SCOPE) - set(${outVer} - "${CMAKE_MATCH_1}" - PARENT_SCOPE - ) - else() - # Boldly assume that the file name is the package name. - # - # Yes, something like `irrelevant/ACTUAL_NAME/irrelevant/download.zip` will ruin our day, but - # such cases should be quite rare. No popular service does this... we think. - set(${outName} - "${filename}" - PARENT_SCOPE - ) - unset(${outVer} PARENT_SCOPE) - endif() - else() - # No ideas yet what to do with non-archives - unset(${outName} PARENT_SCOPE) - unset(${outVer} PARENT_SCOPE) - endif() -endfunction() - -function(cpm_find_package NAME VERSION) - string(REPLACE " " ";" EXTRA_ARGS "${ARGN}") - find_package(${NAME} ${VERSION} ${EXTRA_ARGS} QUIET) - if(${CPM_ARGS_NAME}_FOUND) - if(DEFINED ${CPM_ARGS_NAME}_VERSION) - set(VERSION ${${CPM_ARGS_NAME}_VERSION}) - endif() - cpm_message(STATUS "${CPM_INDENT} Using local package ${CPM_ARGS_NAME}@${VERSION}") - CPMRegisterPackage(${CPM_ARGS_NAME} "${VERSION}") - set(CPM_PACKAGE_FOUND - YES - PARENT_SCOPE - ) - else() - set(CPM_PACKAGE_FOUND - NO - PARENT_SCOPE - ) - endif() -endfunction() - -# Create a custom FindXXX.cmake module for a CPM package This prevents `find_package(NAME)` from -# finding the system library -function(cpm_create_module_file Name) - if(NOT CPM_DONT_UPDATE_MODULE_PATH) - # erase any previous modules - file(WRITE ${CPM_MODULE_PATH}/Find${Name}.cmake - "include(\"${CPM_FILE}\")\n${ARGN}\nset(${Name}_FOUND TRUE)" - ) - endif() -endfunction() - -# Find a package locally or fallback to CPMAddPackage -function(CPMFindPackage) - set(oneValueArgs NAME VERSION GIT_TAG FIND_PACKAGE_ARGUMENTS) - - cmake_parse_arguments(CPM_ARGS "" "${oneValueArgs}" "" ${ARGN}) - - if(NOT DEFINED CPM_ARGS_VERSION) - if(DEFINED CPM_ARGS_GIT_TAG) - cpm_get_version_from_git_tag("${CPM_ARGS_GIT_TAG}" CPM_ARGS_VERSION) - endif() - endif() - - set(downloadPackage ${CPM_DOWNLOAD_ALL}) - if(DEFINED CPM_DOWNLOAD_${CPM_ARGS_NAME}) - set(downloadPackage ${CPM_DOWNLOAD_${CPM_ARGS_NAME}}) - elseif(DEFINED ENV{CPM_DOWNLOAD_${CPM_ARGS_NAME}}) - set(downloadPackage $ENV{CPM_DOWNLOAD_${CPM_ARGS_NAME}}) - endif() - if(downloadPackage) - CPMAddPackage(${ARGN}) - cpm_export_variables(${CPM_ARGS_NAME}) - return() - endif() - - cpm_find_package(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}" ${CPM_ARGS_FIND_PACKAGE_ARGUMENTS}) - - if(NOT CPM_PACKAGE_FOUND) - CPMAddPackage(${ARGN}) - cpm_export_variables(${CPM_ARGS_NAME}) - endif() - -endfunction() - -# checks if a package has been added before -function(cpm_check_if_package_already_added CPM_ARGS_NAME CPM_ARGS_VERSION) - if("${CPM_ARGS_NAME}" IN_LIST CPM_PACKAGES) - CPMGetPackageVersion(${CPM_ARGS_NAME} CPM_PACKAGE_VERSION) - if("${CPM_PACKAGE_VERSION}" VERSION_LESS "${CPM_ARGS_VERSION}") - message( - WARNING - "${CPM_INDENT} Requires a newer version of ${CPM_ARGS_NAME} (${CPM_ARGS_VERSION}) than currently included (${CPM_PACKAGE_VERSION})." - ) - endif() - cpm_get_fetch_properties(${CPM_ARGS_NAME}) - set(${CPM_ARGS_NAME}_ADDED NO) - set(CPM_PACKAGE_ALREADY_ADDED - YES - PARENT_SCOPE - ) - cpm_export_variables(${CPM_ARGS_NAME}) - else() - set(CPM_PACKAGE_ALREADY_ADDED - NO - PARENT_SCOPE - ) - endif() -endfunction() - -# Parse the argument of CPMAddPackage in case a single one was provided and convert it to a list of -# arguments which can then be parsed idiomatically. For example gh:foo/bar@1.2.3 will be converted -# to: GITHUB_REPOSITORY;foo/bar;VERSION;1.2.3 -function(cpm_parse_add_package_single_arg arg outArgs) - # Look for a scheme - if("${arg}" MATCHES "^([a-zA-Z]+):(.+)$") - string(TOLOWER "${CMAKE_MATCH_1}" scheme) - set(uri "${CMAKE_MATCH_2}") - - # Check for CPM-specific schemes - if(scheme STREQUAL "gh") - set(out "GITHUB_REPOSITORY;${uri}") - set(packageType "git") - elseif(scheme STREQUAL "gl") - set(out "GITLAB_REPOSITORY;${uri}") - set(packageType "git") - elseif(scheme STREQUAL "bb") - set(out "BITBUCKET_REPOSITORY;${uri}") - set(packageType "git") - # A CPM-specific scheme was not found. Looks like this is a generic URL so try to determine - # type - elseif(arg MATCHES ".git/?(@|#|$)") - set(out "GIT_REPOSITORY;${arg}") - set(packageType "git") - else() - # Fall back to a URL - set(out "URL;${arg}") - set(packageType "archive") - - # We could also check for SVN since FetchContent supports it, but SVN is so rare these days. - # We just won't bother with the additional complexity it will induce in this function. SVN is - # done by multi-arg - endif() - else() - if(arg MATCHES ".git/?(@|#|$)") - set(out "GIT_REPOSITORY;${arg}") - set(packageType "git") - else() - # Give up - message(FATAL_ERROR "${CPM_INDENT} Can't determine package type of '${arg}'") - endif() - endif() - - # For all packages we interpret @... as version. Only replace the last occurrence. Thus URIs - # containing '@' can be used - string(REGEX REPLACE "@([^@]+)$" ";VERSION;\\1" out "${out}") - - # Parse the rest according to package type - if(packageType STREQUAL "git") - # For git repos we interpret #... as a tag or branch or commit hash - string(REGEX REPLACE "#([^#]+)$" ";GIT_TAG;\\1" out "${out}") - elseif(packageType STREQUAL "archive") - # For archives we interpret #... as a URL hash. - string(REGEX REPLACE "#([^#]+)$" ";URL_HASH;\\1" out "${out}") - # We don't try to parse the version if it's not provided explicitly. cpm_get_version_from_url - # should do this at a later point - else() - # We should never get here. This is an assertion and hitting it means there's a problem with the - # code above. A packageType was set, but not handled by this if-else. - message(FATAL_ERROR "${CPM_INDENT} Unsupported package type '${packageType}' of '${arg}'") - endif() - - set(${outArgs} - ${out} - PARENT_SCOPE - ) -endfunction() - -# Check that the working directory for a git repo is clean -function(cpm_check_git_working_dir_is_clean repoPath gitTag isClean) - - find_package(Git REQUIRED) - - if(NOT GIT_EXECUTABLE) - # No git executable, assume directory is clean - set(${isClean} - TRUE - PARENT_SCOPE - ) - return() - endif() - - # check for uncommitted changes - execute_process( - COMMAND ${GIT_EXECUTABLE} status --porcelain - RESULT_VARIABLE resultGitStatus - OUTPUT_VARIABLE repoStatus - OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET - WORKING_DIRECTORY ${repoPath} - ) - if(resultGitStatus) - # not supposed to happen, assume clean anyway - message(WARNING "${CPM_INDENT} Calling git status on folder ${repoPath} failed") - set(${isClean} - TRUE - PARENT_SCOPE - ) - return() - endif() - - if(NOT "${repoStatus}" STREQUAL "") - set(${isClean} - FALSE - PARENT_SCOPE - ) - return() - endif() - - # check for committed changes - execute_process( - COMMAND ${GIT_EXECUTABLE} diff -s --exit-code ${gitTag} - RESULT_VARIABLE resultGitDiff - OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_QUIET - WORKING_DIRECTORY ${repoPath} - ) - - if(${resultGitDiff} EQUAL 0) - set(${isClean} - TRUE - PARENT_SCOPE - ) - else() - set(${isClean} - FALSE - PARENT_SCOPE - ) - endif() - -endfunction() - -# Add PATCH_COMMAND to CPM_ARGS_UNPARSED_ARGUMENTS. This method consumes a list of files in ARGN -# then generates a `PATCH_COMMAND` appropriate for `ExternalProject_Add()`. This command is appended -# to the parent scope's `CPM_ARGS_UNPARSED_ARGUMENTS`. -function(cpm_add_patches) - # Return if no patch files are supplied. - if(NOT ARGN) - return() - endif() - - # Find the patch program. - find_program(PATCH_EXECUTABLE patch) - if(WIN32 AND NOT PATCH_EXECUTABLE) - # The Windows git executable is distributed with patch.exe. Find the path to the executable, if - # it exists, then search `../../usr/bin` for patch.exe. - find_package(Git QUIET) - if(GIT_EXECUTABLE) - get_filename_component(extra_search_path ${GIT_EXECUTABLE} DIRECTORY) - get_filename_component(extra_search_path ${extra_search_path} DIRECTORY) - get_filename_component(extra_search_path ${extra_search_path} DIRECTORY) - find_program(PATCH_EXECUTABLE patch HINTS "${extra_search_path}/usr/bin") - endif() - endif() - if(NOT PATCH_EXECUTABLE) - message(FATAL_ERROR "Couldn't find `patch` executable to use with PATCHES keyword.") - endif() - - # Create a temporary - set(temp_list ${CPM_ARGS_UNPARSED_ARGUMENTS}) - - # Ensure each file exists (or error out) and add it to the list. - set(first_item True) - foreach(PATCH_FILE ${ARGN}) - # Make sure the patch file exists, if we can't find it, try again in the current directory. - if(NOT EXISTS "${PATCH_FILE}") - if(NOT EXISTS "${CMAKE_CURRENT_LIST_DIR}/${PATCH_FILE}") - message(FATAL_ERROR "Couldn't find patch file: '${PATCH_FILE}'") - endif() - set(PATCH_FILE "${CMAKE_CURRENT_LIST_DIR}/${PATCH_FILE}") - endif() - - # Convert to absolute path for use with patch file command. - get_filename_component(PATCH_FILE "${PATCH_FILE}" ABSOLUTE) - - # The first patch entry must be preceded by "PATCH_COMMAND" while the following items are - # preceded by "&&". - if(first_item) - set(first_item False) - list(APPEND temp_list "PATCH_COMMAND") - else() - list(APPEND temp_list "&&") - endif() - # Add the patch command to the list - list(APPEND temp_list "${PATCH_EXECUTABLE}" "-p1" "<" "${PATCH_FILE}") - endforeach() - - # Move temp out into parent scope. - set(CPM_ARGS_UNPARSED_ARGUMENTS - ${temp_list} - PARENT_SCOPE - ) - -endfunction() - -# method to overwrite internal FetchContent properties, to allow using CPM.cmake to overload -# FetchContent calls. As these are internal cmake properties, this method should be used carefully -# and may need modification in future CMake versions. Source: -# https://github.com/Kitware/CMake/blob/dc3d0b5a0a7d26d43d6cfeb511e224533b5d188f/Modules/FetchContent.cmake#L1152 -function(cpm_override_fetchcontent contentName) - cmake_parse_arguments(PARSE_ARGV 1 arg "" "SOURCE_DIR;BINARY_DIR" "") - if(NOT "${arg_UNPARSED_ARGUMENTS}" STREQUAL "") - message(FATAL_ERROR "${CPM_INDENT} Unsupported arguments: ${arg_UNPARSED_ARGUMENTS}") - endif() - - string(TOLOWER ${contentName} contentNameLower) - set(prefix "_FetchContent_${contentNameLower}") - - set(propertyName "${prefix}_sourceDir") - define_property( - GLOBAL - PROPERTY ${propertyName} - BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()" - FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}" - ) - set_property(GLOBAL PROPERTY ${propertyName} "${arg_SOURCE_DIR}") - - set(propertyName "${prefix}_binaryDir") - define_property( - GLOBAL - PROPERTY ${propertyName} - BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()" - FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}" - ) - set_property(GLOBAL PROPERTY ${propertyName} "${arg_BINARY_DIR}") - - set(propertyName "${prefix}_populated") - define_property( - GLOBAL - PROPERTY ${propertyName} - BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()" - FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}" - ) - set_property(GLOBAL PROPERTY ${propertyName} TRUE) -endfunction() - -# Download and add a package from source -function(CPMAddPackage) - cpm_set_policies() - - list(LENGTH ARGN argnLength) - if(argnLength EQUAL 1) - cpm_parse_add_package_single_arg("${ARGN}" ARGN) - - # The shorthand syntax implies EXCLUDE_FROM_ALL and SYSTEM - set(ARGN "${ARGN};EXCLUDE_FROM_ALL;YES;SYSTEM;YES;") - endif() - - set(oneValueArgs - NAME - FORCE - VERSION - GIT_TAG - DOWNLOAD_ONLY - GITHUB_REPOSITORY - GITLAB_REPOSITORY - BITBUCKET_REPOSITORY - GIT_REPOSITORY - SOURCE_DIR - FIND_PACKAGE_ARGUMENTS - NO_CACHE - SYSTEM - GIT_SHALLOW - EXCLUDE_FROM_ALL - SOURCE_SUBDIR - CUSTOM_CACHE_KEY - ) - - set(multiValueArgs URL OPTIONS DOWNLOAD_COMMAND PATCHES) - - cmake_parse_arguments(CPM_ARGS "" "${oneValueArgs}" "${multiValueArgs}" "${ARGN}") - - # Set default values for arguments - - if(NOT DEFINED CPM_ARGS_VERSION) - if(DEFINED CPM_ARGS_GIT_TAG) - cpm_get_version_from_git_tag("${CPM_ARGS_GIT_TAG}" CPM_ARGS_VERSION) - endif() - endif() - - if(CPM_ARGS_DOWNLOAD_ONLY) - set(DOWNLOAD_ONLY ${CPM_ARGS_DOWNLOAD_ONLY}) - else() - set(DOWNLOAD_ONLY NO) - endif() - - if(DEFINED CPM_ARGS_GITHUB_REPOSITORY) - set(CPM_ARGS_GIT_REPOSITORY "https://github.com/${CPM_ARGS_GITHUB_REPOSITORY}.git") - elseif(DEFINED CPM_ARGS_GITLAB_REPOSITORY) - set(CPM_ARGS_GIT_REPOSITORY "https://gitlab.com/${CPM_ARGS_GITLAB_REPOSITORY}.git") - elseif(DEFINED CPM_ARGS_BITBUCKET_REPOSITORY) - set(CPM_ARGS_GIT_REPOSITORY "https://bitbucket.org/${CPM_ARGS_BITBUCKET_REPOSITORY}.git") - endif() - - if(DEFINED CPM_ARGS_GIT_REPOSITORY) - list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_REPOSITORY ${CPM_ARGS_GIT_REPOSITORY}) - if(NOT DEFINED CPM_ARGS_GIT_TAG) - set(CPM_ARGS_GIT_TAG v${CPM_ARGS_VERSION}) - endif() - - # If a name wasn't provided, try to infer it from the git repo - if(NOT DEFINED CPM_ARGS_NAME) - cpm_package_name_from_git_uri(${CPM_ARGS_GIT_REPOSITORY} CPM_ARGS_NAME) - endif() - endif() - - set(CPM_SKIP_FETCH FALSE) - - if(DEFINED CPM_ARGS_GIT_TAG) - list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_TAG ${CPM_ARGS_GIT_TAG}) - # If GIT_SHALLOW is explicitly specified, honor the value. - if(DEFINED CPM_ARGS_GIT_SHALLOW) - list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_SHALLOW ${CPM_ARGS_GIT_SHALLOW}) - endif() - endif() - - if(DEFINED CPM_ARGS_URL) - # If a name or version aren't provided, try to infer them from the URL - list(GET CPM_ARGS_URL 0 firstUrl) - cpm_package_name_and_ver_from_url(${firstUrl} nameFromUrl verFromUrl) - # If we fail to obtain name and version from the first URL, we could try other URLs if any. - # However multiple URLs are expected to be quite rare, so for now we won't bother. - - # If the caller provided their own name and version, they trump the inferred ones. - if(NOT DEFINED CPM_ARGS_NAME) - set(CPM_ARGS_NAME ${nameFromUrl}) - endif() - if(NOT DEFINED CPM_ARGS_VERSION) - set(CPM_ARGS_VERSION ${verFromUrl}) - endif() - - list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS URL "${CPM_ARGS_URL}") - endif() - - # Check for required arguments - - if(NOT DEFINED CPM_ARGS_NAME) - message( - FATAL_ERROR - "${CPM_INDENT} 'NAME' was not provided and couldn't be automatically inferred for package added with arguments: '${ARGN}'" - ) - endif() - - # Check if package has been added before - cpm_check_if_package_already_added(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}") - if(CPM_PACKAGE_ALREADY_ADDED) - cpm_export_variables(${CPM_ARGS_NAME}) - return() - endif() - - # Check for manual overrides - if(NOT CPM_ARGS_FORCE AND NOT "${CPM_${CPM_ARGS_NAME}_SOURCE}" STREQUAL "") - set(PACKAGE_SOURCE ${CPM_${CPM_ARGS_NAME}_SOURCE}) - set(CPM_${CPM_ARGS_NAME}_SOURCE "") - CPMAddPackage( - NAME "${CPM_ARGS_NAME}" - SOURCE_DIR "${PACKAGE_SOURCE}" - EXCLUDE_FROM_ALL "${CPM_ARGS_EXCLUDE_FROM_ALL}" - SYSTEM "${CPM_ARGS_SYSTEM}" - PATCHES "${CPM_ARGS_PATCHES}" - OPTIONS "${CPM_ARGS_OPTIONS}" - SOURCE_SUBDIR "${CPM_ARGS_SOURCE_SUBDIR}" - DOWNLOAD_ONLY "${DOWNLOAD_ONLY}" - FORCE True - ) - cpm_export_variables(${CPM_ARGS_NAME}) - return() - endif() - - # Check for available declaration - if(NOT CPM_ARGS_FORCE AND NOT "${CPM_DECLARATION_${CPM_ARGS_NAME}}" STREQUAL "") - set(declaration ${CPM_DECLARATION_${CPM_ARGS_NAME}}) - set(CPM_DECLARATION_${CPM_ARGS_NAME} "") - CPMAddPackage(${declaration}) - cpm_export_variables(${CPM_ARGS_NAME}) - # checking again to ensure version and option compatibility - cpm_check_if_package_already_added(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}") - return() - endif() - - if(NOT CPM_ARGS_FORCE) - if(CPM_USE_LOCAL_PACKAGES OR CPM_LOCAL_PACKAGES_ONLY) - cpm_find_package(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}" ${CPM_ARGS_FIND_PACKAGE_ARGUMENTS}) - - if(CPM_PACKAGE_FOUND) - cpm_export_variables(${CPM_ARGS_NAME}) - return() - endif() - - if(CPM_LOCAL_PACKAGES_ONLY) - message( - SEND_ERROR - "${CPM_INDENT} ${CPM_ARGS_NAME} not found via find_package(${CPM_ARGS_NAME} ${CPM_ARGS_VERSION})" - ) - endif() - endif() - endif() - - CPMRegisterPackage("${CPM_ARGS_NAME}" "${CPM_ARGS_VERSION}") - - if(DEFINED CPM_ARGS_GIT_TAG) - set(PACKAGE_INFO "${CPM_ARGS_GIT_TAG}") - elseif(DEFINED CPM_ARGS_SOURCE_DIR) - set(PACKAGE_INFO "${CPM_ARGS_SOURCE_DIR}") - else() - set(PACKAGE_INFO "${CPM_ARGS_VERSION}") - endif() - - if(DEFINED FETCHCONTENT_BASE_DIR) - # respect user's FETCHCONTENT_BASE_DIR if set - set(CPM_FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR}) - else() - set(CPM_FETCHCONTENT_BASE_DIR ${CMAKE_BINARY_DIR}/_deps) - endif() - - cpm_add_patches(${CPM_ARGS_PATCHES}) - - if(DEFINED CPM_ARGS_DOWNLOAD_COMMAND) - list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS DOWNLOAD_COMMAND ${CPM_ARGS_DOWNLOAD_COMMAND}) - elseif(DEFINED CPM_ARGS_SOURCE_DIR) - list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS SOURCE_DIR ${CPM_ARGS_SOURCE_DIR}) - if(NOT IS_ABSOLUTE ${CPM_ARGS_SOURCE_DIR}) - # Expand `CPM_ARGS_SOURCE_DIR` relative path. This is important because EXISTS doesn't work - # for relative paths. - get_filename_component( - source_directory ${CPM_ARGS_SOURCE_DIR} REALPATH BASE_DIR ${CMAKE_CURRENT_BINARY_DIR} - ) - else() - set(source_directory ${CPM_ARGS_SOURCE_DIR}) - endif() - if(NOT EXISTS ${source_directory}) - string(TOLOWER ${CPM_ARGS_NAME} lower_case_name) - # remove timestamps so CMake will re-download the dependency - file(REMOVE_RECURSE "${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-subbuild") - endif() - elseif(CPM_SOURCE_CACHE AND NOT CPM_ARGS_NO_CACHE) - string(TOLOWER ${CPM_ARGS_NAME} lower_case_name) - set(origin_parameters ${CPM_ARGS_UNPARSED_ARGUMENTS}) - list(SORT origin_parameters) - if(CPM_ARGS_CUSTOM_CACHE_KEY) - # Application set a custom unique directory name - set(download_directory ${CPM_SOURCE_CACHE}/${lower_case_name}/${CPM_ARGS_CUSTOM_CACHE_KEY}) - elseif(CPM_USE_NAMED_CACHE_DIRECTORIES) - string(SHA1 origin_hash "${origin_parameters};NEW_CACHE_STRUCTURE_TAG") - set(download_directory ${CPM_SOURCE_CACHE}/${lower_case_name}/${origin_hash}/${CPM_ARGS_NAME}) - else() - string(SHA1 origin_hash "${origin_parameters}") - set(download_directory ${CPM_SOURCE_CACHE}/${lower_case_name}/${origin_hash}) - endif() - # Expand `download_directory` relative path. This is important because EXISTS doesn't work for - # relative paths. - get_filename_component(download_directory ${download_directory} ABSOLUTE) - list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS SOURCE_DIR ${download_directory}) - - if(CPM_SOURCE_CACHE) - file(LOCK ${download_directory}/../cmake.lock) - endif() - - if(EXISTS ${download_directory}) - if(CPM_SOURCE_CACHE) - file(LOCK ${download_directory}/../cmake.lock RELEASE) - endif() - - cpm_store_fetch_properties( - ${CPM_ARGS_NAME} "${download_directory}" - "${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-build" - ) - cpm_get_fetch_properties("${CPM_ARGS_NAME}") - - if(DEFINED CPM_ARGS_GIT_TAG AND NOT (PATCH_COMMAND IN_LIST CPM_ARGS_UNPARSED_ARGUMENTS)) - # warn if cache has been changed since checkout - cpm_check_git_working_dir_is_clean(${download_directory} ${CPM_ARGS_GIT_TAG} IS_CLEAN) - if(NOT ${IS_CLEAN}) - message( - WARNING "${CPM_INDENT} Cache for ${CPM_ARGS_NAME} (${download_directory}) is dirty" - ) - endif() - endif() - - cpm_add_subdirectory( - "${CPM_ARGS_NAME}" - "${DOWNLOAD_ONLY}" - "${${CPM_ARGS_NAME}_SOURCE_DIR}/${CPM_ARGS_SOURCE_SUBDIR}" - "${${CPM_ARGS_NAME}_BINARY_DIR}" - "${CPM_ARGS_EXCLUDE_FROM_ALL}" - "${CPM_ARGS_SYSTEM}" - "${CPM_ARGS_OPTIONS}" - ) - set(PACKAGE_INFO "${PACKAGE_INFO} at ${download_directory}") - - # As the source dir is already cached/populated, we override the call to FetchContent. - set(CPM_SKIP_FETCH TRUE) - cpm_override_fetchcontent( - "${lower_case_name}" SOURCE_DIR "${${CPM_ARGS_NAME}_SOURCE_DIR}/${CPM_ARGS_SOURCE_SUBDIR}" - BINARY_DIR "${${CPM_ARGS_NAME}_BINARY_DIR}" - ) - - else() - # Enable shallow clone when GIT_TAG is not a commit hash. Our guess may not be accurate, but - # it should guarantee no commit hash get mis-detected. - if(NOT DEFINED CPM_ARGS_GIT_SHALLOW) - cpm_is_git_tag_commit_hash("${CPM_ARGS_GIT_TAG}" IS_HASH) - if(NOT ${IS_HASH}) - list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_SHALLOW TRUE) - endif() - endif() - - # remove timestamps so CMake will re-download the dependency - file(REMOVE_RECURSE ${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-subbuild) - set(PACKAGE_INFO "${PACKAGE_INFO} to ${download_directory}") - endif() - endif() - - cpm_create_module_file(${CPM_ARGS_NAME} "CPMAddPackage(\"${ARGN}\")") - - if(CPM_PACKAGE_LOCK_ENABLED) - if((CPM_ARGS_VERSION AND NOT CPM_ARGS_SOURCE_DIR) OR CPM_INCLUDE_ALL_IN_PACKAGE_LOCK) - cpm_add_to_package_lock(${CPM_ARGS_NAME} "${ARGN}") - elseif(CPM_ARGS_SOURCE_DIR) - cpm_add_comment_to_package_lock(${CPM_ARGS_NAME} "local directory") - else() - cpm_add_comment_to_package_lock(${CPM_ARGS_NAME} "${ARGN}") - endif() - endif() - - cpm_message( - STATUS "${CPM_INDENT} Adding package ${CPM_ARGS_NAME}@${CPM_ARGS_VERSION} (${PACKAGE_INFO})" - ) - - if(NOT CPM_SKIP_FETCH) - cpm_declare_fetch( - "${CPM_ARGS_NAME}" "${CPM_ARGS_VERSION}" "${PACKAGE_INFO}" "${CPM_ARGS_UNPARSED_ARGUMENTS}" - ) - cpm_fetch_package("${CPM_ARGS_NAME}" populated) - if(CPM_SOURCE_CACHE AND download_directory) - file(LOCK ${download_directory}/../cmake.lock RELEASE) - endif() - if(${populated}) - cpm_add_subdirectory( - "${CPM_ARGS_NAME}" - "${DOWNLOAD_ONLY}" - "${${CPM_ARGS_NAME}_SOURCE_DIR}/${CPM_ARGS_SOURCE_SUBDIR}" - "${${CPM_ARGS_NAME}_BINARY_DIR}" - "${CPM_ARGS_EXCLUDE_FROM_ALL}" - "${CPM_ARGS_SYSTEM}" - "${CPM_ARGS_OPTIONS}" - ) - endif() - cpm_get_fetch_properties("${CPM_ARGS_NAME}") - endif() - - set(${CPM_ARGS_NAME}_ADDED YES) - cpm_export_variables("${CPM_ARGS_NAME}") -endfunction() - -# Fetch a previously declared package -macro(CPMGetPackage Name) - if(DEFINED "CPM_DECLARATION_${Name}") - CPMAddPackage(NAME ${Name}) - else() - message(SEND_ERROR "${CPM_INDENT} Cannot retrieve package ${Name}: no declaration available") - endif() -endmacro() - -# export variables available to the caller to the parent scope expects ${CPM_ARGS_NAME} to be set -macro(cpm_export_variables name) - set(${name}_SOURCE_DIR - "${${name}_SOURCE_DIR}" - PARENT_SCOPE - ) - set(${name}_BINARY_DIR - "${${name}_BINARY_DIR}" - PARENT_SCOPE - ) - set(${name}_ADDED - "${${name}_ADDED}" - PARENT_SCOPE - ) - set(CPM_LAST_PACKAGE_NAME - "${name}" - PARENT_SCOPE - ) -endmacro() - -# declares a package, so that any call to CPMAddPackage for the package name will use these -# arguments instead. Previous declarations will not be overridden. -macro(CPMDeclarePackage Name) - if(NOT DEFINED "CPM_DECLARATION_${Name}") - set("CPM_DECLARATION_${Name}" "${ARGN}") - endif() -endmacro() - -function(cpm_add_to_package_lock Name) - if(NOT CPM_DONT_CREATE_PACKAGE_LOCK) - cpm_prettify_package_arguments(PRETTY_ARGN false ${ARGN}) - file(APPEND ${CPM_PACKAGE_LOCK_FILE} "# ${Name}\nCPMDeclarePackage(${Name}\n${PRETTY_ARGN})\n") - endif() -endfunction() - -function(cpm_add_comment_to_package_lock Name) - if(NOT CPM_DONT_CREATE_PACKAGE_LOCK) - cpm_prettify_package_arguments(PRETTY_ARGN true ${ARGN}) - file(APPEND ${CPM_PACKAGE_LOCK_FILE} - "# ${Name} (unversioned)\n# CPMDeclarePackage(${Name}\n${PRETTY_ARGN}#)\n" - ) - endif() -endfunction() - -# includes the package lock file if it exists and creates a target `cpm-update-package-lock` to -# update it -macro(CPMUsePackageLock file) - if(NOT CPM_DONT_CREATE_PACKAGE_LOCK) - get_filename_component(CPM_ABSOLUTE_PACKAGE_LOCK_PATH ${file} ABSOLUTE) - if(EXISTS ${CPM_ABSOLUTE_PACKAGE_LOCK_PATH}) - include(${CPM_ABSOLUTE_PACKAGE_LOCK_PATH}) - endif() - if(NOT TARGET cpm-update-package-lock) - add_custom_target( - cpm-update-package-lock COMMAND ${CMAKE_COMMAND} -E copy ${CPM_PACKAGE_LOCK_FILE} - ${CPM_ABSOLUTE_PACKAGE_LOCK_PATH} - ) - endif() - set(CPM_PACKAGE_LOCK_ENABLED true) - endif() -endmacro() - -# registers a package that has been added to CPM -function(CPMRegisterPackage PACKAGE VERSION) - list(APPEND CPM_PACKAGES ${PACKAGE}) - set(CPM_PACKAGES - ${CPM_PACKAGES} - CACHE INTERNAL "" - ) - set("CPM_PACKAGE_${PACKAGE}_VERSION" - ${VERSION} - CACHE INTERNAL "" - ) -endfunction() - -# retrieve the current version of the package to ${OUTPUT} -function(CPMGetPackageVersion PACKAGE OUTPUT) - set(${OUTPUT} - "${CPM_PACKAGE_${PACKAGE}_VERSION}" - PARENT_SCOPE - ) -endfunction() - -# declares a package in FetchContent_Declare -function(cpm_declare_fetch PACKAGE VERSION INFO) - if(${CPM_DRY_RUN}) - cpm_message(STATUS "${CPM_INDENT} Package not declared (dry run)") - return() - endif() - - FetchContent_Declare(${PACKAGE} ${ARGN}) -endfunction() - -# returns properties for a package previously defined by cpm_declare_fetch -function(cpm_get_fetch_properties PACKAGE) - if(${CPM_DRY_RUN}) - return() - endif() - - set(${PACKAGE}_SOURCE_DIR - "${CPM_PACKAGE_${PACKAGE}_SOURCE_DIR}" - PARENT_SCOPE - ) - set(${PACKAGE}_BINARY_DIR - "${CPM_PACKAGE_${PACKAGE}_BINARY_DIR}" - PARENT_SCOPE - ) -endfunction() - -function(cpm_store_fetch_properties PACKAGE source_dir binary_dir) - if(${CPM_DRY_RUN}) - return() - endif() - - set(CPM_PACKAGE_${PACKAGE}_SOURCE_DIR - "${source_dir}" - CACHE INTERNAL "" - ) - set(CPM_PACKAGE_${PACKAGE}_BINARY_DIR - "${binary_dir}" - CACHE INTERNAL "" - ) -endfunction() - -# adds a package as a subdirectory if viable, according to provided options -function( - cpm_add_subdirectory - PACKAGE - DOWNLOAD_ONLY - SOURCE_DIR - BINARY_DIR - EXCLUDE - SYSTEM - OPTIONS -) - - if(NOT DOWNLOAD_ONLY AND EXISTS ${SOURCE_DIR}/CMakeLists.txt) - set(addSubdirectoryExtraArgs "") - if(EXCLUDE) - list(APPEND addSubdirectoryExtraArgs EXCLUDE_FROM_ALL) - endif() - if("${SYSTEM}" AND "${CMAKE_VERSION}" VERSION_GREATER_EQUAL "3.25") - # https://cmake.org/cmake/help/latest/prop_dir/SYSTEM.html#prop_dir:SYSTEM - list(APPEND addSubdirectoryExtraArgs SYSTEM) - endif() - if(OPTIONS) - foreach(OPTION ${OPTIONS}) - cpm_parse_option("${OPTION}") - set(${OPTION_KEY} "${OPTION_VALUE}") - endforeach() - endif() - set(CPM_OLD_INDENT "${CPM_INDENT}") - set(CPM_INDENT "${CPM_INDENT} ${PACKAGE}:") - add_subdirectory(${SOURCE_DIR} ${BINARY_DIR} ${addSubdirectoryExtraArgs}) - set(CPM_INDENT "${CPM_OLD_INDENT}") - endif() -endfunction() - -# downloads a previously declared package via FetchContent and exports the variables -# `${PACKAGE}_SOURCE_DIR` and `${PACKAGE}_BINARY_DIR` to the parent scope -function(cpm_fetch_package PACKAGE populated) - set(${populated} - FALSE - PARENT_SCOPE - ) - if(${CPM_DRY_RUN}) - cpm_message(STATUS "${CPM_INDENT} Package ${PACKAGE} not fetched (dry run)") - return() - endif() - - FetchContent_GetProperties(${PACKAGE}) - - string(TOLOWER "${PACKAGE}" lower_case_name) - - if(NOT ${lower_case_name}_POPULATED) - FetchContent_Populate(${PACKAGE}) - set(${populated} - TRUE - PARENT_SCOPE - ) - endif() - - cpm_store_fetch_properties( - ${CPM_ARGS_NAME} ${${lower_case_name}_SOURCE_DIR} ${${lower_case_name}_BINARY_DIR} - ) - - set(${PACKAGE}_SOURCE_DIR - ${${lower_case_name}_SOURCE_DIR} - PARENT_SCOPE - ) - set(${PACKAGE}_BINARY_DIR - ${${lower_case_name}_BINARY_DIR} - PARENT_SCOPE - ) -endfunction() - -# splits a package option -function(cpm_parse_option OPTION) - string(REGEX MATCH "^[^ ]+" OPTION_KEY "${OPTION}") - string(LENGTH "${OPTION}" OPTION_LENGTH) - string(LENGTH "${OPTION_KEY}" OPTION_KEY_LENGTH) - if(OPTION_KEY_LENGTH STREQUAL OPTION_LENGTH) - # no value for key provided, assume user wants to set option to "ON" - set(OPTION_VALUE "ON") - else() - math(EXPR OPTION_KEY_LENGTH "${OPTION_KEY_LENGTH}+1") - string(SUBSTRING "${OPTION}" "${OPTION_KEY_LENGTH}" "-1" OPTION_VALUE) - endif() - set(OPTION_KEY - "${OPTION_KEY}" - PARENT_SCOPE - ) - set(OPTION_VALUE - "${OPTION_VALUE}" - PARENT_SCOPE - ) -endfunction() - -# guesses the package version from a git tag -function(cpm_get_version_from_git_tag GIT_TAG RESULT) - string(LENGTH ${GIT_TAG} length) - if(length EQUAL 40) - # GIT_TAG is probably a git hash - set(${RESULT} - 0 - PARENT_SCOPE - ) - else() - string(REGEX MATCH "v?([0123456789.]*).*" _ ${GIT_TAG}) - set(${RESULT} - ${CMAKE_MATCH_1} - PARENT_SCOPE - ) - endif() -endfunction() - -# guesses if the git tag is a commit hash or an actual tag or a branch name. -function(cpm_is_git_tag_commit_hash GIT_TAG RESULT) - string(LENGTH "${GIT_TAG}" length) - # full hash has 40 characters, and short hash has at least 7 characters. - if(length LESS 7 OR length GREATER 40) - set(${RESULT} - 0 - PARENT_SCOPE - ) - else() - if(${GIT_TAG} MATCHES "^[a-fA-F0-9]+$") - set(${RESULT} - 1 - PARENT_SCOPE - ) - else() - set(${RESULT} - 0 - PARENT_SCOPE - ) - endif() - endif() -endfunction() - -function(cpm_prettify_package_arguments OUT_VAR IS_IN_COMMENT) - set(oneValueArgs - NAME - FORCE - VERSION - GIT_TAG - DOWNLOAD_ONLY - GITHUB_REPOSITORY - GITLAB_REPOSITORY - BITBUCKET_REPOSITORY - GIT_REPOSITORY - SOURCE_DIR - FIND_PACKAGE_ARGUMENTS - NO_CACHE - SYSTEM - GIT_SHALLOW - EXCLUDE_FROM_ALL - SOURCE_SUBDIR - ) - set(multiValueArgs URL OPTIONS DOWNLOAD_COMMAND) - cmake_parse_arguments(CPM_ARGS "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) - - foreach(oneArgName ${oneValueArgs}) - if(DEFINED CPM_ARGS_${oneArgName}) - if(${IS_IN_COMMENT}) - string(APPEND PRETTY_OUT_VAR "#") - endif() - if(${oneArgName} STREQUAL "SOURCE_DIR") - string(REPLACE ${CMAKE_SOURCE_DIR} "\${CMAKE_SOURCE_DIR}" CPM_ARGS_${oneArgName} - ${CPM_ARGS_${oneArgName}} - ) - endif() - string(APPEND PRETTY_OUT_VAR " ${oneArgName} ${CPM_ARGS_${oneArgName}}\n") - endif() - endforeach() - foreach(multiArgName ${multiValueArgs}) - if(DEFINED CPM_ARGS_${multiArgName}) - if(${IS_IN_COMMENT}) - string(APPEND PRETTY_OUT_VAR "#") - endif() - string(APPEND PRETTY_OUT_VAR " ${multiArgName}\n") - foreach(singleOption ${CPM_ARGS_${multiArgName}}) - if(${IS_IN_COMMENT}) - string(APPEND PRETTY_OUT_VAR "#") - endif() - string(APPEND PRETTY_OUT_VAR " \"${singleOption}\"\n") - endforeach() - endif() - endforeach() - - if(NOT "${CPM_ARGS_UNPARSED_ARGUMENTS}" STREQUAL "") - if(${IS_IN_COMMENT}) - string(APPEND PRETTY_OUT_VAR "#") - endif() - string(APPEND PRETTY_OUT_VAR " ") - foreach(CPM_ARGS_UNPARSED_ARGUMENT ${CPM_ARGS_UNPARSED_ARGUMENTS}) - string(APPEND PRETTY_OUT_VAR " ${CPM_ARGS_UNPARSED_ARGUMENT}") - endforeach() - string(APPEND PRETTY_OUT_VAR "\n") - endif() - - set(${OUT_VAR} - ${PRETTY_OUT_VAR} - PARENT_SCOPE - ) - -endfunction() diff --git a/packages/react-native-quick-crypto/deps/ncrypto/cmake/ncrypto-flags.cmake b/packages/react-native-quick-crypto/deps/ncrypto/cmake/ncrypto-flags.cmake deleted file mode 100644 index bdb10121..00000000 --- a/packages/react-native-quick-crypto/deps/ncrypto/cmake/ncrypto-flags.cmake +++ /dev/null @@ -1,15 +0,0 @@ -option(NCRYPTO_DEVELOPMENT_CHECKS "development checks (useful for debugging)" OFF) -option(NCRYPTO_TESTING "Build tests" ON) - -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -set(CMAKE_CXX_STANDARD 20) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_EXTENSIONS OFF) - -find_program(CCACHE_FOUND ccache) -if(CCACHE_FOUND) - message(STATUS "Ccache found using it as compiler launcher.") - set(CMAKE_C_COMPILER_LAUNCHER ccache) - set(CMAKE_CXX_COMPILER_LAUNCHER ccache) -endif(CCACHE_FOUND) diff --git a/packages/react-native-quick-crypto/deps/ncrypto/include/dh-primes.h b/packages/react-native-quick-crypto/deps/ncrypto/include/dh-primes.h deleted file mode 100644 index 6564d779..00000000 --- a/packages/react-native-quick-crypto/deps/ncrypto/include/dh-primes.h +++ /dev/null @@ -1,67 +0,0 @@ -/* ==================================================================== - * Copyright (c) 2011 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * licensing@OpenSSL.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). */ - -#ifndef DEPS_NCRYPTO_DH_PRIMES_H_ -#define DEPS_NCRYPTO_DH_PRIMES_H_ - -#include - -// Backporting primes that may not be supported in earlier boringssl versions. -// Intentionally keeping the existing C-style formatting. - -BIGNUM* BN_get_rfc3526_prime_2048(BIGNUM* ret); -BIGNUM* BN_get_rfc3526_prime_3072(BIGNUM* ret); -BIGNUM* BN_get_rfc3526_prime_4096(BIGNUM* ret); -BIGNUM* BN_get_rfc3526_prime_6144(BIGNUM* ret); -BIGNUM* BN_get_rfc3526_prime_8192(BIGNUM* ret); - -#endif // DEPS_NCRYPTO_DH_PRIMES_H_ diff --git a/packages/react-native-quick-crypto/deps/ncrypto/src/ncrypto.cpp b/packages/react-native-quick-crypto/deps/ncrypto/ncrypto.cc similarity index 73% rename from packages/react-native-quick-crypto/deps/ncrypto/src/ncrypto.cpp rename to packages/react-native-quick-crypto/deps/ncrypto/ncrypto.cc index 732f0c38..d7a26edd 100644 --- a/packages/react-native-quick-crypto/deps/ncrypto/src/ncrypto.cpp +++ b/packages/react-native-quick-crypto/deps/ncrypto/ncrypto.cc @@ -1,5 +1,4 @@ #include "ncrypto.h" - #include #include #include @@ -8,28 +7,56 @@ #include #include #include - -#ifndef NCRYPTO_NO_KDF_H -#include -#else -#include -#endif - #include #include #if OPENSSL_VERSION_MAJOR >= 3 +#include +#include #include +#if OPENSSL_VERSION_NUMBER >= 0x30200000L +#include +#endif +#endif +#if OPENSSL_WITH_PQC +struct PQCMapping { + const char* name; + int nid; +}; + +constexpr static PQCMapping pqc_mappings[] = { + {"ML-DSA-44", EVP_PKEY_ML_DSA_44}, + {"ML-DSA-65", EVP_PKEY_ML_DSA_65}, + {"ML-DSA-87", EVP_PKEY_ML_DSA_87}, + {"ML-KEM-512", EVP_PKEY_ML_KEM_512}, + {"ML-KEM-768", EVP_PKEY_ML_KEM_768}, + {"ML-KEM-1024", EVP_PKEY_ML_KEM_1024}, + {"SLH-DSA-SHA2-128f", EVP_PKEY_SLH_DSA_SHA2_128F}, + {"SLH-DSA-SHA2-128s", EVP_PKEY_SLH_DSA_SHA2_128S}, + {"SLH-DSA-SHA2-192f", EVP_PKEY_SLH_DSA_SHA2_192F}, + {"SLH-DSA-SHA2-192s", EVP_PKEY_SLH_DSA_SHA2_192S}, + {"SLH-DSA-SHA2-256f", EVP_PKEY_SLH_DSA_SHA2_256F}, + {"SLH-DSA-SHA2-256s", EVP_PKEY_SLH_DSA_SHA2_256S}, + {"SLH-DSA-SHAKE-128f", EVP_PKEY_SLH_DSA_SHAKE_128F}, + {"SLH-DSA-SHAKE-128s", EVP_PKEY_SLH_DSA_SHAKE_128S}, + {"SLH-DSA-SHAKE-192f", EVP_PKEY_SLH_DSA_SHAKE_192F}, + {"SLH-DSA-SHAKE-192s", EVP_PKEY_SLH_DSA_SHAKE_192S}, + {"SLH-DSA-SHAKE-256f", EVP_PKEY_SLH_DSA_SHAKE_256F}, + {"SLH-DSA-SHAKE-256s", EVP_PKEY_SLH_DSA_SHAKE_256S}, +}; + #endif // EVP_PKEY_CTX_set_dsa_paramgen_q_bits was added in OpenSSL 1.1.1e. #if OPENSSL_VERSION_NUMBER < 0x1010105fL -#define EVP_PKEY_CTX_set_dsa_paramgen_q_bits(ctx, qbits) \ - EVP_PKEY_CTX_ctrl((ctx), EVP_PKEY_DSA, EVP_PKEY_OP_PARAMGEN, \ - EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS, (qbits), nullptr) +#define EVP_PKEY_CTX_set_dsa_paramgen_q_bits(ctx, qbits) \ + EVP_PKEY_CTX_ctrl((ctx), \ + EVP_PKEY_DSA, \ + EVP_PKEY_OP_PARAMGEN, \ + EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS, \ + (qbits), \ + nullptr) #endif -// ============================================================================ - namespace ncrypto { namespace { using BignumCtxPointer = DeleteFnPtr; @@ -52,7 +79,9 @@ ClearErrorOnReturn::~ClearErrorOnReturn() { ERR_clear_error(); } -int ClearErrorOnReturn::peekError() { return ERR_peek_error(); } +int ClearErrorOnReturn::peekError() { + return ERR_peek_error(); +} MarkPopErrorOnReturn::MarkPopErrorOnReturn(CryptoErrorList* errors) : errors_(errors) { @@ -64,7 +93,9 @@ MarkPopErrorOnReturn::~MarkPopErrorOnReturn() { ERR_pop_to_mark(); } -int MarkPopErrorOnReturn::peekError() { return ERR_peek_error(); } +int MarkPopErrorOnReturn::peekError() { + return ERR_peek_error(); +} CryptoErrorList::CryptoErrorList(CryptoErrorList::Option option) { if (option == Option::CAPTURE_ON_CONSTRUCT) capture(); @@ -79,7 +110,9 @@ void CryptoErrorList::capture() { } } -void CryptoErrorList::add(std::string error) { errors_.push_back(error); } +void CryptoErrorList::add(std::string error) { + errors_.push_back(error); +} std::optional CryptoErrorList::pop_back() { if (errors_.empty()) return std::nullopt; @@ -108,20 +141,64 @@ DataPointer DataPointer::Alloc(size_t len) { #endif } +DataPointer DataPointer::SecureAlloc(size_t len) { +#ifndef OPENSSL_IS_BORINGSSL + auto ptr = OPENSSL_secure_zalloc(len); + if (ptr == nullptr) return {}; + return DataPointer(ptr, len, true); +#else + // BoringSSL does not implement the OPENSSL_secure_zalloc API. + auto ptr = OPENSSL_malloc(len); + if (ptr == nullptr) return {}; + memset(ptr, 0, len); + return DataPointer(ptr, len); +#endif +} + +size_t DataPointer::GetSecureHeapUsed() { +#ifndef OPENSSL_IS_BORINGSSL + return CRYPTO_secure_malloc_initialized() ? CRYPTO_secure_used() : 0; +#else + // BoringSSL does not have the secure heap and therefore + // will always return 0. + return 0; +#endif +} + +DataPointer::InitSecureHeapResult DataPointer::TryInitSecureHeap(size_t amount, + size_t min) { +#ifndef OPENSSL_IS_BORINGSSL + switch (CRYPTO_secure_malloc_init(amount, min)) { + case 0: + return InitSecureHeapResult::FAILED; + case 2: + return InitSecureHeapResult::UNABLE_TO_MEMORY_MAP; + case 1: + return InitSecureHeapResult::OK; + default: + return InitSecureHeapResult::FAILED; + } +#else + // BoringSSL does not actually support the secure heap + return InitSecureHeapResult::FAILED; +#endif +} + DataPointer DataPointer::Copy(const Buffer& buffer) { return DataPointer(OPENSSL_memdup(buffer.data, buffer.len), buffer.len); } -DataPointer::DataPointer(void* data, size_t length) - : data_(data), len_(length) {} +DataPointer::DataPointer(void* data, size_t length, bool secure) + : data_(data), len_(length), secure_(secure) {} -DataPointer::DataPointer(const Buffer& buffer) - : data_(buffer.data), len_(buffer.len) {} +DataPointer::DataPointer(const Buffer& buffer, bool secure) + : data_(buffer.data), len_(buffer.len), secure_(secure) {} DataPointer::DataPointer(DataPointer&& other) noexcept - : data_(other.data_), len_(other.len_) { + : data_(other.data_), len_(other.len_), secure_(other.secure_) { other.data_ = nullptr; other.len_ = 0; + other.secure_ = false; } DataPointer& DataPointer::operator=(DataPointer&& other) noexcept { @@ -130,7 +207,9 @@ DataPointer& DataPointer::operator=(DataPointer&& other) noexcept { return *new (this) DataPointer(std::move(other)); } -DataPointer::~DataPointer() { reset(); } +DataPointer::~DataPointer() { + reset(); +} void DataPointer::zero() { if (!data_) return; @@ -139,7 +218,11 @@ void DataPointer::zero() { void DataPointer::reset(void* data, size_t length) { if (data_ != nullptr) { - OPENSSL_clear_free(data_, len_); + if (secure_) { + OPENSSL_secure_clear_free(data_, len_); + } else { + OPENSSL_clear_free(data_, len_); + } } data_ = data; len_ = length; @@ -162,7 +245,7 @@ Buffer DataPointer::release() { DataPointer DataPointer::resize(size_t len) { size_t actual_len = std::min(len_, len); auto buf = release(); - if (actual_len == len_) return DataPointer(buf); + if (actual_len == len_) return DataPointer(buf.data, actual_len); buf.data = OPENSSL_realloc(buf.data, actual_len); buf.len = actual_len; return DataPointer(buf); @@ -170,6 +253,7 @@ DataPointer DataPointer::resize(size_t len) { // ============================================================================ bool isFipsEnabled() { + ClearErrorOnReturn clear_error_on_return; #if OPENSSL_VERSION_MAJOR >= 3 return EVP_default_properties_is_fips_enabled(nullptr) == 1; #else @@ -181,30 +265,31 @@ bool setFipsEnabled(bool enable, CryptoErrorList* errors) { if (isFipsEnabled() == enable) return true; ClearErrorOnReturn clearErrorOnReturn(errors); #if OPENSSL_VERSION_MAJOR >= 3 - return EVP_default_properties_enable_fips(nullptr, enable ? 1 : 0) == 1; + return EVP_default_properties_enable_fips(nullptr, enable ? 1 : 0) == 1 && + EVP_default_properties_is_fips_enabled(nullptr); #else return FIPS_mode_set(enable ? 1 : 0) == 1; #endif } bool testFipsEnabled() { + ClearErrorOnReturn clear_error_on_return; #if OPENSSL_VERSION_MAJOR >= 3 OSSL_PROVIDER* fips_provider = nullptr; if (OSSL_PROVIDER_available(nullptr, "fips")) { fips_provider = OSSL_PROVIDER_load(nullptr, "fips"); } - const auto enabled = fips_provider == nullptr ? 0 - : OSSL_PROVIDER_self_test(fips_provider) ? 1 - : 0; + if (fips_provider == nullptr) return false; + int result = OSSL_PROVIDER_self_test(fips_provider); + OSSL_PROVIDER_unload(fips_provider); + return result; #else #ifdef OPENSSL_FIPS - const auto enabled = FIPS_selftest() ? 1 : 0; -#else // OPENSSL_FIPS - const auto enabled = 0; + return FIPS_selftest(); +#else // OPENSSL_FIPS + return false; #endif // OPENSSL_FIPS #endif - - return enabled; } // ============================================================================ @@ -217,7 +302,9 @@ BignumPointer::BignumPointer(const unsigned char* data, size_t len) BignumPointer::BignumPointer(BignumPointer&& other) noexcept : bn_(other.release()) {} -BignumPointer BignumPointer::New() { return BignumPointer(BN_new()); } +BignumPointer BignumPointer::New() { + return BignumPointer(BN_new()); +} BignumPointer BignumPointer::NewSecure() { #ifdef OPENSSL_IS_BORINGSSL @@ -234,26 +321,27 @@ BignumPointer& BignumPointer::operator=(BignumPointer&& other) noexcept { return *new (this) BignumPointer(std::move(other)); } -BignumPointer::~BignumPointer() { reset(); } +BignumPointer::~BignumPointer() { + reset(); +} -void BignumPointer::reset(BIGNUM* bn) { bn_.reset(bn); } +void BignumPointer::reset(BIGNUM* bn) { + bn_.reset(bn); +} void BignumPointer::reset(const unsigned char* data, size_t len) { reset(BN_bin2bn(data, len, nullptr)); } -BIGNUM* BignumPointer::release() { return bn_.release(); } +BIGNUM* BignumPointer::release() { + return bn_.release(); +} size_t BignumPointer::byteLength() const { - if (!bn_) return 0; + if (bn_ == nullptr) return 0; return BN_num_bytes(bn_.get()); } -size_t BignumPointer::bitLength() const { - if (!bn_) return 0; - return BN_num_bits(bn_.get()); -} - DataPointer BignumPointer::encode() const { return EncodePadded(bn_.get(), byteLength()); } @@ -297,7 +385,8 @@ DataPointer BignumPointer::EncodePadded(const BIGNUM* bn, size_t s) { BN_bn2binpad(bn, reinterpret_cast(buf.get()), size); return buf; } -size_t BignumPointer::EncodePaddedInto(const BIGNUM* bn, unsigned char* out, +size_t BignumPointer::EncodePaddedInto(const BIGNUM* bn, + unsigned char* out, size_t size) { if (bn == nullptr) return 0; return BN_bn2binpad(bn, out, size); @@ -324,15 +413,25 @@ DataPointer BignumPointer::toHex() const { return DataPointer(hex, strlen(hex)); } -int BignumPointer::GetBitCount(const BIGNUM* bn) { return BN_num_bits(bn); } +int BignumPointer::GetBitCount(const BIGNUM* bn) { + return BN_num_bits(bn); +} -int BignumPointer::GetByteCount(const BIGNUM* bn) { return BN_num_bytes(bn); } +int BignumPointer::GetByteCount(const BIGNUM* bn) { + return BN_num_bytes(bn); +} -bool BignumPointer::isZero() const { return bn_ && BN_is_zero(bn_.get()); } +bool BignumPointer::isZero() const { + return bn_ && BN_is_zero(bn_.get()); +} -bool BignumPointer::isOne() const { return bn_ && BN_is_one(bn_.get()); } +bool BignumPointer::isOne() const { + return bn_ && BN_is_one(bn_.get()); +} -const BIGNUM* BignumPointer::One() { return BN_value_one(); } +const BIGNUM* BignumPointer::One() { + return BN_value_one(); +} BignumPointer BignumPointer::clone() { if (!bn_) return {}; @@ -352,11 +451,8 @@ int BignumPointer::isPrime(int nchecks, // TODO(@jasnell): This could be refactored to allow inlining. // Not too important right now tho. [](int a, int b, BN_GENCB* ctx) mutable -> int { - // PrimeCheckCallback& ptr = *static_cast(ctx->arg); - // Newer versions of openssl and boringssl define the BN_GENCB_get_arg - // API which is what is supposed to be used here. Older versions, - // however, omit that API. - PrimeCheckCallback& ptr = *static_cast(BN_GENCB_get_arg(ctx)); + PrimeCheckCallback& ptr = + *static_cast(BN_GENCB_get_arg(ctx)); return ptr(a, b) ? 1 : 0; }, &innerCb); @@ -386,17 +482,18 @@ bool BignumPointer::generate(const PrimeConfig& params, BN_GENCB_set( cb.get(), [](int a, int b, BN_GENCB* ctx) mutable -> int { -// PrimeCheckCallback& ptr = *static_cast(ctx->arg); - // Newer versions of openssl and boringssl define the BN_GENCB_get_arg - // API which is what is supposed to be used here. Older versions, - // however, omit that API. - PrimeCheckCallback& ptr = *static_cast(BN_GENCB_get_arg(ctx)); + PrimeCheckCallback& ptr = + *static_cast(BN_GENCB_get_arg(ctx)); return ptr(a, b) ? 1 : 0; }, &innerCb); } - if (BN_generate_prime_ex(get(), params.bits, params.safe ? 1 : 0, - params.add.get(), params.rem.get(), cb.get()) == 0) { + if (BN_generate_prime_ex(get(), + params.bits, + params.safe ? 1 : 0, + params.add.get(), + params.rem.get(), + cb.get()) == 0) { return false; } @@ -461,7 +558,9 @@ bool CSPRNG(void* buffer, size_t length) { return false; } -int NoPasswordCallback(char* buf, int size, int rwflag, void* u) { return 0; } +int NoPasswordCallback(char* buf, int size, int rwflag, void* u) { + return 0; +} int PasswordCallback(char* buf, int size, int rwflag, void* u) { auto passphrase = static_cast*>(u); @@ -513,9 +612,7 @@ int64_t PortableTimeGM(struct tm* t) { // ============================================================================ // SPKAC -namespace { -bool VerifySpkacImpl(const char* input, size_t length) { - ClearErrorOnReturn clearErrorOnReturn; +bool VerifySpkac(const char* input, size_t length) { #ifdef OPENSSL_IS_BORINGSSL // OpenSSL uses EVP_DecodeBlock, which explicitly removes trailing characters, // while BoringSSL uses EVP_DecodedLength and EVP_DecodeBase64, which do not. @@ -533,11 +630,9 @@ bool VerifySpkacImpl(const char* input, size_t length) { return pkey ? NETSCAPE_SPKI_verify(spki.get(), pkey.get()) > 0 : false; } -BIOPointer ExportPublicKeyImpl(const char* input, size_t length) { - ClearErrorOnReturn clearErrorOnReturn; - auto bio = BIOPointer::NewMem(); - if (!bio) [[unlikely]] - return {}; +BIOPointer ExportPublicKey(const char* input, size_t length) { + BIOPointer bio(BIO_new(BIO_s_mem())); + if (!bio) return {}; #ifdef OPENSSL_IS_BORINGSSL // OpenSSL uses EVP_DecodeBlock, which explicitly removes trailing characters, @@ -546,21 +641,17 @@ BIOPointer ExportPublicKeyImpl(const char* input, size_t length) { length = std::string_view(input, length).find_last_not_of(" \n\r\t") + 1; #endif NetscapeSPKIPointer spki(NETSCAPE_SPKI_b64_decode(input, length)); - if (!spki) [[unlikely]] { - return {}; - } + if (!spki) return {}; EVPKeyPointer pkey(NETSCAPE_SPKI_get_pubkey(spki.get())); + if (!pkey) return {}; - if (!pkey || PEM_write_bio_PUBKEY(bio.get(), pkey.get()) <= 0) [[unlikely]] { - return {}; - } + if (PEM_write_bio_PUBKEY(bio.get(), pkey.get()) <= 0) return {}; return bio; } -DataPointer ExportChallengeImpl(const char* input, size_t length) { - ClearErrorOnReturn clearErrorOnReturn; +Buffer ExportChallenge(const char* input, size_t length) { #ifdef OPENSSL_IS_BORINGSSL // OpenSSL uses EVP_DecodeBlock, which explicitly removes trailing characters, // while BoringSSL uses EVP_DecodedLength and EVP_DecodeBase64, which do not. @@ -573,44 +664,12 @@ DataPointer ExportChallengeImpl(const char* input, size_t length) { unsigned char* buf = nullptr; int buf_size = ASN1_STRING_to_UTF8(&buf, sp->spkac->challenge); if (buf_size >= 0) { - return DataPointer({ + return { .data = reinterpret_cast(buf), .len = static_cast(buf_size), - }); - } - - return {}; -} -} // namespace - -bool VerifySpkac(const Buffer& input) { - return VerifySpkacImpl(input.data, input.len); -} - -BIOPointer ExportPublicKey(const Buffer& input) { - return ExportPublicKeyImpl(input.data, input.len); -} - -DataPointer ExportChallenge(const Buffer& input) { - return ExportChallengeImpl(input.data, input.len); -} - -bool VerifySpkac(const char* input, size_t length) { - return VerifySpkacImpl(input, length); -} - -BIOPointer ExportPublicKey(const char* input, size_t length) { - return ExportPublicKeyImpl(input, length); -} - -Buffer ExportChallenge(const char* input, size_t length) { - if (auto dp = ExportChallengeImpl(input, length)) { - auto released = dp.release(); - return Buffer{ - .data = static_cast(released.data), - .len = released.len, }; } + return {}; } @@ -660,7 +719,9 @@ bool IsSafeAltName(const char* name, size_t length, AltNameOption option) { return true; } -void PrintAltName(const BIOPointer& out, const char* name, size_t length, +void PrintAltName(const BIOPointer& out, + const char* name, + size_t length, AltNameOption option = AltNameOption::NONE, const char* safe_prefix = nullptr) { if (IsSafeAltName(name, length, option)) { @@ -743,15 +804,19 @@ bool PrintGeneralName(const BIOPointer& out, const GENERAL_NAME* gen) { BIO_printf(out.get(), "DirName:"); BIOPointer tmp(BIO_new(BIO_s_mem())); NCRYPTO_ASSERT_TRUE(tmp); - if (X509_NAME_print_ex(tmp.get(), gen->d.dirn, 0, - kX509NameFlagsRFC2253WithinUtf8JSON) < 0) { + if (X509_NAME_print_ex( + tmp.get(), gen->d.dirn, 0, kX509NameFlagsRFC2253WithinUtf8JSON) < + 0) { return false; } char* oline = nullptr; long n_bytes = BIO_get_mem_data(tmp.get(), &oline); // NOLINT(runtime/int) NCRYPTO_ASSERT_TRUE(n_bytes >= 0); - PrintAltName(out, oline, static_cast(n_bytes), - ncrypto::AltNameOption::UTF8, nullptr); + PrintAltName(out, + oline, + static_cast(n_bytes), + ncrypto::AltNameOption::UTF8, + nullptr); } else if (gen->type == GEN_IPADD) { BIO_printf(out.get(), "IP Address:"); const ASN1_OCTET_STRING* ip = gen->d.ip; @@ -814,12 +879,18 @@ bool PrintGeneralName(const BIOPointer& out, const GENERAL_NAME* gen) { BIO_printf(out.get(), "othername:"); if (unicode) { auto name = gen->d.otherName->value->value.utf8string; - PrintAltName(out, reinterpret_cast(name->data), - name->length, AltNameOption::UTF8, prefix); + PrintAltName(out, + reinterpret_cast(name->data), + name->length, + AltNameOption::UTF8, + prefix); } else { auto name = gen->d.otherName->value->value.ia5string; - PrintAltName(out, reinterpret_cast(name->data), - name->length, AltNameOption::NONE, prefix); + PrintAltName(out, + reinterpret_cast(name->data), + name->length, + AltNameOption::NONE, + prefix); } } } else if (gen->type == GEN_X400) { @@ -906,13 +977,21 @@ X509Pointer& X509Pointer::operator=(X509Pointer&& other) noexcept { return *new (this) X509Pointer(std::move(other)); } -X509Pointer::~X509Pointer() { reset(); } +X509Pointer::~X509Pointer() { + reset(); +} -void X509Pointer::reset(X509* x509) { cert_.reset(x509); } +void X509Pointer::reset(X509* x509) { + cert_.reset(x509); +} -X509* X509Pointer::release() { return cert_.release(); } +X509* X509Pointer::release() { + return cert_.release(); +} -X509View X509Pointer::view() const { return X509View(cert_.get()); } +X509View X509Pointer::view() const { + return X509View(cert_.get()); +} BIOPointer X509View::toPEM() const { ClearErrorOnReturn clearErrorOnReturn; @@ -949,7 +1028,9 @@ BIOPointer X509View::getSubject() const { if (cert_ == nullptr) return {}; BIOPointer bio(BIO_new(BIO_s_mem())); if (!bio) return {}; - if (X509_NAME_print_ex(bio.get(), X509_get_subject_name(cert_), 0, + if (X509_NAME_print_ex(bio.get(), + X509_get_subject_name(cert_), + 0, kX509NameFlagsMultiline) <= 0) { return {}; } @@ -974,8 +1055,9 @@ BIOPointer X509View::getIssuer() const { if (cert_ == nullptr) return {}; BIOPointer bio(BIO_new(BIO_s_mem())); if (!bio) return {}; - if (X509_NAME_print_ex(bio.get(), X509_get_issuer_name(cert_), 0, - kX509NameFlagsMultiline) <= 0) { + if (X509_NAME_print_ex( + bio.get(), X509_get_issuer_name(cert_), 0, kX509NameFlagsMultiline) <= + 0) { return {}; } return bio; @@ -1014,7 +1096,6 @@ BIOPointer X509View::getValidTo() const { int64_t X509View::getValidToTime() const { #ifdef OPENSSL_IS_BORINGSSL -#ifndef NCRYPTO_NO_ASN1_TIME // Boringssl does not implement ASN1_TIME_to_tm in a public way, // and only recently added ASN1_TIME_to_posix. Some boringssl // users on older version may still need to patch around this @@ -1023,11 +1104,6 @@ int64_t X509View::getValidToTime() const { ASN1_TIME_to_posix(X509_get0_notAfter(cert_), &tp); return tp; #else - // Older versions of Boringssl do not implement the ASN1_TIME_to_* - // version functions. For now, neither shall we. - return 0LL; -#endif // NCRYPTO_NO_ASN1_TIME -#else // OPENSSL_IS_BORINGSSL struct tm tp; ASN1_TIME_to_tm(X509_get0_notAfter(cert_), &tp); return PortableTimeGM(&tp); @@ -1036,15 +1112,9 @@ int64_t X509View::getValidToTime() const { int64_t X509View::getValidFromTime() const { #ifdef OPENSSL_IS_BORINGSSL -#ifndef NCRYPTO_NO_ASN1_TIME int64_t tp; ASN1_TIME_to_posix(X509_get0_notBefore(cert_), &tp); return tp; -#else - // Older versions of Boringssl do not implement the ASN1_TIME_to_* - // version functions. For now, neither shall we. - return 0LL; -#endif // NCRYPTO_NO_ASN1_TIME #else struct tm tp; ASN1_TIME_to_tm(X509_get0_notBefore(cert_), &tp); @@ -1104,13 +1174,14 @@ bool X509View::checkPublicKey(const EVPKeyPointer& pkey) const { return X509_verify(const_cast(cert_), pkey.get()) == 1; } -X509View::CheckMatch X509View::checkHost(const std::string_view host, int flags, +X509View::CheckMatch X509View::checkHost(const std::string_view host, + int flags, DataPointer* peerName) const { ClearErrorOnReturn clearErrorOnReturn; if (cert_ == nullptr) return CheckMatch::NO_MATCH; char* peername; - switch (X509_check_host(const_cast(cert_), host.data(), host.size(), - flags, &peername)) { + switch (X509_check_host( + const_cast(cert_), host.data(), host.size(), flags, &peername)) { case 0: return CheckMatch::NO_MATCH; case 1: { @@ -1131,8 +1202,8 @@ X509View::CheckMatch X509View::checkEmail(const std::string_view email, int flags) const { ClearErrorOnReturn clearErrorOnReturn; if (cert_ == nullptr) return CheckMatch::NO_MATCH; - switch (X509_check_email(const_cast(cert_), email.data(), email.size(), - flags)) { + switch (X509_check_email( + const_cast(cert_), email.data(), email.size(), flags)) { case 0: return CheckMatch::NO_MATCH; case 1: @@ -1173,7 +1244,7 @@ X509View X509View::From(const SSLCtxPointer& ctx) { } std::optional X509View::getFingerprint( - const EVP_MD* method) const { + const Digest& method) const { unsigned int md_size; unsigned char md[EVP_MAX_MD_SIZE]; static constexpr char hex[] = "0123456789ABCDEF"; @@ -1237,16 +1308,10 @@ bool X509View::enumUsages(UsageCallback callback) const { bool X509View::ifRsa(KeyCallback callback) const { if (cert_ == nullptr) return true; - // The const_cast is a bit unfortunate. The X509_get_pubkey API accepts - // a const X509* in newer versions of openssl and boringssl but a non-const - // X509* in older versions. By removing the const if it exists we can - // support both. - EVPKeyPointer pkey(X509_get_pubkey(const_cast(cert_))); - if (!pkey) [[unlikely]] - return true; - auto id = pkey.id(); + OSSL3_CONST EVP_PKEY* pkey = X509_get0_pubkey(cert_); + auto id = EVP_PKEY_id(pkey); if (id == EVP_PKEY_RSA || id == EVP_PKEY_RSA2 || id == EVP_PKEY_RSA_PSS) { - Rsa rsa = pkey; + Rsa rsa(EVP_PKEY_get0_RSA(pkey)); if (!rsa) [[unlikely]] return true; return callback(rsa); @@ -1256,16 +1321,10 @@ bool X509View::ifRsa(KeyCallback callback) const { bool X509View::ifEc(KeyCallback callback) const { if (cert_ == nullptr) return true; - // The const_cast is a bit unfortunate. The X509_get_pubkey API accepts - // a const X509* in newer versions of openssl and boringssl but a non-const - // X509* in older versions. By removing the const if it exists we can - // support both. - EVPKeyPointer pkey(X509_get_pubkey(const_cast(cert_))); - if (!pkey) [[unlikely]] - return true; - auto id = pkey.id(); + OSSL3_CONST EVP_PKEY* pkey = X509_get0_pubkey(cert_); + auto id = EVP_PKEY_id(pkey); if (id == EVP_PKEY_EC) { - Ec ec = pkey; + Ec ec(EVP_PKEY_get0_EC_KEY(pkey)); if (!ec) [[unlikely]] return true; return callback(ec); @@ -1299,9 +1358,9 @@ X509Pointer X509Pointer::PeerFrom(const SSLPointer& ssl) { // When adding or removing errors below, please also update the list in the API // documentation. See the "OpenSSL Error Codes" section of doc/api/errors.md // Also *please* update the respective section in doc/api/tls.md as well -std::string_view X509Pointer::ErrorCode(int32_t err) { // NOLINT(runtime/int) -#define CASE(CODE) \ - case X509_V_ERR_##CODE: \ +const char* X509Pointer::ErrorCode(int32_t err) { // NOLINT(runtime/int) +#define CASE(CODE) \ + case X509_V_ERR_##CODE: \ return #CODE; switch (err) { CASE(UNABLE_TO_GET_ISSUER_CERT) @@ -1337,7 +1396,7 @@ std::string_view X509Pointer::ErrorCode(int32_t err) { // NOLINT(runtime/int) return "UNSPECIFIED"; } -std::optional X509Pointer::ErrorReason(int32_t err) { +std::optional X509Pointer::ErrorReason(int32_t err) { if (err == X509_V_OK) return std::nullopt; return X509_verify_cert_error_string(err); } @@ -1355,18 +1414,26 @@ BIOPointer& BIOPointer::operator=(BIOPointer&& other) noexcept { return *new (this) BIOPointer(std::move(other)); } -BIOPointer::~BIOPointer() { reset(); } +BIOPointer::~BIOPointer() { + reset(); +} -void BIOPointer::reset(BIO* bio) { bio_.reset(bio); } +void BIOPointer::reset(BIO* bio) { + bio_.reset(bio); +} -BIO* BIOPointer::release() { return bio_.release(); } +BIO* BIOPointer::release() { + return bio_.release(); +} bool BIOPointer::resetBio() const { if (!bio_) return 0; return BIO_reset(bio_.get()) == 1; } -BIOPointer BIOPointer::NewMem() { return BIOPointer(BIO_new(BIO_s_mem())); } +BIOPointer BIOPointer::NewMem() { + return BIOPointer(BIO_new(BIO_s_mem())); +} BIOPointer BIOPointer::NewSecMem() { #ifdef OPENSSL_IS_BORINGSSL @@ -1385,9 +1452,8 @@ BIOPointer BIOPointer::New(const void* data, size_t len) { return BIOPointer(BIO_new_mem_buf(data, len)); } -BIOPointer BIOPointer::NewFile(std::string_view filename, - std::string_view mode) { - return BIOPointer(BIO_new_file(filename.data(), mode.data())); +BIOPointer BIOPointer::NewFile(const char* filename, const char* mode) { + return BIOPointer(BIO_new_file(filename, mode)); } BIOPointer BIOPointer::NewFp(FILE* fd, int close_flag) { @@ -1427,15 +1493,21 @@ DHPointer& DHPointer::operator=(DHPointer&& other) noexcept { return *new (this) DHPointer(std::move(other)); } -DHPointer::~DHPointer() { reset(); } +DHPointer::~DHPointer() { + reset(); +} -void DHPointer::reset(DH* dh) { dh_.reset(dh); } +void DHPointer::reset(DH* dh) { + dh_.reset(dh); +} -DH* DHPointer::release() { return dh_.release(); } +DH* DHPointer::release() { + return dh_.release(); +} BignumPointer DHPointer::FindGroup(const std::string_view name, FindGroupOption option) { -#define V(n, p) \ +#define V(n, p) \ if (EqualNoCase(name, n)) return BignumPointer(p(nullptr)); if (option != FindGroupOption::NO_SMALL_PRIMES) { #ifndef OPENSSL_IS_BORINGSSL @@ -1645,8 +1717,8 @@ DataPointer DHPointer::stateless(const EVPKeyPointer& ourKey, if (out_size == 0) return {}; auto out = DataPointer::Alloc(out_size); - if (EVP_PKEY_derive(ctx.get(), reinterpret_cast(out.get()), - &out_size) <= 0) { + if (EVP_PKEY_derive( + ctx.get(), reinterpret_cast(out.get()), &out_size) <= 0) { return {}; } @@ -1663,38 +1735,49 @@ DataPointer DHPointer::stateless(const EVPKeyPointer& ourKey, // ============================================================================ // KDF -const EVP_MD* getDigestByName(const std::string_view name) { +const EVP_MD* getDigestByName(const char* name) { // Historically, "dss1" and "DSS1" were DSA aliases for SHA-1 // exposed through the public API. - if (name == "dss1" || name == "DSS1") [[unlikely]] { + if (strcmp(name, "dss1") == 0 || strcmp(name, "DSS1") == 0) [[unlikely]] { return EVP_sha1(); } - return EVP_get_digestbyname(name.data()); + return EVP_get_digestbyname(name); } -const EVP_CIPHER* getCipherByName(const std::string_view name) { - return EVP_get_cipherbyname(name.data()); +const EVP_CIPHER* getCipherByName(const char* name) { + return EVP_get_cipherbyname(name); } -bool checkHkdfLength(const EVP_MD* md, size_t length) { +bool checkHkdfLength(const Digest& md, size_t length) { // HKDF-Expand computes up to 255 HMAC blocks, each having as many bits as // the output of the hash function. 255 is a hard limit because HKDF appends // an 8-bit counter to each HMAC'd message, starting at 1. static constexpr size_t kMaxDigestMultiplier = 255; - size_t max_length = EVP_MD_size(md) * kMaxDigestMultiplier; + size_t max_length = md.size() * kMaxDigestMultiplier; if (length > max_length) return false; return true; } -bool hkdfInfo(const EVP_MD* md, const Buffer& key, - const Buffer& info, - const Buffer& salt, size_t length, - Buffer* out) { +DataPointer hkdf(const Digest& md, + const Buffer& key, + const Buffer& info, + const Buffer& salt, + size_t length) { ClearErrorOnReturn clearErrorOnReturn; if (!checkHkdfLength(md, length) || info.len > INT_MAX || salt.len > INT_MAX) { - return false; + return {}; + } + + auto ctx = EVPKeyCtxPointer::NewFromID(EVP_PKEY_HKDF); + // OpenSSL < 3.0.0 accepted only a void* as the argument of + // EVP_PKEY_CTX_set_hkdf_md. + const EVP_MD* md_ptr = md; + if (!ctx || !EVP_PKEY_derive_init(ctx.get()) || + !EVP_PKEY_CTX_set_hkdf_md(ctx.get(), md_ptr) || + !EVP_PKEY_CTX_add1_hkdf_info(ctx.get(), info.data, info.len)) { + return {}; } std::string_view actual_salt; @@ -1702,54 +1785,42 @@ bool hkdfInfo(const EVP_MD* md, const Buffer& key, if (salt.len > 0) { actual_salt = {reinterpret_cast(salt.data), salt.len}; } else { - actual_salt = {default_salt, static_cast(EVP_MD_size(md))}; - } - -#ifndef NCRYPTO_NO_KDF_H - auto ctx = EVPKeyCtxPointer::NewFromID(EVP_PKEY_HKDF); - if (!ctx || !EVP_PKEY_derive_init(ctx.get()) || - !EVP_PKEY_CTX_set_hkdf_md(ctx.get(), md) || - !EVP_PKEY_CTX_add1_hkdf_info(ctx.get(), info.data, info.len)) { - return false; + actual_salt = {default_salt, static_cast(md.size())}; } // We do not use EVP_PKEY_HKDF_MODE_EXTRACT_AND_EXPAND because and instead // implement the extraction step ourselves because EVP_PKEY_derive does not // handle zero-length keys, which are required for Web Crypto. // TODO(jasnell): Once OpenSSL 1.1.1 support is dropped completely, and once - // BoringSSL is confirmed to support it, we can hopefully drop this and use + // BoringSSL is confirmed to support it, wen can hopefully drop this and use // EVP_KDF directly which does support zero length keys. unsigned char pseudorandom_key[EVP_MAX_MD_SIZE]; unsigned pseudorandom_key_len = sizeof(pseudorandom_key); - if (HMAC(md, actual_salt.data(), actual_salt.size(), key.data, key.len, - pseudorandom_key, &pseudorandom_key_len) == nullptr) { - return false; + if (HMAC(md, + actual_salt.data(), + actual_salt.size(), + key.data, + key.len, + pseudorandom_key, + &pseudorandom_key_len) == nullptr) { + return {}; } if (!EVP_PKEY_CTX_hkdf_mode(ctx.get(), EVP_PKEY_HKDEF_MODE_EXPAND_ONLY) || - !EVP_PKEY_CTX_set1_hkdf_key(ctx.get(), pseudorandom_key, - pseudorandom_key_len)) { - return false; + !EVP_PKEY_CTX_set1_hkdf_key( + ctx.get(), pseudorandom_key, pseudorandom_key_len)) { + return {}; } - if (out == nullptr || out->len != length) return false; - - return EVP_PKEY_derive(ctx.get(), out->data, &length) > 0; -#else - return HKDF(out->data, length, md, key.data, key.len, salt.data, salt.len, - info.data, info.len); -#endif -} - -DataPointer hkdf(const EVP_MD* md, const Buffer& key, - const Buffer& info, - const Buffer& salt, size_t length) { auto buf = DataPointer::Alloc(length); if (!buf) return {}; - Buffer out = buf; - return hkdfInfo(md, key, info, salt, length, &out) ? std::move(buf) - : DataPointer(); + if (EVP_PKEY_derive( + ctx.get(), static_cast(buf.get()), &length) <= 0) { + return {}; + } + + return buf; } bool checkScryptParams(uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem) { @@ -1757,74 +1828,165 @@ bool checkScryptParams(uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem) { 1; } -bool scryptInto(const Buffer& pass, - const Buffer& salt, uint64_t N, uint64_t r, - uint64_t p, uint64_t maxmem, size_t length, - Buffer* out) { +DataPointer scrypt(const Buffer& pass, + const Buffer& salt, + uint64_t N, + uint64_t r, + uint64_t p, + uint64_t maxmem, + size_t length) { ClearErrorOnReturn clearErrorOnReturn; - if (pass.len > INT_MAX || salt.len > INT_MAX || out == nullptr) { - return false; + if (pass.len > INT_MAX || salt.len > INT_MAX) { + return {}; } - if (auto dp = DataPointer::Alloc(length)) { - return EVP_PBE_scrypt(pass.data, pass.len, salt.data, salt.len, N, r, p, - maxmem, out->data, length); + auto dp = DataPointer::Alloc(length); + if (dp && EVP_PBE_scrypt(pass.data, + pass.len, + salt.data, + salt.len, + N, + r, + p, + maxmem, + reinterpret_cast(dp.get()), + length)) { + return dp; } - return false; + return {}; } -DataPointer scrypt(const Buffer& pass, - const Buffer& salt, uint64_t N, - uint64_t r, uint64_t p, uint64_t maxmem, size_t length) { - if (auto dp = DataPointer::Alloc(length)) { - Buffer buf = dp; - if (scryptInto(pass, salt, N, r, p, maxmem, length, &buf)) { - return dp; - } +DataPointer pbkdf2(const Digest& md, + const Buffer& pass, + const Buffer& salt, + uint32_t iterations, + size_t length) { + ClearErrorOnReturn clearErrorOnReturn; + + if (pass.len > INT_MAX || salt.len > INT_MAX || length > INT_MAX) { + return {}; + } + + auto dp = DataPointer::Alloc(length); + const EVP_MD* md_ptr = md; + if (dp && PKCS5_PBKDF2_HMAC(pass.data, + pass.len, + salt.data, + salt.len, + iterations, + md_ptr, + length, + reinterpret_cast(dp.get()))) { + return dp; } return {}; } -bool pbkdf2Into(const EVP_MD* md, const Buffer& pass, - const Buffer& salt, uint32_t iterations, - size_t length, Buffer* out) { +#if OPENSSL_VERSION_NUMBER >= 0x30200000L +#ifndef OPENSSL_NO_ARGON2 +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) { ClearErrorOnReturn clearErrorOnReturn; - if (pass.len > INT_MAX || salt.len > INT_MAX || length > INT_MAX || - out == nullptr) { - return false; + std::string_view algorithm; + switch (type) { + case Argon2Type::ARGON2I: + algorithm = "ARGON2I"; + break; + case Argon2Type::ARGON2D: + algorithm = "ARGON2D"; + break; + case Argon2Type::ARGON2ID: + algorithm = "ARGON2ID"; + break; + default: + // Invalid Argon2 type + return {}; } - if (PKCS5_PBKDF2_HMAC(pass.data, pass.len, salt.data, salt.len, iterations, - md, length, out->data)) { - return true; + // creates a new library context to avoid locking when running concurrently + auto ctx = DeleteFnPtr{OSSL_LIB_CTX_new()}; + if (!ctx) { + return {}; } - return false; -} + // required if threads > 1 + if (lanes > 1 && OSSL_set_max_threads(ctx.get(), lanes) != 1) { + return {}; + } -DataPointer pbkdf2(const EVP_MD* md, const Buffer& pass, - const Buffer& salt, uint32_t iterations, - size_t length) { - if (auto dp = DataPointer::Alloc(length)) { - Buffer buf = dp; - if (pbkdf2Into(md, pass, salt, iterations, length, &buf)) { - return dp; - } + auto kdf = DeleteFnPtr{ + EVP_KDF_fetch(ctx.get(), algorithm.data(), nullptr)}; + if (!kdf) { + return {}; + } + + auto kctx = + DeleteFnPtr{EVP_KDF_CTX_new(kdf.get())}; + if (!kctx) { + return {}; + } + + std::vector params; + params.reserve(9); + + params.push_back(OSSL_PARAM_construct_octet_string( + OSSL_KDF_PARAM_PASSWORD, + const_cast(pass.len > 0 ? pass.data : ""), + pass.len)); + params.push_back(OSSL_PARAM_construct_octet_string( + OSSL_KDF_PARAM_SALT, const_cast(salt.data), salt.len)); + params.push_back(OSSL_PARAM_construct_uint32(OSSL_KDF_PARAM_THREADS, &lanes)); + params.push_back( + OSSL_PARAM_construct_uint32(OSSL_KDF_PARAM_ARGON2_LANES, &lanes)); + params.push_back( + OSSL_PARAM_construct_uint32(OSSL_KDF_PARAM_ARGON2_MEMCOST, &memcost)); + params.push_back(OSSL_PARAM_construct_uint32(OSSL_KDF_PARAM_ITER, &iter)); + + if (ad.len != 0) { + params.push_back(OSSL_PARAM_construct_octet_string( + OSSL_KDF_PARAM_ARGON2_AD, const_cast(ad.data), ad.len)); + } + + if (secret.len != 0) { + params.push_back(OSSL_PARAM_construct_octet_string( + OSSL_KDF_PARAM_SECRET, + const_cast(secret.data), + secret.len)); + } + + params.push_back(OSSL_PARAM_construct_end()); + + auto dp = DataPointer::Alloc(length); + if (dp && EVP_KDF_derive(kctx.get(), + reinterpret_cast(dp.get()), + length, + params.data()) == 1) { + return dp; } return {}; } +#endif +#endif // ============================================================================ EVPKeyPointer::PrivateKeyEncodingConfig::PrivateKeyEncodingConfig( const PrivateKeyEncodingConfig& other) - : PrivateKeyEncodingConfig(other.output_key_object, other.format, - other.type) { + : PrivateKeyEncodingConfig( + other.output_key_object, other.format, other.type) { cipher = other.cipher; if (other.passphrase.has_value()) { auto& otherPassphrase = other.passphrase.value(); @@ -1846,7 +2008,9 @@ EVPKeyPointer::PrivateKeyEncodingConfig::operator=( return *new (this) PrivateKeyEncodingConfig(other); } -EVPKeyPointer EVPKeyPointer::New() { return EVPKeyPointer(EVP_PKEY_new()); } +EVPKeyPointer EVPKeyPointer::New() { + return EVPKeyPointer(EVP_PKEY_new()); +} EVPKeyPointer EVPKeyPointer::NewRawPublic( int id, const Buffer& data) { @@ -1862,8 +2026,32 @@ EVPKeyPointer EVPKeyPointer::NewRawPrivate( EVP_PKEY_new_raw_private_key(id, nullptr, data.data, data.len)); } +#if OPENSSL_WITH_PQC +EVPKeyPointer EVPKeyPointer::NewRawSeed( + int id, const Buffer& data) { + if (id == 0) return {}; + + OSSL_PARAM params[] = { + OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_ML_DSA_SEED, + const_cast(data.data), + data.len), + OSSL_PARAM_END}; + + EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new_id(id, nullptr); + if (ctx == nullptr) return {}; + + EVP_PKEY* pkey = nullptr; + if (ctx == nullptr || EVP_PKEY_fromdata_init(ctx) <= 0 || + EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_KEYPAIR, params) <= 0) { + EVP_PKEY_CTX_free(ctx); + return {}; + } + + return EVPKeyPointer(pkey); +} +#endif + EVPKeyPointer EVPKeyPointer::NewDH(DHPointer&& dh) { -#ifndef NCRYPTO_NO_EVP_DH if (!dh) return {}; auto key = New(); if (!key) return {}; @@ -1871,11 +2059,6 @@ EVPKeyPointer EVPKeyPointer::NewDH(DHPointer&& dh) { dh.release(); } return key; -#else - // Older versions of openssl/boringssl do not implement the EVP_PKEY_*_DH - // APIs - return {}; -#endif } EVPKeyPointer EVPKeyPointer::NewRSA(RSAPointer&& rsa) { @@ -1893,27 +2076,46 @@ EVPKeyPointer::EVPKeyPointer(EVP_PKEY* pkey) : pkey_(pkey) {} EVPKeyPointer::EVPKeyPointer(EVPKeyPointer&& other) noexcept : pkey_(other.release()) {} -EVPKeyPointer EVPKeyPointer::clone() const { - if (!pkey_) return {}; - if (!EVP_PKEY_up_ref(pkey_.get())) return {}; - return EVPKeyPointer(pkey_.get()); -} - EVPKeyPointer& EVPKeyPointer::operator=(EVPKeyPointer&& other) noexcept { if (this == &other) return *this; this->~EVPKeyPointer(); return *new (this) EVPKeyPointer(std::move(other)); } -EVPKeyPointer::~EVPKeyPointer() { reset(); } +EVPKeyPointer::~EVPKeyPointer() { + reset(); +} -void EVPKeyPointer::reset(EVP_PKEY* pkey) { pkey_.reset(pkey); } +void EVPKeyPointer::reset(EVP_PKEY* pkey) { + pkey_.reset(pkey); +} -EVP_PKEY* EVPKeyPointer::release() { return pkey_.release(); } +EVP_PKEY* EVPKeyPointer::release() { + return pkey_.release(); +} int EVPKeyPointer::id(const EVP_PKEY* key) { if (key == nullptr) return 0; - return EVP_PKEY_id(key); + int type = EVP_PKEY_id(key); +#if OPENSSL_WITH_PQC + // EVP_PKEY_id returns -1 when EVP_PKEY_* is only implemented in a provider + // which is the case for all post-quantum NIST algorithms + // one suggested way would be to use a chain of `EVP_PKEY_is_a` + // https://github.com/openssl/openssl/issues/27738#issuecomment-3013215870 + // or, this way there are less calls to the OpenSSL provider, just + // getting the name once + if (type == -1) { + const char* type_name = EVP_PKEY_get0_type_name(key); + if (type_name == nullptr) return -1; + + for (const auto& mapping : pqc_mappings) { + if (strcmp(type_name, mapping.name) == 0) { + return mapping.nid; + } + } + } +#endif + return type; } int EVPKeyPointer::base_id(const EVP_PKEY* key) { @@ -1921,9 +2123,13 @@ int EVPKeyPointer::base_id(const EVP_PKEY* key) { return EVP_PKEY_base_id(key); } -int EVPKeyPointer::id() const { return id(get()); } +int EVPKeyPointer::id() const { + return id(get()); +} -int EVPKeyPointer::base_id() const { return base_id(get()); } +int EVPKeyPointer::base_id() const { + return base_id(get()); +} int EVPKeyPointer::bits() const { if (get() == nullptr) return 0; @@ -1965,6 +2171,44 @@ DataPointer EVPKeyPointer::rawPublicKey() const { return {}; } +#if OPENSSL_WITH_PQC +DataPointer EVPKeyPointer::rawSeed() const { + if (!pkey_) return {}; + + // Determine seed length and parameter name based on key type + size_t seed_len; + const char* param_name; + + switch (id()) { + case EVP_PKEY_ML_DSA_44: + case EVP_PKEY_ML_DSA_65: + case EVP_PKEY_ML_DSA_87: + seed_len = 32; // ML-DSA uses 32-byte seeds + param_name = OSSL_PKEY_PARAM_ML_DSA_SEED; + break; + case EVP_PKEY_ML_KEM_512: + case EVP_PKEY_ML_KEM_768: + case EVP_PKEY_ML_KEM_1024: + seed_len = 64; // ML-KEM uses 64-byte seeds + param_name = OSSL_PKEY_PARAM_ML_KEM_SEED; + break; + default: + unreachable(); + } + + if (auto data = DataPointer::Alloc(seed_len)) { + const Buffer buf = data; + size_t len = data.size(); + + if (EVP_PKEY_get_octet_string_param( + get(), param_name, buf.data, len, &seed_len) != 1) + return {}; + return data; + } + return {}; +} +#endif + DataPointer EVPKeyPointer::rawPrivateKey() const { if (!pkey_) return {}; if (auto data = DataPointer::Alloc(rawPrivateKeySize())) { @@ -2012,8 +2256,9 @@ EVPKeyPointer::ParseKeyResult TryParsePublicKeyInner(const BIOPointer& bp, // This skips surrounding data and decodes PEM to DER. { MarkPopErrorOnReturn mark_pop_error_on_return; - if (PEM_bytes_read_bio(&der_data, &der_len, nullptr, name, bp.get(), - nullptr, nullptr) != 1) + if (PEM_bytes_read_bio( + &der_data, &der_len, nullptr, name, bp.get(), nullptr, nullptr) != + 1) return EVPKeyPointer::ParseKeyResult( EVPKeyPointer::PKParseError::NOT_RECOGNIZED); } @@ -2027,8 +2272,10 @@ EVPKeyPointer::ParseKeyResult TryParsePublicKeyInner(const BIOPointer& bp, return EVPKeyPointer::ParseKeyResult(std::move(pkey)); } -constexpr bool IsASN1Sequence(const unsigned char* data, size_t size, - size_t* data_offset, size_t* data_size) { +constexpr bool IsASN1Sequence(const unsigned char* data, + size_t size, + size_t* data_offset, + size_t* data_size) { if (size < 2 || data[0] != 0x30) return false; if (data[1] & 0x80) { @@ -2083,7 +2330,8 @@ EVPKeyPointer::ParseKeyResult EVPKeyPointer::TryParsePublicKeyPEM( // Try parsing as SubjectPublicKeyInfo (SPKI) first. if (auto ret = TryParsePublicKeyInner( - bp, "PUBLIC KEY", + bp, + "PUBLIC KEY", [](const unsigned char** p, long l) { // NOLINT(runtime/int) return d2i_PUBKEY(nullptr, p, l); })) { @@ -2092,7 +2340,8 @@ EVPKeyPointer::ParseKeyResult EVPKeyPointer::TryParsePublicKeyPEM( // Maybe it is PKCS#1. if (auto ret = TryParsePublicKeyInner( - bp, "RSA PUBLIC KEY", + bp, + "RSA PUBLIC KEY", [](const unsigned char** p, long l) { // NOLINT(runtime/int) return d2i_PublicKey(EVP_PKEY_RSA, nullptr, p, l); })) { @@ -2101,7 +2350,8 @@ EVPKeyPointer::ParseKeyResult EVPKeyPointer::TryParsePublicKeyPEM( // X.509 fallback. if (auto ret = TryParsePublicKeyInner( - bp, "CERTIFICATE", + bp, + "CERTIFICATE", [](const unsigned char** p, long l) { // NOLINT(runtime/int) X509Pointer x509(d2i_X509(nullptr, p, l)); return x509 ? X509_get_pubkey(x509.get()) : nullptr; @@ -2174,7 +2424,6 @@ EVPKeyPointer::ParseKeyResult EVPKeyPointer::TryParsePrivateKey( ERR_GET_REASON(err) == PEM_R_BAD_PASSWORD_READ && !had_passphrase) { return ParseKeyResult(PKParseError::NEED_PASSPHRASE); } - return ParseKeyResult(PKParseError::FAILED, err); } if (!pkey) return ParseKeyResult(PKParseError::FAILED); @@ -2188,7 +2437,9 @@ EVPKeyPointer::ParseKeyResult EVPKeyPointer::TryParsePrivateKey( if (config.format == PKFormatType::PEM) { auto key = PEM_read_bio_PrivateKey( - bio.get(), nullptr, PasswordCallback, + bio.get(), + nullptr, + PasswordCallback, config.passphrase.has_value() ? &passphrase : nullptr); return keyOrError(EVPKeyPointer(key), config.passphrase.has_value()); } @@ -2205,7 +2456,9 @@ EVPKeyPointer::ParseKeyResult EVPKeyPointer::TryParsePrivateKey( case PKEncodingType::PKCS8: { if (IsEncryptedPrivateKeyInfo(buffer)) { auto key = d2i_PKCS8PrivateKey_bio( - bio.get(), nullptr, PasswordCallback, + bio.get(), + nullptr, + PasswordCallback, config.passphrase.has_value() ? &passphrase : nullptr); return keyOrError(EVPKeyPointer(key), config.passphrase.has_value()); } @@ -2246,14 +2499,21 @@ Result EVPKeyPointer::writePrivateKey( // PKCS1 is only permitted for RSA keys. if (id() != EVP_PKEY_RSA) return Result(false); - OSSL3_CONST RSA* rsa = EVP_PKEY_get0_RSA(get()); - +#if OPENSSL_VERSION_MAJOR >= 3 + const RSA* rsa = EVP_PKEY_get0_RSA(get()); +#else + RSA* rsa = EVP_PKEY_get0_RSA(get()); +#endif switch (config.format) { case PKFormatType::PEM: { err = PEM_write_bio_RSAPrivateKey( - bio.get(), rsa, config.cipher, + bio.get(), + rsa, + config.cipher, reinterpret_cast(passphrase.data), - passphrase.len, nullptr, nullptr) != 1; + passphrase.len, + nullptr, + nullptr) != 1; break; } case PKFormatType::DER: { @@ -2272,15 +2532,23 @@ Result EVPKeyPointer::writePrivateKey( switch (config.format) { case PKFormatType::PEM: { // Encode PKCS#8 as PEM. - err = PEM_write_bio_PKCS8PrivateKey(bio.get(), get(), config.cipher, - passphrase.data, passphrase.len, - nullptr, nullptr) != 1; + err = PEM_write_bio_PKCS8PrivateKey(bio.get(), + get(), + config.cipher, + passphrase.data, + passphrase.len, + nullptr, + nullptr) != 1; break; } case PKFormatType::DER: { - err = i2d_PKCS8PrivateKey_bio(bio.get(), get(), config.cipher, - passphrase.data, passphrase.len, - nullptr, nullptr) != 1; + err = i2d_PKCS8PrivateKey_bio(bio.get(), + get(), + config.cipher, + passphrase.data, + passphrase.len, + nullptr, + nullptr) != 1; break; } default: { @@ -2294,14 +2562,21 @@ Result EVPKeyPointer::writePrivateKey( // SEC1 is only permitted for EC keys if (id() != EVP_PKEY_EC) return Result(false); - OSSL3_CONST EC_KEY* ec = EVP_PKEY_get0_EC_KEY(get()); - +#if OPENSSL_VERSION_MAJOR >= 3 + const EC_KEY* ec = EVP_PKEY_get0_EC_KEY(get()); +#else + EC_KEY* ec = EVP_PKEY_get0_EC_KEY(get()); +#endif switch (config.format) { case PKFormatType::PEM: { err = PEM_write_bio_ECPrivateKey( - bio.get(), ec, config.cipher, + bio.get(), + ec, + config.cipher, reinterpret_cast(passphrase.data), - passphrase.len, nullptr, nullptr) != 1; + passphrase.len, + nullptr, + nullptr) != 1; break; } case PKFormatType::DER: { @@ -2389,7 +2664,30 @@ bool EVPKeyPointer::isRsaVariant() const { bool EVPKeyPointer::isOneShotVariant() const { if (!pkey_) return false; int type = id(); - return type == EVP_PKEY_ED25519 || type == EVP_PKEY_ED448; + switch (type) { + case EVP_PKEY_ED25519: + case EVP_PKEY_ED448: +#if OPENSSL_WITH_PQC + case EVP_PKEY_ML_DSA_44: + case EVP_PKEY_ML_DSA_65: + case EVP_PKEY_ML_DSA_87: + case EVP_PKEY_SLH_DSA_SHA2_128F: + case EVP_PKEY_SLH_DSA_SHA2_128S: + case EVP_PKEY_SLH_DSA_SHA2_192F: + case EVP_PKEY_SLH_DSA_SHA2_192S: + case EVP_PKEY_SLH_DSA_SHA2_256F: + case EVP_PKEY_SLH_DSA_SHA2_256S: + case EVP_PKEY_SLH_DSA_SHAKE_128F: + case EVP_PKEY_SLH_DSA_SHAKE_128S: + case EVP_PKEY_SLH_DSA_SHAKE_192F: + case EVP_PKEY_SLH_DSA_SHAKE_192S: + case EVP_PKEY_SLH_DSA_SHAKE_256F: + case EVP_PKEY_SLH_DSA_SHAKE_256S: +#endif + return true; + default: + return false; + } } bool EVPKeyPointer::isSigVariant() const { @@ -2444,15 +2742,6 @@ EVPKeyPointer::operator Dsa() const { return Dsa(dsa); } -EVPKeyPointer::operator Ec() const { - int type = id(); - if (type != EVP_PKEY_EC) return {}; - - OSSL3_CONST EC_KEY* ec = EVP_PKEY_get0_EC_KEY(get()); - if (ec == nullptr) return {}; - return Ec(ec); -} - bool EVPKeyPointer::validateDsaParameters() const { if (!pkey_) return false; /* Validate DSA2 parameters from FIPS 186-4 */ @@ -2487,19 +2776,24 @@ SSLPointer& SSLPointer::operator=(SSLPointer&& other) noexcept { return *new (this) SSLPointer(std::move(other)); } -SSLPointer::~SSLPointer() { reset(); } +SSLPointer::~SSLPointer() { + reset(); +} -void SSLPointer::reset(SSL* ssl) { ssl_.reset(ssl); } +void SSLPointer::reset(SSL* ssl) { + ssl_.reset(ssl); +} -SSL* SSLPointer::release() { return ssl_.release(); } +SSL* SSLPointer::release() { + return ssl_.release(); +} SSLPointer SSLPointer::New(const SSLCtxPointer& ctx) { if (!ctx) return {}; return SSLPointer(SSL_new(ctx.get())); } -void SSLPointer::getCiphers( - std::function cb) const { +void SSLPointer::getCiphers(std::function cb) const { if (!ssl_) return; STACK_OF(SSL_CIPHER)* ciphers = SSL_get_ciphers(get()); @@ -2508,8 +2802,10 @@ void SSLPointer::getCiphers( // and not have to explain their absence in the API docs. They are lower-cased // because the docs say they will be. static constexpr const char* TLS13_CIPHERS[] = { - "tls_aes_256_gcm_sha384", "tls_chacha20_poly1305_sha256", - "tls_aes_128_gcm_sha256", "tls_aes_128_ccm_8_sha256", + "tls_aes_256_gcm_sha384", + "tls_chacha20_poly1305_sha256", + "tls_aes_128_gcm_sha256", + "tls_aes_128_ccm_8_sha256", "tls_aes_128_ccm_sha256"}; const int n = sk_SSL_CIPHER_num(ciphers); @@ -2562,7 +2858,7 @@ std::optional SSLPointer::verifyPeerCertificate() const { return std::nullopt; } -const std::string_view SSLPointer::getClientHelloAlpn() const { +const char* SSLPointer::getClientHelloAlpn() const { if (ssl_ == nullptr) return {}; #ifndef OPENSSL_IS_BORINGSSL const unsigned char* buf; @@ -2570,7 +2866,9 @@ const std::string_view SSLPointer::getClientHelloAlpn() const { size_t rem; if (!SSL_client_hello_get0_ext( - get(), TLSEXT_TYPE_application_layer_protocol_negotiation, &buf, + get(), + TLSEXT_TYPE_application_layer_protocol_negotiation, + &buf, &rem) || rem < 2) { return {}; @@ -2585,7 +2883,7 @@ const std::string_view SSLPointer::getClientHelloAlpn() const { #endif } -const std::string_view SSLPointer::getClientHelloServerName() const { +const char* SSLPointer::getClientHelloServerName() const { if (ssl_ == nullptr) return {}; #ifndef OPENSSL_IS_BORINGSSL const unsigned char* buf; @@ -2637,7 +2935,9 @@ const SSL_CIPHER* SSLPointer::getCipher() const { return SSL_get_current_cipher(get()); } -bool SSLPointer::isServer() const { return SSL_is_server(get()) != 0; } +bool SSLPointer::isServer() const { + return SSL_is_server(get()) != 0; +} EVPKeyPointer SSLPointer::getPeerTempKey() const { if (!ssl_) return {}; @@ -2668,6 +2968,22 @@ std::optional SSLPointer::getCipherVersion() const { return SSL_CIPHER_get_version(cipher); } +std::optional SSLPointer::getSecurityLevel() { +#ifndef OPENSSL_IS_BORINGSSL + auto ctx = SSLCtxPointer::New(); + if (!ctx) return std::nullopt; + + auto ssl = SSLPointer::New(ctx); + if (!ssl) return std::nullopt; + + return SSL_get_security_level(ssl); +#else + // OPENSSL_TLS_SECURITY_LEVEL is not defined in BoringSSL + // so assume it is the default OPENSSL_TLS_SECURITY_LEVEL value. + return 1; +#endif // OPENSSL_IS_BORINGSSL +} + SSLCtxPointer::SSLCtxPointer(SSL_CTX* ctx) : ctx_(ctx) {} SSLCtxPointer::SSLCtxPointer(SSLCtxPointer&& other) noexcept @@ -2679,15 +2995,21 @@ SSLCtxPointer& SSLCtxPointer::operator=(SSLCtxPointer&& other) noexcept { return *new (this) SSLCtxPointer(std::move(other)); } -SSLCtxPointer::~SSLCtxPointer() { reset(); } +SSLCtxPointer::~SSLCtxPointer() { + reset(); +} -void SSLCtxPointer::reset(SSL_CTX* ctx) { ctx_.reset(ctx); } +void SSLCtxPointer::reset(SSL_CTX* ctx) { + ctx_.reset(ctx); +} void SSLCtxPointer::reset(const SSL_METHOD* method) { ctx_.reset(SSL_CTX_new(method)); } -SSL_CTX* SSLCtxPointer::release() { return ctx_.release(); } +SSL_CTX* SSLCtxPointer::release() { + return ctx_.release(); +} SSLCtxPointer SSLCtxPointer::NewServer() { return SSLCtxPointer(SSL_CTX_new(TLS_server_method())); @@ -2702,19 +3024,24 @@ SSLCtxPointer SSLCtxPointer::New(const SSL_METHOD* method) { } bool SSLCtxPointer::setGroups(const char* groups) { -#ifndef NCRYPTO_NO_SSL_GROUP_LIST return SSL_CTX_set1_groups_list(get(), groups) == 1; +} + +bool SSLCtxPointer::setCipherSuites(const char* ciphers) { +#ifndef OPENSSL_IS_BORINGSSL + if (!ctx_) return false; + return SSL_CTX_set_ciphersuites(ctx_.get(), ciphers); #else - // Older versions of openssl/boringssl do not implement the - // SSL_CTX_set1_groups_list API - return false; + // BoringSSL does not allow API config of TLS 1.3 cipher suites. + // We treat this as a non-op. + return true; #endif } // ============================================================================ -const Cipher Cipher::FromName(std::string_view name) { - return Cipher(EVP_get_cipherbyname(name.data())); +const Cipher Cipher::FromName(const char* name) { + return Cipher(EVP_get_cipherbyname(name)); } const Cipher Cipher::FromNid(int nid) { @@ -2725,6 +3052,59 @@ const Cipher Cipher::FromCtx(const CipherCtxPointer& ctx) { return Cipher(EVP_CIPHER_CTX_cipher(ctx.get())); } +const Cipher Cipher::EMPTY = Cipher(); +const Cipher Cipher::AES_128_CBC = Cipher::FromNid(NID_aes_128_cbc); +const Cipher Cipher::AES_192_CBC = Cipher::FromNid(NID_aes_192_cbc); +const Cipher Cipher::AES_256_CBC = Cipher::FromNid(NID_aes_256_cbc); +const Cipher Cipher::AES_128_CTR = Cipher::FromNid(NID_aes_128_ctr); +const Cipher Cipher::AES_192_CTR = Cipher::FromNid(NID_aes_192_ctr); +const Cipher Cipher::AES_256_CTR = Cipher::FromNid(NID_aes_256_ctr); +const Cipher Cipher::AES_128_GCM = Cipher::FromNid(NID_aes_128_gcm); +const Cipher Cipher::AES_192_GCM = Cipher::FromNid(NID_aes_192_gcm); +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); +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); +const Cipher Cipher::CHACHA20_POLY1305 = Cipher::FromNid(NID_chacha20_poly1305); + +bool Cipher::isGcmMode() const { + if (!cipher_) return false; + return getMode() == EVP_CIPH_GCM_MODE; +} + +bool Cipher::isWrapMode() const { + if (!cipher_) return false; + return getMode() == EVP_CIPH_WRAP_MODE; +} + +bool Cipher::isCtrMode() const { + if (!cipher_) return false; + return getMode() == EVP_CIPH_CTR_MODE; +} + +bool Cipher::isCcmMode() const { + if (!cipher_) return false; + return getMode() == EVP_CIPH_CCM_MODE; +} + +bool Cipher::isOcbMode() const { + if (!cipher_) return false; + return getMode() == EVP_CIPH_OCB_MODE; +} + +bool Cipher::isStreamMode() const { + if (!cipher_) return false; + return getMode() == EVP_CIPH_STREAM_CIPHER; +} + +bool Cipher::isChaCha20Poly1305() const { + if (!cipher_) return false; + return getNid() == NID_chacha20_poly1305; +} + int Cipher::getMode() const { if (!cipher_) return 0; return EVP_CIPHER_mode(cipher_); @@ -2779,7 +3159,7 @@ std::string_view Cipher::getModeLabel() const { return "{unknown}"; } -std::string_view Cipher::getName() const { +const char* Cipher::getName() const { if (!cipher_) return {}; // OBJ_nid2sn(EVP_CIPHER_nid(cipher)) is used here instead of // EVP_CIPHER_name(cipher) for compatibility with BoringSSL. @@ -2801,6 +3181,14 @@ bool Cipher::isSupportedAuthenticatedMode() const { } } +int Cipher::bytesToKey(const Digest& digest, + const Buffer& input, + unsigned char* key, + unsigned char* iv) const { + return EVP_BytesToKey( + *this, Digest::MD5, nullptr, input.data, input.len, 1, key, iv); +} + // ============================================================================ CipherCtxPointer CipherCtxPointer::New() { @@ -2822,15 +3210,21 @@ CipherCtxPointer& CipherCtxPointer::operator=( return *new (this) CipherCtxPointer(std::move(other)); } -CipherCtxPointer::~CipherCtxPointer() { reset(); } +CipherCtxPointer::~CipherCtxPointer() { + reset(); +} -void CipherCtxPointer::reset(EVP_CIPHER_CTX* ctx) { ctx_.reset(ctx); } +void CipherCtxPointer::reset(EVP_CIPHER_CTX* ctx) { + ctx_.reset(ctx); +} -EVP_CIPHER_CTX* CipherCtxPointer::release() { return ctx_.release(); } +EVP_CIPHER_CTX* CipherCtxPointer::release() { + return ctx_.release(); +} -void CipherCtxPointer::setFlags(int flags) { +void CipherCtxPointer::setAllowWrap() { if (!ctx_) return; - EVP_CIPHER_CTX_set_flags(ctx_.get(), flags); + EVP_CIPHER_CTX_set_flags(ctx_.get(), EVP_CIPHER_CTX_FLAG_WRAP_ALLOW); } bool CipherCtxPointer::setKeyLength(size_t length) { @@ -2840,20 +3234,20 @@ bool CipherCtxPointer::setKeyLength(size_t length) { bool CipherCtxPointer::setIvLength(size_t length) { if (!ctx_) return false; - return EVP_CIPHER_CTX_ctrl(ctx_.get(), EVP_CTRL_AEAD_SET_IVLEN, length, - nullptr); + return EVP_CIPHER_CTX_ctrl( + ctx_.get(), EVP_CTRL_AEAD_SET_IVLEN, length, nullptr); } bool CipherCtxPointer::setAeadTag(const Buffer& tag) { if (!ctx_) return false; - return EVP_CIPHER_CTX_ctrl(ctx_.get(), EVP_CTRL_AEAD_SET_TAG, tag.len, - const_cast(tag.data)); + return EVP_CIPHER_CTX_ctrl( + ctx_.get(), EVP_CTRL_AEAD_SET_TAG, tag.len, const_cast(tag.data)); } bool CipherCtxPointer::setAeadTagLength(size_t length) { if (!ctx_) return false; - return EVP_CIPHER_CTX_ctrl(ctx_.get(), EVP_CTRL_AEAD_SET_TAG, length, - nullptr); + return EVP_CIPHER_CTX_ctrl( + ctx_.get(), EVP_CTRL_AEAD_SET_TAG, length, nullptr); } bool CipherCtxPointer::setPadding(bool padding) { @@ -2871,20 +3265,49 @@ int CipherCtxPointer::getMode() const { return EVP_CIPHER_CTX_mode(ctx_.get()); } +bool CipherCtxPointer::isGcmMode() const { + if (!ctx_) return false; + return getMode() == EVP_CIPH_GCM_MODE; +} + +bool CipherCtxPointer::isOcbMode() const { + if (!ctx_) return false; + return getMode() == EVP_CIPH_OCB_MODE; +} + +bool CipherCtxPointer::isCcmMode() const { + if (!ctx_) return false; + return getMode() == EVP_CIPH_CCM_MODE; +} + +bool CipherCtxPointer::isWrapMode() const { + if (!ctx_) return false; + return getMode() == EVP_CIPH_WRAP_MODE; +} + +bool CipherCtxPointer::isChaCha20Poly1305() const { + if (!ctx_) return false; + return getNid() == NID_chacha20_poly1305; +} + int CipherCtxPointer::getNid() const { if (!ctx_) return 0; return EVP_CIPHER_CTX_nid(ctx_.get()); } -bool CipherCtxPointer::init(const Cipher& cipher, bool encrypt, - const unsigned char* key, const unsigned char* iv) { +bool CipherCtxPointer::init(const Cipher& cipher, + bool encrypt, + const unsigned char* key, + const unsigned char* iv) { if (!ctx_) return false; - return EVP_CipherInit_ex(ctx_.get(), cipher, nullptr, key, iv, - encrypt ? 1 : 0) == 1; + return EVP_CipherInit_ex( + ctx_.get(), cipher, nullptr, key, iv, encrypt ? 1 : 0) == 1; } bool CipherCtxPointer::update(const Buffer& in, - unsigned char* out, int* out_len, bool finalize) { + unsigned char* out, + int* out_len, + bool finalize) { if (!ctx_) return false; if (!finalize) { return EVP_CipherUpdate(ctx_.get(), out, out_len, in.data, in.len) == 1; @@ -2920,7 +3343,9 @@ ECDSASigPointer& ECDSASigPointer::operator=(ECDSASigPointer&& other) noexcept { return *this; } -ECDSASigPointer::~ECDSASigPointer() { reset(); } +ECDSASigPointer::~ECDSASigPointer() { + reset(); +} void ECDSASigPointer::reset(ECDSA_SIG* sig) { sig_.reset(); @@ -2973,11 +3398,17 @@ ECGroupPointer& ECGroupPointer::operator=(ECGroupPointer&& other) noexcept { return *this; } -ECGroupPointer::~ECGroupPointer() { reset(); } +ECGroupPointer::~ECGroupPointer() { + reset(); +} -void ECGroupPointer::reset(EC_GROUP* group) { group_.reset(); } +void ECGroupPointer::reset(EC_GROUP* group) { + group_.reset(); +} -EC_GROUP* ECGroupPointer::release() { return group_.release(); } +EC_GROUP* ECGroupPointer::release() { + return group_.release(); +} ECGroupPointer ECGroupPointer::NewByCurveName(int nid) { return ECGroupPointer(EC_GROUP_new_by_curve_name(nid)); @@ -2997,11 +3428,17 @@ ECPointPointer& ECPointPointer::operator=(ECPointPointer&& other) noexcept { return *this; } -ECPointPointer::~ECPointPointer() { reset(); } +ECPointPointer::~ECPointPointer() { + reset(); +} -void ECPointPointer::reset(EC_POINT* point) { point_.reset(point); } +void ECPointPointer::reset(EC_POINT* point) { + point_.reset(point); +} -EC_POINT* ECPointPointer::release() { return point_.release(); } +EC_POINT* ECPointPointer::release() { + return point_.release(); +} ECPointPointer ECPointPointer::New(const EC_GROUP* group) { return ECPointPointer(EC_POINT_new(group)); @@ -3010,8 +3447,8 @@ ECPointPointer ECPointPointer::New(const EC_GROUP* group) { bool ECPointPointer::setFromBuffer(const Buffer& buffer, const EC_GROUP* group) { if (!point_) return false; - return EC_POINT_oct2point(group, point_.get(), buffer.data, buffer.len, - nullptr); + return EC_POINT_oct2point( + group, point_.get(), buffer.data, buffer.len, nullptr); } bool ECPointPointer::mul(const EC_GROUP* group, const BIGNUM* priv_key) { @@ -3033,11 +3470,17 @@ ECKeyPointer& ECKeyPointer::operator=(ECKeyPointer&& other) noexcept { return *this; } -ECKeyPointer::~ECKeyPointer() { reset(); } +ECKeyPointer::~ECKeyPointer() { + reset(); +} -void ECKeyPointer::reset(EC_KEY* key) { key_.reset(key); } +void ECKeyPointer::reset(EC_KEY* key) { + key_.reset(key); +} -EC_KEY* ECKeyPointer::release() { return key_.release(); } +EC_KEY* ECKeyPointer::release() { + return key_.release(); +} ECKeyPointer ECKeyPointer::clone() const { if (!key_) return {}; @@ -3057,8 +3500,8 @@ 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; + return EC_KEY_set_public_key_affine_coordinates( + key_.get(), x.get(), y.get()) == 1; } bool ECKeyPointer::setPrivateKey(const BignumPointer& priv) { @@ -3133,11 +3576,17 @@ EVPKeyCtxPointer& EVPKeyCtxPointer::operator=( return *this; } -EVPKeyCtxPointer::~EVPKeyCtxPointer() { reset(); } +EVPKeyCtxPointer::~EVPKeyCtxPointer() { + reset(); +} -void EVPKeyCtxPointer::reset(EVP_PKEY_CTX* ctx) { ctx_.reset(ctx); } +void EVPKeyCtxPointer::reset(EVP_PKEY_CTX* ctx) { + ctx_.reset(ctx); +} -EVP_PKEY_CTX* EVPKeyCtxPointer::release() { return ctx_.release(); } +EVP_PKEY_CTX* EVPKeyCtxPointer::release() { + return ctx_.release(); +} EVPKeyCtxPointer EVPKeyCtxPointer::New(const EVPKeyPointer& key) { if (!key) return {}; @@ -3145,6 +3594,10 @@ EVPKeyCtxPointer EVPKeyCtxPointer::New(const EVPKeyPointer& key) { } EVPKeyCtxPointer EVPKeyCtxPointer::NewFromID(int id) { +#ifdef OPENSSL_IS_BORINGSSL + // DSA keys are not supported with BoringSSL + if (id == EVP_PKEY_DSA) return {}; +#endif return EVPKeyCtxPointer(EVP_PKEY_CTX_new_id(id, nullptr)); } @@ -3188,7 +3641,6 @@ bool EVPKeyCtxPointer::setDhParameters(int prime_size, uint32_t generator) { bool EVPKeyCtxPointer::setDsaParameters(uint32_t bits, std::optional q_bits) { -#ifndef NCRYPTO_NO_DSA_KEYGEN if (!ctx_) return false; if (EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx_.get(), bits) != 1) { return false; @@ -3198,10 +3650,6 @@ bool EVPKeyCtxPointer::setDsaParameters(uint32_t bits, return false; } return true; -#else - // Older versions of openssl/boringssl do not implement the DSA keygen. - return false; -#endif } bool EVPKeyCtxPointer::setEcParameters(int curve, int encoding) { @@ -3210,21 +3658,24 @@ bool EVPKeyCtxPointer::setEcParameters(int curve, int encoding) { EVP_PKEY_CTX_set_ec_param_enc(ctx_.get(), encoding) == 1; } -bool EVPKeyCtxPointer::setRsaOaepMd(const EVP_MD* md) { - if (md == nullptr || !ctx_) return false; - return EVP_PKEY_CTX_set_rsa_oaep_md(ctx_.get(), md) > 0; +bool EVPKeyCtxPointer::setRsaOaepMd(const Digest& md) { + if (!md || !ctx_) return false; + const EVP_MD* md_ptr = md; + return EVP_PKEY_CTX_set_rsa_oaep_md(ctx_.get(), md_ptr) > 0; } -bool EVPKeyCtxPointer::setRsaMgf1Md(const EVP_MD* md) { - if (md == nullptr || !ctx_) return false; - return EVP_PKEY_CTX_set_rsa_mgf1_md(ctx_.get(), md) > 0; +bool EVPKeyCtxPointer::setRsaMgf1Md(const Digest& md) { + if (!md || !ctx_) return false; + const EVP_MD* md_ptr = md; + return EVP_PKEY_CTX_set_rsa_mgf1_md(ctx_.get(), md_ptr) > 0; } bool EVPKeyCtxPointer::setRsaPadding(int padding) { return setRsaPadding(ctx_.get(), padding, std::nullopt); } -bool EVPKeyCtxPointer::setRsaPadding(EVP_PKEY_CTX* ctx, int padding, +bool EVPKeyCtxPointer::setRsaPadding(EVP_PKEY_CTX* ctx, + int padding, std::optional salt_len) { if (ctx == nullptr) return false; if (EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0) { @@ -3251,14 +3702,17 @@ bool EVPKeyCtxPointer::setRsaKeygenPubExp(BignumPointer&& e) { return false; } -bool EVPKeyCtxPointer::setRsaPssKeygenMd(const EVP_MD* md) { - if (md == nullptr || !ctx_) return false; - return EVP_PKEY_CTX_set_rsa_pss_keygen_md(ctx_.get(), md) > 0; +bool EVPKeyCtxPointer::setRsaPssKeygenMd(const Digest& md) { + if (!md || !ctx_) return false; + // OpenSSL < 3 accepts a void* for the md parameter. + const EVP_MD* md_ptr = md; + return EVP_PKEY_CTX_set_rsa_pss_keygen_md(ctx_.get(), md_ptr) > 0; } -bool EVPKeyCtxPointer::setRsaPssKeygenMgf1Md(const EVP_MD* md) { - if (md == nullptr || !ctx_) return false; - return EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md(ctx_.get(), md) > 0; +bool EVPKeyCtxPointer::setRsaPssKeygenMgf1Md(const Digest& md) { + if (!md || !ctx_) return false; + const EVP_MD* md_ptr = md; + return EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md(ctx_.get(), md_ptr) > 0; } bool EVPKeyCtxPointer::setRsaPssSaltlen(int salt_len) { @@ -3269,8 +3723,8 @@ bool EVPKeyCtxPointer::setRsaPssSaltlen(int salt_len) { bool EVPKeyCtxPointer::setRsaImplicitRejection() { #ifndef OPENSSL_IS_BORINGSSL if (!ctx_) return false; - return EVP_PKEY_CTX_ctrl_str(ctx_.get(), "rsa_pkcs1_implicit_rejection", - "1") > 0; + return EVP_PKEY_CTX_ctrl_str( + ctx_.get(), "rsa_pkcs1_implicit_rejection", "1") > 0; // From the doc -2 means that the option is not supported. // The default for the option is enabled and if it has been // specifically disabled we want to respect that so we will @@ -3319,8 +3773,8 @@ DataPointer EVPKeyCtxPointer::derive() const { if (EVP_PKEY_derive(ctx_.get(), nullptr, &len) != 1) return {}; auto data = DataPointer::Alloc(len); if (!data) return {}; - if (EVP_PKEY_derive(ctx_.get(), static_cast(data.get()), - &len) != 1) { + if (EVP_PKEY_derive( + ctx_.get(), static_cast(data.get()), &len) != 1) { return {}; } return data; @@ -3336,7 +3790,6 @@ EVPKeyPointer EVPKeyCtxPointer::paramgen() const { bool EVPKeyCtxPointer::publicCheck() const { if (!ctx_) return false; #ifndef OPENSSL_IS_BORINGSSL - return EVP_PKEY_public_check(ctx_.get()) == 1; #if OPENSSL_VERSION_MAJOR >= 3 return EVP_PKEY_public_check_quick(ctx_.get()) == 1; #else @@ -3377,8 +3830,11 @@ DataPointer EVPKeyCtxPointer::sign(const Buffer& data) { } auto buf = DataPointer::Alloc(len); if (!buf) return {}; - if (EVP_PKEY_sign(ctx_.get(), static_cast(buf.get()), &len, - data.data, data.len) != 1) { + if (EVP_PKEY_sign(ctx_.get(), + static_cast(buf.get()), + &len, + data.data, + data.len) != 1) { return {}; } return buf.resize(len); @@ -3400,8 +3856,10 @@ bool EVPKeyCtxPointer::signInto(const Buffer& data, namespace { using EVP_PKEY_cipher_init_t = int(EVP_PKEY_CTX* ctx); -using EVP_PKEY_cipher_t = int(EVP_PKEY_CTX* ctx, unsigned char* out, - size_t* outlen, const unsigned char* in, +using EVP_PKEY_cipher_t = int(EVP_PKEY_CTX* ctx, + unsigned char* out, + size_t* outlen, + const unsigned char* in, size_t inlen); template @@ -3423,16 +3881,22 @@ DataPointer RSA_Cipher(const EVPKeyPointer& key, } size_t out_len = 0; - if (cipher(ctx.get(), nullptr, &out_len, - reinterpret_cast(in.data), in.len) <= 0) { + if (cipher(ctx.get(), + nullptr, + &out_len, + reinterpret_cast(in.data), + in.len) <= 0) { return {}; } auto buf = DataPointer::Alloc(out_len); if (!buf) return {}; - if (cipher(ctx.get(), static_cast(buf.get()), &out_len, - static_cast(in.data), in.len) <= 0) { + if (cipher(ctx.get(), + static_cast(buf.get()), + &out_len, + static_cast(in.data), + in.len) <= 0) { return {}; } @@ -3456,16 +3920,22 @@ DataPointer CipherImpl(const EVPKeyPointer& key, } size_t out_len = 0; - if (cipher(ctx.get(), nullptr, &out_len, - static_cast(in.data), in.len) <= 0) { + if (cipher(ctx.get(), + nullptr, + &out_len, + static_cast(in.data), + in.len) <= 0) { return {}; } auto buf = DataPointer::Alloc(out_len); if (!buf) return {}; - if (cipher(ctx.get(), static_cast(buf.get()), &out_len, - static_cast(in.data), in.len) <= 0) { + if (cipher(ctx.get(), + static_cast(buf.get()), + &out_len, + static_cast(in.data), + in.len) <= 0) { return {}; } @@ -3520,14 +3990,9 @@ const std::optional Rsa::getPssParams() const { } if (params->saltLength != nullptr) { - // Older versions of openssl/boringssl do not implement - // ASN1_INTEGER_get_int64, which the salt length here technically - // is. Let's walk it through uint64_t with a conversion. - uint64_t temp; - if (ASN1_INTEGER_get_uint64(&temp, params->saltLength) != 1) { + if (ASN1_INTEGER_get_int64(&ret.salt_length, params->saltLength) != 1) { return std::nullopt; } - ret.salt_length = static_cast(temp); } return ret; } @@ -3542,8 +4007,11 @@ bool Rsa::setPublicKey(BignumPointer&& n, BignumPointer&& e) { return false; } -bool Rsa::setPrivateKey(BignumPointer&& d, BignumPointer&& q, BignumPointer&& p, - BignumPointer&& dp, BignumPointer&& dq, +bool Rsa::setPrivateKey(BignumPointer&& d, + BignumPointer&& q, + BignumPointer&& p, + BignumPointer&& dp, + BignumPointer&& dq, BignumPointer&& qi) { if (!RSA_set0_key(const_cast(rsa_), nullptr, nullptr, d.get())) { return false; @@ -3556,8 +4024,8 @@ bool Rsa::setPrivateKey(BignumPointer&& d, BignumPointer&& q, BignumPointer&& p, p.release(); q.release(); - if (!RSA_set0_crt_params(const_cast(rsa_), dp.get(), dq.get(), - qi.get())) { + if (!RSA_set0_crt_params( + const_cast(rsa_), dp.get(), dq.get(), qi.get())) { return false; } dp.release(); @@ -3594,7 +4062,8 @@ DataPointer Cipher::decrypt(const EVPKeyPointer& key, return CipherImpl(key, params, in); } -DataPointer Cipher::sign(const EVPKeyPointer& key, const CipherParams& params, +DataPointer Cipher::sign(const EVPKeyPointer& key, + const CipherParams& params, const Buffer in) { // private operation return CipherImpl(key, params, in); @@ -3608,32 +4077,107 @@ DataPointer Cipher::recover(const EVPKeyPointer& key, key, params, in); } -// ============================================================================ +namespace { +struct CipherCallbackContext { + Cipher::CipherNameCallback cb; + void operator()(const char* name) { cb(name); } +}; -Ec::Ec() : ec_(nullptr) {} +#if OPENSSL_VERSION_MAJOR >= 3 +template +void array_push_back(const TypeName* evp_ref, + const char* from, + const char* to, + void* arg) { + if (from == nullptr) return; + + const TypeName* real_instance = getbyname(from); + if (!real_instance) return; + + const char* real_name = getname(real_instance); + if (!real_name) return; + + // EVP_*_fetch() does not support alias names, so we need to pass it the + // real/original algorithm name. + // We use EVP_*_fetch() as a filter here because it will only return an + // instance if the algorithm is supported by the public OpenSSL APIs (some + // algorithms are used internally by OpenSSL and are also passed to this + // callback). + TypeName* fetched = fetch_type(nullptr, real_name, nullptr); + if (fetched == nullptr) return; + + free_type(fetched); + auto& cb = *(static_cast(arg)); + cb(from); +} +#else +template +void array_push_back(const TypeName* evp_ref, + const char* from, + const char* to, + void* arg) { + if (!from) return; + auto& cb = *(static_cast(arg)); + cb(from); +} +#endif +} // namespace -Ec::Ec(OSSL3_CONST EC_KEY* key) - : ec_(key), x_(BignumPointer::New()), y_(BignumPointer::New()) { - if (ec_ != nullptr) { - MarkPopErrorOnReturn mark_pop_error_on_return; - EC_POINT_get_affine_coordinates(getGroup(), getPublicKey(), x_.get(), - y_.get(), nullptr); - } +void Cipher::ForEach(Cipher::CipherNameCallback callback) { + ClearErrorOnReturn clearErrorOnReturn; + CipherCallbackContext context; + context.cb = std::move(callback); + + EVP_CIPHER_do_all_sorted( +#if OPENSSL_VERSION_MAJOR >= 3 + array_push_back, +#else + array_push_back, +#endif + &context); } -const EC_GROUP* Ec::getGroup() const { return ECKeyPointer::GetGroup(ec_); } +// ============================================================================ -int Ec::getCurve() const { return EC_GROUP_get_curve_name(getGroup()); } +Ec::Ec() : ec_(nullptr) {} -uint32_t Ec::getDegree() const { return EC_GROUP_get_degree(getGroup()); } +Ec::Ec(OSSL3_CONST EC_KEY* key) : ec_(key) {} -std::string Ec::getCurveName() const { - return std::string(OBJ_nid2sn(getCurve())); +const EC_GROUP* Ec::getGroup() const { + return ECKeyPointer::GetGroup(ec_); } -const EC_POINT* Ec::getPublicKey() const { return EC_KEY_get0_public_key(ec_); } +int Ec::getCurve() const { + return EC_GROUP_get_curve_name(getGroup()); +} -const BIGNUM* Ec::getPrivateKey() const { return EC_KEY_get0_private_key(ec_); } +int Ec::GetCurveIdFromName(const char* name) { + int nid = EC_curve_nist2nid(name); + if (nid == NID_undef) { + nid = OBJ_sn2nid(name); + } + return nid; +} + +bool Ec::GetCurves(Ec::GetCurveCallback callback) { + const size_t count = EC_get_builtin_curves(nullptr, 0); + std::vector curves(count); + if (EC_get_builtin_curves(curves.data(), count) != count) { + return false; + } + for (auto curve : curves) { + if (!callback(OBJ_nid2sn(curve.nid))) return false; + } + return true; +} // ============================================================================ @@ -3649,13 +4193,19 @@ EVPMDCtxPointer& EVPMDCtxPointer::operator=(EVPMDCtxPointer&& other) noexcept { return *this; } -EVPMDCtxPointer::~EVPMDCtxPointer() { reset(); } +EVPMDCtxPointer::~EVPMDCtxPointer() { + reset(); +} -void EVPMDCtxPointer::reset(EVP_MD_CTX* ctx) { ctx_.reset(ctx); } +void EVPMDCtxPointer::reset(EVP_MD_CTX* ctx) { + ctx_.reset(ctx); +} -EVP_MD_CTX* EVPMDCtxPointer::release() { return ctx_.release(); } +EVP_MD_CTX* EVPMDCtxPointer::release() { + return ctx_.release(); +} -bool EVPMDCtxPointer::digestInit(const EVP_MD* digest) { +bool EVPMDCtxPointer::digestInit(const Digest& digest) { if (!ctx_) return false; return EVP_DigestInit_ex(ctx_.get(), digest, nullptr) > 0; } @@ -3721,7 +4271,7 @@ bool EVPMDCtxPointer::copyTo(const EVPMDCtxPointer& other) const { } std::optional EVPMDCtxPointer::signInit(const EVPKeyPointer& key, - const EVP_MD* digest) { + const Digest& digest) { EVP_PKEY_CTX* ctx = nullptr; if (!EVP_DigestSignInit(ctx_.get(), &ctx, digest, nullptr, key.get())) { return std::nullopt; @@ -3730,7 +4280,7 @@ std::optional EVPMDCtxPointer::signInit(const EVPKeyPointer& key, } std::optional EVPMDCtxPointer::verifyInit( - const EVPKeyPointer& key, const EVP_MD* digest) { + const EVPKeyPointer& key, const Digest& digest) { EVP_PKEY_CTX* ctx = nullptr; if (!EVP_DigestVerifyInit(ctx_.get(), &ctx, digest, nullptr, key.get())) { return std::nullopt; @@ -3749,8 +4299,11 @@ DataPointer EVPMDCtxPointer::signOneShot( if (!data) [[unlikely]] return {}; - if (!EVP_DigestSign(ctx_.get(), static_cast(data.get()), &len, - buf.data, buf.len)) { + if (!EVP_DigestSign(ctx_.get(), + static_cast(data.get()), + &len, + buf.data, + buf.len)) { return {}; } return data; @@ -3768,8 +4321,8 @@ DataPointer EVPMDCtxPointer::sign( auto data = DataPointer::Alloc(len); if (!data) [[unlikely]] return {}; - if (!EVP_DigestSignFinal(ctx_.get(), static_cast(data.get()), - &len)) { + if (!EVP_DigestSignFinal( + ctx_.get(), static_cast(data.get()), &len)) { return {}; } return data.resize(len); @@ -3788,7 +4341,8 @@ EVPMDCtxPointer EVPMDCtxPointer::New() { // ============================================================================ -bool extractP1363(const Buffer& buf, unsigned char* dest, +bool extractP1363(const Buffer& buf, + unsigned char* dest, size_t n) { auto asn1_sig = ECDSASigPointer::Parse(buf); if (!asn1_sig) return false; @@ -3811,20 +4365,28 @@ HMACCtxPointer& HMACCtxPointer::operator=(HMACCtxPointer&& other) noexcept { return *this; } -HMACCtxPointer::~HMACCtxPointer() { reset(); } +HMACCtxPointer::~HMACCtxPointer() { + reset(); +} -void HMACCtxPointer::reset(HMAC_CTX* ctx) { ctx_.reset(ctx); } +void HMACCtxPointer::reset(HMAC_CTX* ctx) { + ctx_.reset(ctx); +} -HMAC_CTX* HMACCtxPointer::release() { return ctx_.release(); } +HMAC_CTX* HMACCtxPointer::release() { + return ctx_.release(); +} -bool HMACCtxPointer::init(const Buffer& buf, const EVP_MD* md) { +bool HMACCtxPointer::init(const Buffer& buf, const Digest& md) { if (!ctx_) return false; - return HMAC_Init_ex(ctx_.get(), buf.data, buf.len, md, nullptr) == 1; + const EVP_MD* md_ptr = md; + return HMAC_Init_ex(ctx_.get(), buf.data, buf.len, md_ptr, nullptr) == 1; } bool HMACCtxPointer::update(const Buffer& buf) { if (!ctx_) return false; - return HMAC_Update(ctx_.get(), static_cast(buf.data), + return HMAC_Update(ctx_.get(), + static_cast(buf.data), buf.len) == 1; } @@ -3847,7 +4409,9 @@ bool HMACCtxPointer::digestInto(Buffer* buf) { return true; } -HMACCtxPointer HMACCtxPointer::New() { return HMACCtxPointer(HMAC_CTX_new()); } +HMACCtxPointer HMACCtxPointer::New() { + return HMACCtxPointer(HMAC_CTX_new()); +} DataPointer hashDigest(const Buffer& buf, const EVP_MD* md) { @@ -3857,15 +4421,34 @@ DataPointer hashDigest(const Buffer& buf, auto data = DataPointer::Alloc(md_len); if (!data) return {}; - if (!EVP_Digest(buf.data, buf.len, - reinterpret_cast(data.get()), &result_size, - md, nullptr)) { + if (!EVP_Digest(buf.data, + buf.len, + reinterpret_cast(data.get()), + &result_size, + md, + nullptr)) { return {}; } return data.resize(result_size); } +DataPointer xofHashDigest(const Buffer& buf, + const EVP_MD* md, + size_t output_length) { + if (md == nullptr) return {}; + + EVPMDCtxPointer ctx = EVPMDCtxPointer::New(); + if (!ctx) return {}; + if (ctx.digestInit(md) != 1) { + return {}; + } + if (ctx.digestUpdate(reinterpret_cast&>(buf)) != 1) { + return {}; + } + return ctx.digestFinal(output_length); +} + // ============================================================================ X509Name::X509Name() : name_(nullptr), total_(0) {} @@ -3881,7 +4464,9 @@ X509Name::Iterator& X509Name::Iterator::operator++() { return *this; } -X509Name::Iterator::operator bool() const { return loc_ < name_.total_; } +X509Name::Iterator::operator bool() const { + return loc_ < name_.total_; +} bool X509Name::Iterator::operator==(const Iterator& other) const { return loc_ == other.loc_; @@ -3952,259 +4537,143 @@ size_t Dsa::getDivisorLength() const { if (dsa_ == nullptr) return 0; return BignumPointer::GetBitCount(getQ()); } -} // namespace ncrypto -// =========================================================================== -#ifdef NCRYPTO_BSSL_NEEDS_DH_PRIMES -// While newer versions of BoringSSL have these primes, older versions do not, -// in particular older versions that conform to fips. We conditionally add -// them here only if the NCRYPTO_BSSL_NEEDS_DH_PRIMES define is set. Their -// implementations are defined here to prevent duplicating the symbols. -extern "C" int bn_set_words(BIGNUM* bn, const BN_ULONG* words, size_t num); +// ============================================================================ -// Backporting primes that may not be supported in earlier boringssl versions. -// Intentionally keeping the existing C-style formatting. +size_t Digest::size() const { + if (md_ == nullptr) return 0; + return EVP_MD_size(md_); +} -#define OPENSSL_ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) +const Digest Digest::MD5 = Digest(EVP_md5()); +const Digest Digest::SHA1 = Digest(EVP_sha1()); +const Digest Digest::SHA256 = Digest(EVP_sha256()); +const Digest Digest::SHA384 = Digest(EVP_sha384()); +const Digest Digest::SHA512 = Digest(EVP_sha512()); -#if defined(OPENSSL_64_BIT) -#define TOBN(hi, lo) ((BN_ULONG)(hi) << 32 | (lo)) -#elif defined(OPENSSL_32_BIT) -#define TOBN(hi, lo) (lo), (hi) -#else -#error "Must define either OPENSSL_32_BIT or OPENSSL_64_BIT" +const Digest Digest::FromName(const char* name) { + return ncrypto::getDigestByName(name); +} + +// ============================================================================ +// KEM Implementation +#if OPENSSL_VERSION_MAJOR >= 3 +#if !OPENSSL_VERSION_PREREQ(3, 5) +bool KEM::SetOperationParameter(EVP_PKEY_CTX* ctx, const EVPKeyPointer& key) { + const char* operation = nullptr; + + switch (EVP_PKEY_id(key.get())) { + case EVP_PKEY_RSA: + operation = OSSL_KEM_PARAM_OPERATION_RSASVE; + break; +#if OPENSSL_VERSION_PREREQ(3, 2) + case EVP_PKEY_EC: + case EVP_PKEY_X25519: + case EVP_PKEY_X448: + operation = OSSL_KEM_PARAM_OPERATION_DHKEM; + break; #endif + default: + unreachable(); + } + + if (operation != nullptr) { + OSSL_PARAM params[] = { + OSSL_PARAM_utf8_string( + OSSL_KEM_PARAM_OPERATION, const_cast(operation), 0), + OSSL_PARAM_END}; -static BIGNUM* get_params(BIGNUM* ret, const BN_ULONG* words, - size_t num_words) { - BIGNUM* alloc = nullptr; - if (ret == nullptr) { - alloc = BN_new(); - if (alloc == nullptr) { - return nullptr; + if (EVP_PKEY_CTX_set_params(ctx, params) <= 0) { + return false; } - ret = alloc; } - if (!bn_set_words(ret, words, num_words)) { - BN_free(alloc); - return nullptr; + return true; +} +#endif + +std::optional KEM::Encapsulate( + const EVPKeyPointer& public_key) { + ClearErrorOnReturn clear_error_on_return; + + auto ctx = public_key.newCtx(); + if (!ctx) return std::nullopt; + + if (EVP_PKEY_encapsulate_init(ctx.get(), nullptr) <= 0) { + return std::nullopt; } - return ret; -} +#if !OPENSSL_VERSION_PREREQ(3, 5) + if (!SetOperationParameter(ctx.get(), public_key)) { + return std::nullopt; + } +#endif -BIGNUM* BN_get_rfc3526_prime_2048(BIGNUM* ret) { - static const BN_ULONG kWords[] = { - TOBN(0xffffffff, 0xffffffff), TOBN(0x15728e5a, 0x8aacaa68), - TOBN(0x15d22618, 0x98fa0510), TOBN(0x3995497c, 0xea956ae5), - TOBN(0xde2bcbf6, 0x95581718), TOBN(0xb5c55df0, 0x6f4c52c9), - TOBN(0x9b2783a2, 0xec07a28f), TOBN(0xe39e772c, 0x180e8603), - TOBN(0x32905e46, 0x2e36ce3b), TOBN(0xf1746c08, 0xca18217c), - TOBN(0x670c354e, 0x4abc9804), TOBN(0x9ed52907, 0x7096966d), - TOBN(0x1c62f356, 0x208552bb), TOBN(0x83655d23, 0xdca3ad96), - TOBN(0x69163fa8, 0xfd24cf5f), TOBN(0x98da4836, 0x1c55d39a), - TOBN(0xc2007cb8, 0xa163bf05), TOBN(0x49286651, 0xece45b3d), - TOBN(0xae9f2411, 0x7c4b1fe6), TOBN(0xee386bfb, 0x5a899fa5), - TOBN(0x0bff5cb6, 0xf406b7ed), TOBN(0xf44c42e9, 0xa637ed6b), - TOBN(0xe485b576, 0x625e7ec6), TOBN(0x4fe1356d, 0x6d51c245), - TOBN(0x302b0a6d, 0xf25f1437), TOBN(0xef9519b3, 0xcd3a431b), - TOBN(0x514a0879, 0x8e3404dd), TOBN(0x020bbea6, 0x3b139b22), - TOBN(0x29024e08, 0x8a67cc74), TOBN(0xc4c6628b, 0x80dc1cd1), - TOBN(0xc90fdaa2, 0x2168c234), TOBN(0xffffffff, 0xffffffff), - }; - return get_params(ret, kWords, OPENSSL_ARRAY_SIZE(kWords)); -} - -BIGNUM* BN_get_rfc3526_prime_3072(BIGNUM* ret) { - static const BN_ULONG kWords[] = { - TOBN(0xffffffff, 0xffffffff), TOBN(0x4b82d120, 0xa93ad2ca), - TOBN(0x43db5bfc, 0xe0fd108e), TOBN(0x08e24fa0, 0x74e5ab31), - TOBN(0x770988c0, 0xbad946e2), TOBN(0xbbe11757, 0x7a615d6c), - TOBN(0x521f2b18, 0x177b200c), TOBN(0xd8760273, 0x3ec86a64), - TOBN(0xf12ffa06, 0xd98a0864), TOBN(0xcee3d226, 0x1ad2ee6b), - TOBN(0x1e8c94e0, 0x4a25619d), TOBN(0xabf5ae8c, 0xdb0933d7), - TOBN(0xb3970f85, 0xa6e1e4c7), TOBN(0x8aea7157, 0x5d060c7d), - TOBN(0xecfb8504, 0x58dbef0a), TOBN(0xa85521ab, 0xdf1cba64), - TOBN(0xad33170d, 0x04507a33), TOBN(0x15728e5a, 0x8aaac42d), - TOBN(0x15d22618, 0x98fa0510), TOBN(0x3995497c, 0xea956ae5), - TOBN(0xde2bcbf6, 0x95581718), TOBN(0xb5c55df0, 0x6f4c52c9), - TOBN(0x9b2783a2, 0xec07a28f), TOBN(0xe39e772c, 0x180e8603), - TOBN(0x32905e46, 0x2e36ce3b), TOBN(0xf1746c08, 0xca18217c), - TOBN(0x670c354e, 0x4abc9804), TOBN(0x9ed52907, 0x7096966d), - TOBN(0x1c62f356, 0x208552bb), TOBN(0x83655d23, 0xdca3ad96), - TOBN(0x69163fa8, 0xfd24cf5f), TOBN(0x98da4836, 0x1c55d39a), - TOBN(0xc2007cb8, 0xa163bf05), TOBN(0x49286651, 0xece45b3d), - TOBN(0xae9f2411, 0x7c4b1fe6), TOBN(0xee386bfb, 0x5a899fa5), - TOBN(0x0bff5cb6, 0xf406b7ed), TOBN(0xf44c42e9, 0xa637ed6b), - TOBN(0xe485b576, 0x625e7ec6), TOBN(0x4fe1356d, 0x6d51c245), - TOBN(0x302b0a6d, 0xf25f1437), TOBN(0xef9519b3, 0xcd3a431b), - TOBN(0x514a0879, 0x8e3404dd), TOBN(0x020bbea6, 0x3b139b22), - TOBN(0x29024e08, 0x8a67cc74), TOBN(0xc4c6628b, 0x80dc1cd1), - TOBN(0xc90fdaa2, 0x2168c234), TOBN(0xffffffff, 0xffffffff), - }; - return get_params(ret, kWords, OPENSSL_ARRAY_SIZE(kWords)); -} - -BIGNUM* BN_get_rfc3526_prime_4096(BIGNUM* ret) { - static const BN_ULONG kWords[] = { - TOBN(0xffffffff, 0xffffffff), TOBN(0x4df435c9, 0x34063199), - TOBN(0x86ffb7dc, 0x90a6c08f), TOBN(0x93b4ea98, 0x8d8fddc1), - TOBN(0xd0069127, 0xd5b05aa9), TOBN(0xb81bdd76, 0x2170481c), - TOBN(0x1f612970, 0xcee2d7af), TOBN(0x233ba186, 0x515be7ed), - TOBN(0x99b2964f, 0xa090c3a2), TOBN(0x287c5947, 0x4e6bc05d), - TOBN(0x2e8efc14, 0x1fbecaa6), TOBN(0xdbbbc2db, 0x04de8ef9), - TOBN(0x2583e9ca, 0x2ad44ce8), TOBN(0x1a946834, 0xb6150bda), - TOBN(0x99c32718, 0x6af4e23c), TOBN(0x88719a10, 0xbdba5b26), - TOBN(0x1a723c12, 0xa787e6d7), TOBN(0x4b82d120, 0xa9210801), - TOBN(0x43db5bfc, 0xe0fd108e), TOBN(0x08e24fa0, 0x74e5ab31), - TOBN(0x770988c0, 0xbad946e2), TOBN(0xbbe11757, 0x7a615d6c), - TOBN(0x521f2b18, 0x177b200c), TOBN(0xd8760273, 0x3ec86a64), - TOBN(0xf12ffa06, 0xd98a0864), TOBN(0xcee3d226, 0x1ad2ee6b), - TOBN(0x1e8c94e0, 0x4a25619d), TOBN(0xabf5ae8c, 0xdb0933d7), - TOBN(0xb3970f85, 0xa6e1e4c7), TOBN(0x8aea7157, 0x5d060c7d), - TOBN(0xecfb8504, 0x58dbef0a), TOBN(0xa85521ab, 0xdf1cba64), - TOBN(0xad33170d, 0x04507a33), TOBN(0x15728e5a, 0x8aaac42d), - TOBN(0x15d22618, 0x98fa0510), TOBN(0x3995497c, 0xea956ae5), - TOBN(0xde2bcbf6, 0x95581718), TOBN(0xb5c55df0, 0x6f4c52c9), - TOBN(0x9b2783a2, 0xec07a28f), TOBN(0xe39e772c, 0x180e8603), - TOBN(0x32905e46, 0x2e36ce3b), TOBN(0xf1746c08, 0xca18217c), - TOBN(0x670c354e, 0x4abc9804), TOBN(0x9ed52907, 0x7096966d), - TOBN(0x1c62f356, 0x208552bb), TOBN(0x83655d23, 0xdca3ad96), - TOBN(0x69163fa8, 0xfd24cf5f), TOBN(0x98da4836, 0x1c55d39a), - TOBN(0xc2007cb8, 0xa163bf05), TOBN(0x49286651, 0xece45b3d), - TOBN(0xae9f2411, 0x7c4b1fe6), TOBN(0xee386bfb, 0x5a899fa5), - TOBN(0x0bff5cb6, 0xf406b7ed), TOBN(0xf44c42e9, 0xa637ed6b), - TOBN(0xe485b576, 0x625e7ec6), TOBN(0x4fe1356d, 0x6d51c245), - TOBN(0x302b0a6d, 0xf25f1437), TOBN(0xef9519b3, 0xcd3a431b), - TOBN(0x514a0879, 0x8e3404dd), TOBN(0x020bbea6, 0x3b139b22), - TOBN(0x29024e08, 0x8a67cc74), TOBN(0xc4c6628b, 0x80dc1cd1), - TOBN(0xc90fdaa2, 0x2168c234), TOBN(0xffffffff, 0xffffffff), - }; - return get_params(ret, kWords, OPENSSL_ARRAY_SIZE(kWords)); -} - -BIGNUM* BN_get_rfc3526_prime_6144(BIGNUM* ret) { - static const BN_ULONG kWords[] = { - TOBN(0xffffffff, 0xffffffff), TOBN(0xe694f91e, 0x6dcc4024), - TOBN(0x12bf2d5b, 0x0b7474d6), TOBN(0x043e8f66, 0x3f4860ee), - TOBN(0x387fe8d7, 0x6e3c0468), TOBN(0xda56c9ec, 0x2ef29632), - TOBN(0xeb19ccb1, 0xa313d55c), TOBN(0xf550aa3d, 0x8a1fbff0), - TOBN(0x06a1d58b, 0xb7c5da76), TOBN(0xa79715ee, 0xf29be328), - TOBN(0x14cc5ed2, 0x0f8037e0), TOBN(0xcc8f6d7e, 0xbf48e1d8), - TOBN(0x4bd407b2, 0x2b4154aa), TOBN(0x0f1d45b7, 0xff585ac5), - TOBN(0x23a97a7e, 0x36cc88be), TOBN(0x59e7c97f, 0xbec7e8f3), - TOBN(0xb5a84031, 0x900b1c9e), TOBN(0xd55e702f, 0x46980c82), - TOBN(0xf482d7ce, 0x6e74fef6), TOBN(0xf032ea15, 0xd1721d03), - TOBN(0x5983ca01, 0xc64b92ec), TOBN(0x6fb8f401, 0x378cd2bf), - TOBN(0x33205151, 0x2bd7af42), TOBN(0xdb7f1447, 0xe6cc254b), - TOBN(0x44ce6cba, 0xced4bb1b), TOBN(0xda3edbeb, 0xcf9b14ed), - TOBN(0x179727b0, 0x865a8918), TOBN(0xb06a53ed, 0x9027d831), - TOBN(0xe5db382f, 0x413001ae), TOBN(0xf8ff9406, 0xad9e530e), - TOBN(0xc9751e76, 0x3dba37bd), TOBN(0xc1d4dcb2, 0x602646de), - TOBN(0x36c3fab4, 0xd27c7026), TOBN(0x4df435c9, 0x34028492), - TOBN(0x86ffb7dc, 0x90a6c08f), TOBN(0x93b4ea98, 0x8d8fddc1), - TOBN(0xd0069127, 0xd5b05aa9), TOBN(0xb81bdd76, 0x2170481c), - TOBN(0x1f612970, 0xcee2d7af), TOBN(0x233ba186, 0x515be7ed), - TOBN(0x99b2964f, 0xa090c3a2), TOBN(0x287c5947, 0x4e6bc05d), - TOBN(0x2e8efc14, 0x1fbecaa6), TOBN(0xdbbbc2db, 0x04de8ef9), - TOBN(0x2583e9ca, 0x2ad44ce8), TOBN(0x1a946834, 0xb6150bda), - TOBN(0x99c32718, 0x6af4e23c), TOBN(0x88719a10, 0xbdba5b26), - TOBN(0x1a723c12, 0xa787e6d7), TOBN(0x4b82d120, 0xa9210801), - TOBN(0x43db5bfc, 0xe0fd108e), TOBN(0x08e24fa0, 0x74e5ab31), - TOBN(0x770988c0, 0xbad946e2), TOBN(0xbbe11757, 0x7a615d6c), - TOBN(0x521f2b18, 0x177b200c), TOBN(0xd8760273, 0x3ec86a64), - TOBN(0xf12ffa06, 0xd98a0864), TOBN(0xcee3d226, 0x1ad2ee6b), - TOBN(0x1e8c94e0, 0x4a25619d), TOBN(0xabf5ae8c, 0xdb0933d7), - TOBN(0xb3970f85, 0xa6e1e4c7), TOBN(0x8aea7157, 0x5d060c7d), - TOBN(0xecfb8504, 0x58dbef0a), TOBN(0xa85521ab, 0xdf1cba64), - TOBN(0xad33170d, 0x04507a33), TOBN(0x15728e5a, 0x8aaac42d), - TOBN(0x15d22618, 0x98fa0510), TOBN(0x3995497c, 0xea956ae5), - TOBN(0xde2bcbf6, 0x95581718), TOBN(0xb5c55df0, 0x6f4c52c9), - TOBN(0x9b2783a2, 0xec07a28f), TOBN(0xe39e772c, 0x180e8603), - TOBN(0x32905e46, 0x2e36ce3b), TOBN(0xf1746c08, 0xca18217c), - TOBN(0x670c354e, 0x4abc9804), TOBN(0x9ed52907, 0x7096966d), - TOBN(0x1c62f356, 0x208552bb), TOBN(0x83655d23, 0xdca3ad96), - TOBN(0x69163fa8, 0xfd24cf5f), TOBN(0x98da4836, 0x1c55d39a), - TOBN(0xc2007cb8, 0xa163bf05), TOBN(0x49286651, 0xece45b3d), - TOBN(0xae9f2411, 0x7c4b1fe6), TOBN(0xee386bfb, 0x5a899fa5), - TOBN(0x0bff5cb6, 0xf406b7ed), TOBN(0xf44c42e9, 0xa637ed6b), - TOBN(0xe485b576, 0x625e7ec6), TOBN(0x4fe1356d, 0x6d51c245), - TOBN(0x302b0a6d, 0xf25f1437), TOBN(0xef9519b3, 0xcd3a431b), - TOBN(0x514a0879, 0x8e3404dd), TOBN(0x020bbea6, 0x3b139b22), - TOBN(0x29024e08, 0x8a67cc74), TOBN(0xc4c6628b, 0x80dc1cd1), - TOBN(0xc90fdaa2, 0x2168c234), TOBN(0xffffffff, 0xffffffff), - }; - return get_params(ret, kWords, OPENSSL_ARRAY_SIZE(kWords)); -} - -BIGNUM* BN_get_rfc3526_prime_8192(BIGNUM* ret) { - static const BN_ULONG kWords[] = { - TOBN(0xffffffff, 0xffffffff), TOBN(0x60c980dd, 0x98edd3df), - TOBN(0xc81f56e8, 0x80b96e71), TOBN(0x9e3050e2, 0x765694df), - TOBN(0x9558e447, 0x5677e9aa), TOBN(0xc9190da6, 0xfc026e47), - TOBN(0x889a002e, 0xd5ee382b), TOBN(0x4009438b, 0x481c6cd7), - TOBN(0x359046f4, 0xeb879f92), TOBN(0xfaf36bc3, 0x1ecfa268), - TOBN(0xb1d510bd, 0x7ee74d73), TOBN(0xf9ab4819, 0x5ded7ea1), - TOBN(0x64f31cc5, 0x0846851d), TOBN(0x4597e899, 0xa0255dc1), - TOBN(0xdf310ee0, 0x74ab6a36), TOBN(0x6d2a13f8, 0x3f44f82d), - TOBN(0x062b3cf5, 0xb3a278a6), TOBN(0x79683303, 0xed5bdd3a), - TOBN(0xfa9d4b7f, 0xa2c087e8), TOBN(0x4bcbc886, 0x2f8385dd), - TOBN(0x3473fc64, 0x6cea306b), TOBN(0x13eb57a8, 0x1a23f0c7), - TOBN(0x22222e04, 0xa4037c07), TOBN(0xe3fdb8be, 0xfc848ad9), - TOBN(0x238f16cb, 0xe39d652d), TOBN(0x3423b474, 0x2bf1c978), - TOBN(0x3aab639c, 0x5ae4f568), TOBN(0x2576f693, 0x6ba42466), - TOBN(0x741fa7bf, 0x8afc47ed), TOBN(0x3bc832b6, 0x8d9dd300), - TOBN(0xd8bec4d0, 0x73b931ba), TOBN(0x38777cb6, 0xa932df8c), - TOBN(0x74a3926f, 0x12fee5e4), TOBN(0xe694f91e, 0x6dbe1159), - TOBN(0x12bf2d5b, 0x0b7474d6), TOBN(0x043e8f66, 0x3f4860ee), - TOBN(0x387fe8d7, 0x6e3c0468), TOBN(0xda56c9ec, 0x2ef29632), - TOBN(0xeb19ccb1, 0xa313d55c), TOBN(0xf550aa3d, 0x8a1fbff0), - TOBN(0x06a1d58b, 0xb7c5da76), TOBN(0xa79715ee, 0xf29be328), - TOBN(0x14cc5ed2, 0x0f8037e0), TOBN(0xcc8f6d7e, 0xbf48e1d8), - TOBN(0x4bd407b2, 0x2b4154aa), TOBN(0x0f1d45b7, 0xff585ac5), - TOBN(0x23a97a7e, 0x36cc88be), TOBN(0x59e7c97f, 0xbec7e8f3), - TOBN(0xb5a84031, 0x900b1c9e), TOBN(0xd55e702f, 0x46980c82), - TOBN(0xf482d7ce, 0x6e74fef6), TOBN(0xf032ea15, 0xd1721d03), - TOBN(0x5983ca01, 0xc64b92ec), TOBN(0x6fb8f401, 0x378cd2bf), - TOBN(0x33205151, 0x2bd7af42), TOBN(0xdb7f1447, 0xe6cc254b), - TOBN(0x44ce6cba, 0xced4bb1b), TOBN(0xda3edbeb, 0xcf9b14ed), - TOBN(0x179727b0, 0x865a8918), TOBN(0xb06a53ed, 0x9027d831), - TOBN(0xe5db382f, 0x413001ae), TOBN(0xf8ff9406, 0xad9e530e), - TOBN(0xc9751e76, 0x3dba37bd), TOBN(0xc1d4dcb2, 0x602646de), - TOBN(0x36c3fab4, 0xd27c7026), TOBN(0x4df435c9, 0x34028492), - TOBN(0x86ffb7dc, 0x90a6c08f), TOBN(0x93b4ea98, 0x8d8fddc1), - TOBN(0xd0069127, 0xd5b05aa9), TOBN(0xb81bdd76, 0x2170481c), - TOBN(0x1f612970, 0xcee2d7af), TOBN(0x233ba186, 0x515be7ed), - TOBN(0x99b2964f, 0xa090c3a2), TOBN(0x287c5947, 0x4e6bc05d), - TOBN(0x2e8efc14, 0x1fbecaa6), TOBN(0xdbbbc2db, 0x04de8ef9), - TOBN(0x2583e9ca, 0x2ad44ce8), TOBN(0x1a946834, 0xb6150bda), - TOBN(0x99c32718, 0x6af4e23c), TOBN(0x88719a10, 0xbdba5b26), - TOBN(0x1a723c12, 0xa787e6d7), TOBN(0x4b82d120, 0xa9210801), - TOBN(0x43db5bfc, 0xe0fd108e), TOBN(0x08e24fa0, 0x74e5ab31), - TOBN(0x770988c0, 0xbad946e2), TOBN(0xbbe11757, 0x7a615d6c), - TOBN(0x521f2b18, 0x177b200c), TOBN(0xd8760273, 0x3ec86a64), - TOBN(0xf12ffa06, 0xd98a0864), TOBN(0xcee3d226, 0x1ad2ee6b), - TOBN(0x1e8c94e0, 0x4a25619d), TOBN(0xabf5ae8c, 0xdb0933d7), - TOBN(0xb3970f85, 0xa6e1e4c7), TOBN(0x8aea7157, 0x5d060c7d), - TOBN(0xecfb8504, 0x58dbef0a), TOBN(0xa85521ab, 0xdf1cba64), - TOBN(0xad33170d, 0x04507a33), TOBN(0x15728e5a, 0x8aaac42d), - TOBN(0x15d22618, 0x98fa0510), TOBN(0x3995497c, 0xea956ae5), - TOBN(0xde2bcbf6, 0x95581718), TOBN(0xb5c55df0, 0x6f4c52c9), - TOBN(0x9b2783a2, 0xec07a28f), TOBN(0xe39e772c, 0x180e8603), - TOBN(0x32905e46, 0x2e36ce3b), TOBN(0xf1746c08, 0xca18217c), - TOBN(0x670c354e, 0x4abc9804), TOBN(0x9ed52907, 0x7096966d), - TOBN(0x1c62f356, 0x208552bb), TOBN(0x83655d23, 0xdca3ad96), - TOBN(0x69163fa8, 0xfd24cf5f), TOBN(0x98da4836, 0x1c55d39a), - TOBN(0xc2007cb8, 0xa163bf05), TOBN(0x49286651, 0xece45b3d), - TOBN(0xae9f2411, 0x7c4b1fe6), TOBN(0xee386bfb, 0x5a899fa5), - TOBN(0x0bff5cb6, 0xf406b7ed), TOBN(0xf44c42e9, 0xa637ed6b), - TOBN(0xe485b576, 0x625e7ec6), TOBN(0x4fe1356d, 0x6d51c245), - TOBN(0x302b0a6d, 0xf25f1437), TOBN(0xef9519b3, 0xcd3a431b), - TOBN(0x514a0879, 0x8e3404dd), TOBN(0x020bbea6, 0x3b139b22), - TOBN(0x29024e08, 0x8a67cc74), TOBN(0xc4c6628b, 0x80dc1cd1), - TOBN(0xc90fdaa2, 0x2168c234), TOBN(0xffffffff, 0xffffffff), - }; - return get_params(ret, kWords, OPENSSL_ARRAY_SIZE(kWords)); + // Determine output buffer sizes + size_t ciphertext_len = 0; + size_t shared_key_len = 0; + + if (EVP_PKEY_encapsulate( + ctx.get(), nullptr, &ciphertext_len, nullptr, &shared_key_len) <= 0) { + return std::nullopt; + } + + auto ciphertext = DataPointer::Alloc(ciphertext_len); + auto shared_key = DataPointer::Alloc(shared_key_len); + if (!ciphertext || !shared_key) return std::nullopt; + + if (EVP_PKEY_encapsulate(ctx.get(), + static_cast(ciphertext.get()), + &ciphertext_len, + static_cast(shared_key.get()), + &shared_key_len) <= 0) { + return std::nullopt; + } + + return EncapsulateResult(std::move(ciphertext), std::move(shared_key)); } + +DataPointer KEM::Decapsulate(const EVPKeyPointer& private_key, + const Buffer& ciphertext) { + ClearErrorOnReturn clear_error_on_return; + + auto ctx = private_key.newCtx(); + if (!ctx) return {}; + + if (EVP_PKEY_decapsulate_init(ctx.get(), nullptr) <= 0) { + return {}; + } + +#if !OPENSSL_VERSION_PREREQ(3, 5) + if (!SetOperationParameter(ctx.get(), private_key)) { + return {}; + } #endif + + // First pass: determine shared secret size + size_t shared_key_len = 0; + if (EVP_PKEY_decapsulate(ctx.get(), + nullptr, + &shared_key_len, + static_cast(ciphertext.data), + ciphertext.len) <= 0) { + return {}; + } + + auto shared_key = DataPointer::Alloc(shared_key_len); + if (!shared_key) return {}; + + if (EVP_PKEY_decapsulate(ctx.get(), + static_cast(shared_key.get()), + &shared_key_len, + static_cast(ciphertext.data), + ciphertext.len) <= 0) { + return {}; + } + + return shared_key; +} + +#endif // OPENSSL_VERSION_MAJOR >= 3 + +} // namespace ncrypto diff --git a/packages/react-native-quick-crypto/deps/ncrypto/include/ncrypto.h b/packages/react-native-quick-crypto/deps/ncrypto/ncrypto.h similarity index 78% rename from packages/react-native-quick-crypto/deps/ncrypto/include/ncrypto.h rename to packages/react-native-quick-crypto/deps/ncrypto/ncrypto.h index be9e0ca7..6c62aa28 100644 --- a/packages/react-native-quick-crypto/deps/ncrypto/include/ncrypto.h +++ b/packages/react-native-quick-crypto/deps/ncrypto/ncrypto.h @@ -8,10 +8,10 @@ #include #include #include +#include #include #include #include - #include #include #include @@ -28,6 +28,15 @@ #include #endif // OPENSSL_FIPS +// Define OPENSSL_WITH_PQC for post-quantum cryptography support +#if OPENSSL_VERSION_NUMBER >= 0x30500000L +#define OPENSSL_WITH_PQC 1 +#define EVP_PKEY_ML_KEM_512 NID_ML_KEM_512 +#define EVP_PKEY_ML_KEM_768 NID_ML_KEM_768 +#define EVP_PKEY_ML_KEM_1024 NID_ML_KEM_1024 +#include +#endif + #if OPENSSL_VERSION_MAJOR >= 3 #define OSSL3_CONST const #else @@ -48,12 +57,6 @@ using OPENSSL_SIZE_T = size_t; using OPENSSL_SIZE_T = int; #endif -#ifdef OPENSSL_IS_BORINGSSL -#ifdef NCRYPTO_BSSL_NEEDS_DH_PRIMES -#include "dh-primes.h" -#endif // NCRYPTO_BSSL_NEEDS_DH_PRIMES -#endif // OPENSSL_IS_BORINGSSL - namespace ncrypto { // ============================================================================ @@ -61,14 +64,14 @@ namespace ncrypto { #if NCRYPTO_DEVELOPMENT_CHECKS #define NCRYPTO_STR(x) #x -#define NCRYPTO_REQUIRE(EXPR) \ - { \ +#define NCRYPTO_REQUIRE(EXPR) \ + { \ if (!(EXPR) { abort(); }) } -#define NCRYPTO_FAIL(MESSAGE) \ - do { \ - std::cerr << "FAIL: " << (MESSAGE) << std::endl; \ - abort(); \ +#define NCRYPTO_FAIL(MESSAGE) \ + do { \ + std::cerr << "FAIL: " << (MESSAGE) << std::endl; \ + abort(); \ } while (0); #define NCRYPTO_ASSERT_EQUAL(LHS, RHS, MESSAGE) \ do { \ @@ -77,13 +80,13 @@ namespace ncrypto { NCRYPTO_FAIL(MESSAGE); \ } \ } while (0); -#define NCRYPTO_ASSERT_TRUE(COND) \ - do { \ - if (!(COND)) { \ - std::cerr << "Assert at line " << __LINE__ << " of file " << __FILE__ \ - << std::endl; \ - NCRYPTO_FAIL(NCRYPTO_STR(COND)); \ - } \ +#define NCRYPTO_ASSERT_TRUE(COND) \ + do { \ + if (!(COND)) { \ + std::cerr << "Assert at line " << __LINE__ << " of file " << __FILE__ \ + << std::endl; \ + NCRYPTO_FAIL(NCRYPTO_STR(COND)); \ + } \ } while (0); #else #define NCRYPTO_FAIL(MESSAGE) @@ -91,17 +94,17 @@ namespace ncrypto { #define NCRYPTO_ASSERT_TRUE(COND) #endif -#define NCRYPTO_DISALLOW_COPY(Name) \ - Name(const Name&) = delete; \ +#define NCRYPTO_DISALLOW_COPY(Name) \ + Name(const Name&) = delete; \ Name& operator=(const Name&) = delete; -#define NCRYPTO_DISALLOW_MOVE(Name) \ - Name(Name&&) = delete; \ +#define NCRYPTO_DISALLOW_MOVE(Name) \ + Name(Name&&) = delete; \ Name& operator=(Name&&) = delete; -#define NCRYPTO_DISALLOW_COPY_AND_MOVE(Name) \ - NCRYPTO_DISALLOW_COPY(Name) \ +#define NCRYPTO_DISALLOW_COPY_AND_MOVE(Name) \ + NCRYPTO_DISALLOW_COPY(Name) \ NCRYPTO_DISALLOW_MOVE(Name) -#define NCRYPTO_DISALLOW_NEW_DELETE() \ - void* operator new(size_t) = delete; \ +#define NCRYPTO_DISALLOW_NEW_DELETE() \ + void* operator new(size_t) = delete; \ void operator delete(void*) = delete; [[noreturn]] inline void unreachable() { @@ -253,11 +256,58 @@ struct Buffer { size_t len = 0; }; +class Digest final { + public: + static constexpr size_t MAX_SIZE = EVP_MAX_MD_SIZE; + Digest() = default; + Digest(const EVP_MD* md) : md_(md) {} + Digest(const Digest&) = default; + Digest& operator=(const Digest&) = default; + inline Digest& operator=(const EVP_MD* md) { + md_ = md; + return *this; + } + NCRYPTO_DISALLOW_MOVE(Digest) + + size_t size() const; + + inline const EVP_MD* get() const { return md_; } + inline operator const EVP_MD*() const { return md_; } + inline operator bool() const { return md_ != nullptr; } + + static const Digest MD5; + static const Digest SHA1; + static const Digest SHA256; + static const Digest SHA384; + static const Digest SHA512; + + static const Digest FromName(const char* name); + + private: + const EVP_MD* md_ = nullptr; +}; + +// Computes a fixed-length digest. DataPointer hashDigest(const Buffer& data, const EVP_MD* md); +// Computes a variable-length digest for XOF algorithms (e.g. SHAKE128). +DataPointer xofHashDigest(const Buffer& data, + const EVP_MD* md, + size_t length); class Cipher final { public: + static constexpr size_t MAX_KEY_LENGTH = EVP_MAX_KEY_LENGTH; + static constexpr size_t MAX_IV_LENGTH = EVP_MAX_IV_LENGTH; +#ifdef EVP_MAX_AEAD_TAG_LENGTH + static constexpr size_t MAX_AUTH_TAG_LENGTH = EVP_MAX_AEAD_TAG_LENGTH; +#else + static constexpr size_t MAX_AUTH_TAG_LENGTH = 16; +#endif + static_assert(EVP_GCM_TLS_TAG_LEN <= MAX_AUTH_TAG_LENGTH && + EVP_CCM_TLS_TAG_LEN <= MAX_AUTH_TAG_LENGTH && + EVP_CHACHAPOLY_TLS_TAG_LEN <= MAX_AUTH_TAG_LENGTH); + Cipher() = default; Cipher(const EVP_CIPHER* cipher) : cipher_(cipher) {} Cipher(const Cipher&) = default; @@ -278,17 +328,59 @@ class Cipher final { int getKeyLength() const; int getBlockSize() const; std::string_view getModeLabel() const; - std::string_view getName() const; + const char* getName() const; + + bool isGcmMode() const; + bool isWrapMode() const; + bool isCtrMode() const; + bool isCcmMode() const; + bool isOcbMode() const; + bool isStreamMode() const; + bool isChaCha20Poly1305() const; bool isSupportedAuthenticatedMode() const; - static const Cipher FromName(std::string_view name); + int bytesToKey(const Digest& digest, + const Buffer& input, + unsigned char* key, + unsigned char* iv) const; + + static const Cipher FromName(const char* name); static const Cipher FromNid(int nid); static const Cipher FromCtx(const CipherCtxPointer& ctx); + using CipherNameCallback = std::function; + + // Iterates the known ciphers if the underlying implementation + // is able to do so. + static void ForEach(CipherNameCallback callback); + + // Utilities to get various ciphers by type. If the underlying + // implementation does not support the requested cipher, then + // the result will be an empty Cipher object whose bool operator + // will return false. + + static const Cipher EMPTY; + static const Cipher AES_128_CBC; + static const Cipher AES_192_CBC; + static const Cipher AES_256_CBC; + static const Cipher AES_128_CTR; + static const Cipher AES_192_CTR; + static const Cipher AES_256_CTR; + static const Cipher AES_128_GCM; + static const Cipher AES_192_GCM; + static const Cipher AES_256_GCM; + static const Cipher AES_128_KW; + static const Cipher AES_192_KW; + static const Cipher AES_256_KW; + static const Cipher AES_128_OCB; + static const Cipher AES_192_OCB; + static const Cipher AES_256_OCB; + static const Cipher CHACHA20_POLY1305; + struct CipherParams { int padding; - const EVP_MD* digest; + Digest digest; const Buffer label; }; @@ -299,7 +391,8 @@ class Cipher final { const CipherParams& params, const Buffer in); - static DataPointer sign(const EVPKeyPointer& key, const CipherParams& params, + static DataPointer sign(const EVPKeyPointer& key, + const CipherParams& params, const Buffer in); static DataPointer recover(const EVPKeyPointer& key, @@ -335,77 +428,8 @@ class Dsa final { OSSL3_CONST DSA* dsa_; }; -class BignumPointer final { - public: - BignumPointer() = default; - explicit BignumPointer(BIGNUM* bignum); - explicit BignumPointer(const unsigned char* data, size_t len); - BignumPointer(BignumPointer&& other) noexcept; - BignumPointer& operator=(BignumPointer&& other) noexcept; - NCRYPTO_DISALLOW_COPY(BignumPointer) - ~BignumPointer(); - - int operator<=>(const BignumPointer& other) const noexcept; - int operator<=>(const BIGNUM* other) const noexcept; - inline operator bool() const { return bn_ != nullptr; } - inline BIGNUM* get() const noexcept { return bn_.get(); } - void reset(BIGNUM* bn = nullptr); - void reset(const unsigned char* data, size_t len); - BIGNUM* release(); - - bool isZero() const; - bool isOne() const; - - bool setWord(unsigned long w); // NOLINT(runtime/int) - unsigned long getWord() const; // NOLINT(runtime/int) - - size_t byteLength() const; - size_t bitLength() const; - - DataPointer toHex() const; - DataPointer encode() const; - DataPointer encodePadded(size_t size) const; - size_t encodeInto(unsigned char* out) const; - size_t encodePaddedInto(unsigned char* out, size_t size) const; - - using PrimeCheckCallback = std::function; - int isPrime(int checks, - PrimeCheckCallback cb = defaultPrimeCheckCallback) const; - struct PrimeConfig { - int bits; - bool safe = false; - const BignumPointer& add; - const BignumPointer& rem; - }; - - static BignumPointer NewPrime( - const PrimeConfig& params, - PrimeCheckCallback cb = defaultPrimeCheckCallback); - - bool generate(const PrimeConfig& params, - PrimeCheckCallback cb = defaultPrimeCheckCallback) const; - - static BignumPointer New(); - static BignumPointer NewSecure(); - static BignumPointer NewSub(const BignumPointer& a, const BignumPointer& b); - static BignumPointer NewLShift(size_t length); - - static DataPointer Encode(const BIGNUM* bn); - static DataPointer EncodePadded(const BIGNUM* bn, size_t size); - static size_t EncodePaddedInto(const BIGNUM* bn, unsigned char* out, - size_t size); - static int GetBitCount(const BIGNUM* bn); - static int GetByteCount(const BIGNUM* bn); - static unsigned long GetWord(const BIGNUM* bn); // NOLINT(runtime/int) - static const BIGNUM* One(); - - BignumPointer clone(); - - private: - DeleteFnPtr bn_; - - static bool defaultPrimeCheckCallback(int, int) { return 1; } -}; +// ============================================================================ +// RSA class Rsa final { public: @@ -439,8 +463,11 @@ class Rsa final { const std::optional getPssParams() const; bool setPublicKey(BignumPointer&& n, BignumPointer&& e); - bool setPrivateKey(BignumPointer&& d, BignumPointer&& q, BignumPointer&& p, - BignumPointer&& dp, BignumPointer&& dq, + bool setPrivateKey(BignumPointer&& d, + BignumPointer&& q, + BignumPointer&& p, + BignumPointer&& dp, + BignumPointer&& dq, BignumPointer&& qi); using CipherParams = Cipher::CipherParams; @@ -464,24 +491,17 @@ class Ec final { const EC_GROUP* getGroup() const; int getCurve() const; - uint32_t getDegree() const; - std::string getCurveName() const; - const EC_POINT* getPublicKey() const; - const BIGNUM* getPrivateKey() const; inline operator bool() const { return ec_ != nullptr; } inline operator OSSL3_CONST EC_KEY*() const { return ec_; } - inline const BignumPointer& getX() const { return x_; } - inline const BignumPointer& getY() const { return y_; } - inline const BignumPointer& getD() const { return d_; } + static int GetCurveIdFromName(const char* name); + + using GetCurveCallback = std::function; + static bool GetCurves(GetCurveCallback callback); private: OSSL3_CONST EC_KEY* ec_ = nullptr; - // Affine coordinates for the EC_KEY. - BignumPointer x_; - BignumPointer y_; - BignumPointer d_; }; // A managed pointer to a buffer of data. When destroyed the underlying @@ -491,9 +511,31 @@ class DataPointer final { static DataPointer Alloc(size_t len); static DataPointer Copy(const Buffer& buffer); + // Attempts to allocate the buffer space using the secure heap, if + // supported/enabled. If the secure heap is disabled, then this + // ends up being equivalent to Alloc(len). Note that allocation + // will fail if there is not enough free space remaining in the + // secure heap space. + static DataPointer SecureAlloc(size_t len); + + // If the secure heap is enabled, returns the amount of data that + // has been allocated from the heap. + static size_t GetSecureHeapUsed(); + + enum class InitSecureHeapResult { + FAILED, + UNABLE_TO_MEMORY_MAP, + OK, + }; + + // Attempt to initialize the secure heap. The secure heap is not + // supported on all operating systems and whenever boringssl is + // used. + static InitSecureHeapResult TryInitSecureHeap(size_t amount, size_t min); + DataPointer() = default; - explicit DataPointer(void* data, size_t len); - explicit DataPointer(const Buffer& buffer); + explicit DataPointer(void* data, size_t len, bool secure = false); + explicit DataPointer(const Buffer& buffer, bool secure = false); DataPointer(DataPointer&& other) noexcept; DataPointer& operator=(DataPointer&& other) noexcept; NCRYPTO_DISALLOW_COPY(DataPointer) @@ -529,9 +571,12 @@ class DataPointer final { }; } + bool isSecure() const { return secure_; } + private: void* data_ = nullptr; size_t len_ = 0; + bool secure_ = false; }; class BIOPointer final { @@ -541,7 +586,7 @@ class BIOPointer final { static BIOPointer New(const BIO_METHOD* method); static BIOPointer New(const void* data, size_t len); static BIOPointer New(const BIGNUM* bn); - static BIOPointer NewFile(std::string_view filename, std::string_view mode); + static BIOPointer NewFile(const char* filename, const char* mode); static BIOPointer NewFp(FILE* fd, int flags); template @@ -587,6 +632,78 @@ class BIOPointer final { mutable DeleteFnPtr bio_; }; +class BignumPointer final { + public: + BignumPointer() = default; + explicit BignumPointer(BIGNUM* bignum); + explicit BignumPointer(const unsigned char* data, size_t len); + BignumPointer(BignumPointer&& other) noexcept; + BignumPointer& operator=(BignumPointer&& other) noexcept; + NCRYPTO_DISALLOW_COPY(BignumPointer) + ~BignumPointer(); + + int operator<=>(const BignumPointer& other) const noexcept; + int operator<=>(const BIGNUM* other) const noexcept; + inline operator bool() const { return bn_ != nullptr; } + inline BIGNUM* get() const noexcept { return bn_.get(); } + void reset(BIGNUM* bn = nullptr); + void reset(const unsigned char* data, size_t len); + BIGNUM* release(); + + bool isZero() const; + bool isOne() const; + + bool setWord(unsigned long w); // NOLINT(runtime/int) + unsigned long getWord() const; // NOLINT(runtime/int) + + size_t byteLength() const; + + DataPointer toHex() const; + DataPointer encode() const; + DataPointer encodePadded(size_t size) const; + size_t encodeInto(unsigned char* out) const; + size_t encodePaddedInto(unsigned char* out, size_t size) const; + + using PrimeCheckCallback = std::function; + int isPrime(int checks, + PrimeCheckCallback cb = defaultPrimeCheckCallback) const; + struct PrimeConfig { + int bits; + bool safe = false; + const BignumPointer& add; + const BignumPointer& rem; + }; + + static BignumPointer NewPrime( + const PrimeConfig& params, + PrimeCheckCallback cb = defaultPrimeCheckCallback); + + bool generate(const PrimeConfig& params, + PrimeCheckCallback cb = defaultPrimeCheckCallback) const; + + static BignumPointer New(); + static BignumPointer NewSecure(); + static BignumPointer NewSub(const BignumPointer& a, const BignumPointer& b); + static BignumPointer NewLShift(size_t length); + + static DataPointer Encode(const BIGNUM* bn); + static DataPointer EncodePadded(const BIGNUM* bn, size_t size); + static size_t EncodePaddedInto(const BIGNUM* bn, + unsigned char* out, + size_t size); + static int GetBitCount(const BIGNUM* bn); + static int GetByteCount(const BIGNUM* bn); + static unsigned long GetWord(const BIGNUM* bn); // NOLINT(runtime/int) + static const BIGNUM* One(); + + BignumPointer clone(); + + private: + DeleteFnPtr bn_; + + static bool defaultPrimeCheckCallback(int, int) { return 1; } +}; + class CipherCtxPointer final { public: static CipherCtxPointer New(); @@ -607,13 +724,15 @@ class CipherCtxPointer final { void reset(EVP_CIPHER_CTX* ctx = nullptr); EVP_CIPHER_CTX* release(); - void setFlags(int flags); + void setAllowWrap(); + bool setKeyLength(size_t length); bool setIvLength(size_t length); bool setAeadTag(const Buffer& tag); bool setAeadTagLength(size_t length); bool setPadding(bool padding); - bool init(const Cipher& cipher, bool encrypt, + bool init(const Cipher& cipher, + bool encrypt, const unsigned char* key = nullptr, const unsigned char* iv = nullptr); @@ -621,8 +740,16 @@ class CipherCtxPointer final { int getMode() const; int getNid() const; - bool update(const Buffer& in, unsigned char* out, - int* out_len, bool finalize = false); + bool isGcmMode() const; + bool isOcbMode() const; + bool isCcmMode() const; + bool isWrapMode() const; + bool isChaCha20Poly1305() const; + + bool update(const Buffer& in, + unsigned char* out, + int* out_len, + bool finalize = false); bool getAeadTag(size_t len, unsigned char* out); private: @@ -654,13 +781,13 @@ class EVPKeyCtxPointer final { bool setDsaParameters(uint32_t bits, std::optional q_bits); bool setEcParameters(int curve, int encoding); - bool setRsaOaepMd(const EVP_MD* md); - bool setRsaMgf1Md(const EVP_MD* md); + bool setRsaOaepMd(const Digest& md); + bool setRsaMgf1Md(const Digest& md); bool setRsaPadding(int padding); bool setRsaKeygenPubExp(BignumPointer&& e); bool setRsaKeygenBits(int bits); - bool setRsaPssKeygenMd(const EVP_MD* md); - bool setRsaPssKeygenMgf1Md(const EVP_MD* md); + bool setRsaPssKeygenMd(const Digest& md); + bool setRsaPssKeygenMgf1Md(const Digest& md); bool setRsaPssSaltlen(int salt_len); bool setRsaImplicitRejection(); bool setRsaOaepLabel(DataPointer&& data); @@ -678,7 +805,8 @@ class EVPKeyCtxPointer final { static constexpr int kDefaultRsaExponent = 0x10001; - static bool setRsaPadding(EVP_PKEY_CTX* ctx, int padding, + static bool setRsaPadding(EVP_PKEY_CTX* ctx, + int padding, std::optional salt_len = std::nullopt); EVPKeyPointer paramgen() const; @@ -703,6 +831,10 @@ class EVPKeyPointer final { const Buffer& data); static EVPKeyPointer NewRawPrivate(int id, const Buffer& data); +#if OPENSSL_WITH_PQC + static EVPKeyPointer NewRawSeed(int id, + const Buffer& data); +#endif static EVPKeyPointer NewDH(DHPointer&& dh); static EVPKeyPointer NewRSA(RSAPointer&& rsa); @@ -731,7 +863,8 @@ class EVPKeyPointer final { PKFormatType format = PKFormatType::DER; PKEncodingType type = PKEncodingType::PKCS8; AsymmetricKeyEncodingConfig() = default; - AsymmetricKeyEncodingConfig(bool output_key_object, PKFormatType format, + AsymmetricKeyEncodingConfig(bool output_key_object, + PKFormatType format, PKEncodingType type); AsymmetricKeyEncodingConfig(const AsymmetricKeyEncodingConfig&) = default; AsymmetricKeyEncodingConfig& operator=(const AsymmetricKeyEncodingConfig&) = @@ -743,7 +876,8 @@ class EVPKeyPointer final { const EVP_CIPHER* cipher = nullptr; std::optional passphrase = std::nullopt; PrivateKeyEncodingConfig() = default; - PrivateKeyEncodingConfig(bool output_key_object, PKFormatType format, + PrivateKeyEncodingConfig(bool output_key_object, + PKFormatType format, PKEncodingType type) : AsymmetricKeyEncodingConfig(output_key_object, format, type) {} PrivateKeyEncodingConfig(const PrivateKeyEncodingConfig&); @@ -794,6 +928,10 @@ class EVPKeyPointer final { DataPointer rawPrivateKey() const; BIOPointer derPublicKey() const; +#if OPENSSL_WITH_PQC + DataPointer rawSeed() const; +#endif + Result writePrivateKey( const PrivateKeyEncodingConfig& config) const; Result writePublicKey( @@ -807,15 +945,12 @@ class EVPKeyPointer final { int getDefaultSignPadding() const; operator Rsa() const; operator Dsa() const; - operator Ec() const; bool isRsaVariant() const; bool isOneShotVariant() const; bool isSigVariant() const; bool validateDsaParameters() const; - EVPKeyPointer clone() const; - private: DeleteFnPtr pkey_; }; @@ -833,9 +968,8 @@ class DHPointer final { static BignumPointer GetStandardGenerator(); static BignumPointer FindGroup( - const std::string_view name, - FindGroupOption option = FindGroupOption::NONE); - static DHPointer FromGroup(const std::string_view name, + std::string_view name, FindGroupOption option = FindGroupOption::NONE); + static DHPointer FromGroup(std::string_view name, FindGroupOption option = FindGroupOption::NONE); static DHPointer New(BignumPointer&& p, BignumPointer&& g); @@ -934,6 +1068,8 @@ class SSLCtxPointer final { SSL_CTX_set_tlsext_status_arg(get(), nullptr); } + bool setCipherSuites(const char* ciphers); + static SSLCtxPointer NewServer(); static SSLCtxPointer NewClient(); static SSLCtxPointer New(const SSL_METHOD* method = TLS_method()); @@ -961,8 +1097,8 @@ class SSLPointer final { bool setSession(const SSLSessionPointer& session); bool setSniContext(const SSLCtxPointer& ctx) const; - const std::string_view getClientHelloAlpn() const; - const std::string_view getClientHelloServerName() const; + const char* getClientHelloAlpn() const; + const char* getClientHelloServerName() const; std::optional getServerName() const; X509View getCertificate() const; @@ -976,7 +1112,9 @@ class SSLPointer final { std::optional verifyPeerCertificate() const; - void getCiphers(std::function cb) const; + static std::optional getSecurityLevel(); + + void getCiphers(std::function cb) const; static SSLPointer New(const SSLCtxPointer& ctx); static std::optional GetServerName(const SSL* ssl); @@ -1062,7 +1200,7 @@ class X509View final { bool checkPrivateKey(const EVPKeyPointer& pkey) const; bool checkPublicKey(const EVPKeyPointer& pkey) const; - std::optional getFingerprint(const EVP_MD* method) const; + std::optional getFingerprint(const Digest& method) const; X509Pointer clone() const; @@ -1072,12 +1210,13 @@ class X509View final { INVALID_NAME, OPERATION_FAILED, }; - CheckMatch checkHost(const std::string_view host, int flags, + CheckMatch checkHost(std::string_view host, + int flags, DataPointer* peerName = nullptr) const; - CheckMatch checkEmail(const std::string_view email, int flags) const; - CheckMatch checkIp(const std::string_view ip, int flags) const; + CheckMatch checkEmail(std::string_view email, int flags) const; + CheckMatch checkIp(std::string_view ip, int flags) const; - using UsageCallback = std::function; + using UsageCallback = std::function; bool enumUsages(UsageCallback callback) const; template @@ -1114,8 +1253,8 @@ class X509Pointer final { X509View view() const; operator X509View() const { return view(); } - static std::string_view ErrorCode(int32_t err); - static std::optional ErrorReason(int32_t err); + static const char* ErrorCode(int32_t err); + static std::optional ErrorReason(int32_t err); private: DeleteFnPtr cert_; @@ -1257,16 +1396,16 @@ class EVPMDCtxPointer final { void reset(EVP_MD_CTX* ctx = nullptr); EVP_MD_CTX* release(); - bool digestInit(const EVP_MD* digest); + bool digestInit(const Digest& digest); bool digestUpdate(const Buffer& in); DataPointer digestFinal(size_t length); bool digestFinalInto(Buffer* buf); size_t getExpectedSize(); std::optional signInit(const EVPKeyPointer& key, - const EVP_MD* digest); + const Digest& digest); std::optional verifyInit(const EVPKeyPointer& key, - const EVP_MD* digest); + const Digest& digest); DataPointer signOneShot(const Buffer& buf) const; DataPointer sign(const Buffer& buf) const; @@ -1301,7 +1440,7 @@ class HMACCtxPointer final { void reset(HMAC_CTX* ctx = nullptr); HMAC_CTX* release(); - bool init(const Buffer& buf, const EVP_MD* md); + bool init(const Buffer& buf, const Digest& md); bool update(const Buffer& buf); DataPointer digest(); bool digestInto(Buffer* buf); @@ -1331,7 +1470,7 @@ class EnginePointer final { bool setAsDefault(uint32_t flags, CryptoErrorList* errors = nullptr); bool init(bool finish_on_exit = false); - EVPKeyPointer loadPrivateKey(const std::string_view key_name); + EVPKeyPointer loadPrivateKey(const char* key_name); // Release ownership of the ENGINE* pointer. ENGINE* release(); @@ -1339,7 +1478,7 @@ class EnginePointer final { // Retrieve an OpenSSL Engine instance by name. If the name does not // identify a valid named engine, the returned EnginePointer will be // empty. - static EnginePointer getEngineByName(const std::string_view name, + static EnginePointer getEngineByName(const char* name, CryptoErrorList* errors = nullptr); // Call once when initializing OpenSSL at startup for the process. @@ -1379,62 +1518,100 @@ bool SafeX509InfoAccessPrint(const BIOPointer& out, X509_EXTENSION* ext); // ============================================================================ // SPKAC -[[deprecated("Use the version that takes a Buffer")]] bool VerifySpkac( - const char* input, size_t length); - -[[deprecated("Use the version that takes a Buffer")]] BIOPointer -ExportPublicKey(const char* input, size_t length); +bool VerifySpkac(const char* input, size_t length); +BIOPointer ExportPublicKey(const char* input, size_t length); // The caller takes ownership of the returned Buffer -[[deprecated("Use the version that takes a Buffer")]] Buffer -ExportChallenge(const char* input, size_t length); - -bool VerifySpkac(const Buffer& buf); -BIOPointer ExportPublicKey(const Buffer& buf); -DataPointer ExportChallenge(const Buffer& buf); +Buffer ExportChallenge(const char* input, size_t length); // ============================================================================ // KDF -const EVP_MD* getDigestByName(const std::string_view name); -const EVP_CIPHER* getCipherByName(const std::string_view name); +const EVP_MD* getDigestByName(const char* name); +const EVP_CIPHER* getCipherByName(const char* name); // Verify that the specified HKDF output length is valid for the given digest. // The maximum length for HKDF output for a given digest is 255 times the // hash size for the given digest algorithm. -bool checkHkdfLength(const EVP_MD* md, size_t length); +bool checkHkdfLength(const Digest& digest, size_t length); -bool extractP1363(const Buffer& buf, unsigned char* dest, +bool extractP1363(const Buffer& buf, + unsigned char* dest, size_t n); -bool hkdfInfo(const EVP_MD* md, const Buffer& key, - const Buffer& info, - const Buffer& salt, size_t length, - Buffer* out); - -DataPointer hkdf(const EVP_MD* md, const Buffer& key, +DataPointer hkdf(const Digest& md, + const Buffer& key, const Buffer& info, - const Buffer& salt, size_t length); + const Buffer& salt, + size_t length); bool checkScryptParams(uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem); -bool scryptInto(const Buffer& pass, - const Buffer& salt, uint64_t N, uint64_t r, - uint64_t p, uint64_t maxmem, size_t length, - Buffer* out); - DataPointer scrypt(const Buffer& pass, - const Buffer& salt, uint64_t N, - uint64_t r, uint64_t p, uint64_t maxmem, size_t length); - -bool pbkdf2Into(const EVP_MD* md, const Buffer& pass, - const Buffer& salt, uint32_t iterations, - size_t length, Buffer* out); + const Buffer& salt, + uint64_t N, + uint64_t r, + uint64_t p, + uint64_t maxmem, + size_t length); -DataPointer pbkdf2(const EVP_MD* md, const Buffer& pass, - const Buffer& salt, uint32_t iterations, +DataPointer pbkdf2(const Digest& md, + const Buffer& pass, + const Buffer& salt, + uint32_t iterations, size_t length); +#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 + // ============================================================================ // Version metadata #define NCRYPTO_VERSION "0.0.1" diff --git a/packages/react-native-quick-crypto/deps/ncrypto/pyproject.toml b/packages/react-native-quick-crypto/deps/ncrypto/pyproject.toml deleted file mode 100644 index 655257f0..00000000 --- a/packages/react-native-quick-crypto/deps/ncrypto/pyproject.toml +++ /dev/null @@ -1,38 +0,0 @@ -[project] -name = "ncrypto" -requires-python = ">=3.12" - -[tool.ruff] -line-length = 120 -target-version = "py312" - -[tool.ruff.format] -quote-style = "single" -indent-style = "space" -docstring-code-format = true - -[tool.ruff.lint] -select = [ - "C90", # McCabe cyclomatic complexity - "E", # pycodestyle - "F", # Pyflakes - "ICN", # flake8-import-conventions - "INT", # flake8-gettext - "PLC", # Pylint conventions - "PLE", # Pylint errors - "PLR09", # Pylint refactoring: max-args, max-branches, max returns, max-statements - "PYI", # flake8-pyi - "RSE", # flake8-raise - "RUF", # Ruff-specific rules - "T10", # flake8-debugger - "TCH", # flake8-type-checking - "TID", # flake8-tidy-imports - "W", # pycodestyle - "YTT", # flake8-2020 - "ANN" # flake8-annotations -] -ignore = [ - "E722", # Do not use bare `except` - "ANN101", # Missing type annotation for self in method - "TID252", # Prefer absolute imports over relative imports from parent modules -] \ No newline at end of file diff --git a/packages/react-native-quick-crypto/deps/ncrypto/src/CMakeLists.txt b/packages/react-native-quick-crypto/deps/ncrypto/src/CMakeLists.txt deleted file mode 100644 index cb07cb8c..00000000 --- a/packages/react-native-quick-crypto/deps/ncrypto/src/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -add_library(ncrypto ncrypto.cpp engine.cpp) -target_link_libraries(ncrypto PUBLIC ssl crypto) -target_include_directories(ncrypto - PUBLIC - $ - $ - $ -) diff --git a/packages/react-native-quick-crypto/deps/ncrypto/src/engine.cpp b/packages/react-native-quick-crypto/deps/ncrypto/src/engine.cpp deleted file mode 100644 index 3f01ac54..00000000 --- a/packages/react-native-quick-crypto/deps/ncrypto/src/engine.cpp +++ /dev/null @@ -1,91 +0,0 @@ -#include "ncrypto.h" - -namespace ncrypto { - -// ============================================================================ -// Engine - -#ifndef OPENSSL_NO_ENGINE -EnginePointer::EnginePointer(ENGINE* engine_, bool finish_on_exit_) - : engine(engine_), finish_on_exit(finish_on_exit_) {} - -EnginePointer::EnginePointer(EnginePointer&& other) noexcept - : engine(other.engine), finish_on_exit(other.finish_on_exit) { - other.release(); -} - -EnginePointer::~EnginePointer() { reset(); } - -EnginePointer& EnginePointer::operator=(EnginePointer&& other) noexcept { - if (this == &other) return *this; - this->~EnginePointer(); - return *new (this) EnginePointer(std::move(other)); -} - -void EnginePointer::reset(ENGINE* engine_, bool finish_on_exit_) { - if (engine != nullptr) { - if (finish_on_exit) { - // This also does the equivalent of ENGINE_free. - ENGINE_finish(engine); - } else { - ENGINE_free(engine); - } - } - engine = engine_; - finish_on_exit = finish_on_exit_; -} - -ENGINE* EnginePointer::release() { - ENGINE* ret = engine; - engine = nullptr; - finish_on_exit = false; - return ret; -} - -EnginePointer EnginePointer::getEngineByName(const std::string_view name, - CryptoErrorList* errors) { - MarkPopErrorOnReturn mark_pop_error_on_return(errors); - EnginePointer engine(ENGINE_by_id(name.data())); - if (!engine) { - // Engine not found, try loading dynamically. - engine = EnginePointer(ENGINE_by_id("dynamic")); - if (engine) { - if (!ENGINE_ctrl_cmd_string(engine.get(), "SO_PATH", name.data(), 0) || - !ENGINE_ctrl_cmd_string(engine.get(), "LOAD", nullptr, 0)) { - engine.reset(); - } - } - } - return engine; -} - -bool EnginePointer::setAsDefault(uint32_t flags, CryptoErrorList* errors) { - if (engine == nullptr) return false; - ClearErrorOnReturn clear_error_on_return(errors); - return ENGINE_set_default(engine, flags) != 0; -} - -bool EnginePointer::init(bool finish_on_exit) { - if (engine == nullptr) return false; - if (finish_on_exit) setFinishOnExit(); - return ENGINE_init(engine) == 1; -} - -EVPKeyPointer EnginePointer::loadPrivateKey(const std::string_view key_name) { - if (engine == nullptr) return EVPKeyPointer(); - return EVPKeyPointer( - ENGINE_load_private_key(engine, key_name.data(), nullptr, nullptr)); -} - -void EnginePointer::initEnginesOnce() { - static bool initialized = false; - if (!initialized) { - ENGINE_load_builtin_engines(); - ENGINE_register_all_complete(); - initialized = true; - } -} - -#endif // OPENSSL_NO_ENGINE - -} // namespace ncrypto diff --git a/packages/react-native-quick-crypto/deps/ncrypto/tests/BUILD.bazel b/packages/react-native-quick-crypto/deps/ncrypto/tests/BUILD.bazel deleted file mode 100644 index 7d9563b4..00000000 --- a/packages/react-native-quick-crypto/deps/ncrypto/tests/BUILD.bazel +++ /dev/null @@ -1,9 +0,0 @@ -cc_test( - name = "basic", - srcs = ["basic.cpp"], - deps = [ - "//:ncrypto", - "@googletest//:gtest", - "@googletest//:gtest_main", - ], -) diff --git a/packages/react-native-quick-crypto/deps/ncrypto/tests/CMakeLists.txt b/packages/react-native-quick-crypto/deps/ncrypto/tests/CMakeLists.txt deleted file mode 100644 index 17866ff6..00000000 --- a/packages/react-native-quick-crypto/deps/ncrypto/tests/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -include(GoogleTest) -add_executable(basic basic.cpp) -target_link_libraries(basic PRIVATE ncrypto GTest::gtest_main) -gtest_discover_tests(basic) -if(MSVC OR MINGW) - target_compile_definitions(basic PRIVATE _CRT_SECURE_NO_WARNINGS) -endif() diff --git a/packages/react-native-quick-crypto/deps/ncrypto/tests/basic.cpp b/packages/react-native-quick-crypto/deps/ncrypto/tests/basic.cpp deleted file mode 100644 index 8054a449..00000000 --- a/packages/react-native-quick-crypto/deps/ncrypto/tests/basic.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// #include - -// #include - -// TEST(basic, test_it) { SUCCEED(); } diff --git a/packages/react-native-quick-crypto/deps/ncrypto/tools/run-clang-format.sh b/packages/react-native-quick-crypto/deps/ncrypto/tools/run-clang-format.sh deleted file mode 100755 index ce1a664a..00000000 --- a/packages/react-native-quick-crypto/deps/ncrypto/tools/run-clang-format.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env bash - -# Copyright 2023 Yagiz Nizipli and Daniel Lemire - -# Permission is hereby granted, free of charge, to any person obtaining a copy of -# this software and associated documentation files (the "Software"), to deal in -# the Software without restriction, including without limitation the rights to -# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -# the Software, and to permit persons to whom the Software is furnished to do so, -# subject to the following conditions: - -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -set -e -COMMAND=$* -SCRIPTPATH="$( cd "$(dirname "$0")" ; pwd -P )" -MAINSOURCE=$SCRIPTPATH/.. -ALL_FILES=$(cd $MAINSOURCE && git ls-tree --full-tree --name-only -r HEAD | grep -e ".*\.\(c\|h\|cc\|cpp\|hh\)\$") - -if clang-format-17 --version 2>/dev/null | grep -qF 'version 17.'; then - cd $MAINSOURCE; clang-format-17 --style=file --verbose -i "$@" $ALL_FILES - exit 0 -elif clang-format --version 2>/dev/null | grep -qF 'version 17.'; then - cd $MAINSOURCE; clang-format --style=file --verbose -i "$@" $ALL_FILES - exit 0 -fi -echo "Trying to use docker" -command -v docker >/dev/null 2>&1 || { echo >&2 "Please install docker. E.g., go to https://www.docker.com/products/docker-desktop Type 'docker' to diagnose the problem."; exit 1; } -docker info >/dev/null 2>&1 || { echo >&2 "Docker server is not running? type 'docker info'."; exit 1; } - -if [ -t 0 ]; then DOCKER_ARGS=-it; fi -docker pull kszonek/clang-format-17 - -docker run --rm $DOCKER_ARGS -v "$MAINSOURCE":"$MAINSOURCE":Z -w "$MAINSOURCE" -u "$(id -u $USER):$(id -g $USER)" kszonek/clang-format-17 --style=file --verbose -i "$@" $ALL_FILES diff --git a/scripts/setup_clang_env.sh b/scripts/setup_clang_env.sh index 4b01e971..bee691ec 100755 --- a/scripts/setup_clang_env.sh +++ b/scripts/setup_clang_env.sh @@ -43,7 +43,7 @@ include_directories( "cpp/random" "cpp/utils" "deps/fastpbkdf2" - "deps/ncrypto/include" + "deps/ncrypto" "build/includes" "nitrogen/generated/shared/c++" "../../node_modules/react-native/ReactCommon/jsi" @@ -65,7 +65,7 @@ add_library(QuickCrypto STATIC cpp/pbkdf2/HybridPbkdf2.cpp cpp/random/HybridRandom.cpp deps/fastpbkdf2/fastpbkdf2.c - deps/ncrypto/src/ncrypto.cpp + deps/ncrypto/ncrypto.cc ) EOF From cc8129b75c9fdb41475bb3cd8d357867cc553e7c Mon Sep 17 00:00:00 2001 From: Brad Anderson Date: Wed, 10 Sep 2025 23:14:03 -0400 Subject: [PATCH 2/2] feat: subtle.sign/verify for `ec` --- docs/implementation-coverage.md | 4 +- .../cpp/ec/HybridEcKeyPair.cpp | 256 ++++++++++++++- .../cpp/ec/HybridEcKeyPair.hpp | 4 + .../cpp/keys/HybridKeyObjectHandle.cpp | 3 + .../cpp/keys/KeyObjectData.cpp | 80 +++-- .../cpp/keys/KeyObjectData.hpp | 2 +- .../shared/c++/HybridEcKeyPairSpec.cpp | 2 + .../shared/c++/HybridEcKeyPairSpec.hpp | 2 + packages/react-native-quick-crypto/src/ec.ts | 294 +++++++++++------- .../src/keys/classes.ts | 33 +- .../src/specs/ecKeyPair.nitro.ts | 8 + .../react-native-quick-crypto/src/subtle.ts | 31 +- .../src/utils/types.ts | 14 + 13 files changed, 549 insertions(+), 184 deletions(-) diff --git a/docs/implementation-coverage.md b/docs/implementation-coverage.md index ce7dac38..97fd026b 100644 --- a/docs/implementation-coverage.md +++ b/docs/implementation-coverage.md @@ -400,7 +400,7 @@ This document attempts to describe the implementation status of Crypto APIs/Inte ## `subtle.sign` | Algorithm | Status | | --------- | :----: | -| `ECDSA` | ❌ | +| `ECDSA` | ✅ | | `Ed25519` | ❌ | | `Ed448` | ❌ | | `HMAC` | ❌ | @@ -452,7 +452,7 @@ This document attempts to describe the implementation status of Crypto APIs/Inte ## `subtle.verify` | Algorithm | Status | | --------- | :----: | -| `ECDSA` | ❌ | +| `ECDSA` | ✅ | | `Ed25519` | ❌ | | `Ed448` | ❌ | | `HMAC` | ❌ | diff --git a/packages/react-native-quick-crypto/cpp/ec/HybridEcKeyPair.cpp b/packages/react-native-quick-crypto/cpp/ec/HybridEcKeyPair.cpp index 80b37fb5..b0855e1e 100644 --- a/packages/react-native-quick-crypto/cpp/ec/HybridEcKeyPair.cpp +++ b/packages/react-native-quick-crypto/cpp/ec/HybridEcKeyPair.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -102,13 +103,148 @@ void HybridEcKeyPair::generateKeyPairSync() { this->pkey = raw_pkey; } -KeyObject HybridEcKeyPair::importKey(const std::string& format, const std::shared_ptr& keyData, const std::string& algorithm, - bool extractable, const std::vector& keyUsages) { - throw std::runtime_error("HybridEcKeyPair::importKey() is not yet implemented"); +KeyObject HybridEcKeyPair::importKey(const std::string& format, const std::shared_ptr& keyData, + const std::string& /* algorithm */, bool /* extractable */, + const std::vector& /* keyUsages */) { + // Clean up any existing key + if (this->pkey != nullptr) { + EVP_PKEY_free(this->pkey); + this->pkey = nullptr; + } + // Reset curve state to avoid interference between different uses + this->curve.clear(); + + // Import key from DER format + if (format != "der") { + throw std::runtime_error("Only DER format is supported for key import"); + } + + const unsigned char* keyPtr = static_cast(keyData->data()); + size_t keyLen = keyData->size(); + + // Try to import as public key first (SPKI format) + EVP_PKEY* pkey = d2i_PUBKEY(nullptr, &keyPtr, keyLen); + + if (!pkey) { + // Reset pointer and try as private key (PKCS8 format) + keyPtr = static_cast(keyData->data()); + + // Try PKCS8 format for private keys + BIO* pkcs8_bio = BIO_new_mem_buf(keyData->data(), static_cast(keyData->size())); + if (pkcs8_bio) { + PKCS8_PRIV_KEY_INFO* p8inf = d2i_PKCS8_PRIV_KEY_INFO_bio(pkcs8_bio, nullptr); + if (p8inf != nullptr) { + EVP_PKEY* pkcs8_pkey = EVP_PKCS82PKEY(p8inf); + PKCS8_PRIV_KEY_INFO_free(p8inf); + BIO_free(pkcs8_bio); + if (pkcs8_pkey != nullptr) { + this->pkey = pkcs8_pkey; + KeyObject keyObj; + return keyObj; + } + } + BIO_free(pkcs8_bio); + } + + // Try to parse as SPKI (public key) with BIO + BIO* spki_bio = BIO_new_mem_buf(keyData->data(), static_cast(keyData->size())); + if (spki_bio) { + EVP_PKEY* spki_pkey = d2i_PUBKEY_bio(spki_bio, nullptr); + BIO_free(spki_bio); + if (spki_pkey != nullptr) { + this->pkey = spki_pkey; + KeyObject keyObj; + return keyObj; + } + } + + throw std::runtime_error("Failed to import EC key from DER data"); + } + + this->pkey = pkey; + + // Return a placeholder KeyObject - this would need proper implementation + // For now, we just need the key imported into this->pkey for sign/verify + KeyObject keyObj; + return keyObj; } std::shared_ptr HybridEcKeyPair::exportKey(const KeyObject& key, const std::string& format) { - throw std::runtime_error("HybridEcKeyPair::exportKey() is not yet implemented"); + // Suppress unused parameter warning + (void)key; + + if (!this->pkey) { + throw std::runtime_error("No key pair generated"); + } + + if (format == "der-spki") { + // Export public key in DER SPKI format + int len = i2d_PUBKEY(this->pkey, nullptr); + if (len <= 0) { + throw std::runtime_error("Failed to get public key DER length"); + } + + std::vector derData(len); + unsigned char* ptr = derData.data(); + i2d_PUBKEY(this->pkey, &ptr); + return ToNativeArrayBuffer(std::string(derData.begin(), derData.end())); + } else if (format == "der-pkcs8") { + // Export private key in DER PKCS8 format + BIO* bio = BIO_new(BIO_s_mem()); + if (!bio) { + throw std::runtime_error("Failed to create BIO for private key export"); + } + + if (i2d_PKCS8PrivateKey_bio(bio, this->pkey, nullptr, nullptr, 0, nullptr, nullptr) != 1) { + BIO_free(bio); + throw std::runtime_error("Failed to export private key to DER PKCS8 format"); + } + + BUF_MEM* mem; + BIO_get_mem_ptr(bio, &mem); + std::string derData(mem->data, mem->length); + BIO_free(bio); + + return ToNativeArrayBuffer(derData); + } else if (format == "pem-spki") { + // Export public key in PEM SPKI format + BIO* bio = BIO_new(BIO_s_mem()); + if (!bio) { + throw std::runtime_error("Failed to create BIO for public key export"); + } + + if (PEM_write_bio_PUBKEY(bio, this->pkey) != 1) { + BIO_free(bio); + throw std::runtime_error("Failed to export public key to PEM SPKI format"); + } + + BUF_MEM* mem; + BIO_get_mem_ptr(bio, &mem); + std::string pemData(mem->data, mem->length); + BIO_free(bio); + + return ToNativeArrayBuffer(pemData); + } else if (format == "pem-pkcs8") { + // Export private key in PEM PKCS8 format + BIO* bio = BIO_new(BIO_s_mem()); + if (!bio) { + throw std::runtime_error("Failed to create BIO for private key export"); + } + + if (PEM_write_bio_PKCS8PrivateKey(bio, this->pkey, nullptr, nullptr, 0, nullptr, nullptr) != 1) { + BIO_free(bio); + throw std::runtime_error("Failed to export private key to PEM PKCS8 format"); + } + + BUF_MEM* mem; + BIO_get_mem_ptr(bio, &mem); + std::string pemData(mem->data, mem->length); + BIO_free(bio); + + return ToNativeArrayBuffer(pemData); + } + + throw std::runtime_error("Unsupported export format: " + format); } std::shared_ptr HybridEcKeyPair::getPublicKey() { @@ -136,23 +272,19 @@ std::shared_ptr HybridEcKeyPair::getPublicKey() { } std::shared_ptr HybridEcKeyPair::getPrivateKey() { - this->checkKeyPair(); - - // Export as DER format in PKCS8 format using direct OpenSSL calls - BIO* bio = BIO_new(BIO_s_mem()); - if (!bio) { - throw std::runtime_error("Failed to create BIO for private key export"); + if (this->pkey == nullptr) { + throw std::runtime_error("No private key available"); } + // Export private key in PKCS8 DER format + BIO* bio = BIO_new(BIO_s_mem()); if (i2d_PKCS8PrivateKey_bio(bio, this->pkey, nullptr, nullptr, 0, nullptr, nullptr) != 1) { BIO_free(bio); - throw std::runtime_error("Failed to export private key to DER PKCS8 format"); + throw std::runtime_error("Failed to export private key"); } BUF_MEM* mem; BIO_get_mem_ptr(bio, &mem); - - // Create a string from the DER data and use ToNativeArrayBuffer utility std::string derData(mem->data, mem->length); BIO_free(bio); @@ -189,6 +321,104 @@ int HybridEcKeyPair::GetCurveFromName(const char* name) { return nid; } +std::shared_ptr HybridEcKeyPair::sign(const std::shared_ptr& data, const std::string& hashAlgorithm) { + this->checkKeyPair(); + + // Get the hash algorithm EVP_MD + const EVP_MD* md = nullptr; + if (hashAlgorithm == "SHA-256") { + md = EVP_sha256(); + } else if (hashAlgorithm == "SHA-384") { + md = EVP_sha384(); + } else if (hashAlgorithm == "SHA-512") { + md = EVP_sha512(); + } else if (hashAlgorithm == "SHA-1") { + md = EVP_sha1(); + } else { + throw std::runtime_error("Unsupported hash algorithm: " + hashAlgorithm); + } + + // Create signing context + std::unique_ptr md_ctx(EVP_MD_CTX_new(), EVP_MD_CTX_free); + if (!md_ctx) { + throw std::runtime_error("Failed to create message digest context"); + } + + // Initialize signing + if (EVP_DigestSignInit(md_ctx.get(), nullptr, md, nullptr, this->pkey) <= 0) { + throw std::runtime_error("Failed to initialize ECDSA signing"); + } + + // Update with data + if (EVP_DigestSignUpdate(md_ctx.get(), data->data(), data->size()) <= 0) { + throw std::runtime_error("Failed to update ECDSA signing with data"); + } + + // Get signature length + size_t sig_len = 0; + if (EVP_DigestSignFinal(md_ctx.get(), nullptr, &sig_len) <= 0) { + throw std::runtime_error("Failed to get ECDSA signature length"); + } + + // Allocate signature buffer + std::vector signature(sig_len); + + // Get the actual signature + if (EVP_DigestSignFinal(md_ctx.get(), signature.data(), &sig_len) <= 0) { + throw std::runtime_error("Failed to generate ECDSA signature"); + } + + // Resize to actual signature length + signature.resize(sig_len); + + // Convert to ArrayBuffer + return ToNativeArrayBuffer(std::string(signature.begin(), signature.end())); +} + +bool HybridEcKeyPair::verify(const std::shared_ptr& data, const std::shared_ptr& signature, + const std::string& hashAlgorithm) { + this->checkKeyPair(); + + // Get the hash algorithm EVP_MD + const EVP_MD* md = nullptr; + if (hashAlgorithm == "SHA-256") { + md = EVP_sha256(); + } else if (hashAlgorithm == "SHA-384") { + md = EVP_sha384(); + } else if (hashAlgorithm == "SHA-512") { + md = EVP_sha512(); + } else if (hashAlgorithm == "SHA-1") { + md = EVP_sha1(); + } else { + throw std::runtime_error("Unsupported hash algorithm: " + hashAlgorithm); + } + + // Create verification context + std::unique_ptr md_ctx(EVP_MD_CTX_new(), EVP_MD_CTX_free); + if (!md_ctx) { + throw std::runtime_error("Failed to create message digest context"); + } + + // Initialize verification + if (EVP_DigestVerifyInit(md_ctx.get(), nullptr, md, nullptr, this->pkey) <= 0) { + throw std::runtime_error("Failed to initialize ECDSA verification"); + } + + // Update with data + if (EVP_DigestVerifyUpdate(md_ctx.get(), data->data(), data->size()) <= 0) { + throw std::runtime_error("Failed to update ECDSA verification with data"); + } + + // Verify signature + int result = EVP_DigestVerifyFinal(md_ctx.get(), static_cast(signature->data()), signature->size()); + + if (result < 0) { + throw std::runtime_error("ECDSA verification failed with error"); + } + + return result == 1; +} + void HybridEcKeyPair::checkKeyPair() { if (this->pkey == nullptr) { throw std::runtime_error("EC KeyPair not initialized"); diff --git a/packages/react-native-quick-crypto/cpp/ec/HybridEcKeyPair.hpp b/packages/react-native-quick-crypto/cpp/ec/HybridEcKeyPair.hpp index 3bdeda4f..ba4a1bcc 100644 --- a/packages/react-native-quick-crypto/cpp/ec/HybridEcKeyPair.hpp +++ b/packages/react-native-quick-crypto/cpp/ec/HybridEcKeyPair.hpp @@ -29,7 +29,11 @@ class HybridEcKeyPair : public HybridEcKeyPairSpec { std::shared_ptr exportKey(const KeyObject& key, const std::string& format) override; std::shared_ptr getPublicKey() override; std::shared_ptr getPrivateKey() override; + void setCurve(const std::string& curve) override; + std::shared_ptr sign(const std::shared_ptr& data, const std::string& hashAlgorithm) override; + bool verify(const std::shared_ptr& data, const std::shared_ptr& signature, + const std::string& hashAlgorithm) override; protected: void checkKeyPair(); diff --git a/packages/react-native-quick-crypto/cpp/keys/HybridKeyObjectHandle.cpp b/packages/react-native-quick-crypto/cpp/keys/HybridKeyObjectHandle.cpp index 4f6eb4b7..a7a38ad2 100644 --- a/packages/react-native-quick-crypto/cpp/keys/HybridKeyObjectHandle.cpp +++ b/packages/react-native-quick-crypto/cpp/keys/HybridKeyObjectHandle.cpp @@ -126,6 +126,9 @@ CFRGKeyPairType HybridKeyObjectHandle::getAsymmetricKeyType() { bool HybridKeyObjectHandle::init(KeyType keyType, const std::variant>& key, std::optional format, std::optional type, const std::optional>& passphrase) { + // Reset any existing data to prevent state leakage + data_ = KeyObjectData(); + // get ArrayBuffer from key std::shared_ptr ab; if (std::holds_alternative(key)) { diff --git a/packages/react-native-quick-crypto/cpp/keys/KeyObjectData.cpp b/packages/react-native-quick-crypto/cpp/keys/KeyObjectData.cpp index 2eadb487..801e3a31 100644 --- a/packages/react-native-quick-crypto/cpp/keys/KeyObjectData.cpp +++ b/packages/react-native-quick-crypto/cpp/keys/KeyObjectData.cpp @@ -21,7 +21,7 @@ ncrypto::EVPKeyPointer::PublicKeyEncodingConfig GetPublicKeyEncodingConfig(KForm } KeyObjectData TryParsePrivateKey(std::shared_ptr key, std::optional format, std::optional type, - const std::optional>& passphrase) { + const std::optional>& /* passphrase */) { auto config = GetPrivateKeyEncodingConfig(format.value(), type.value()); auto buffer = ncrypto::Buffer{key->data(), key->size()}; auto res = ncrypto::EVPKeyPointer::TryParsePrivateKey(config, buffer); @@ -100,10 +100,13 @@ KeyObjectData KeyObjectData::GetPublicOrPrivateKey(std::shared_ptr throw std::runtime_error(error_msg); } - if (format.has_value() && (format.value() == KFormatType::PEM || format.value() == KFormatType::DER)) { + // If no format is specified, assume DER format for binary data + KFormatType actualFormat = format.has_value() ? format.value() : KFormatType::DER; + + if (actualFormat == KFormatType::PEM || actualFormat == KFormatType::DER) { auto buffer = ncrypto::Buffer{key->data(), key->size()}; - if (format.value() == KFormatType::PEM) { + if (actualFormat == KFormatType::PEM) { // For PEM, we can easily determine whether it is a public or private key // by looking for the respective PEM tags. auto res = ncrypto::EVPKeyPointer::TryParsePublicKeyPEM(buffer); @@ -112,7 +115,7 @@ KeyObjectData KeyObjectData::GetPublicOrPrivateKey(std::shared_ptr } if (res.error.has_value() && res.error.value() == ncrypto::EVPKeyPointer::PKParseError::NOT_RECOGNIZED) { - auto config = GetPrivateKeyEncodingConfig(format.value(), type.value()); + auto config = GetPrivateKeyEncodingConfig(actualFormat, type.value()); if (passphrase.has_value()) { auto& passphrase_ptr = passphrase.value(); config.passphrase = std::make_optional(ncrypto::DataPointer(passphrase_ptr->data(), passphrase_ptr->size())); @@ -124,16 +127,16 @@ KeyObjectData KeyObjectData::GetPublicOrPrivateKey(std::shared_ptr } } throw std::runtime_error("Failed to read PEM asymmetric key"); - } else if (format.value() == KFormatType::DER) { + } else if (actualFormat == KFormatType::DER) { // For DER, try parsing as public key first if (type.has_value() && type.value() == KeyEncoding::SPKI) { - auto public_config = GetPublicKeyEncodingConfig(format.value(), type.value()); + auto public_config = GetPublicKeyEncodingConfig(actualFormat, type.value()); auto res = ncrypto::EVPKeyPointer::TryParsePublicKey(public_config, buffer); if (res) { return CreateAsymmetric(KeyType::PUBLIC, std::move(res.value)); } } else if (type.has_value() && type.value() == KeyEncoding::PKCS8) { - auto private_config = GetPrivateKeyEncodingConfig(format.value(), type.value()); + auto private_config = GetPrivateKeyEncodingConfig(actualFormat, type.value()); if (passphrase.has_value()) { auto& passphrase_ptr = passphrase.value(); private_config.passphrase = std::make_optional(ncrypto::DataPointer(passphrase_ptr->data(), passphrase_ptr->size())); @@ -142,6 +145,19 @@ KeyObjectData KeyObjectData::GetPublicOrPrivateKey(std::shared_ptr if (res) { return CreateAsymmetric(KeyType::PRIVATE, std::move(res.value)); } + } else { + // If no encoding type specified, try both SPKI and PKCS8 + auto public_config = GetPublicKeyEncodingConfig(actualFormat, KeyEncoding::SPKI); + auto public_res = ncrypto::EVPKeyPointer::TryParsePublicKey(public_config, buffer); + if (public_res) { + return CreateAsymmetric(KeyType::PUBLIC, std::move(public_res.value)); + } + + auto private_config = GetPrivateKeyEncodingConfig(actualFormat, KeyEncoding::PKCS8); + auto private_res = ncrypto::EVPKeyPointer::TryParsePrivateKey(private_config, buffer); + if (private_res) { + return CreateAsymmetric(KeyType::PRIVATE, std::move(private_res.value)); + } } throw std::runtime_error("Failed to read DER asymmetric key"); } @@ -152,7 +168,7 @@ KeyObjectData KeyObjectData::GetPublicOrPrivateKey(std::shared_ptr KeyObjectData KeyObjectData::GetPrivateKey(std::shared_ptr key, std::optional format, std::optional type, const std::optional>& passphrase, - bool isPublic) { + bool /* isPublic */) { // Check if key size fits in int32_t without using double conversion if (key->size() > static_cast(std::numeric_limits::max())) { std::string error_msg = "key is too big (int32): size=" + std::to_string(key->size()) + @@ -160,22 +176,44 @@ KeyObjectData KeyObjectData::GetPrivateKey(std::shared_ptr key, std throw std::runtime_error(error_msg); } - if (format.has_value() && (format.value() == KFormatType::PEM || format.value() == KFormatType::DER)) { + // If no format is specified, assume DER format for binary data + KFormatType actualFormat = format.has_value() ? format.value() : KFormatType::DER; + + if (actualFormat == KFormatType::PEM || actualFormat == KFormatType::DER) { auto buffer = ncrypto::Buffer{key->data(), key->size()}; - if (format.value() == KFormatType::PEM) { + if (actualFormat == KFormatType::PEM) { return TryParsePrivateKey(key, format, type, passphrase); - } else if (format.value() == KFormatType::DER) { - // For DER private keys, use PKCS8 encoding - if (type.has_value() && type.value() == KeyEncoding::PKCS8) { - auto private_config = GetPrivateKeyEncodingConfig(format.value(), type.value()); - if (passphrase.has_value()) { - auto& passphrase_ptr = passphrase.value(); - private_config.passphrase = std::make_optional(ncrypto::DataPointer(passphrase_ptr->data(), passphrase_ptr->size())); - } - auto res = ncrypto::EVPKeyPointer::TryParsePrivateKey(private_config, buffer); - if (res) { - return CreateAsymmetric(KeyType::PRIVATE, std::move(res.value)); + } else if (actualFormat == KFormatType::DER) { + // Try the specified encoding first, or PKCS8 as default + KeyEncoding primaryEncoding = type.value_or(KeyEncoding::PKCS8); + auto private_config = GetPrivateKeyEncodingConfig(actualFormat, primaryEncoding); + if (passphrase.has_value()) { + auto& passphrase_ptr = passphrase.value(); + private_config.passphrase = std::make_optional(ncrypto::DataPointer(passphrase_ptr->data(), passphrase_ptr->size())); + } + + // Clear any existing OpenSSL errors before parsing + ERR_clear_error(); + + auto res = ncrypto::EVPKeyPointer::TryParsePrivateKey(private_config, buffer); + if (res) { + return CreateAsymmetric(KeyType::PRIVATE, std::move(res.value)); + } + + // If no specific encoding was provided, try other encodings as fallback + if (!type.has_value()) { + std::vector fallbackEncodings = {KeyEncoding::SEC1, KeyEncoding::PKCS1}; + for (auto encoding : fallbackEncodings) { + auto config = GetPrivateKeyEncodingConfig(actualFormat, encoding); + if (passphrase.has_value()) { + auto& passphrase_ptr = passphrase.value(); + config.passphrase = std::make_optional(ncrypto::DataPointer(passphrase_ptr->data(), passphrase_ptr->size())); + } + auto fallback_res = ncrypto::EVPKeyPointer::TryParsePrivateKey(config, buffer); + if (fallback_res) { + return CreateAsymmetric(KeyType::PRIVATE, std::move(fallback_res.value)); + } } } throw std::runtime_error("Failed to read DER private key"); diff --git a/packages/react-native-quick-crypto/cpp/keys/KeyObjectData.hpp b/packages/react-native-quick-crypto/cpp/keys/KeyObjectData.hpp index 17b21413..c5d048a2 100644 --- a/packages/react-native-quick-crypto/cpp/keys/KeyObjectData.hpp +++ b/packages/react-native-quick-crypto/cpp/keys/KeyObjectData.hpp @@ -2,11 +2,11 @@ #include +#include "../../deps/ncrypto/ncrypto.h" #include "KFormatType.hpp" #include "KeyEncoding.hpp" #include "KeyType.hpp" #include "Utils.hpp" -#include "ncrypto.h" namespace margelo::nitro::crypto { diff --git a/packages/react-native-quick-crypto/nitrogen/generated/shared/c++/HybridEcKeyPairSpec.cpp b/packages/react-native-quick-crypto/nitrogen/generated/shared/c++/HybridEcKeyPairSpec.cpp index 2f97819c..1d0fc671 100644 --- a/packages/react-native-quick-crypto/nitrogen/generated/shared/c++/HybridEcKeyPairSpec.cpp +++ b/packages/react-native-quick-crypto/nitrogen/generated/shared/c++/HybridEcKeyPairSpec.cpp @@ -21,6 +21,8 @@ namespace margelo::nitro::crypto { prototype.registerHybridMethod("getPublicKey", &HybridEcKeyPairSpec::getPublicKey); prototype.registerHybridMethod("getPrivateKey", &HybridEcKeyPairSpec::getPrivateKey); prototype.registerHybridMethod("setCurve", &HybridEcKeyPairSpec::setCurve); + prototype.registerHybridMethod("sign", &HybridEcKeyPairSpec::sign); + prototype.registerHybridMethod("verify", &HybridEcKeyPairSpec::verify); }); } diff --git a/packages/react-native-quick-crypto/nitrogen/generated/shared/c++/HybridEcKeyPairSpec.hpp b/packages/react-native-quick-crypto/nitrogen/generated/shared/c++/HybridEcKeyPairSpec.hpp index 0b3fddce..cec58400 100644 --- a/packages/react-native-quick-crypto/nitrogen/generated/shared/c++/HybridEcKeyPairSpec.hpp +++ b/packages/react-native-quick-crypto/nitrogen/generated/shared/c++/HybridEcKeyPairSpec.hpp @@ -62,6 +62,8 @@ namespace margelo::nitro::crypto { virtual std::shared_ptr getPublicKey() = 0; virtual std::shared_ptr getPrivateKey() = 0; virtual void setCurve(const std::string& curve) = 0; + virtual std::shared_ptr sign(const std::shared_ptr& data, const std::string& hashAlgorithm) = 0; + virtual bool verify(const std::shared_ptr& data, const std::shared_ptr& signature, const std::string& hashAlgorithm) = 0; protected: // Hybrid Setup diff --git a/packages/react-native-quick-crypto/src/ec.ts b/packages/react-native-quick-crypto/src/ec.ts index 44212a8c..19d550df 100644 --- a/packages/react-native-quick-crypto/src/ec.ts +++ b/packages/react-native-quick-crypto/src/ec.ts @@ -1,36 +1,31 @@ import { NitroModules } from 'react-native-nitro-modules'; +import type { EcKeyPair } from './specs/ecKeyPair.nitro'; import { - PublicKeyObject, - PrivateKeyObject, CryptoKey, KeyObject, -} from './keys/classes'; -import type { EcKeyPair } from './specs/ecKeyPair.nitro'; + PublicKeyObject, + PrivateKeyObject, +} from './keys'; +import type { + CryptoKeyPair, + KeyPairOptions, + KeyUsage, + SubtleAlgorithm, + BufferLike, + BinaryLike, + JWK, + ImportFormat, +} from './utils/types'; import { - // KeyType, - // KeyFormat, - // ab2str, - // bufferLikeToArrayBuffer, - // binaryLikeToArrayBuffer, + bufferLikeToArrayBuffer, getUsagesUnion, hasAnyNotIn, kNamedCurveAliases, lazyDOMException, - // normalizeHashName, - // validateKeyOps, -} from './utils'; -import type { - // AnyAlgorithm, - // BufferLike, - // BinaryLike, - CryptoKeyPair, - // ImportFormat, - KeyUsage, - // NamedCurve, - // JWK, - SubtleAlgorithm, - // AsymmetricKeyType, - // KeyObjectHandle, + normalizeHashName, + HashContext, + KeyEncoding, + KFormatType, } from './utils'; export class Ec { @@ -87,7 +82,7 @@ export class Ec { // function createECPublicKeyRaw( // namedCurve: NamedCurve | undefined, -// keyData: ArrayBuffer, +// keyDataBuffer: ArrayBuffer, // ): PublicKeyObject { // if (!namedCurve) { // throw new Error('Invalid namedCurve'); @@ -96,8 +91,8 @@ export class Ec { // 'KeyObjectHandle', // ) as KeyObjectHandle; -// if (!handle.initECRaw(kNamedCurveAliases[namedCurve], keyData)) { -// console.log('keyData', ab2str(keyData)); +// if (!handle.initECRaw(kNamedCurveAliases[namedCurve], keyDataBuffer)) { +// console.log('keyData', ab2str(keyDataBuffer)); // throw new Error('Invalid keyData 1'); // } @@ -109,49 +104,84 @@ export class Ec { // return ec.native.exportKey(format, key.keyObject.handle); // } -// // Node API -// export function ecImportKey( -// format: ImportFormat, -// keyData: BufferLike | BinaryLike | JWK, -// algorithm: SubtleAlgorithm, -// extractable: boolean, -// keyUsages: KeyUsage[], -// ): CryptoKey { -// const { name, namedCurve } = algorithm; - -// // if (!ArrayPrototypeIncludes(ObjectKeys(kNamedCurveAliases), namedCurve)) { -// // throw lazyDOMException('Unrecognized namedCurve', 'NotSupportedError'); -// // } +// Node API +export function ecImportKey( + format: ImportFormat, + keyData: BufferLike | BinaryLike | JWK, + algorithm: SubtleAlgorithm, + extractable: boolean, + keyUsages: KeyUsage[], +): CryptoKey { + const { name, namedCurve } = algorithm; + + if ( + !namedCurve || + !kNamedCurveAliases[namedCurve as keyof typeof kNamedCurveAliases] + ) { + throw lazyDOMException('Unrecognized namedCurve', 'NotSupportedError'); + } + + if (format !== 'spki' && format !== 'pkcs8' && format !== 'raw') { + throw lazyDOMException( + `Unsupported format: ${format}`, + 'NotSupportedError', + ); + } + + // Handle JWK format separately + if (typeof keyData === 'object' && 'kty' in keyData) { + throw lazyDOMException('JWK format not yet supported', 'NotSupportedError'); + } + + // Convert keyData to ArrayBuffer + const keyBuffer = bufferLikeToArrayBuffer(keyData as BufferLike); + + // Create EC instance with the curve + const ec = new Ec(namedCurve); + + // Import the key using Nitro module + ec.native.importKey( + format === 'raw' ? 'der' : format, // Convert raw to der for now + keyBuffer, + name, + extractable, + keyUsages, + ); + + // Create a KeyObject wrapper for the imported key + // Use the EC instance's key data to create a proper KeyObject + const privateKeyData = ec.native.getPrivateKey(); + const keyObject = new KeyObject('private', privateKeyData); + + // Create and return CryptoKey + return new CryptoKey(keyObject, algorithm, keyUsages, extractable); + // // // verifyAcceptableEcKeyUse(name, true, usagesSet); + // // try { + // // keyObject = createPublicKey({ + // // key: keyData, + // // format: 'der', + // // type: 'spki', + // // }); + // // } catch (err) { + // // throw new Error(`Invalid keyData 2: ${err}`); + // // } + // // break; + // // } + // // case 'pkcs8': { + // // // verifyAcceptableEcKeyUse(name, false, usagesSet); + // // try { + // // keyObject = createPrivateKey({ + // // key: keyData, + // // format: 'der', + // // type: 'pkcs8', + // // }); + // // } catch (err) { + // // throw new Error(`Invalid keyData 3 ${err}`); + // // } + // // break; + // // } +} -// let keyObject; -// // const usagesSet = new SafeSet(keyUsages); -// switch (format) { -// // case 'spki': { -// // // verifyAcceptableEcKeyUse(name, true, usagesSet); -// // try { -// // keyObject = createPublicKey({ -// // key: keyData, -// // format: 'der', -// // type: 'spki', -// // }); -// // } catch (err) { -// // throw new Error(`Invalid keyData 2: ${err}`); -// // } -// // break; -// // } -// // case 'pkcs8': { -// // // verifyAcceptableEcKeyUse(name, false, usagesSet); -// // try { -// // keyObject = createPrivateKey({ -// // key: keyData, -// // format: 'der', -// // type: 'pkcs8', -// // }); -// // } catch (err) { -// // throw new Error(`Invalid keyData 3 ${err}`); -// // } -// // break; -// // } // case 'jwk': { // const data = keyData as JWK; @@ -250,48 +280,75 @@ export class Ec { // return new CryptoKey(keyObject, { name, namedCurve }, keyUsages, extractable); // } -// // Node API -// export const ecdsaSignVerify = ( -// key: CryptoKey, -// data: BufferLike, -// { hash }: SubtleAlgorithm, -// signature?: BufferLike, -// ) => { -// const mode: SignMode = -// signature === undefined -// ? SignMode.kSignJobModeSign -// : SignMode.kSignJobModeVerify; -// const type = mode === SignMode.kSignJobModeSign ? 'private' : 'public'; - -// if (key.type !== type) -// throw lazyDOMException(`Key must be a ${type} key`, 'InvalidAccessError'); - -// const hashname = normalizeHashName(hash); - -// return NativeQuickCrypto.webcrypto.signVerify( -// mode, -// key.keyObject.handle, -// // three undefined args because C++ uses `GetPublicOrPrivateKeyFromJs` & friends -// undefined, -// undefined, -// undefined, -// bufferLikeToArrayBuffer(data), -// hashname, -// undefined, // salt length, not used with ECDSA -// undefined, // pss padding, not used with ECDSA -// DSASigEnc.kSigEncP1363, -// bufferLikeToArrayBuffer(signature || new ArrayBuffer(0)), -// ); -// }; +// Node API +export const ecdsaSignVerify = ( + key: CryptoKey, + data: BufferLike, + { hash }: SubtleAlgorithm, + signature?: BufferLike, +): ArrayBuffer | boolean => { + const isSign = signature === undefined; + const expectedKeyType = isSign ? 'private' : 'public'; + + if (key.type !== expectedKeyType) { + throw lazyDOMException( + `Key must be a ${expectedKeyType} key`, + 'InvalidAccessError', + ); + } + + const hashName = typeof hash === 'string' ? hash : hash?.name; + + if (!hashName) { + throw lazyDOMException( + 'Hash algorithm is required for ECDSA', + 'InvalidAccessError', + ); + } + + // Normalize hash algorithm name to WebCrypto format for C++ layer + const normalizedHashName = normalizeHashName(hashName, HashContext.WebCrypto); + + // Create EC instance with the curve from the key + const namedCurve = key.algorithm.namedCurve!; + const ec = new Ec(namedCurve); + + // Extract and import the actual key data from the CryptoKey + // Export in DER format with appropriate encoding + const encoding = + key.type === 'private' ? KeyEncoding.PKCS8 : KeyEncoding.SPKI; + const keyData = key.keyObject.handle.exportKey(KFormatType.DER, encoding); + const keyBuffer = bufferLikeToArrayBuffer(keyData); + ec.native.importKey( + 'der', + keyBuffer, + key.algorithm.name!, + key.extractable, + key.usages, + ); + + const dataBuffer = bufferLikeToArrayBuffer(data); + + if (isSign) { + // Sign operation + return ec.native.sign(dataBuffer, normalizedHashName); + } else { + // Verify operation + const signatureBuffer = bufferLikeToArrayBuffer(signature!); + return ec.native.verify(dataBuffer, signatureBuffer, normalizedHashName); + } +}; // Node API -export const ec_generateKeyPair = async ( - algorithm: SubtleAlgorithm, + +export async function ec_generateKeyPair( + name: string, + namedCurve: string, extractable: boolean, keyUsages: KeyUsage[], -): Promise => { - const { name, namedCurve } = algorithm; - + // eslint-disable-next-line @typescript-eslint/no-unused-vars + _options?: KeyPairOptions, // TODO: Implement format options support +): Promise { // validation checks if (!Object.keys(kNamedCurveAliases).includes(namedCurve || '')) { throw lazyDOMException( @@ -338,25 +395,38 @@ export const ec_generateKeyPair = async ( const keyAlgorithm = { name, namedCurve: namedCurve! }; - // Create KeyObject instances using the standard createKeyObject method + // Export keys directly from the EC key pair using the internal EVP_PKEY + // These methods export in DER format (SPKI for public, PKCS8 for private) const publicKeyData = ec.native.getPublicKey(); + const privateKeyData = ec.native.getPrivateKey(); + const pub = KeyObject.createKeyObject( 'public', publicKeyData, + 'der', + 'spki', ) as PublicKeyObject; - const publicKey = new CryptoKey(pub, keyAlgorithm, publicUsages, true); + const publicKey = new CryptoKey( + pub, + keyAlgorithm as SubtleAlgorithm, + publicUsages, + true, + ); - const privateKeyData = ec.native.getPrivateKey(); + // All keys are now exported in PKCS8 format for consistency + const privateEncoding = 'pkcs8'; const priv = KeyObject.createKeyObject( 'private', privateKeyData, + 'der', + privateEncoding as 'pkcs8' | 'spki' | 'sec1', ) as PrivateKeyObject; const privateKey = new CryptoKey( priv, - keyAlgorithm, + keyAlgorithm as SubtleAlgorithm, privateUsages, extractable, ); return { publicKey, privateKey }; -}; +} diff --git a/packages/react-native-quick-crypto/src/keys/classes.ts b/packages/react-native-quick-crypto/src/keys/classes.ts index 33025209..a3771820 100644 --- a/packages/react-native-quick-crypto/src/keys/classes.ts +++ b/packages/react-native-quick-crypto/src/keys/classes.ts @@ -116,7 +116,12 @@ export class KeyObject { // return key[kKeyObject]; // } - static createKeyObject(type: string, key: ArrayBuffer): KeyObject { + static createKeyObject( + type: string, + key: ArrayBuffer, + format?: 'der' | 'pem', + encoding?: 'pkcs8' | 'spki' | 'sec1', + ): KeyObject { if (type !== 'secret' && type !== 'public' && type !== 'private') throw new Error(`invalid KeyObject type: ${type}`); @@ -138,16 +143,22 @@ export class KeyObject { throw new Error('invalid key type'); } - // Detect DER format by checking if the key starts with DER ASN.1 structure - const keyData = new Uint8Array(key); - const isDER = keyData.length > 10 && keyData[0] === 0x30; // ASN.1 SEQUENCE tag - - if (isDER && (keyType === KeyType.PUBLIC || keyType === KeyType.PRIVATE)) { - // For DER-encoded keys, specify format and type - const format = KFormatType.DER; - const encoding = - keyType === KeyType.PUBLIC ? KeyEncoding.SPKI : KeyEncoding.PKCS8; - handle.init(keyType, key, format, encoding); + // If format and encoding are explicitly provided, use them + if ( + format && + encoding && + (keyType === KeyType.PUBLIC || keyType === KeyType.PRIVATE) + ) { + const kFormat = format === 'der' ? KFormatType.DER : KFormatType.PEM; + const kEncoding = + encoding === 'spki' + ? KeyEncoding.SPKI + : encoding === 'pkcs8' + ? KeyEncoding.PKCS8 + : encoding === 'sec1' + ? KeyEncoding.SEC1 + : KeyEncoding.SEC1; + handle.init(keyType, key, kFormat, kEncoding); } else { handle.init(keyType, key); } diff --git a/packages/react-native-quick-crypto/src/specs/ecKeyPair.nitro.ts b/packages/react-native-quick-crypto/src/specs/ecKeyPair.nitro.ts index 44bd0532..5b6aaabd 100644 --- a/packages/react-native-quick-crypto/src/specs/ecKeyPair.nitro.ts +++ b/packages/react-native-quick-crypto/src/specs/ecKeyPair.nitro.ts @@ -27,4 +27,12 @@ export interface EcKeyPair getPrivateKey(): ArrayBuffer; setCurve(curve: string): void; + + // ECDSA sign/verify operations + sign(data: ArrayBuffer, hashAlgorithm: string): ArrayBuffer; + verify( + data: ArrayBuffer, + signature: ArrayBuffer, + hashAlgorithm: string, + ): boolean; } diff --git a/packages/react-native-quick-crypto/src/subtle.ts b/packages/react-native-quick-crypto/src/subtle.ts index fe49a2e7..0616150c 100644 --- a/packages/react-native-quick-crypto/src/subtle.ts +++ b/packages/react-native-quick-crypto/src/subtle.ts @@ -21,11 +21,8 @@ import { validateMaxBufferLength } from './utils/validation'; import { asyncDigest } from './hash'; import { createSecretKey } from './keys'; import { pbkdf2DeriveBits } from './pbkdf2'; -import { ec_generateKeyPair } from './ec'; +import { ecImportKey, ecdsaSignVerify, ec_generateKeyPair } from './ec'; import { rsa_generateKeyPair } from './rsa'; - -// Placeholder imports - these modules need to be implemented or adapted -// import { ecImportKey, ecExportKey, ecGenerateKey, ecdsaSignVerify } from './ec'; // import { pbkdf2DeriveBits } from './pbkdf2'; // import { aesCipher, aesGenerateKey, aesImportKey, getAlgorithmName } from './aes'; // import { rsaCipher, rsaExportKey, rsaImportKey, rsaKeyGenerate } from './rsa'; @@ -79,15 +76,6 @@ function rsaExportKey( throw new Error('rsaExportKey not implemented'); } -function ecdsaSignVerify( - _key: CryptoKey, - _data: BufferLike, - _algorithm: SubtleAlgorithm, - _signature?: BufferLike, -): ArrayBuffer | boolean { - throw new Error('ecdsaSignVerify not implemented'); -} - function rsaCipher( _mode: CipherOrWrapMode, _key: CryptoKey, @@ -124,16 +112,6 @@ function rsaImportKey( throw new Error('rsaImportKey not implemented'); } -function ecImportKey( - _format: ImportFormat, - _data: BufferLike | BinaryLike | JWK, - _algorithm: SubtleAlgorithm, - _extractable: boolean, - _keyUsages: KeyUsage[], -): CryptoKey { - throw new Error('ecImportKey not implemented'); -} - async function hmacImportKey( _algorithm: SubtleAlgorithm, _format: ImportFormat, @@ -499,7 +477,12 @@ export class Subtle { case 'ECDSA': // Fall through case 'ECDH': - result = await ec_generateKeyPair(algorithm, extractable, keyUsages); + result = await ec_generateKeyPair( + algorithm.name, + algorithm.namedCurve!, + extractable, + keyUsages, + ); checkCryptoKeyPairUsages(result as CryptoKeyPair); break; case 'AES-CTR': diff --git a/packages/react-native-quick-crypto/src/utils/types.ts b/packages/react-native-quick-crypto/src/utils/types.ts index 66832390..d489af7e 100644 --- a/packages/react-native-quick-crypto/src/utils/types.ts +++ b/packages/react-native-quick-crypto/src/utils/types.ts @@ -419,3 +419,17 @@ export type Operation = | 'importKey' | 'exportKey' | 'deriveBits'; + +export interface KeyPairOptions { + namedCurve: string; + publicKeyEncoding?: { + type: 'spki'; + format: 'pem' | 'der'; + }; + privateKeyEncoding?: { + type: 'pkcs8'; + format: 'pem' | 'der'; + cipher?: string; + passphrase?: string; + }; +}