react-native-quick-crypto 1.0.8 → 1.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. package/QuickCrypto.podspec +56 -6
  2. package/README.md +17 -11
  3. package/android/CMakeLists.txt +4 -0
  4. package/android/build.gradle +3 -0
  5. package/cpp/cipher/HybridCipherFactory.hpp +15 -1
  6. package/cpp/cipher/OCBCipher.cpp +4 -4
  7. package/cpp/cipher/XChaCha20Poly1305Cipher.cpp +161 -0
  8. package/cpp/cipher/XChaCha20Poly1305Cipher.hpp +43 -0
  9. package/cpp/cipher/XSalsa20Poly1305Cipher.cpp +145 -0
  10. package/cpp/cipher/XSalsa20Poly1305Cipher.hpp +42 -0
  11. package/cpp/dh/HybridDiffieHellman.cpp +10 -0
  12. package/cpp/dh/HybridDiffieHellman.hpp +1 -0
  13. package/cpp/ec/HybridEcKeyPair.cpp +21 -0
  14. package/cpp/ec/HybridEcKeyPair.hpp +1 -0
  15. package/cpp/hash/HybridHash.cpp +1 -1
  16. package/cpp/hash/HybridHash.hpp +1 -1
  17. package/cpp/hmac/HybridHmac.cpp +1 -1
  18. package/cpp/hmac/HybridHmac.hpp +1 -1
  19. package/cpp/keys/HybridKeyObjectHandle.cpp +112 -1
  20. package/cpp/keys/HybridKeyObjectHandle.hpp +5 -1
  21. package/deps/ncrypto/.bazelrc +0 -1
  22. package/deps/ncrypto/.bazelversion +1 -1
  23. package/deps/ncrypto/.github/workflows/commitlint.yml +16 -0
  24. package/deps/ncrypto/.github/workflows/linter.yml +2 -2
  25. package/deps/ncrypto/.github/workflows/release-please.yml +16 -0
  26. package/deps/ncrypto/.github/workflows/ubuntu.yml +82 -0
  27. package/deps/ncrypto/.release-please-manifest.json +3 -0
  28. package/deps/ncrypto/BUILD.bazel +9 -1
  29. package/deps/ncrypto/CHANGELOG.md +37 -0
  30. package/deps/ncrypto/CMakeLists.txt +35 -11
  31. package/deps/ncrypto/MODULE.bazel +16 -1
  32. package/deps/ncrypto/MODULE.bazel.lock +299 -118
  33. package/deps/ncrypto/cmake/ncrypto-flags.cmake +1 -0
  34. package/deps/ncrypto/include/ncrypto/aead.h +137 -0
  35. package/deps/ncrypto/include/ncrypto/version.h +14 -0
  36. package/deps/ncrypto/include/ncrypto.h +85 -230
  37. package/deps/ncrypto/ncrypto.pc.in +10 -0
  38. package/deps/ncrypto/release-please-config.json +11 -0
  39. package/deps/ncrypto/src/CMakeLists.txt +31 -6
  40. package/deps/ncrypto/src/aead.cpp +302 -0
  41. package/deps/ncrypto/src/ncrypto.cpp +274 -556
  42. package/deps/ncrypto/tests/BUILD.bazel +2 -0
  43. package/deps/ncrypto/tests/basic.cpp +772 -2
  44. package/deps/ncrypto/tools/run-clang-format.sh +5 -5
  45. package/lib/commonjs/diffie-hellman.js +4 -1
  46. package/lib/commonjs/diffie-hellman.js.map +1 -1
  47. package/lib/commonjs/ec.js +20 -25
  48. package/lib/commonjs/ec.js.map +1 -1
  49. package/lib/commonjs/ed.js +1 -2
  50. package/lib/commonjs/ed.js.map +1 -1
  51. package/lib/commonjs/hash.js +7 -0
  52. package/lib/commonjs/hash.js.map +1 -1
  53. package/lib/commonjs/index.js +24 -2
  54. package/lib/commonjs/index.js.map +1 -1
  55. package/lib/commonjs/keys/classes.js +9 -5
  56. package/lib/commonjs/keys/classes.js.map +1 -1
  57. package/lib/commonjs/subtle.js +82 -31
  58. package/lib/commonjs/subtle.js.map +1 -1
  59. package/lib/commonjs/utils/types.js.map +1 -1
  60. package/lib/module/diffie-hellman.js +4 -0
  61. package/lib/module/diffie-hellman.js.map +1 -1
  62. package/lib/module/ec.js +19 -25
  63. package/lib/module/ec.js.map +1 -1
  64. package/lib/module/ed.js +1 -2
  65. package/lib/module/ed.js.map +1 -1
  66. package/lib/module/hash.js +6 -0
  67. package/lib/module/hash.js.map +1 -1
  68. package/lib/module/index.js +10 -1
  69. package/lib/module/index.js.map +1 -1
  70. package/lib/module/keys/classes.js +9 -5
  71. package/lib/module/keys/classes.js.map +1 -1
  72. package/lib/module/subtle.js +83 -32
  73. package/lib/module/subtle.js.map +1 -1
  74. package/lib/module/utils/types.js.map +1 -1
  75. package/lib/tsconfig.tsbuildinfo +1 -1
  76. package/lib/typescript/diffie-hellman.d.ts +2 -0
  77. package/lib/typescript/diffie-hellman.d.ts.map +1 -1
  78. package/lib/typescript/ec.d.ts +1 -0
  79. package/lib/typescript/ec.d.ts.map +1 -1
  80. package/lib/typescript/ed.d.ts.map +1 -1
  81. package/lib/typescript/hash.d.ts +2 -0
  82. package/lib/typescript/hash.d.ts.map +1 -1
  83. package/lib/typescript/index.d.ts +7 -0
  84. package/lib/typescript/index.d.ts.map +1 -1
  85. package/lib/typescript/keys/classes.d.ts +2 -0
  86. package/lib/typescript/keys/classes.d.ts.map +1 -1
  87. package/lib/typescript/specs/diffie-hellman.nitro.d.ts +1 -0
  88. package/lib/typescript/specs/diffie-hellman.nitro.d.ts.map +1 -1
  89. package/lib/typescript/specs/ecKeyPair.nitro.d.ts +1 -0
  90. package/lib/typescript/specs/ecKeyPair.nitro.d.ts.map +1 -1
  91. package/lib/typescript/specs/keyObjectHandle.nitro.d.ts +2 -0
  92. package/lib/typescript/specs/keyObjectHandle.nitro.d.ts.map +1 -1
  93. package/lib/typescript/subtle.d.ts.map +1 -1
  94. package/lib/typescript/utils/types.d.ts +12 -5
  95. package/lib/typescript/utils/types.d.ts.map +1 -1
  96. package/nitrogen/generated/android/QuickCrypto+autolinking.cmake +8 -5
  97. package/nitrogen/generated/android/QuickCrypto+autolinking.gradle +1 -1
  98. package/nitrogen/generated/android/QuickCryptoOnLoad.cpp +54 -54
  99. package/nitrogen/generated/android/QuickCryptoOnLoad.hpp +1 -1
  100. package/nitrogen/generated/android/kotlin/com/margelo/nitro/crypto/QuickCryptoOnLoad.kt +1 -1
  101. package/nitrogen/generated/ios/QuickCrypto+autolinking.rb +2 -2
  102. package/nitrogen/generated/ios/QuickCrypto-Swift-Cxx-Bridge.cpp +1 -1
  103. package/nitrogen/generated/ios/QuickCrypto-Swift-Cxx-Bridge.hpp +1 -1
  104. package/nitrogen/generated/ios/QuickCrypto-Swift-Cxx-Umbrella.hpp +1 -1
  105. package/nitrogen/generated/ios/QuickCryptoAutolinking.mm +54 -54
  106. package/nitrogen/generated/ios/QuickCryptoAutolinking.swift +5 -1
  107. package/nitrogen/generated/shared/c++/AsymmetricKeyType.hpp +1 -1
  108. package/nitrogen/generated/shared/c++/CipherArgs.hpp +34 -19
  109. package/nitrogen/generated/shared/c++/HybridBlake3Spec.cpp +1 -1
  110. package/nitrogen/generated/shared/c++/HybridBlake3Spec.hpp +1 -3
  111. package/nitrogen/generated/shared/c++/HybridCipherFactorySpec.cpp +1 -1
  112. package/nitrogen/generated/shared/c++/HybridCipherFactorySpec.hpp +1 -1
  113. package/nitrogen/generated/shared/c++/HybridCipherSpec.cpp +1 -1
  114. package/nitrogen/generated/shared/c++/HybridCipherSpec.hpp +1 -3
  115. package/nitrogen/generated/shared/c++/HybridDiffieHellmanSpec.cpp +2 -1
  116. package/nitrogen/generated/shared/c++/HybridDiffieHellmanSpec.hpp +3 -3
  117. package/nitrogen/generated/shared/c++/HybridECDHSpec.cpp +1 -1
  118. package/nitrogen/generated/shared/c++/HybridECDHSpec.hpp +2 -3
  119. package/nitrogen/generated/shared/c++/HybridEcKeyPairSpec.cpp +2 -1
  120. package/nitrogen/generated/shared/c++/HybridEcKeyPairSpec.hpp +2 -3
  121. package/nitrogen/generated/shared/c++/HybridEdKeyPairSpec.cpp +1 -1
  122. package/nitrogen/generated/shared/c++/HybridEdKeyPairSpec.hpp +2 -3
  123. package/nitrogen/generated/shared/c++/HybridHashSpec.cpp +1 -1
  124. package/nitrogen/generated/shared/c++/HybridHashSpec.hpp +2 -4
  125. package/nitrogen/generated/shared/c++/HybridHkdfSpec.cpp +1 -1
  126. package/nitrogen/generated/shared/c++/HybridHkdfSpec.hpp +2 -3
  127. package/nitrogen/generated/shared/c++/HybridHmacSpec.cpp +1 -1
  128. package/nitrogen/generated/shared/c++/HybridHmacSpec.hpp +3 -4
  129. package/nitrogen/generated/shared/c++/HybridKeyObjectHandleSpec.cpp +3 -1
  130. package/nitrogen/generated/shared/c++/HybridKeyObjectHandleSpec.hpp +8 -4
  131. package/nitrogen/generated/shared/c++/HybridMlDsaKeyPairSpec.cpp +1 -1
  132. package/nitrogen/generated/shared/c++/HybridMlDsaKeyPairSpec.hpp +2 -3
  133. package/nitrogen/generated/shared/c++/HybridPbkdf2Spec.cpp +1 -1
  134. package/nitrogen/generated/shared/c++/HybridPbkdf2Spec.hpp +2 -3
  135. package/nitrogen/generated/shared/c++/HybridRandomSpec.cpp +1 -1
  136. package/nitrogen/generated/shared/c++/HybridRandomSpec.hpp +2 -3
  137. package/nitrogen/generated/shared/c++/HybridRsaCipherSpec.cpp +1 -1
  138. package/nitrogen/generated/shared/c++/HybridRsaCipherSpec.hpp +1 -3
  139. package/nitrogen/generated/shared/c++/HybridRsaKeyPairSpec.cpp +1 -1
  140. package/nitrogen/generated/shared/c++/HybridRsaKeyPairSpec.hpp +1 -3
  141. package/nitrogen/generated/shared/c++/HybridScryptSpec.cpp +1 -1
  142. package/nitrogen/generated/shared/c++/HybridScryptSpec.hpp +2 -3
  143. package/nitrogen/generated/shared/c++/HybridSignHandleSpec.cpp +1 -1
  144. package/nitrogen/generated/shared/c++/HybridSignHandleSpec.hpp +1 -3
  145. package/nitrogen/generated/shared/c++/HybridUtilsSpec.cpp +1 -1
  146. package/nitrogen/generated/shared/c++/HybridUtilsSpec.hpp +2 -3
  147. package/nitrogen/generated/shared/c++/HybridVerifyHandleSpec.cpp +1 -1
  148. package/nitrogen/generated/shared/c++/HybridVerifyHandleSpec.hpp +1 -3
  149. package/nitrogen/generated/shared/c++/JWK.hpp +84 -68
  150. package/nitrogen/generated/shared/c++/JWKkty.hpp +5 -1
  151. package/nitrogen/generated/shared/c++/JWKuse.hpp +1 -1
  152. package/nitrogen/generated/shared/c++/KFormatType.hpp +1 -1
  153. package/nitrogen/generated/shared/c++/KeyDetail.hpp +39 -23
  154. package/nitrogen/generated/shared/c++/KeyEncoding.hpp +1 -1
  155. package/nitrogen/generated/shared/c++/KeyObject.hpp +21 -5
  156. package/nitrogen/generated/shared/c++/KeyType.hpp +1 -1
  157. package/nitrogen/generated/shared/c++/KeyUsage.hpp +1 -1
  158. package/nitrogen/generated/shared/c++/NamedCurve.hpp +1 -1
  159. package/package.json +10 -7
  160. package/src/diffie-hellman.ts +6 -0
  161. package/src/ec.ts +23 -19
  162. package/src/ed.ts +1 -2
  163. package/src/hash.ts +11 -0
  164. package/src/index.ts +9 -0
  165. package/src/keys/classes.ts +10 -3
  166. package/src/specs/diffie-hellman.nitro.ts +1 -0
  167. package/src/specs/ecKeyPair.nitro.ts +2 -0
  168. package/src/specs/keyObjectHandle.nitro.ts +2 -0
  169. package/src/subtle.ts +131 -32
  170. package/src/utils/types.ts +18 -3
  171. package/deps/ncrypto/WORKSPACE +0 -15
@@ -22,10 +22,50 @@ Pod::Spec.new do |s|
22
22
  sodium_enabled = ENV['SODIUM_ENABLED'] == '1'
23
23
  Pod::UI.puts("[QuickCrypto] 🧂 has libsodium #{sodium_enabled ? "enabled" : "disabled"}!")
24
24
 
25
+ # Ensure libsodium source is present during podspec evaluation when enabled.
26
+ # This is necessary because prepare_command is skipped for :path pods.
27
+ if sodium_enabled
28
+ sodium_version = "1.0.20"
29
+ sodium_dir = File.join(__dir__, "ios", "libsodium-stable")
30
+ sodium_header = File.join(sodium_dir, "src", "libsodium", "include", "sodium.h")
31
+ unless File.exist?(sodium_header)
32
+ FileUtils.mkdir_p(File.join(__dir__, "ios"))
33
+ FileUtils.rm_rf(sodium_dir) if File.directory?(sodium_dir)
34
+
35
+ Pod::UI.puts "[QuickCrypto] ⬇️ Downloading libsodium source..."
36
+ Dir.chdir(__dir__) do
37
+ system("curl -sSfL --connect-timeout 30 --max-time 300 -o ios/libsodium.tar.gz https://download.libsodium.org/libsodium/releases/libsodium-#{sodium_version}-stable.tar.gz") || raise("Failed to download libsodium")
38
+ system("tar -xzf ios/libsodium.tar.gz -C ios") || raise("Failed to extract libsodium")
39
+ File.delete("ios/libsodium.tar.gz") if File.exist?("ios/libsodium.tar.gz")
40
+ end
41
+ Pod::UI.puts "[QuickCrypto] ✅ libsodium source downloaded successfully"
42
+ end
43
+ end
44
+
25
45
  # OpenSSL 3.6+ vendored xcframework (not yet on CocoaPods trunk)
26
- openssl_version = "3.6.0000"
46
+ openssl_version = "3.6.0001"
27
47
  openssl_url = "https://github.com/krzyzanowskim/OpenSSL/releases/download/#{openssl_version}/OpenSSL.xcframework.zip"
28
48
 
49
+ # Ensure OpenSSL.xcframework is present during podspec evaluation.
50
+ # This is necessary because prepare_command is skipped for :path pods,
51
+ # which is how React Native native modules are installed.
52
+ # See: https://github.com/margelo/react-native-quick-crypto/issues/882
53
+ openssl_dir = File.join(__dir__, "OpenSSL.xcframework")
54
+ openssl_plist = File.join(openssl_dir, "Info.plist")
55
+ unless File.exist?(openssl_plist)
56
+ # Clean up any partial download
57
+ FileUtils.rm_rf(openssl_dir) if File.directory?(openssl_dir)
58
+ FileUtils.rm_f(File.join(__dir__, "OpenSSL.xcframework.zip"))
59
+
60
+ Pod::UI.puts "[QuickCrypto] ⬇️ Downloading OpenSSL.xcframework..."
61
+ Dir.chdir(__dir__) do
62
+ system("curl -sSfL --connect-timeout 30 --max-time 300 -o OpenSSL.xcframework.zip #{openssl_url}") || raise("Failed to download OpenSSL")
63
+ system("unzip -q -o OpenSSL.xcframework.zip") || raise("Failed to unzip OpenSSL")
64
+ File.delete("OpenSSL.xcframework.zip") if File.exist?("OpenSSL.xcframework.zip")
65
+ end
66
+ Pod::UI.puts "[QuickCrypto] ✅ OpenSSL.xcframework downloaded successfully"
67
+ end
68
+
29
69
  if sodium_enabled
30
70
  # Build libsodium from source for XSalsa20 cipher support
31
71
  # CocoaPods packages are outdated (1.0.12) and SPM causes module conflicts
@@ -72,7 +112,7 @@ Pod::Spec.new do |s|
72
112
  # implementation (C++)
73
113
  "cpp/**/*.{hpp,cpp}",
74
114
  # dependencies (C++) - ncrypto
75
- "deps/ncrypto/include/*.{h}",
115
+ "deps/ncrypto/include/**/*.{h}",
76
116
  "deps/ncrypto/src/*.{cpp}",
77
117
  # dependencies (C) - exclude BLAKE3 x86 SIMD files (only use portable + NEON for ARM)
78
118
  "deps/blake3/c/*.{h,c}",
@@ -103,6 +143,9 @@ Pod::Spec.new do |s|
103
143
  "deps/blake3/c/example.c",
104
144
  "deps/blake3/c/example_tbb.c",
105
145
  "deps/blake3/c/blake3_tbb.cpp",
146
+ # Exclude ncrypto version.h to avoid header name collision with libsodium's version.h
147
+ # (ncrypto.h includes it via relative path "ncrypto/version.h" which still resolves)
148
+ "deps/ncrypto/include/ncrypto/version.h",
106
149
  # Exclude non-C parts of BLAKE3 repo (Rust, benchmarks, tools, etc.)
107
150
  "deps/blake3/src/**/*",
108
151
  "deps/blake3/b3sum/**/*",
@@ -125,7 +168,11 @@ Pod::Spec.new do |s|
125
168
  "CLANG_CXX_LANGUAGE_STANDARD" => "c++20",
126
169
  "CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES" => "YES",
127
170
  # Exclude ARM NEON source when building x86_64 simulator (no NEON support).
128
- "EXCLUDED_SOURCE_FILE_NAMES[sdk=iphonesimulator*][arch=x86_64]" => "deps/blake3/c/blake3_neon.c"
171
+ "EXCLUDED_SOURCE_FILE_NAMES[sdk=iphonesimulator*][arch=x86_64]" => "deps/blake3/c/blake3_neon.c",
172
+ # Disable x86 SIMD intrinsics on iOS simulator — the .c implementation files are already
173
+ # excluded above, but blake3_dispatch.c still references the symbols unless these macros
174
+ # are defined. Mirrors the Android CMakeLists.txt approach (line 18-22).
175
+ "GCC_PREPROCESSOR_DEFINITIONS[sdk=iphonesimulator*][arch=x86_64]" => "$(inherited) BLAKE3_NO_AVX512 BLAKE3_NO_AVX2 BLAKE3_NO_SSE41 BLAKE3_NO_SSE2"
129
176
  }
130
177
 
131
178
  # Add cpp subdirectories to header search paths
@@ -141,12 +188,15 @@ Pod::Spec.new do |s|
141
188
  ]
142
189
 
143
190
  if sodium_enabled
191
+ # Use absolute path from __dir__ which resolves symlinks correctly.
192
+ # This is necessary in monorepo setups where the podspec is accessed via symlink
193
+ # but the source files are resolved to their real paths during compilation.
194
+ real_sodium_include = File.join(__dir__, "ios", "libsodium-stable", "src", "libsodium", "include")
144
195
  sodium_headers = [
145
196
  "\"$(PODS_TARGET_SRCROOT)/ios/libsodium-stable/src/libsodium/include\"",
146
197
  "\"$(PODS_TARGET_SRCROOT)/ios/libsodium-stable/src/libsodium/include/sodium\"",
147
- "\"$(PODS_TARGET_SRCROOT)/ios/libsodium-stable\"",
148
- "\"$(PODS_ROOT)/../../packages/react-native-quick-crypto/ios/libsodium-stable/src/libsodium/include\"",
149
- "\"$(PODS_ROOT)/../../packages/react-native-quick-crypto/ios/libsodium-stable/src/libsodium/include/sodium\""
198
+ "\"#{real_sodium_include}\"",
199
+ "\"#{real_sodium_include}/sodium\""
150
200
  ]
151
201
  xcconfig["HEADER_SEARCH_PATHS"] = (cpp_headers + sodium_headers).join(' ')
152
202
  xcconfig["GCC_PREPROCESSOR_DEFINITIONS"] = "$(inherited) FOLLY_NO_CONFIG FOLLY_CFG_NO_COROUTINES BLSALLOC_SODIUM=1"
package/README.md CHANGED
@@ -10,19 +10,15 @@
10
10
 
11
11
  A fast implementation of Node's `crypto` module.
12
12
 
13
- > Note: This version `1.x` completed a major refactor, porting to OpenSSL 3.6+, New Architecture, Bridgeless, and [`Nitro Modules`](https://github.com/mrousavy/react-native-nitro). It should be at or above feature-parity compared to the `0.x` version. Status, as always, will be represented in [implementation-coverage.md](./.docs/implementation-coverage.md).
14
-
15
- > Note: Minimum supported version of React Native is `0.75`. If you need to use earlier versions, please use `0.x` versions of this library.
16
-
17
13
  ## Features
18
14
 
19
15
  Unlike any other current JS-based polyfills, react-native-quick-crypto is written in C/C++ JSI and provides much greater performance - especially on mobile devices.
20
- QuickCrypto can be used as a drop-in replacement for your Web3/Crypto apps to speed up common cryptography functions.
16
+ QuickCrypto can be used as a drop-in replacement for your Web3/Crypto apps or CRDT-based local first databases to speed up common cryptography functions.
21
17
 
22
- - 🏎️ Up to 58x faster than all other solutions
23
- - ⚡️ Lightning fast implementation with pure C++ and JSI, instead of JS
18
+ - 🏎️ Hundreds of times faster than all JS-based solutions
19
+ - ⚡️ Lightning fast implementation with Nitro Modules (pure C++ and JSI) instead of JS
24
20
  - 🧪 Well tested in JS and C++ (OpenSSL)
25
- - 💰 Made for crypto apps and Wallets
21
+ - 💰 Made for crypto apps and wallets
26
22
  - 🔢 Secure native compiled cryptography
27
23
  - 🔁 Easy drop-in replacement for [crypto-browserify](https://github.com/browserify/crypto-browserify) or [react-native-crypto](https://github.com/tradle/react-native-crypto)
28
24
 
@@ -33,6 +29,8 @@ QuickCrypto can be used as a drop-in replacement for your Web3/Crypto apps to sp
33
29
  | `1.x` | new [->](https://github.com/reactwg/react-native-new-architecture/blob/main/docs/enable-apps.md) | Nitro Modules [->](https://github.com/mrousavy/nitro) |
34
30
  | `0.x` | old, new 🤞 | Bridge & JSI |
35
31
 
32
+ > Note: Minimum supported version of React Native is `0.75`. If you need to use earlier versions, please use `0.x` versions of this library.
33
+
36
34
  ## Migration
37
35
 
38
36
  Our goal in refactoring to v1.0 was to maintain API compatibility. If you are upgrading to v1.0 from v0.x, and find any discrepancies, please open an issue in this repo.
@@ -50,12 +48,18 @@ There is a benchmark suite in the Example app in this repo that has benchmarks o
50
48
  </h3>
51
49
 
52
50
  ```sh
53
- bun add react-native-quick-crypto react-native-nitro-modules
51
+ bun add react-native-quick-crypto react-native-nitro-modules react-native-quick-base64
54
52
  cd ios && pod install
55
53
  ```
56
54
 
57
55
  <h3>
58
- Expo  <a href="#"><img src="./.docs/img/expo.png" height="12" /></a>
56
+ Expo  <a href="#">
57
+ <picture>
58
+ <source media="(prefers-color-scheme: dark)" srcset="./.docs/img/expo/dark.png" />
59
+ <source media="(prefers-color-scheme: light)" srcset="./.docs/img/expo/light.png" />
60
+ <img alt="Expo" src="./.docs/img/expo/light.png" height="12" />
61
+ </picture>
62
+ </a>
59
63
  </h3>
60
64
 
61
65
  ```sh
@@ -114,7 +118,7 @@ module.exports = {
114
118
  + alias: {
115
119
  + 'crypto': 'react-native-quick-crypto',
116
120
  + 'stream': 'readable-stream',
117
- + 'buffer': '@craftzdog/react-native-buffer',
121
+ + 'buffer': 'react-native-quick-crypto',
118
122
  + },
119
123
  + },
120
124
  + ],
@@ -123,6 +127,8 @@ module.exports = {
123
127
  };
124
128
  ```
125
129
 
130
+ > **Note:** `react-native-quick-crypto` re-exports `Buffer` from `@craftzdog/react-native-buffer`, so you can use either as the buffer alias. Using `react-native-quick-crypto` ensures a single Buffer instance across your app.
131
+
126
132
  Then restart your bundler using `yarn start --reset-cache`.
127
133
 
128
134
  ## Usage
@@ -32,6 +32,8 @@ add_library(
32
32
  ../cpp/cipher/HybridRsaCipher.cpp
33
33
  ../cpp/cipher/OCBCipher.cpp
34
34
  ../cpp/cipher/XSalsa20Cipher.cpp
35
+ ../cpp/cipher/XSalsa20Poly1305Cipher.cpp
36
+ ../cpp/cipher/XChaCha20Poly1305Cipher.cpp
35
37
  ../cpp/cipher/ChaCha20Cipher.cpp
36
38
  ../cpp/cipher/ChaCha20Poly1305Cipher.cpp
37
39
  ../cpp/dh/HybridDiffieHellman.cpp
@@ -53,6 +55,8 @@ add_library(
53
55
  ../cpp/utils/HybridUtils.cpp
54
56
  ${BLAKE3_SOURCES}
55
57
  ../deps/fastpbkdf2/fastpbkdf2.c
58
+ ../deps/ncrypto/src/aead.cpp
59
+ ../deps/ncrypto/src/engine.cpp
56
60
  ../deps/ncrypto/src/ncrypto.cpp
57
61
  )
58
62
 
@@ -79,6 +79,9 @@ android {
79
79
  buildFeatures {
80
80
  buildConfig true
81
81
  prefab true
82
+ // Explicitly disable RenderScript (deprecated since Android 12, removed in AGP 9.0)
83
+ // to suppress 'isRenderscriptDebuggable is obsolete' warning. See #802.
84
+ renderScript = false
82
85
  }
83
86
 
84
87
  packagingOptions {
@@ -11,7 +11,9 @@
11
11
  #include "HybridCipherFactorySpec.hpp"
12
12
  #include "OCBCipher.hpp"
13
13
  #include "QuickCryptoUtils.hpp"
14
+ #include "XChaCha20Poly1305Cipher.hpp"
14
15
  #include "XSalsa20Cipher.hpp"
16
+ #include "XSalsa20Poly1305Cipher.hpp"
15
17
 
16
18
  namespace margelo::nitro::crypto {
17
19
 
@@ -88,7 +90,7 @@ class HybridCipherFactory : public HybridCipherFactorySpec {
88
90
  }
89
91
  EVP_CIPHER_free(cipher);
90
92
 
91
- // libsodium
93
+ // libsodium ciphers
92
94
  std::string cipherName = toLower(args.cipherType);
93
95
  if (cipherName == "xsalsa20") {
94
96
  cipherInstance = std::make_shared<XSalsa20Cipher>();
@@ -96,6 +98,18 @@ class HybridCipherFactory : public HybridCipherFactorySpec {
96
98
  cipherInstance->init(args.cipherKey, args.iv);
97
99
  return cipherInstance;
98
100
  }
101
+ if (cipherName == "xsalsa20-poly1305") {
102
+ cipherInstance = std::make_shared<XSalsa20Poly1305Cipher>();
103
+ cipherInstance->setArgs(args);
104
+ cipherInstance->init(args.cipherKey, args.iv);
105
+ return cipherInstance;
106
+ }
107
+ if (cipherName == "xchacha20-poly1305") {
108
+ cipherInstance = std::make_shared<XChaCha20Poly1305Cipher>();
109
+ cipherInstance->setArgs(args);
110
+ cipherInstance->init(args.cipherKey, args.iv);
111
+ return cipherInstance;
112
+ }
99
113
 
100
114
  // Unsupported cipher type
101
115
  throw std::runtime_error("Unsupported or unknown cipher type: " + args.cipherType);
@@ -13,9 +13,9 @@ void OCBCipher::init(const std::shared_ptr<ArrayBuffer>& key, const std::shared_
13
13
  HybridCipher::init(key, iv);
14
14
  auth_tag_len = tag_len;
15
15
 
16
- // Set tag length for OCB (must be 12-16 bytes)
17
- if (auth_tag_len < 12 || auth_tag_len > 16) {
18
- throw std::runtime_error("OCB tag length must be between 12 and 16 bytes");
16
+ // Set tag length for OCB (must be 8-16 bytes)
17
+ if (auth_tag_len < 8 || auth_tag_len > 16) {
18
+ throw std::runtime_error("OCB tag length must be between 8 and 16 bytes");
19
19
  }
20
20
  if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, auth_tag_len, nullptr) != 1) {
21
21
  throw std::runtime_error("Failed to set OCB tag length");
@@ -42,7 +42,7 @@ bool OCBCipher::setAuthTag(const std::shared_ptr<ArrayBuffer>& tag) {
42
42
  }
43
43
  auto native_tag = ToNativeArrayBuffer(tag);
44
44
  size_t tag_len = native_tag->size();
45
- if (tag_len < 12 || tag_len > 16) {
45
+ if (tag_len < 8 || tag_len > 16) {
46
46
  throw std::runtime_error("Invalid OCB tag length");
47
47
  }
48
48
  if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, tag_len, native_tag->data()) != 1) {
@@ -0,0 +1,161 @@
1
+ #include "XChaCha20Poly1305Cipher.hpp"
2
+
3
+ #include <cstring>
4
+ #include <stdexcept>
5
+
6
+ #include "NitroModules/ArrayBuffer.hpp"
7
+ #include "QuickCryptoUtils.hpp"
8
+
9
+ namespace margelo::nitro::crypto {
10
+
11
+ XChaCha20Poly1305Cipher::~XChaCha20Poly1305Cipher() {
12
+ #ifdef BLSALLOC_SODIUM
13
+ sodium_memzero(key_, kKeySize);
14
+ sodium_memzero(nonce_, kNonceSize);
15
+ sodium_memzero(auth_tag_, kTagSize);
16
+ if (!data_buffer_.empty()) {
17
+ sodium_memzero(data_buffer_.data(), data_buffer_.size());
18
+ }
19
+ if (!aad_.empty()) {
20
+ sodium_memzero(aad_.data(), aad_.size());
21
+ }
22
+ #else
23
+ std::memset(key_, 0, kKeySize);
24
+ std::memset(nonce_, 0, kNonceSize);
25
+ std::memset(auth_tag_, 0, kTagSize);
26
+ #endif
27
+ data_buffer_.clear();
28
+ aad_.clear();
29
+ }
30
+
31
+ void XChaCha20Poly1305Cipher::init(const std::shared_ptr<ArrayBuffer> cipher_key, const std::shared_ptr<ArrayBuffer> iv) {
32
+ auto native_key = ToNativeArrayBuffer(cipher_key);
33
+ auto native_iv = ToNativeArrayBuffer(iv);
34
+
35
+ if (native_key->size() != kKeySize) {
36
+ throw std::runtime_error("XChaCha20-Poly1305 key must be 32 bytes, got " + std::to_string(native_key->size()) + " bytes");
37
+ }
38
+
39
+ if (native_iv->size() != kNonceSize) {
40
+ throw std::runtime_error("XChaCha20-Poly1305 nonce must be 24 bytes, got " + std::to_string(native_iv->size()) + " bytes");
41
+ }
42
+
43
+ std::memcpy(key_, native_key->data(), kKeySize);
44
+ std::memcpy(nonce_, native_iv->data(), kNonceSize);
45
+
46
+ data_buffer_.clear();
47
+ aad_.clear();
48
+ final_called_ = false;
49
+ }
50
+
51
+ std::shared_ptr<ArrayBuffer> XChaCha20Poly1305Cipher::update(const std::shared_ptr<ArrayBuffer>& data) {
52
+ #ifndef BLSALLOC_SODIUM
53
+ throw std::runtime_error("XChaCha20Poly1305Cipher: libsodium must be enabled (BLSALLOC_SODIUM)");
54
+ #else
55
+ auto native_data = ToNativeArrayBuffer(data);
56
+ size_t data_len = native_data->size();
57
+
58
+ size_t old_size = data_buffer_.size();
59
+ data_buffer_.resize(old_size + data_len);
60
+ std::memcpy(data_buffer_.data() + old_size, native_data->data(), data_len);
61
+
62
+ return std::make_shared<NativeArrayBuffer>(nullptr, 0, nullptr);
63
+ #endif
64
+ }
65
+
66
+ std::shared_ptr<ArrayBuffer> XChaCha20Poly1305Cipher::final() {
67
+ #ifndef BLSALLOC_SODIUM
68
+ throw std::runtime_error("XChaCha20Poly1305Cipher: libsodium must be enabled (BLSALLOC_SODIUM)");
69
+ #else
70
+ if (is_cipher) {
71
+ uint8_t* ciphertext = new uint8_t[data_buffer_.size()];
72
+
73
+ int result =
74
+ crypto_aead_xchacha20poly1305_ietf_encrypt_detached(ciphertext, auth_tag_, nullptr, data_buffer_.data(), data_buffer_.size(),
75
+ aad_.empty() ? nullptr : aad_.data(), aad_.size(), nullptr, nonce_, key_);
76
+
77
+ if (result != 0) {
78
+ sodium_memzero(ciphertext, data_buffer_.size());
79
+ delete[] ciphertext;
80
+ throw std::runtime_error("XChaCha20Poly1305Cipher: encryption failed");
81
+ }
82
+
83
+ final_called_ = true;
84
+ size_t ct_len = data_buffer_.size();
85
+ return std::make_shared<NativeArrayBuffer>(ciphertext, ct_len, [=]() { delete[] ciphertext; });
86
+ } else {
87
+ if (data_buffer_.empty()) {
88
+ final_called_ = true;
89
+ return std::make_shared<NativeArrayBuffer>(nullptr, 0, nullptr);
90
+ }
91
+
92
+ uint8_t* plaintext = new uint8_t[data_buffer_.size()];
93
+
94
+ int result =
95
+ crypto_aead_xchacha20poly1305_ietf_decrypt_detached(plaintext, nullptr, data_buffer_.data(), data_buffer_.size(), auth_tag_,
96
+ aad_.empty() ? nullptr : aad_.data(), aad_.size(), nonce_, key_);
97
+
98
+ if (result != 0) {
99
+ sodium_memzero(plaintext, data_buffer_.size());
100
+ delete[] plaintext;
101
+ throw std::runtime_error("XChaCha20Poly1305Cipher: decryption failed - authentication tag mismatch");
102
+ }
103
+
104
+ final_called_ = true;
105
+ size_t pt_len = data_buffer_.size();
106
+ return std::make_shared<NativeArrayBuffer>(plaintext, pt_len, [=]() { delete[] plaintext; });
107
+ }
108
+ #endif
109
+ }
110
+
111
+ bool XChaCha20Poly1305Cipher::setAAD(const std::shared_ptr<ArrayBuffer>& data, std::optional<double> plaintextLength) {
112
+ #ifndef BLSALLOC_SODIUM
113
+ throw std::runtime_error("XChaCha20Poly1305Cipher: libsodium must be enabled (BLSALLOC_SODIUM)");
114
+ #else
115
+ auto native_aad = ToNativeArrayBuffer(data);
116
+ aad_.resize(native_aad->size());
117
+ std::memcpy(aad_.data(), native_aad->data(), native_aad->size());
118
+ return true;
119
+ #endif
120
+ }
121
+
122
+ std::shared_ptr<ArrayBuffer> XChaCha20Poly1305Cipher::getAuthTag() {
123
+ #ifndef BLSALLOC_SODIUM
124
+ throw std::runtime_error("XChaCha20Poly1305Cipher: libsodium must be enabled (BLSALLOC_SODIUM)");
125
+ #else
126
+ if (!is_cipher) {
127
+ throw std::runtime_error("getAuthTag can only be called during encryption");
128
+ }
129
+ if (!final_called_) {
130
+ throw std::runtime_error("getAuthTag must be called after final()");
131
+ }
132
+
133
+ uint8_t* tag_copy = new uint8_t[kTagSize];
134
+ std::memcpy(tag_copy, auth_tag_, kTagSize);
135
+ return std::make_shared<NativeArrayBuffer>(tag_copy, kTagSize, [=]() { delete[] tag_copy; });
136
+ #endif
137
+ }
138
+
139
+ bool XChaCha20Poly1305Cipher::setAuthTag(const std::shared_ptr<ArrayBuffer>& tag) {
140
+ #ifndef BLSALLOC_SODIUM
141
+ throw std::runtime_error("XChaCha20Poly1305Cipher: libsodium must be enabled (BLSALLOC_SODIUM)");
142
+ #else
143
+ if (is_cipher) {
144
+ throw std::runtime_error("setAuthTag can only be called during decryption");
145
+ }
146
+
147
+ auto native_tag = ToNativeArrayBuffer(tag);
148
+ if (native_tag->size() != kTagSize) {
149
+ throw std::runtime_error("XChaCha20-Poly1305 tag must be 16 bytes, got " + std::to_string(native_tag->size()) + " bytes");
150
+ }
151
+
152
+ std::memcpy(auth_tag_, native_tag->data(), kTagSize);
153
+ return true;
154
+ #endif
155
+ }
156
+
157
+ bool XChaCha20Poly1305Cipher::setAutoPadding(bool autoPad) {
158
+ throw std::runtime_error("setAutoPadding is not supported for xchacha20-poly1305");
159
+ }
160
+
161
+ } // namespace margelo::nitro::crypto
@@ -0,0 +1,43 @@
1
+ #pragma once
2
+
3
+ #ifdef BLSALLOC_SODIUM
4
+ #include "sodium.h"
5
+ #else
6
+ #define crypto_aead_xchacha20poly1305_ietf_KEYBYTES 32U
7
+ #define crypto_aead_xchacha20poly1305_ietf_NPUBBYTES 24U
8
+ #define crypto_aead_xchacha20poly1305_ietf_ABYTES 16U
9
+ #endif
10
+
11
+ #include <vector>
12
+
13
+ #include "HybridCipher.hpp"
14
+
15
+ namespace margelo::nitro::crypto {
16
+
17
+ class XChaCha20Poly1305Cipher : public HybridCipher {
18
+ public:
19
+ XChaCha20Poly1305Cipher() : HybridObject(TAG), final_called_(false) {}
20
+ ~XChaCha20Poly1305Cipher();
21
+
22
+ void init(const std::shared_ptr<ArrayBuffer> cipher_key, const std::shared_ptr<ArrayBuffer> iv) override;
23
+ std::shared_ptr<ArrayBuffer> update(const std::shared_ptr<ArrayBuffer>& data) override;
24
+ std::shared_ptr<ArrayBuffer> final() override;
25
+ bool setAAD(const std::shared_ptr<ArrayBuffer>& data, std::optional<double> plaintextLength) override;
26
+ std::shared_ptr<ArrayBuffer> getAuthTag() override;
27
+ bool setAuthTag(const std::shared_ptr<ArrayBuffer>& tag) override;
28
+ bool setAutoPadding(bool autoPad) override;
29
+
30
+ private:
31
+ static constexpr size_t kKeySize = crypto_aead_xchacha20poly1305_ietf_KEYBYTES;
32
+ static constexpr size_t kNonceSize = crypto_aead_xchacha20poly1305_ietf_NPUBBYTES;
33
+ static constexpr size_t kTagSize = crypto_aead_xchacha20poly1305_ietf_ABYTES;
34
+
35
+ uint8_t key_[kKeySize];
36
+ uint8_t nonce_[kNonceSize];
37
+ std::vector<uint8_t> aad_;
38
+ std::vector<uint8_t> data_buffer_;
39
+ uint8_t auth_tag_[kTagSize];
40
+ bool final_called_;
41
+ };
42
+
43
+ } // namespace margelo::nitro::crypto
@@ -0,0 +1,145 @@
1
+ #include "XSalsa20Poly1305Cipher.hpp"
2
+
3
+ #include <cstring>
4
+ #include <stdexcept>
5
+
6
+ #include "NitroModules/ArrayBuffer.hpp"
7
+ #include "QuickCryptoUtils.hpp"
8
+
9
+ namespace margelo::nitro::crypto {
10
+
11
+ XSalsa20Poly1305Cipher::~XSalsa20Poly1305Cipher() {
12
+ #ifdef BLSALLOC_SODIUM
13
+ sodium_memzero(key_, kKeySize);
14
+ sodium_memzero(nonce_, kNonceSize);
15
+ sodium_memzero(auth_tag_, kTagSize);
16
+ if (!data_buffer_.empty()) {
17
+ sodium_memzero(data_buffer_.data(), data_buffer_.size());
18
+ }
19
+ #else
20
+ std::memset(key_, 0, kKeySize);
21
+ std::memset(nonce_, 0, kNonceSize);
22
+ std::memset(auth_tag_, 0, kTagSize);
23
+ #endif
24
+ data_buffer_.clear();
25
+ }
26
+
27
+ void XSalsa20Poly1305Cipher::init(const std::shared_ptr<ArrayBuffer> cipher_key, const std::shared_ptr<ArrayBuffer> iv) {
28
+ auto native_key = ToNativeArrayBuffer(cipher_key);
29
+ auto native_iv = ToNativeArrayBuffer(iv);
30
+
31
+ if (native_key->size() != kKeySize) {
32
+ throw std::runtime_error("XSalsa20-Poly1305 key must be 32 bytes, got " + std::to_string(native_key->size()) + " bytes");
33
+ }
34
+
35
+ if (native_iv->size() != kNonceSize) {
36
+ throw std::runtime_error("XSalsa20-Poly1305 nonce must be 24 bytes, got " + std::to_string(native_iv->size()) + " bytes");
37
+ }
38
+
39
+ std::memcpy(key_, native_key->data(), kKeySize);
40
+ std::memcpy(nonce_, native_iv->data(), kNonceSize);
41
+
42
+ data_buffer_.clear();
43
+ final_called_ = false;
44
+ }
45
+
46
+ std::shared_ptr<ArrayBuffer> XSalsa20Poly1305Cipher::update(const std::shared_ptr<ArrayBuffer>& data) {
47
+ #ifndef BLSALLOC_SODIUM
48
+ throw std::runtime_error("XSalsa20Poly1305Cipher: libsodium must be enabled (BLSALLOC_SODIUM)");
49
+ #else
50
+ auto native_data = ToNativeArrayBuffer(data);
51
+ size_t data_len = native_data->size();
52
+
53
+ size_t old_size = data_buffer_.size();
54
+ data_buffer_.resize(old_size + data_len);
55
+ std::memcpy(data_buffer_.data() + old_size, native_data->data(), data_len);
56
+
57
+ return std::make_shared<NativeArrayBuffer>(nullptr, 0, nullptr);
58
+ #endif
59
+ }
60
+
61
+ std::shared_ptr<ArrayBuffer> XSalsa20Poly1305Cipher::final() {
62
+ #ifndef BLSALLOC_SODIUM
63
+ throw std::runtime_error("XSalsa20Poly1305Cipher: libsodium must be enabled (BLSALLOC_SODIUM)");
64
+ #else
65
+ if (is_cipher) {
66
+ uint8_t* ciphertext = new uint8_t[data_buffer_.size()];
67
+
68
+ int result = crypto_secretbox_detached(ciphertext, auth_tag_, data_buffer_.data(), data_buffer_.size(), nonce_, key_);
69
+
70
+ if (result != 0) {
71
+ sodium_memzero(ciphertext, data_buffer_.size());
72
+ delete[] ciphertext;
73
+ throw std::runtime_error("XSalsa20Poly1305Cipher: encryption failed");
74
+ }
75
+
76
+ final_called_ = true;
77
+ size_t ct_len = data_buffer_.size();
78
+ return std::make_shared<NativeArrayBuffer>(ciphertext, ct_len, [=]() { delete[] ciphertext; });
79
+ } else {
80
+ if (data_buffer_.empty()) {
81
+ final_called_ = true;
82
+ return std::make_shared<NativeArrayBuffer>(nullptr, 0, nullptr);
83
+ }
84
+
85
+ uint8_t* plaintext = new uint8_t[data_buffer_.size()];
86
+
87
+ int result = crypto_secretbox_open_detached(plaintext, data_buffer_.data(), auth_tag_, data_buffer_.size(), nonce_, key_);
88
+
89
+ if (result != 0) {
90
+ sodium_memzero(plaintext, data_buffer_.size());
91
+ delete[] plaintext;
92
+ throw std::runtime_error("XSalsa20Poly1305Cipher: decryption failed - authentication tag mismatch");
93
+ }
94
+
95
+ final_called_ = true;
96
+ size_t pt_len = data_buffer_.size();
97
+ return std::make_shared<NativeArrayBuffer>(plaintext, pt_len, [=]() { delete[] plaintext; });
98
+ }
99
+ #endif
100
+ }
101
+
102
+ bool XSalsa20Poly1305Cipher::setAAD(const std::shared_ptr<ArrayBuffer>& data, std::optional<double> plaintextLength) {
103
+ throw std::runtime_error("AAD is not supported for xsalsa20-poly1305 (use xchacha20-poly1305 instead)");
104
+ }
105
+
106
+ std::shared_ptr<ArrayBuffer> XSalsa20Poly1305Cipher::getAuthTag() {
107
+ #ifndef BLSALLOC_SODIUM
108
+ throw std::runtime_error("XSalsa20Poly1305Cipher: libsodium must be enabled (BLSALLOC_SODIUM)");
109
+ #else
110
+ if (!is_cipher) {
111
+ throw std::runtime_error("getAuthTag can only be called during encryption");
112
+ }
113
+ if (!final_called_) {
114
+ throw std::runtime_error("getAuthTag must be called after final()");
115
+ }
116
+
117
+ uint8_t* tag_copy = new uint8_t[kTagSize];
118
+ std::memcpy(tag_copy, auth_tag_, kTagSize);
119
+ return std::make_shared<NativeArrayBuffer>(tag_copy, kTagSize, [=]() { delete[] tag_copy; });
120
+ #endif
121
+ }
122
+
123
+ bool XSalsa20Poly1305Cipher::setAuthTag(const std::shared_ptr<ArrayBuffer>& tag) {
124
+ #ifndef BLSALLOC_SODIUM
125
+ throw std::runtime_error("XSalsa20Poly1305Cipher: libsodium must be enabled (BLSALLOC_SODIUM)");
126
+ #else
127
+ if (is_cipher) {
128
+ throw std::runtime_error("setAuthTag can only be called during decryption");
129
+ }
130
+
131
+ auto native_tag = ToNativeArrayBuffer(tag);
132
+ if (native_tag->size() != kTagSize) {
133
+ throw std::runtime_error("XSalsa20-Poly1305 tag must be 16 bytes, got " + std::to_string(native_tag->size()) + " bytes");
134
+ }
135
+
136
+ std::memcpy(auth_tag_, native_tag->data(), kTagSize);
137
+ return true;
138
+ #endif
139
+ }
140
+
141
+ bool XSalsa20Poly1305Cipher::setAutoPadding(bool autoPad) {
142
+ throw std::runtime_error("setAutoPadding is not supported for xsalsa20-poly1305");
143
+ }
144
+
145
+ } // namespace margelo::nitro::crypto
@@ -0,0 +1,42 @@
1
+ #pragma once
2
+
3
+ #ifdef BLSALLOC_SODIUM
4
+ #include "sodium.h"
5
+ #else
6
+ #define crypto_secretbox_xsalsa20poly1305_KEYBYTES 32U
7
+ #define crypto_secretbox_xsalsa20poly1305_NONCEBYTES 24U
8
+ #define crypto_secretbox_xsalsa20poly1305_MACBYTES 16U
9
+ #endif
10
+
11
+ #include <vector>
12
+
13
+ #include "HybridCipher.hpp"
14
+
15
+ namespace margelo::nitro::crypto {
16
+
17
+ class XSalsa20Poly1305Cipher : public HybridCipher {
18
+ public:
19
+ XSalsa20Poly1305Cipher() : HybridObject(TAG), final_called_(false) {}
20
+ ~XSalsa20Poly1305Cipher();
21
+
22
+ void init(const std::shared_ptr<ArrayBuffer> cipher_key, const std::shared_ptr<ArrayBuffer> iv) override;
23
+ std::shared_ptr<ArrayBuffer> update(const std::shared_ptr<ArrayBuffer>& data) override;
24
+ std::shared_ptr<ArrayBuffer> final() override;
25
+ bool setAAD(const std::shared_ptr<ArrayBuffer>& data, std::optional<double> plaintextLength) override;
26
+ std::shared_ptr<ArrayBuffer> getAuthTag() override;
27
+ bool setAuthTag(const std::shared_ptr<ArrayBuffer>& tag) override;
28
+ bool setAutoPadding(bool autoPad) override;
29
+
30
+ private:
31
+ static constexpr size_t kKeySize = crypto_secretbox_xsalsa20poly1305_KEYBYTES;
32
+ static constexpr size_t kNonceSize = crypto_secretbox_xsalsa20poly1305_NONCEBYTES;
33
+ static constexpr size_t kTagSize = crypto_secretbox_xsalsa20poly1305_MACBYTES;
34
+
35
+ uint8_t key_[kKeySize];
36
+ uint8_t nonce_[kNonceSize];
37
+ std::vector<uint8_t> data_buffer_;
38
+ uint8_t auth_tag_[kTagSize];
39
+ bool final_called_;
40
+ };
41
+
42
+ } // namespace margelo::nitro::crypto
@@ -433,6 +433,16 @@ const DH* HybridDiffieHellman::getDH() const {
433
433
  return dh;
434
434
  }
435
435
 
436
+ double HybridDiffieHellman::getVerifyError() {
437
+ ensureInitialized();
438
+ const DH* dh = getDH();
439
+ int codes = 0;
440
+ if (DH_check(const_cast<DH*>(dh), &codes) != 1) {
441
+ return 0;
442
+ }
443
+ return static_cast<double>(codes);
444
+ }
445
+
436
446
  #pragma clang diagnostic pop
437
447
 
438
448
  } // namespace margelo::nitro::crypto