react-native-quick-crypto 1.0.0-beta.8 → 1.0.0

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 (480) hide show
  1. package/QuickCrypto.podspec +145 -6
  2. package/README.md +14 -27
  3. package/android/CMakeLists.txt +62 -7
  4. package/android/build.gradle +12 -2
  5. package/android/src/main/java/com/margelo/nitro/quickcrypto/QuickCryptoPackage.java +0 -2
  6. package/app.plugin.js +3 -0
  7. package/cpp/blake3/HybridBlake3.cpp +118 -0
  8. package/cpp/blake3/HybridBlake3.hpp +35 -0
  9. package/cpp/cipher/CCMCipher.cpp +199 -0
  10. package/cpp/cipher/CCMCipher.hpp +26 -0
  11. package/cpp/cipher/ChaCha20Cipher.cpp +97 -0
  12. package/cpp/cipher/ChaCha20Cipher.hpp +25 -0
  13. package/cpp/cipher/ChaCha20Poly1305Cipher.cpp +170 -0
  14. package/cpp/cipher/ChaCha20Poly1305Cipher.hpp +30 -0
  15. package/cpp/cipher/GCMCipher.cpp +68 -0
  16. package/cpp/cipher/GCMCipher.hpp +14 -0
  17. package/cpp/cipher/HybridCipher.cpp +322 -0
  18. package/cpp/cipher/HybridCipher.hpp +68 -0
  19. package/cpp/cipher/HybridCipherFactory.hpp +105 -0
  20. package/cpp/cipher/HybridRsaCipher.cpp +348 -0
  21. package/cpp/cipher/HybridRsaCipher.hpp +29 -0
  22. package/cpp/cipher/OCBCipher.cpp +55 -0
  23. package/cpp/cipher/OCBCipher.hpp +19 -0
  24. package/cpp/cipher/XSalsa20Cipher.cpp +61 -0
  25. package/cpp/cipher/XSalsa20Cipher.hpp +33 -0
  26. package/cpp/ec/HybridEcKeyPair.cpp +428 -0
  27. package/cpp/ec/HybridEcKeyPair.hpp +48 -0
  28. package/cpp/ed25519/HybridEdKeyPair.cpp +228 -98
  29. package/cpp/ed25519/HybridEdKeyPair.hpp +42 -56
  30. package/cpp/hash/HybridHash.cpp +185 -0
  31. package/cpp/hash/HybridHash.hpp +43 -0
  32. package/cpp/hmac/HybridHmac.cpp +95 -0
  33. package/cpp/hmac/HybridHmac.hpp +31 -0
  34. package/cpp/keys/HybridKeyObjectHandle.cpp +749 -0
  35. package/cpp/keys/HybridKeyObjectHandle.hpp +51 -0
  36. package/cpp/keys/KeyObjectData.cpp +268 -0
  37. package/cpp/keys/KeyObjectData.hpp +71 -0
  38. package/cpp/keys/node.h +5 -0
  39. package/cpp/pbkdf2/HybridPbkdf2.cpp +34 -55
  40. package/cpp/pbkdf2/HybridPbkdf2.hpp +5 -16
  41. package/cpp/random/HybridRandom.cpp +6 -17
  42. package/cpp/random/HybridRandom.hpp +5 -6
  43. package/cpp/rsa/HybridRsaKeyPair.cpp +154 -0
  44. package/cpp/rsa/HybridRsaKeyPair.hpp +43 -0
  45. package/cpp/sign/HybridSignHandle.cpp +191 -0
  46. package/cpp/sign/HybridSignHandle.hpp +36 -0
  47. package/cpp/sign/HybridVerifyHandle.cpp +158 -0
  48. package/cpp/sign/HybridVerifyHandle.hpp +36 -0
  49. package/cpp/sign/SignUtils.hpp +108 -0
  50. package/cpp/utils/Macros.hpp +68 -0
  51. package/cpp/utils/Utils.hpp +43 -2
  52. package/cpp/utils/base64.h +309 -0
  53. package/deps/blake3/.cargo/config.toml +2 -0
  54. package/deps/blake3/.git-blame-ignore-revs +2 -0
  55. package/deps/blake3/.github/workflows/build_b3sum.py +38 -0
  56. package/deps/blake3/.github/workflows/ci.yml +491 -0
  57. package/deps/blake3/.github/workflows/tag.yml +43 -0
  58. package/deps/blake3/.github/workflows/upload_github_release_asset.py +73 -0
  59. package/deps/blake3/CONTRIBUTING.md +31 -0
  60. package/deps/blake3/Cargo.toml +135 -0
  61. package/deps/blake3/LICENSE_A2 +202 -0
  62. package/deps/blake3/LICENSE_A2LLVM +219 -0
  63. package/deps/blake3/LICENSE_CC0 +121 -0
  64. package/deps/blake3/README.md +229 -0
  65. package/deps/blake3/b3sum/Cargo.lock +513 -0
  66. package/deps/blake3/b3sum/Cargo.toml +26 -0
  67. package/deps/blake3/b3sum/README.md +72 -0
  68. package/deps/blake3/b3sum/src/main.rs +564 -0
  69. package/deps/blake3/b3sum/src/unit_tests.rs +235 -0
  70. package/deps/blake3/b3sum/tests/cli_tests.rs +680 -0
  71. package/deps/blake3/b3sum/what_does_check_do.md +176 -0
  72. package/deps/blake3/benches/bench.rs +623 -0
  73. package/deps/blake3/build.rs +389 -0
  74. package/deps/blake3/c/CMakeLists.txt +383 -0
  75. package/deps/blake3/c/CMakePresets.json +73 -0
  76. package/deps/blake3/c/Makefile.testing +82 -0
  77. package/deps/blake3/c/README.md +403 -0
  78. package/deps/blake3/c/blake3-config.cmake.in +14 -0
  79. package/deps/blake3/c/blake3.c +650 -0
  80. package/deps/blake3/c/blake3.h +86 -0
  81. package/deps/blake3/c/blake3_avx2.c +326 -0
  82. package/deps/blake3/c/blake3_avx2_x86-64_unix.S +1815 -0
  83. package/deps/blake3/c/blake3_avx2_x86-64_windows_gnu.S +1817 -0
  84. package/deps/blake3/c/blake3_avx2_x86-64_windows_msvc.asm +1828 -0
  85. package/deps/blake3/c/blake3_avx512.c +1388 -0
  86. package/deps/blake3/c/blake3_avx512_x86-64_unix.S +4824 -0
  87. package/deps/blake3/c/blake3_avx512_x86-64_windows_gnu.S +2615 -0
  88. package/deps/blake3/c/blake3_avx512_x86-64_windows_msvc.asm +2634 -0
  89. package/deps/blake3/c/blake3_c_rust_bindings/Cargo.toml +32 -0
  90. package/deps/blake3/c/blake3_c_rust_bindings/README.md +4 -0
  91. package/deps/blake3/c/blake3_c_rust_bindings/benches/bench.rs +477 -0
  92. package/deps/blake3/c/blake3_c_rust_bindings/build.rs +253 -0
  93. package/deps/blake3/c/blake3_c_rust_bindings/cross_test.sh +31 -0
  94. package/deps/blake3/c/blake3_c_rust_bindings/src/lib.rs +333 -0
  95. package/deps/blake3/c/blake3_c_rust_bindings/src/test.rs +696 -0
  96. package/deps/blake3/c/blake3_dispatch.c +332 -0
  97. package/deps/blake3/c/blake3_impl.h +333 -0
  98. package/deps/blake3/c/blake3_neon.c +366 -0
  99. package/deps/blake3/c/blake3_portable.c +160 -0
  100. package/deps/blake3/c/blake3_sse2.c +566 -0
  101. package/deps/blake3/c/blake3_sse2_x86-64_unix.S +2291 -0
  102. package/deps/blake3/c/blake3_sse2_x86-64_windows_gnu.S +2332 -0
  103. package/deps/blake3/c/blake3_sse2_x86-64_windows_msvc.asm +2350 -0
  104. package/deps/blake3/c/blake3_sse41.c +560 -0
  105. package/deps/blake3/c/blake3_sse41_x86-64_unix.S +2028 -0
  106. package/deps/blake3/c/blake3_sse41_x86-64_windows_gnu.S +2069 -0
  107. package/deps/blake3/c/blake3_sse41_x86-64_windows_msvc.asm +2089 -0
  108. package/deps/blake3/c/blake3_tbb.cpp +37 -0
  109. package/deps/blake3/c/dependencies/CMakeLists.txt +3 -0
  110. package/deps/blake3/c/dependencies/tbb/CMakeLists.txt +28 -0
  111. package/deps/blake3/c/example.c +36 -0
  112. package/deps/blake3/c/example_tbb.c +57 -0
  113. package/deps/blake3/c/libblake3.pc.in +12 -0
  114. package/deps/blake3/c/main.c +166 -0
  115. package/deps/blake3/c/test.py +97 -0
  116. package/deps/blake3/media/B3.svg +70 -0
  117. package/deps/blake3/media/BLAKE3.svg +85 -0
  118. package/deps/blake3/media/speed.svg +1474 -0
  119. package/deps/blake3/reference_impl/Cargo.toml +8 -0
  120. package/deps/blake3/reference_impl/README.md +14 -0
  121. package/deps/blake3/reference_impl/reference_impl.rs +374 -0
  122. package/deps/blake3/src/ffi_avx2.rs +65 -0
  123. package/deps/blake3/src/ffi_avx512.rs +169 -0
  124. package/deps/blake3/src/ffi_neon.rs +82 -0
  125. package/deps/blake3/src/ffi_sse2.rs +126 -0
  126. package/deps/blake3/src/ffi_sse41.rs +126 -0
  127. package/deps/blake3/src/guts.rs +60 -0
  128. package/deps/blake3/src/hazmat.rs +704 -0
  129. package/deps/blake3/src/io.rs +64 -0
  130. package/deps/blake3/src/join.rs +92 -0
  131. package/deps/blake3/src/lib.rs +1835 -0
  132. package/deps/blake3/src/platform.rs +587 -0
  133. package/deps/blake3/src/portable.rs +198 -0
  134. package/deps/blake3/src/rust_avx2.rs +474 -0
  135. package/deps/blake3/src/rust_sse2.rs +775 -0
  136. package/deps/blake3/src/rust_sse41.rs +766 -0
  137. package/deps/blake3/src/test.rs +1049 -0
  138. package/deps/blake3/src/traits.rs +227 -0
  139. package/deps/blake3/src/wasm32_simd.rs +794 -0
  140. package/deps/blake3/test_vectors/Cargo.toml +19 -0
  141. package/deps/blake3/test_vectors/cross_test.sh +25 -0
  142. package/deps/blake3/test_vectors/src/bin/generate.rs +4 -0
  143. package/deps/blake3/test_vectors/src/lib.rs +350 -0
  144. package/deps/blake3/test_vectors/test_vectors.json +217 -0
  145. package/deps/blake3/tools/compiler_version/Cargo.toml +7 -0
  146. package/deps/blake3/tools/compiler_version/build.rs +6 -0
  147. package/deps/blake3/tools/compiler_version/src/main.rs +27 -0
  148. package/deps/blake3/tools/instruction_set_support/Cargo.toml +6 -0
  149. package/deps/blake3/tools/instruction_set_support/src/main.rs +10 -0
  150. package/deps/blake3/tools/release.md +16 -0
  151. package/deps/fastpbkdf2/fastpbkdf2.c +5 -1
  152. package/deps/ncrypto/ncrypto.cc +4679 -0
  153. package/deps/ncrypto/ncrypto.h +1625 -0
  154. package/lib/commonjs/blake3.js +98 -0
  155. package/lib/commonjs/blake3.js.map +1 -0
  156. package/lib/commonjs/cipher.js +180 -0
  157. package/lib/commonjs/cipher.js.map +1 -0
  158. package/lib/commonjs/constants.js +32 -0
  159. package/lib/commonjs/constants.js.map +1 -0
  160. package/lib/commonjs/ec.js +480 -0
  161. package/lib/commonjs/ec.js.map +1 -0
  162. package/lib/commonjs/ed.js +214 -2
  163. package/lib/commonjs/ed.js.map +1 -1
  164. package/lib/commonjs/expo-plugin/@types.js +2 -0
  165. package/lib/commonjs/expo-plugin/@types.js.map +1 -0
  166. package/lib/commonjs/expo-plugin/withRNQC.js +25 -0
  167. package/lib/commonjs/expo-plugin/withRNQC.js.map +1 -0
  168. package/lib/commonjs/expo-plugin/withSodiumAndroid.js +25 -0
  169. package/lib/commonjs/expo-plugin/withSodiumAndroid.js.map +1 -0
  170. package/lib/commonjs/expo-plugin/withSodiumIos.js +26 -0
  171. package/lib/commonjs/expo-plugin/withSodiumIos.js.map +1 -0
  172. package/lib/commonjs/expo-plugin/withXCode.js +51 -0
  173. package/lib/commonjs/expo-plugin/withXCode.js.map +1 -0
  174. package/lib/commonjs/hash.js +215 -0
  175. package/lib/commonjs/hash.js.map +1 -0
  176. package/lib/commonjs/hmac.js +109 -0
  177. package/lib/commonjs/hmac.js.map +1 -0
  178. package/lib/commonjs/index.js +102 -24
  179. package/lib/commonjs/index.js.map +1 -1
  180. package/lib/commonjs/keys/classes.js +109 -52
  181. package/lib/commonjs/keys/classes.js.map +1 -1
  182. package/lib/commonjs/keys/generateKeyPair.js +141 -144
  183. package/lib/commonjs/keys/generateKeyPair.js.map +1 -1
  184. package/lib/commonjs/keys/index.js +229 -0
  185. package/lib/commonjs/keys/index.js.map +1 -1
  186. package/lib/commonjs/keys/publicCipher.js +152 -0
  187. package/lib/commonjs/keys/publicCipher.js.map +1 -0
  188. package/lib/commonjs/keys/signVerify.js +178 -39
  189. package/lib/commonjs/keys/signVerify.js.map +1 -1
  190. package/lib/commonjs/keys/utils.js +18 -13
  191. package/lib/commonjs/keys/utils.js.map +1 -1
  192. package/lib/commonjs/pbkdf2.js.map +1 -1
  193. package/lib/commonjs/random.js +6 -0
  194. package/lib/commonjs/random.js.map +1 -1
  195. package/lib/commonjs/rsa.js +202 -0
  196. package/lib/commonjs/rsa.js.map +1 -0
  197. package/lib/commonjs/specs/blake3.nitro.js +6 -0
  198. package/lib/commonjs/specs/blake3.nitro.js.map +1 -0
  199. package/lib/commonjs/specs/cipher.nitro.js +6 -0
  200. package/lib/commonjs/specs/cipher.nitro.js.map +1 -0
  201. package/lib/commonjs/specs/ecKeyPair.nitro.js +6 -0
  202. package/lib/commonjs/specs/ecKeyPair.nitro.js.map +1 -0
  203. package/lib/commonjs/specs/hash.nitro.js +6 -0
  204. package/lib/commonjs/specs/hash.nitro.js.map +1 -0
  205. package/lib/commonjs/specs/hmac.nitro.js +6 -0
  206. package/lib/commonjs/specs/hmac.nitro.js.map +1 -0
  207. package/lib/commonjs/specs/rsaCipher.nitro.js +6 -0
  208. package/lib/commonjs/specs/rsaCipher.nitro.js.map +1 -0
  209. package/lib/commonjs/specs/rsaKeyPair.nitro.js +6 -0
  210. package/lib/commonjs/specs/rsaKeyPair.nitro.js.map +1 -0
  211. package/lib/commonjs/specs/sign.nitro.js +6 -0
  212. package/lib/commonjs/specs/sign.nitro.js.map +1 -0
  213. package/lib/commonjs/subtle.js +987 -0
  214. package/lib/commonjs/subtle.js.map +1 -0
  215. package/lib/commonjs/utils/cipher.js +64 -0
  216. package/lib/commonjs/utils/cipher.js.map +1 -0
  217. package/lib/commonjs/utils/conversion.js +44 -5
  218. package/lib/commonjs/utils/conversion.js.map +1 -1
  219. package/lib/commonjs/utils/hashnames.js +2 -1
  220. package/lib/commonjs/utils/hashnames.js.map +1 -1
  221. package/lib/commonjs/utils/index.js +11 -0
  222. package/lib/commonjs/utils/index.js.map +1 -1
  223. package/lib/commonjs/utils/noble.js +82 -0
  224. package/lib/commonjs/utils/noble.js.map +1 -0
  225. package/lib/commonjs/utils/types.js +32 -17
  226. package/lib/commonjs/utils/types.js.map +1 -1
  227. package/lib/commonjs/utils/validation.js +74 -1
  228. package/lib/commonjs/utils/validation.js.map +1 -1
  229. package/lib/module/blake3.js +90 -0
  230. package/lib/module/blake3.js.map +1 -0
  231. package/lib/module/cipher.js +173 -0
  232. package/lib/module/cipher.js.map +1 -0
  233. package/lib/module/constants.js +28 -0
  234. package/lib/module/constants.js.map +1 -0
  235. package/lib/module/ec.js +470 -0
  236. package/lib/module/ec.js.map +1 -0
  237. package/lib/module/ed.js +212 -3
  238. package/lib/module/ed.js.map +1 -1
  239. package/lib/module/expo-plugin/@types.js +2 -0
  240. package/lib/module/expo-plugin/@types.js.map +1 -0
  241. package/lib/module/expo-plugin/withRNQC.js +21 -0
  242. package/lib/module/expo-plugin/withRNQC.js.map +1 -0
  243. package/lib/module/expo-plugin/withSodiumAndroid.js +20 -0
  244. package/lib/module/expo-plugin/withSodiumAndroid.js.map +1 -0
  245. package/lib/module/expo-plugin/withSodiumIos.js +20 -0
  246. package/lib/module/expo-plugin/withSodiumIos.js.map +1 -0
  247. package/lib/module/expo-plugin/withXCode.js +46 -0
  248. package/lib/module/expo-plugin/withXCode.js.map +1 -0
  249. package/lib/module/hash.js +207 -0
  250. package/lib/module/hash.js.map +1 -0
  251. package/lib/module/hmac.js +104 -0
  252. package/lib/module/hmac.js.map +1 -0
  253. package/lib/module/index.js +21 -21
  254. package/lib/module/index.js.map +1 -1
  255. package/lib/module/keys/classes.js +106 -49
  256. package/lib/module/keys/classes.js.map +1 -1
  257. package/lib/module/keys/generateKeyPair.js +134 -143
  258. package/lib/module/keys/generateKeyPair.js.map +1 -1
  259. package/lib/module/keys/index.js +161 -22
  260. package/lib/module/keys/index.js.map +1 -1
  261. package/lib/module/keys/publicCipher.js +145 -0
  262. package/lib/module/keys/publicCipher.js.map +1 -0
  263. package/lib/module/keys/signVerify.js +170 -39
  264. package/lib/module/keys/signVerify.js.map +1 -1
  265. package/lib/module/keys/utils.js +16 -12
  266. package/lib/module/keys/utils.js.map +1 -1
  267. package/lib/module/pbkdf2.js.map +1 -1
  268. package/lib/module/random.js +6 -0
  269. package/lib/module/random.js.map +1 -1
  270. package/lib/module/rsa.js +194 -0
  271. package/lib/module/rsa.js.map +1 -0
  272. package/lib/module/specs/blake3.nitro.js +4 -0
  273. package/lib/module/specs/blake3.nitro.js.map +1 -0
  274. package/lib/module/specs/cipher.nitro.js +4 -0
  275. package/lib/module/specs/cipher.nitro.js.map +1 -0
  276. package/lib/module/specs/ecKeyPair.nitro.js +4 -0
  277. package/lib/module/specs/ecKeyPair.nitro.js.map +1 -0
  278. package/lib/module/specs/hash.nitro.js +4 -0
  279. package/lib/module/specs/hash.nitro.js.map +1 -0
  280. package/lib/module/specs/hmac.nitro.js +4 -0
  281. package/lib/module/specs/hmac.nitro.js.map +1 -0
  282. package/lib/module/specs/rsaCipher.nitro.js +4 -0
  283. package/lib/module/specs/rsaCipher.nitro.js.map +1 -0
  284. package/lib/module/specs/rsaKeyPair.nitro.js +4 -0
  285. package/lib/module/specs/rsaKeyPair.nitro.js.map +1 -0
  286. package/lib/module/specs/sign.nitro.js +4 -0
  287. package/lib/module/specs/sign.nitro.js.map +1 -0
  288. package/lib/module/subtle.js +982 -0
  289. package/lib/module/subtle.js.map +1 -0
  290. package/lib/module/utils/cipher.js +56 -0
  291. package/lib/module/utils/cipher.js.map +1 -0
  292. package/lib/module/utils/conversion.js +26 -5
  293. package/lib/module/utils/conversion.js.map +1 -1
  294. package/lib/module/utils/hashnames.js +2 -1
  295. package/lib/module/utils/hashnames.js.map +1 -1
  296. package/lib/module/utils/index.js +1 -0
  297. package/lib/module/utils/index.js.map +1 -1
  298. package/lib/module/utils/noble.js +76 -0
  299. package/lib/module/utils/noble.js.map +1 -0
  300. package/lib/module/utils/types.js +32 -17
  301. package/lib/module/utils/types.js.map +1 -1
  302. package/lib/module/utils/validation.js +69 -1
  303. package/lib/module/utils/validation.js.map +1 -1
  304. package/lib/tsconfig.tsbuildinfo +1 -1
  305. package/lib/typescript/blake3.d.ts +33 -0
  306. package/lib/typescript/blake3.d.ts.map +1 -0
  307. package/lib/typescript/cipher.d.ts +60 -0
  308. package/lib/typescript/cipher.d.ts.map +1 -0
  309. package/lib/typescript/constants.d.ts +21 -0
  310. package/lib/typescript/constants.d.ts.map +1 -0
  311. package/lib/typescript/ec.d.ts +22 -0
  312. package/lib/typescript/ec.d.ts.map +1 -0
  313. package/lib/typescript/ed.d.ts +28 -1
  314. package/lib/typescript/ed.d.ts.map +1 -1
  315. package/lib/typescript/expo-plugin/@types.d.ts +8 -0
  316. package/lib/typescript/expo-plugin/@types.d.ts.map +1 -0
  317. package/lib/typescript/expo-plugin/withRNQC.d.ts +4 -0
  318. package/lib/typescript/expo-plugin/withRNQC.d.ts.map +1 -0
  319. package/lib/typescript/expo-plugin/withSodiumAndroid.d.ts +4 -0
  320. package/lib/typescript/expo-plugin/withSodiumAndroid.d.ts.map +1 -0
  321. package/lib/typescript/expo-plugin/withSodiumIos.d.ts +4 -0
  322. package/lib/typescript/expo-plugin/withSodiumIos.d.ts.map +1 -0
  323. package/lib/typescript/expo-plugin/withXCode.d.ts +9 -0
  324. package/lib/typescript/expo-plugin/withXCode.d.ts.map +1 -0
  325. package/lib/typescript/hash.d.ts +122 -0
  326. package/lib/typescript/hash.d.ts.map +1 -0
  327. package/lib/typescript/hmac.d.ts +66 -0
  328. package/lib/typescript/hmac.d.ts.map +1 -0
  329. package/lib/typescript/index.d.ts +102 -10
  330. package/lib/typescript/index.d.ts.map +1 -1
  331. package/lib/typescript/keys/classes.d.ts +50 -8
  332. package/lib/typescript/keys/classes.d.ts.map +1 -1
  333. package/lib/typescript/keys/generateKeyPair.d.ts +5 -0
  334. package/lib/typescript/keys/generateKeyPair.d.ts.map +1 -1
  335. package/lib/typescript/keys/index.d.ts +22 -2
  336. package/lib/typescript/keys/index.d.ts.map +1 -1
  337. package/lib/typescript/keys/publicCipher.d.ts +20 -0
  338. package/lib/typescript/keys/publicCipher.d.ts.map +1 -0
  339. package/lib/typescript/keys/signVerify.d.ts +28 -0
  340. package/lib/typescript/keys/signVerify.d.ts.map +1 -1
  341. package/lib/typescript/keys/utils.d.ts +3 -1
  342. package/lib/typescript/keys/utils.d.ts.map +1 -1
  343. package/lib/typescript/pbkdf2.d.ts +1 -1
  344. package/lib/typescript/pbkdf2.d.ts.map +1 -1
  345. package/lib/typescript/random.d.ts +6 -0
  346. package/lib/typescript/random.d.ts.map +1 -1
  347. package/lib/typescript/rsa.d.ts +19 -0
  348. package/lib/typescript/rsa.d.ts.map +1 -0
  349. package/lib/typescript/specs/blake3.nitro.d.ts +15 -0
  350. package/lib/typescript/specs/blake3.nitro.d.ts.map +1 -0
  351. package/lib/typescript/specs/cipher.nitro.d.ts +29 -0
  352. package/lib/typescript/specs/cipher.nitro.d.ts.map +1 -0
  353. package/lib/typescript/specs/ecKeyPair.nitro.d.ts +20 -0
  354. package/lib/typescript/specs/ecKeyPair.nitro.d.ts.map +1 -0
  355. package/lib/typescript/specs/edKeyPair.nitro.d.ts +1 -0
  356. package/lib/typescript/specs/edKeyPair.nitro.d.ts.map +1 -1
  357. package/lib/typescript/specs/hash.nitro.d.ts +13 -0
  358. package/lib/typescript/specs/hash.nitro.d.ts.map +1 -0
  359. package/lib/typescript/specs/hmac.nitro.d.ts +10 -0
  360. package/lib/typescript/specs/hmac.nitro.d.ts.map +1 -0
  361. package/lib/typescript/specs/keyObjectHandle.nitro.d.ts +1 -1
  362. package/lib/typescript/specs/keyObjectHandle.nitro.d.ts.map +1 -1
  363. package/lib/typescript/specs/rsaCipher.nitro.d.ts +44 -0
  364. package/lib/typescript/specs/rsaCipher.nitro.d.ts.map +1 -0
  365. package/lib/typescript/specs/rsaKeyPair.nitro.d.ts +20 -0
  366. package/lib/typescript/specs/rsaKeyPair.nitro.d.ts.map +1 -0
  367. package/lib/typescript/specs/sign.nitro.d.ts +19 -0
  368. package/lib/typescript/specs/sign.nitro.d.ts.map +1 -0
  369. package/lib/typescript/subtle.d.ts +17 -0
  370. package/lib/typescript/subtle.d.ts.map +1 -0
  371. package/lib/typescript/utils/cipher.d.ts +7 -0
  372. package/lib/typescript/utils/cipher.d.ts.map +1 -0
  373. package/lib/typescript/utils/conversion.d.ts +1 -0
  374. package/lib/typescript/utils/conversion.d.ts.map +1 -1
  375. package/lib/typescript/utils/hashnames.d.ts +3 -1
  376. package/lib/typescript/utils/hashnames.d.ts.map +1 -1
  377. package/lib/typescript/utils/index.d.ts +1 -0
  378. package/lib/typescript/utils/index.d.ts.map +1 -1
  379. package/lib/typescript/utils/noble.d.ts +19 -0
  380. package/lib/typescript/utils/noble.d.ts.map +1 -0
  381. package/lib/typescript/utils/types.d.ts +125 -23
  382. package/lib/typescript/utils/types.d.ts.map +1 -1
  383. package/lib/typescript/utils/validation.d.ts +5 -0
  384. package/lib/typescript/utils/validation.d.ts.map +1 -1
  385. package/nitrogen/generated/.gitattributes +1 -0
  386. package/nitrogen/generated/android/QuickCrypto+autolinking.cmake +30 -1
  387. package/nitrogen/generated/android/QuickCrypto+autolinking.gradle +1 -1
  388. package/nitrogen/generated/android/QuickCryptoOnLoad.cpp +115 -1
  389. package/nitrogen/generated/android/QuickCryptoOnLoad.hpp +1 -1
  390. package/nitrogen/generated/android/kotlin/com/margelo/nitro/crypto/QuickCryptoOnLoad.kt +35 -0
  391. package/nitrogen/generated/ios/QuickCrypto+autolinking.rb +3 -1
  392. package/nitrogen/generated/ios/QuickCrypto-Swift-Cxx-Bridge.cpp +1 -1
  393. package/nitrogen/generated/ios/QuickCrypto-Swift-Cxx-Bridge.hpp +1 -1
  394. package/nitrogen/generated/ios/QuickCrypto-Swift-Cxx-Umbrella.hpp +3 -3
  395. package/nitrogen/generated/ios/QuickCryptoAutolinking.mm +111 -1
  396. package/nitrogen/generated/ios/QuickCryptoAutolinking.swift +1 -1
  397. package/nitrogen/generated/shared/c++/AsymmetricKeyType.hpp +104 -0
  398. package/nitrogen/generated/shared/c++/CipherArgs.hpp +86 -0
  399. package/nitrogen/generated/shared/c++/HybridBlake3Spec.cpp +28 -0
  400. package/nitrogen/generated/shared/c++/HybridBlake3Spec.hpp +76 -0
  401. package/nitrogen/generated/shared/c++/HybridCipherFactorySpec.cpp +21 -0
  402. package/nitrogen/generated/shared/c++/HybridCipherFactorySpec.hpp +67 -0
  403. package/nitrogen/generated/shared/c++/HybridCipherSpec.cpp +28 -0
  404. package/nitrogen/generated/shared/c++/HybridCipherSpec.hpp +76 -0
  405. package/nitrogen/generated/shared/c++/HybridEcKeyPairSpec.cpp +29 -0
  406. package/nitrogen/generated/shared/c++/HybridEcKeyPairSpec.hpp +77 -0
  407. package/nitrogen/generated/shared/c++/HybridEdKeyPairSpec.cpp +2 -1
  408. package/nitrogen/generated/shared/c++/HybridEdKeyPairSpec.hpp +5 -4
  409. package/nitrogen/generated/shared/c++/HybridHashSpec.cpp +26 -0
  410. package/nitrogen/generated/shared/c++/HybridHashSpec.hpp +75 -0
  411. package/nitrogen/generated/shared/c++/HybridHmacSpec.cpp +23 -0
  412. package/nitrogen/generated/shared/c++/HybridHmacSpec.hpp +66 -0
  413. package/nitrogen/generated/shared/c++/HybridKeyObjectHandleSpec.cpp +1 -1
  414. package/nitrogen/generated/shared/c++/HybridKeyObjectHandleSpec.hpp +8 -8
  415. package/nitrogen/generated/shared/c++/HybridPbkdf2Spec.cpp +1 -1
  416. package/nitrogen/generated/shared/c++/HybridPbkdf2Spec.hpp +3 -3
  417. package/nitrogen/generated/shared/c++/HybridRandomSpec.cpp +1 -1
  418. package/nitrogen/generated/shared/c++/HybridRandomSpec.hpp +3 -3
  419. package/nitrogen/generated/shared/c++/HybridRsaCipherSpec.cpp +24 -0
  420. package/nitrogen/generated/shared/c++/HybridRsaCipherSpec.hpp +72 -0
  421. package/nitrogen/generated/shared/c++/HybridRsaKeyPairSpec.cpp +29 -0
  422. package/nitrogen/generated/shared/c++/HybridRsaKeyPairSpec.hpp +77 -0
  423. package/nitrogen/generated/shared/c++/HybridSignHandleSpec.cpp +23 -0
  424. package/nitrogen/generated/shared/c++/HybridSignHandleSpec.hpp +71 -0
  425. package/nitrogen/generated/shared/c++/HybridVerifyHandleSpec.cpp +23 -0
  426. package/nitrogen/generated/shared/c++/HybridVerifyHandleSpec.hpp +71 -0
  427. package/nitrogen/generated/shared/c++/JWK.hpp +17 -18
  428. package/nitrogen/generated/shared/c++/JWKkty.hpp +12 -14
  429. package/nitrogen/generated/shared/c++/JWKuse.hpp +8 -10
  430. package/nitrogen/generated/shared/c++/KFormatType.hpp +14 -16
  431. package/nitrogen/generated/shared/c++/KeyDetail.hpp +6 -7
  432. package/nitrogen/generated/shared/c++/KeyEncoding.hpp +15 -17
  433. package/nitrogen/generated/shared/c++/KeyObject.hpp +67 -0
  434. package/nitrogen/generated/shared/c++/KeyType.hpp +11 -13
  435. package/nitrogen/generated/shared/c++/KeyUsage.hpp +38 -24
  436. package/nitrogen/generated/shared/c++/NamedCurve.hpp +10 -12
  437. package/package.json +28 -23
  438. package/src/blake3.ts +123 -0
  439. package/src/cipher.ts +335 -0
  440. package/src/constants.ts +32 -0
  441. package/src/ec.ts +657 -0
  442. package/src/ed.ts +297 -13
  443. package/src/expo-plugin/@types.ts +7 -0
  444. package/src/expo-plugin/withRNQC.ts +23 -0
  445. package/src/expo-plugin/withSodiumAndroid.ts +24 -0
  446. package/src/expo-plugin/withSodiumIos.ts +30 -0
  447. package/src/expo-plugin/withXCode.ts +55 -0
  448. package/src/hash.ts +274 -0
  449. package/src/hmac.ts +135 -0
  450. package/src/index.ts +20 -20
  451. package/src/keys/classes.ts +148 -55
  452. package/src/keys/generateKeyPair.ts +177 -134
  453. package/src/keys/index.ts +226 -14
  454. package/src/keys/publicCipher.ts +229 -0
  455. package/src/keys/signVerify.ts +239 -39
  456. package/src/keys/utils.ts +24 -18
  457. package/src/pbkdf2.ts +1 -1
  458. package/src/random.ts +7 -0
  459. package/src/rsa.ts +310 -0
  460. package/src/specs/blake3.nitro.ts +12 -0
  461. package/src/specs/cipher.nitro.ts +25 -0
  462. package/src/specs/ecKeyPair.nitro.ts +38 -0
  463. package/src/specs/edKeyPair.nitro.ts +2 -0
  464. package/src/specs/hash.nitro.ts +10 -0
  465. package/src/specs/hmac.nitro.ts +7 -0
  466. package/src/specs/keyObjectHandle.nitro.ts +1 -1
  467. package/src/specs/rsaCipher.nitro.ts +65 -0
  468. package/src/specs/rsaKeyPair.nitro.ts +33 -0
  469. package/src/specs/sign.nitro.ts +31 -0
  470. package/src/subtle.ts +1436 -0
  471. package/src/utils/cipher.ts +60 -0
  472. package/src/utils/conversion.ts +33 -4
  473. package/src/utils/hashnames.ts +4 -2
  474. package/src/utils/index.ts +1 -0
  475. package/src/utils/noble.ts +85 -0
  476. package/src/utils/types.ts +209 -29
  477. package/src/utils/validation.ts +96 -1
  478. package/lib/module/package.json +0 -1
  479. package/nitrogen/generated/android/QuickCryptoOnLoad.kt +0 -1
  480. package/nitrogen/generated/shared/c++/CFRGKeyPairType.hpp +0 -86
package/src/subtle.ts ADDED
@@ -0,0 +1,1436 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-vars */
2
+ import { Buffer as SBuffer } from 'safe-buffer';
3
+ import type {
4
+ SubtleAlgorithm,
5
+ KeyUsage,
6
+ BinaryLike,
7
+ BufferLike,
8
+ JWK,
9
+ AnyAlgorithm,
10
+ ImportFormat,
11
+ AesKeyGenParams,
12
+ EncryptDecryptParams,
13
+ Operation,
14
+ AesCtrParams,
15
+ AesCbcParams,
16
+ AesGcmParams,
17
+ RsaOaepParams,
18
+ } from './utils';
19
+ import { KFormatType, KeyEncoding } from './utils';
20
+ import {
21
+ CryptoKey,
22
+ KeyObject,
23
+ PublicKeyObject,
24
+ PrivateKeyObject,
25
+ SecretKeyObject,
26
+ } from './keys';
27
+ import type { CryptoKeyPair } from './utils/types';
28
+ import { bufferLikeToArrayBuffer } from './utils/conversion';
29
+ import { lazyDOMException } from './utils/errors';
30
+ import { normalizeHashName, HashContext } from './utils/hashnames';
31
+ import { validateMaxBufferLength } from './utils/validation';
32
+ import { asyncDigest } from './hash';
33
+ import { createSecretKey } from './keys';
34
+ import { NitroModules } from 'react-native-nitro-modules';
35
+ import type { KeyObjectHandle } from './specs/keyObjectHandle.nitro';
36
+ import type { RsaCipher } from './specs/rsaCipher.nitro';
37
+ import type { CipherFactory } from './specs/cipher.nitro';
38
+ import { pbkdf2DeriveBits } from './pbkdf2';
39
+ import { ecImportKey, ecdsaSignVerify, ec_generateKeyPair } from './ec';
40
+ import { rsa_generateKeyPair } from './rsa';
41
+ import { getRandomValues } from './random';
42
+ import { createHmac } from './hmac';
43
+ import { createSign, createVerify } from './keys/signVerify';
44
+ import { ed_generateKeyPairWebCrypto, Ed } from './ed';
45
+ // import { pbkdf2DeriveBits } from './pbkdf2';
46
+ // import { aesCipher, aesGenerateKey, aesImportKey, getAlgorithmName } from './aes';
47
+ // import { rsaCipher, rsaExportKey, rsaImportKey, rsaKeyGenerate } from './rsa';
48
+ // import { normalizeAlgorithm, type Operation } from './algorithms';
49
+ // import { hmacImportKey } from './mac';
50
+
51
+ // Temporary enums that need to be defined
52
+
53
+ enum KWebCryptoKeyFormat {
54
+ kWebCryptoKeyFormatRaw,
55
+ kWebCryptoKeyFormatSPKI,
56
+ kWebCryptoKeyFormatPKCS8,
57
+ }
58
+
59
+ enum CipherOrWrapMode {
60
+ kWebCryptoCipherEncrypt,
61
+ kWebCryptoCipherDecrypt,
62
+ }
63
+
64
+ // Placeholder functions that need to be implemented
65
+ function hasAnyNotIn(usages: KeyUsage[], allowed: KeyUsage[]): boolean {
66
+ return usages.some(usage => !allowed.includes(usage));
67
+ }
68
+
69
+ function normalizeAlgorithm(
70
+ algorithm: SubtleAlgorithm | AnyAlgorithm,
71
+ _operation: Operation,
72
+ ): SubtleAlgorithm {
73
+ if (typeof algorithm === 'string') {
74
+ return { name: algorithm };
75
+ }
76
+ return algorithm as SubtleAlgorithm;
77
+ }
78
+
79
+ function getAlgorithmName(name: string, length: number): string {
80
+ return `${name}${length}`;
81
+ }
82
+
83
+ // Placeholder implementations for missing functions
84
+ function ecExportKey(key: CryptoKey, format: KWebCryptoKeyFormat): ArrayBuffer {
85
+ const keyObject = key.keyObject;
86
+
87
+ if (format === KWebCryptoKeyFormat.kWebCryptoKeyFormatSPKI) {
88
+ // Export public key in SPKI format
89
+ const exported = keyObject.export({ format: 'der', type: 'spki' });
90
+ return bufferLikeToArrayBuffer(exported);
91
+ } else if (format === KWebCryptoKeyFormat.kWebCryptoKeyFormatPKCS8) {
92
+ // Export private key in PKCS8 format
93
+ const exported = keyObject.export({ format: 'der', type: 'pkcs8' });
94
+ return bufferLikeToArrayBuffer(exported);
95
+ } else {
96
+ throw new Error(`Unsupported EC export format: ${format}`);
97
+ }
98
+ }
99
+
100
+ function rsaExportKey(
101
+ key: CryptoKey,
102
+ format: KWebCryptoKeyFormat,
103
+ ): ArrayBuffer {
104
+ const keyObject = key.keyObject;
105
+
106
+ if (format === KWebCryptoKeyFormat.kWebCryptoKeyFormatSPKI) {
107
+ // Export public key in SPKI format
108
+ const exported = keyObject.export({ format: 'der', type: 'spki' });
109
+ return bufferLikeToArrayBuffer(exported);
110
+ } else if (format === KWebCryptoKeyFormat.kWebCryptoKeyFormatPKCS8) {
111
+ // Export private key in PKCS8 format
112
+ const exported = keyObject.export({ format: 'der', type: 'pkcs8' });
113
+ return bufferLikeToArrayBuffer(exported);
114
+ } else {
115
+ throw new Error(`Unsupported RSA export format: ${format}`);
116
+ }
117
+ }
118
+
119
+ async function rsaCipher(
120
+ mode: CipherOrWrapMode,
121
+ key: CryptoKey,
122
+ data: ArrayBuffer,
123
+ algorithm: EncryptDecryptParams,
124
+ ): Promise<ArrayBuffer> {
125
+ const rsaParams = algorithm as RsaOaepParams;
126
+
127
+ // Validate key type matches operation
128
+ const expectedType =
129
+ mode === CipherOrWrapMode.kWebCryptoCipherEncrypt ? 'public' : 'private';
130
+ if (key.type !== expectedType) {
131
+ throw lazyDOMException(
132
+ 'The requested operation is not valid for the provided key',
133
+ 'InvalidAccessError',
134
+ );
135
+ }
136
+
137
+ // Get hash algorithm from key
138
+ const hashAlgorithm = normalizeHashName(key.algorithm.hash);
139
+
140
+ // Prepare label (optional)
141
+ const label = rsaParams.label
142
+ ? bufferLikeToArrayBuffer(rsaParams.label)
143
+ : undefined;
144
+
145
+ // Create RSA cipher instance
146
+ const rsaCipherModule =
147
+ NitroModules.createHybridObject<RsaCipher>('RsaCipher');
148
+
149
+ // RSA-OAEP padding constant = 4
150
+ const RSA_PKCS1_OAEP_PADDING = 4;
151
+
152
+ if (mode === CipherOrWrapMode.kWebCryptoCipherEncrypt) {
153
+ // Encrypt with public key
154
+ return rsaCipherModule.encrypt(
155
+ key.keyObject.handle,
156
+ data,
157
+ RSA_PKCS1_OAEP_PADDING,
158
+ hashAlgorithm,
159
+ label,
160
+ );
161
+ } else {
162
+ // Decrypt with private key
163
+ return rsaCipherModule.decrypt(
164
+ key.keyObject.handle,
165
+ data,
166
+ RSA_PKCS1_OAEP_PADDING,
167
+ hashAlgorithm,
168
+ label,
169
+ );
170
+ }
171
+ }
172
+
173
+ async function aesCipher(
174
+ mode: CipherOrWrapMode,
175
+ key: CryptoKey,
176
+ data: ArrayBuffer,
177
+ algorithm: EncryptDecryptParams,
178
+ ): Promise<ArrayBuffer> {
179
+ const { name } = algorithm;
180
+
181
+ switch (name) {
182
+ case 'AES-CTR':
183
+ return aesCtrCipher(mode, key, data, algorithm as AesCtrParams);
184
+ case 'AES-CBC':
185
+ return aesCbcCipher(mode, key, data, algorithm as AesCbcParams);
186
+ case 'AES-GCM':
187
+ return aesGcmCipher(mode, key, data, algorithm as AesGcmParams);
188
+ default:
189
+ throw lazyDOMException(
190
+ `Unsupported AES algorithm: ${name}`,
191
+ 'NotSupportedError',
192
+ );
193
+ }
194
+ }
195
+
196
+ async function aesCtrCipher(
197
+ mode: CipherOrWrapMode,
198
+ key: CryptoKey,
199
+ data: ArrayBuffer,
200
+ algorithm: AesCtrParams,
201
+ ): Promise<ArrayBuffer> {
202
+ // Validate counter and length
203
+ if (!algorithm.counter || algorithm.counter.byteLength !== 16) {
204
+ throw lazyDOMException(
205
+ 'AES-CTR algorithm.counter must be 16 bytes',
206
+ 'OperationError',
207
+ );
208
+ }
209
+
210
+ if (algorithm.length < 1 || algorithm.length > 128) {
211
+ throw lazyDOMException(
212
+ 'AES-CTR algorithm.length must be between 1 and 128',
213
+ 'OperationError',
214
+ );
215
+ }
216
+
217
+ // Get cipher type based on key length
218
+ const keyLength = (key.algorithm as { length: number }).length;
219
+ const cipherType = `aes-${keyLength}-ctr`;
220
+
221
+ // Create cipher
222
+ const factory =
223
+ NitroModules.createHybridObject<CipherFactory>('CipherFactory');
224
+ const cipher = factory.createCipher({
225
+ isCipher: mode === CipherOrWrapMode.kWebCryptoCipherEncrypt,
226
+ cipherType,
227
+ cipherKey: bufferLikeToArrayBuffer(key.keyObject.export()),
228
+ iv: bufferLikeToArrayBuffer(algorithm.counter),
229
+ });
230
+
231
+ // Process data
232
+ const updated = cipher.update(data);
233
+ const final = cipher.final();
234
+
235
+ // Concatenate results
236
+ const result = new Uint8Array(updated.byteLength + final.byteLength);
237
+ result.set(new Uint8Array(updated), 0);
238
+ result.set(new Uint8Array(final), updated.byteLength);
239
+
240
+ return result.buffer;
241
+ }
242
+
243
+ async function aesCbcCipher(
244
+ mode: CipherOrWrapMode,
245
+ key: CryptoKey,
246
+ data: ArrayBuffer,
247
+ algorithm: AesCbcParams,
248
+ ): Promise<ArrayBuffer> {
249
+ // Validate IV
250
+ const iv = bufferLikeToArrayBuffer(algorithm.iv);
251
+ if (iv.byteLength !== 16) {
252
+ throw lazyDOMException(
253
+ 'algorithm.iv must contain exactly 16 bytes',
254
+ 'OperationError',
255
+ );
256
+ }
257
+
258
+ // Get cipher type based on key length
259
+ const keyLength = (key.algorithm as { length: number }).length;
260
+ const cipherType = `aes-${keyLength}-cbc`;
261
+
262
+ // Create cipher
263
+ const factory =
264
+ NitroModules.createHybridObject<CipherFactory>('CipherFactory');
265
+ const cipher = factory.createCipher({
266
+ isCipher: mode === CipherOrWrapMode.kWebCryptoCipherEncrypt,
267
+ cipherType,
268
+ cipherKey: bufferLikeToArrayBuffer(key.keyObject.export()),
269
+ iv,
270
+ });
271
+
272
+ // Process data
273
+ const updated = cipher.update(data);
274
+ const final = cipher.final();
275
+
276
+ // Concatenate results
277
+ const result = new Uint8Array(updated.byteLength + final.byteLength);
278
+ result.set(new Uint8Array(updated), 0);
279
+ result.set(new Uint8Array(final), updated.byteLength);
280
+
281
+ return result.buffer;
282
+ }
283
+
284
+ async function aesGcmCipher(
285
+ mode: CipherOrWrapMode,
286
+ key: CryptoKey,
287
+ data: ArrayBuffer,
288
+ algorithm: AesGcmParams,
289
+ ): Promise<ArrayBuffer> {
290
+ const { tagLength = 128 } = algorithm;
291
+
292
+ // Validate tag length
293
+ const validTagLengths = [32, 64, 96, 104, 112, 120, 128];
294
+ if (!validTagLengths.includes(tagLength)) {
295
+ throw lazyDOMException(
296
+ `${tagLength} is not a valid AES-GCM tag length`,
297
+ 'OperationError',
298
+ );
299
+ }
300
+
301
+ const tagByteLength = tagLength / 8;
302
+
303
+ // Get cipher type based on key length
304
+ const keyLength = (key.algorithm as { length: number }).length;
305
+ const cipherType = `aes-${keyLength}-gcm`;
306
+
307
+ // Create cipher
308
+ const factory =
309
+ NitroModules.createHybridObject<CipherFactory>('CipherFactory');
310
+ const cipher = factory.createCipher({
311
+ isCipher: mode === CipherOrWrapMode.kWebCryptoCipherEncrypt,
312
+ cipherType,
313
+ cipherKey: bufferLikeToArrayBuffer(key.keyObject.export()),
314
+ iv: bufferLikeToArrayBuffer(algorithm.iv),
315
+ authTagLen: tagByteLength,
316
+ });
317
+
318
+ let processData: ArrayBuffer;
319
+ let authTag: ArrayBuffer | undefined;
320
+
321
+ if (mode === CipherOrWrapMode.kWebCryptoCipherDecrypt) {
322
+ // For decryption, extract auth tag from end of data
323
+ const dataView = new Uint8Array(data);
324
+
325
+ if (dataView.byteLength < tagByteLength) {
326
+ throw lazyDOMException(
327
+ 'The provided data is too small.',
328
+ 'OperationError',
329
+ );
330
+ }
331
+
332
+ // Split data and tag
333
+ const ciphertextLength = dataView.byteLength - tagByteLength;
334
+ processData = dataView.slice(0, ciphertextLength).buffer;
335
+ authTag = dataView.slice(ciphertextLength).buffer;
336
+
337
+ // Set auth tag for verification
338
+ cipher.setAuthTag(authTag);
339
+ } else {
340
+ processData = data;
341
+ }
342
+
343
+ // Set additional authenticated data if provided
344
+ if (algorithm.additionalData) {
345
+ cipher.setAAD(bufferLikeToArrayBuffer(algorithm.additionalData));
346
+ }
347
+
348
+ // Process data
349
+ const updated = cipher.update(processData);
350
+ const final = cipher.final();
351
+
352
+ if (mode === CipherOrWrapMode.kWebCryptoCipherEncrypt) {
353
+ // For encryption, append auth tag to result
354
+ const tag = cipher.getAuthTag();
355
+ const result = new Uint8Array(
356
+ updated.byteLength + final.byteLength + tag.byteLength,
357
+ );
358
+ result.set(new Uint8Array(updated), 0);
359
+ result.set(new Uint8Array(final), updated.byteLength);
360
+ result.set(new Uint8Array(tag), updated.byteLength + final.byteLength);
361
+ return result.buffer;
362
+ } else {
363
+ // For decryption, just concatenate plaintext
364
+ const result = new Uint8Array(updated.byteLength + final.byteLength);
365
+ result.set(new Uint8Array(updated), 0);
366
+ result.set(new Uint8Array(final), updated.byteLength);
367
+ return result.buffer;
368
+ }
369
+ }
370
+
371
+ async function aesGenerateKey(
372
+ algorithm: AesKeyGenParams,
373
+ extractable: boolean,
374
+ keyUsages: KeyUsage[],
375
+ ): Promise<CryptoKey> {
376
+ const { length } = algorithm;
377
+ const name = algorithm.name;
378
+
379
+ if (!name) {
380
+ throw lazyDOMException('Algorithm name is required', 'OperationError');
381
+ }
382
+
383
+ // Validate key length
384
+ if (![128, 192, 256].includes(length)) {
385
+ throw lazyDOMException(
386
+ `Invalid AES key length: ${length}. Must be 128, 192, or 256.`,
387
+ 'OperationError',
388
+ );
389
+ }
390
+
391
+ // Validate usages
392
+ const validUsages: KeyUsage[] = [
393
+ 'encrypt',
394
+ 'decrypt',
395
+ 'wrapKey',
396
+ 'unwrapKey',
397
+ ];
398
+ if (hasAnyNotIn(keyUsages, validUsages)) {
399
+ throw lazyDOMException(`Unsupported key usage for ${name}`, 'SyntaxError');
400
+ }
401
+
402
+ // Generate random key bytes
403
+ const keyBytes = new Uint8Array(length / 8);
404
+ getRandomValues(keyBytes);
405
+
406
+ // Create secret key
407
+ const keyObject = createSecretKey(keyBytes);
408
+
409
+ // Construct algorithm object with guaranteed name
410
+ const keyAlgorithm: SubtleAlgorithm = { name, length };
411
+
412
+ return new CryptoKey(keyObject, keyAlgorithm, keyUsages, extractable);
413
+ }
414
+
415
+ async function hmacGenerateKey(
416
+ algorithm: SubtleAlgorithm,
417
+ extractable: boolean,
418
+ keyUsages: KeyUsage[],
419
+ ): Promise<CryptoKey> {
420
+ // Validate usages
421
+ if (hasAnyNotIn(keyUsages, ['sign', 'verify'])) {
422
+ throw lazyDOMException('Unsupported key usage for HMAC key', 'SyntaxError');
423
+ }
424
+
425
+ // Get hash algorithm
426
+ const hash = algorithm.hash;
427
+ if (!hash) {
428
+ throw lazyDOMException(
429
+ 'HMAC algorithm requires a hash parameter',
430
+ 'TypeError',
431
+ );
432
+ }
433
+
434
+ const hashName = normalizeHashName(hash);
435
+
436
+ // Determine key length
437
+ let length = algorithm.length;
438
+ if (length === undefined) {
439
+ // Use hash output length as default key length
440
+ switch (hashName) {
441
+ case 'SHA-1':
442
+ length = 160;
443
+ break;
444
+ case 'SHA-256':
445
+ length = 256;
446
+ break;
447
+ case 'SHA-384':
448
+ length = 384;
449
+ break;
450
+ case 'SHA-512':
451
+ length = 512;
452
+ break;
453
+ default:
454
+ length = 256; // Default to 256 bits
455
+ }
456
+ }
457
+
458
+ if (length === 0) {
459
+ throw lazyDOMException(
460
+ 'Zero-length key is not supported',
461
+ 'OperationError',
462
+ );
463
+ }
464
+
465
+ // Generate random key bytes
466
+ const keyBytes = new Uint8Array(Math.ceil(length / 8));
467
+ getRandomValues(keyBytes);
468
+
469
+ // Create secret key
470
+ const keyObject = createSecretKey(keyBytes);
471
+
472
+ // Construct algorithm object
473
+ const keyAlgorithm: SubtleAlgorithm = {
474
+ name: 'HMAC',
475
+ hash: hashName,
476
+ length,
477
+ };
478
+
479
+ return new CryptoKey(keyObject, keyAlgorithm, keyUsages, extractable);
480
+ }
481
+
482
+ function rsaImportKey(
483
+ format: ImportFormat,
484
+ data: BufferLike | JWK,
485
+ algorithm: SubtleAlgorithm,
486
+ extractable: boolean,
487
+ keyUsages: KeyUsage[],
488
+ ): CryptoKey {
489
+ const { name } = algorithm;
490
+
491
+ // Validate usages
492
+ let checkSet: KeyUsage[];
493
+ switch (name) {
494
+ case 'RSASSA-PKCS1-v1_5':
495
+ case 'RSA-PSS':
496
+ checkSet = ['sign', 'verify'];
497
+ break;
498
+ case 'RSA-OAEP':
499
+ checkSet = ['encrypt', 'decrypt', 'wrapKey', 'unwrapKey'];
500
+ break;
501
+ default:
502
+ throw new Error(`Unsupported RSA algorithm: ${name}`);
503
+ }
504
+
505
+ if (hasAnyNotIn(keyUsages, checkSet)) {
506
+ throw new Error(`Unsupported key usage for ${name}`);
507
+ }
508
+
509
+ let keyObject: KeyObject;
510
+
511
+ if (format === 'jwk') {
512
+ const jwk = data as JWK;
513
+
514
+ // Validate JWK
515
+ if (jwk.kty !== 'RSA') {
516
+ throw new Error('Invalid JWK format for RSA key');
517
+ }
518
+
519
+ const handle =
520
+ NitroModules.createHybridObject<KeyObjectHandle>('KeyObjectHandle');
521
+ const keyType = handle.initJwk(jwk, undefined);
522
+
523
+ if (keyType === undefined) {
524
+ throw new Error('Failed to import RSA JWK');
525
+ }
526
+
527
+ // Create the appropriate KeyObject based on type
528
+ if (keyType === 1) {
529
+ keyObject = new PublicKeyObject(handle);
530
+ } else if (keyType === 2) {
531
+ keyObject = new PrivateKeyObject(handle);
532
+ } else {
533
+ throw new Error('Unexpected key type from RSA JWK import');
534
+ }
535
+ } else if (format === 'spki') {
536
+ const keyData = bufferLikeToArrayBuffer(data as BufferLike);
537
+ keyObject = KeyObject.createKeyObject(
538
+ 'public',
539
+ keyData,
540
+ KFormatType.DER,
541
+ KeyEncoding.SPKI,
542
+ );
543
+ } else if (format === 'pkcs8') {
544
+ const keyData = bufferLikeToArrayBuffer(data as BufferLike);
545
+ keyObject = KeyObject.createKeyObject(
546
+ 'private',
547
+ keyData,
548
+ KFormatType.DER,
549
+ KeyEncoding.PKCS8,
550
+ );
551
+ } else {
552
+ throw new Error(`Unsupported format for RSA import: ${format}`);
553
+ }
554
+
555
+ // Get the modulus length from the key and add it to the algorithm
556
+ const keyDetails = (keyObject as PublicKeyObject | PrivateKeyObject)
557
+ .asymmetricKeyDetails;
558
+
559
+ // Convert publicExponent number to big-endian byte array
560
+ let publicExponentBytes: Uint8Array | undefined;
561
+ if (keyDetails?.publicExponent) {
562
+ const exp = keyDetails.publicExponent;
563
+ // Convert number to big-endian bytes
564
+ const bytes: number[] = [];
565
+ let value = exp;
566
+ while (value > 0) {
567
+ bytes.unshift(value & 0xff);
568
+ value = Math.floor(value / 256);
569
+ }
570
+ publicExponentBytes = new Uint8Array(bytes.length > 0 ? bytes : [0]);
571
+ }
572
+
573
+ const algorithmWithDetails = {
574
+ ...algorithm,
575
+ modulusLength: keyDetails?.modulusLength,
576
+ publicExponent: publicExponentBytes,
577
+ };
578
+
579
+ return new CryptoKey(keyObject, algorithmWithDetails, keyUsages, extractable);
580
+ }
581
+
582
+ async function hmacImportKey(
583
+ algorithm: SubtleAlgorithm,
584
+ format: ImportFormat,
585
+ data: BufferLike | JWK,
586
+ extractable: boolean,
587
+ keyUsages: KeyUsage[],
588
+ ): Promise<CryptoKey> {
589
+ // Validate usages
590
+ if (hasAnyNotIn(keyUsages, ['sign', 'verify'])) {
591
+ throw new Error('Unsupported key usage for an HMAC key');
592
+ }
593
+
594
+ let keyObject: KeyObject;
595
+
596
+ if (format === 'jwk') {
597
+ const jwk = data as JWK;
598
+
599
+ // Validate JWK
600
+ if (!jwk || typeof jwk !== 'object') {
601
+ throw new Error('Invalid keyData');
602
+ }
603
+
604
+ if (jwk.kty !== 'oct') {
605
+ throw new Error('Invalid JWK format for HMAC key');
606
+ }
607
+
608
+ // Validate key length if specified
609
+ if (algorithm.length !== undefined) {
610
+ if (!jwk.k) {
611
+ throw new Error('JWK missing key data');
612
+ }
613
+ // Decode to check length
614
+ const decoded = SBuffer.from(jwk.k, 'base64');
615
+ const keyBitLength = decoded.length * 8;
616
+ if (algorithm.length === 0) {
617
+ throw new Error('Zero-length key is not supported');
618
+ }
619
+ if (algorithm.length !== keyBitLength) {
620
+ throw new Error('Invalid key length');
621
+ }
622
+ }
623
+
624
+ const handle =
625
+ NitroModules.createHybridObject<KeyObjectHandle>('KeyObjectHandle');
626
+ const keyType = handle.initJwk(jwk, undefined);
627
+
628
+ if (keyType === undefined || keyType !== 0) {
629
+ throw new Error('Failed to import HMAC JWK');
630
+ }
631
+
632
+ keyObject = new SecretKeyObject(handle);
633
+ } else if (format === 'raw') {
634
+ keyObject = createSecretKey(data as BinaryLike);
635
+ } else {
636
+ throw new Error(`Unable to import HMAC key with format ${format}`);
637
+ }
638
+
639
+ return new CryptoKey(
640
+ keyObject,
641
+ { ...algorithm, name: 'HMAC' },
642
+ keyUsages,
643
+ extractable,
644
+ );
645
+ }
646
+
647
+ async function aesImportKey(
648
+ algorithm: SubtleAlgorithm,
649
+ format: ImportFormat,
650
+ data: BufferLike | JWK,
651
+ extractable: boolean,
652
+ keyUsages: KeyUsage[],
653
+ ): Promise<CryptoKey> {
654
+ const { name, length } = algorithm;
655
+
656
+ // Validate usages
657
+ const validUsages: KeyUsage[] = [
658
+ 'encrypt',
659
+ 'decrypt',
660
+ 'wrapKey',
661
+ 'unwrapKey',
662
+ ];
663
+ if (hasAnyNotIn(keyUsages, validUsages)) {
664
+ throw new Error(`Unsupported key usage for ${name}`);
665
+ }
666
+
667
+ let keyObject: KeyObject;
668
+ let actualLength: number;
669
+
670
+ if (format === 'jwk') {
671
+ const jwk = data as JWK;
672
+
673
+ // Validate JWK
674
+ if (jwk.kty !== 'oct') {
675
+ throw new Error('Invalid JWK format for AES key');
676
+ }
677
+
678
+ const handle =
679
+ NitroModules.createHybridObject<KeyObjectHandle>('KeyObjectHandle');
680
+ const keyType = handle.initJwk(jwk, undefined);
681
+
682
+ if (keyType === undefined || keyType !== 0) {
683
+ throw new Error('Failed to import AES JWK');
684
+ }
685
+
686
+ keyObject = new SecretKeyObject(handle);
687
+
688
+ // Get actual key length from imported key
689
+ const exported = keyObject.export();
690
+ actualLength = exported.byteLength * 8;
691
+ } else if (format === 'raw') {
692
+ const keyData = bufferLikeToArrayBuffer(data as BufferLike);
693
+ actualLength = keyData.byteLength * 8;
694
+
695
+ // Validate key length
696
+ if (![128, 192, 256].includes(actualLength)) {
697
+ throw new Error('Invalid AES key length');
698
+ }
699
+
700
+ keyObject = createSecretKey(keyData);
701
+ } else {
702
+ throw new Error(`Unsupported format for AES import: ${format}`);
703
+ }
704
+
705
+ // Validate length if specified
706
+ if (length !== undefined && length !== actualLength) {
707
+ throw new Error(
708
+ `Key length mismatch: expected ${length}, got ${actualLength}`,
709
+ );
710
+ }
711
+
712
+ return new CryptoKey(
713
+ keyObject,
714
+ { name, length: actualLength },
715
+ keyUsages,
716
+ extractable,
717
+ );
718
+ }
719
+
720
+ function edImportKey(
721
+ format: ImportFormat,
722
+ data: BufferLike,
723
+ algorithm: SubtleAlgorithm,
724
+ extractable: boolean,
725
+ keyUsages: KeyUsage[],
726
+ ): CryptoKey {
727
+ const { name } = algorithm;
728
+
729
+ // Validate usages
730
+ if (hasAnyNotIn(keyUsages, ['sign', 'verify'])) {
731
+ throw lazyDOMException(
732
+ `Unsupported key usage for ${name} key`,
733
+ 'SyntaxError',
734
+ );
735
+ }
736
+
737
+ let keyObject: KeyObject;
738
+
739
+ if (format === 'spki') {
740
+ // Import public key
741
+ const keyData = bufferLikeToArrayBuffer(data);
742
+ keyObject = KeyObject.createKeyObject(
743
+ 'public',
744
+ keyData,
745
+ KFormatType.DER,
746
+ KeyEncoding.SPKI,
747
+ );
748
+ } else if (format === 'pkcs8') {
749
+ // Import private key
750
+ const keyData = bufferLikeToArrayBuffer(data);
751
+ keyObject = KeyObject.createKeyObject(
752
+ 'private',
753
+ keyData,
754
+ KFormatType.DER,
755
+ KeyEncoding.PKCS8,
756
+ );
757
+ } else if (format === 'raw') {
758
+ // Raw format - public key only for Ed keys
759
+ const keyData = bufferLikeToArrayBuffer(data);
760
+ const handle =
761
+ NitroModules.createHybridObject<KeyObjectHandle>('KeyObjectHandle');
762
+ // For raw Ed keys, we need to create them differently
763
+ // Raw public keys are just the key bytes
764
+ handle.init(1, keyData); // 1 = public key type
765
+ keyObject = new PublicKeyObject(handle);
766
+ } else {
767
+ throw lazyDOMException(
768
+ `Unsupported format for ${name} import: ${format}`,
769
+ 'NotSupportedError',
770
+ );
771
+ }
772
+
773
+ return new CryptoKey(keyObject, { name }, keyUsages, extractable);
774
+ }
775
+
776
+ const exportKeySpki = async (
777
+ key: CryptoKey,
778
+ ): Promise<ArrayBuffer | unknown> => {
779
+ switch (key.algorithm.name) {
780
+ case 'RSASSA-PKCS1-v1_5':
781
+ // Fall through
782
+ case 'RSA-PSS':
783
+ // Fall through
784
+ case 'RSA-OAEP':
785
+ if (key.type === 'public') {
786
+ return rsaExportKey(key, KWebCryptoKeyFormat.kWebCryptoKeyFormatSPKI);
787
+ }
788
+ break;
789
+ case 'ECDSA':
790
+ // Fall through
791
+ case 'ECDH':
792
+ if (key.type === 'public') {
793
+ return ecExportKey(key, KWebCryptoKeyFormat.kWebCryptoKeyFormatSPKI);
794
+ }
795
+ break;
796
+ case 'Ed25519':
797
+ // Fall through
798
+ case 'Ed448':
799
+ if (key.type === 'public') {
800
+ // Export Ed key in SPKI DER format
801
+ return bufferLikeToArrayBuffer(
802
+ key.keyObject.handle.exportKey(KFormatType.DER, KeyEncoding.SPKI),
803
+ );
804
+ }
805
+ break;
806
+ }
807
+
808
+ throw new Error(
809
+ `Unable to export a spki ${key.algorithm.name} ${key.type} key`,
810
+ );
811
+ };
812
+
813
+ const exportKeyPkcs8 = async (
814
+ key: CryptoKey,
815
+ ): Promise<ArrayBuffer | unknown> => {
816
+ switch (key.algorithm.name) {
817
+ case 'RSASSA-PKCS1-v1_5':
818
+ // Fall through
819
+ case 'RSA-PSS':
820
+ // Fall through
821
+ case 'RSA-OAEP':
822
+ if (key.type === 'private') {
823
+ return rsaExportKey(key, KWebCryptoKeyFormat.kWebCryptoKeyFormatPKCS8);
824
+ }
825
+ break;
826
+ case 'ECDSA':
827
+ // Fall through
828
+ case 'ECDH':
829
+ if (key.type === 'private') {
830
+ return ecExportKey(key, KWebCryptoKeyFormat.kWebCryptoKeyFormatPKCS8);
831
+ }
832
+ break;
833
+ case 'Ed25519':
834
+ // Fall through
835
+ case 'Ed448':
836
+ if (key.type === 'private') {
837
+ // Export Ed key in PKCS8 DER format
838
+ return bufferLikeToArrayBuffer(
839
+ key.keyObject.handle.exportKey(KFormatType.DER, KeyEncoding.PKCS8),
840
+ );
841
+ }
842
+ break;
843
+ }
844
+
845
+ throw new Error(
846
+ `Unable to export a pkcs8 ${key.algorithm.name} ${key.type} key`,
847
+ );
848
+ };
849
+
850
+ const exportKeyRaw = (key: CryptoKey): ArrayBuffer | unknown => {
851
+ switch (key.algorithm.name) {
852
+ case 'ECDSA':
853
+ // Fall through
854
+ case 'ECDH':
855
+ if (key.type === 'public') {
856
+ return ecExportKey(key, KWebCryptoKeyFormat.kWebCryptoKeyFormatRaw);
857
+ }
858
+ break;
859
+ case 'AES-CTR':
860
+ // Fall through
861
+ case 'AES-CBC':
862
+ // Fall through
863
+ case 'AES-GCM':
864
+ // Fall through
865
+ case 'AES-KW':
866
+ // Fall through
867
+ case 'HMAC': {
868
+ const exported = key.keyObject.export();
869
+ // Convert Buffer to ArrayBuffer
870
+ return exported.buffer.slice(
871
+ exported.byteOffset,
872
+ exported.byteOffset + exported.byteLength,
873
+ );
874
+ }
875
+ }
876
+
877
+ throw lazyDOMException(
878
+ `Unable to export a raw ${key.algorithm.name} ${key.type} key`,
879
+ 'InvalidAccessError',
880
+ );
881
+ };
882
+
883
+ const exportKeyJWK = (key: CryptoKey): ArrayBuffer | unknown => {
884
+ const jwk = key.keyObject.handle.exportJwk(
885
+ {
886
+ key_ops: key.usages,
887
+ ext: key.extractable,
888
+ },
889
+ true,
890
+ );
891
+ switch (key.algorithm.name) {
892
+ case 'RSASSA-PKCS1-v1_5':
893
+ jwk.alg = normalizeHashName(key.algorithm.hash, HashContext.JwkRsa);
894
+ return jwk;
895
+ case 'RSA-PSS':
896
+ jwk.alg = normalizeHashName(key.algorithm.hash, HashContext.JwkRsaPss);
897
+ return jwk;
898
+ case 'RSA-OAEP':
899
+ jwk.alg = normalizeHashName(key.algorithm.hash, HashContext.JwkRsaOaep);
900
+ return jwk;
901
+ case 'HMAC':
902
+ jwk.alg = normalizeHashName(key.algorithm.hash, HashContext.JwkHmac);
903
+ return jwk;
904
+ case 'ECDSA':
905
+ // Fall through
906
+ case 'ECDH':
907
+ jwk.crv ||= key.algorithm.namedCurve;
908
+ return jwk;
909
+ case 'AES-CTR':
910
+ // Fall through
911
+ case 'AES-CBC':
912
+ // Fall through
913
+ case 'AES-GCM':
914
+ // Fall through
915
+ case 'AES-KW':
916
+ if (key.algorithm.length === undefined) {
917
+ throw lazyDOMException(
918
+ `Algorithm ${key.algorithm.name} missing required length property`,
919
+ 'InvalidAccessError',
920
+ );
921
+ }
922
+ jwk.alg = getAlgorithmName(key.algorithm.name, key.algorithm.length);
923
+ return jwk;
924
+ default:
925
+ // Fall through
926
+ }
927
+
928
+ throw lazyDOMException(
929
+ `JWK export not yet supported: ${key.algorithm.name}`,
930
+ 'NotSupportedError',
931
+ );
932
+ };
933
+
934
+ const importGenericSecretKey = async (
935
+ { name, length }: SubtleAlgorithm,
936
+ format: ImportFormat,
937
+ keyData: BufferLike | BinaryLike,
938
+ extractable: boolean,
939
+ keyUsages: KeyUsage[],
940
+ ): Promise<CryptoKey> => {
941
+ if (extractable) {
942
+ throw new Error(`${name} keys are not extractable`);
943
+ }
944
+ if (hasAnyNotIn(keyUsages, ['deriveKey', 'deriveBits'])) {
945
+ throw new Error(`Unsupported key usage for a ${name} key`);
946
+ }
947
+
948
+ switch (format) {
949
+ case 'raw': {
950
+ if (hasAnyNotIn(keyUsages, ['deriveKey', 'deriveBits'])) {
951
+ throw new Error(`Unsupported key usage for a ${name} key`);
952
+ }
953
+
954
+ const checkLength =
955
+ typeof keyData === 'string' || SBuffer.isBuffer(keyData)
956
+ ? keyData.length * 8
957
+ : keyData.byteLength * 8;
958
+
959
+ if (length !== undefined && length !== checkLength) {
960
+ throw new Error('Invalid key length');
961
+ }
962
+
963
+ const keyObject = createSecretKey(keyData as BinaryLike);
964
+ return new CryptoKey(keyObject, { name }, keyUsages, false);
965
+ }
966
+ }
967
+
968
+ throw new Error(`Unable to import ${name} key with format ${format}`);
969
+ };
970
+
971
+ const checkCryptoKeyPairUsages = (pair: CryptoKeyPair) => {
972
+ if (
973
+ pair.privateKey &&
974
+ pair.privateKey instanceof CryptoKey &&
975
+ pair.privateKey.keyUsages &&
976
+ pair.privateKey.keyUsages.length > 0
977
+ ) {
978
+ return;
979
+ }
980
+ throw lazyDOMException(
981
+ 'Usages cannot be empty when creating a key.',
982
+ 'SyntaxError',
983
+ );
984
+ };
985
+
986
+ // Type guard to check if result is CryptoKeyPair
987
+ export function isCryptoKeyPair(
988
+ result: CryptoKey | CryptoKeyPair,
989
+ ): result is CryptoKeyPair {
990
+ return 'publicKey' in result && 'privateKey' in result;
991
+ }
992
+
993
+ function hmacSignVerify(
994
+ key: CryptoKey,
995
+ data: BufferLike,
996
+ signature?: BufferLike,
997
+ ): ArrayBuffer | boolean {
998
+ // Get hash algorithm from key
999
+ const hashName = normalizeHashName(key.algorithm.hash);
1000
+
1001
+ // Export the secret key material
1002
+ const keyData = key.keyObject.export();
1003
+
1004
+ // Create HMAC and compute digest
1005
+ const hmac = createHmac(hashName, keyData);
1006
+ hmac.update(bufferLikeToArrayBuffer(data));
1007
+ const computed = hmac.digest();
1008
+
1009
+ if (signature === undefined) {
1010
+ // Sign operation - return the HMAC as ArrayBuffer
1011
+ return computed.buffer.slice(
1012
+ computed.byteOffset,
1013
+ computed.byteOffset + computed.byteLength,
1014
+ );
1015
+ }
1016
+
1017
+ // Verify operation - compare computed HMAC with provided signature
1018
+ const sigBytes = new Uint8Array(bufferLikeToArrayBuffer(signature));
1019
+ const computedBytes = new Uint8Array(
1020
+ computed.buffer,
1021
+ computed.byteOffset,
1022
+ computed.byteLength,
1023
+ );
1024
+
1025
+ if (computedBytes.length !== sigBytes.length) {
1026
+ return false;
1027
+ }
1028
+
1029
+ // Constant-time comparison to prevent timing attacks
1030
+ let result = 0;
1031
+ for (let i = 0; i < computedBytes.length; i++) {
1032
+ result |= computedBytes[i]! ^ sigBytes[i]!;
1033
+ }
1034
+ return result === 0;
1035
+ }
1036
+
1037
+ function rsaSignVerify(
1038
+ key: CryptoKey,
1039
+ data: BufferLike,
1040
+ padding: 'pkcs1' | 'pss',
1041
+ signature?: BufferLike,
1042
+ saltLength?: number,
1043
+ ): ArrayBuffer | boolean {
1044
+ // Get hash algorithm from key
1045
+ const hashName = normalizeHashName(key.algorithm.hash);
1046
+
1047
+ // Determine RSA padding constant
1048
+ const RSA_PKCS1_PADDING = 1;
1049
+ const RSA_PKCS1_PSS_PADDING = 6;
1050
+ const paddingValue =
1051
+ padding === 'pss' ? RSA_PKCS1_PSS_PADDING : RSA_PKCS1_PADDING;
1052
+
1053
+ if (signature === undefined) {
1054
+ // Sign operation
1055
+ const signer = createSign(hashName);
1056
+ signer.update(data);
1057
+ const sig = signer.sign({
1058
+ key: key,
1059
+ padding: paddingValue,
1060
+ saltLength,
1061
+ });
1062
+ return sig.buffer.slice(sig.byteOffset, sig.byteOffset + sig.byteLength);
1063
+ }
1064
+
1065
+ // Verify operation
1066
+ const verifier = createVerify(hashName);
1067
+ verifier.update(data);
1068
+ return verifier.verify(
1069
+ {
1070
+ key: key,
1071
+ padding: paddingValue,
1072
+ saltLength,
1073
+ },
1074
+ signature,
1075
+ );
1076
+ }
1077
+
1078
+ function edSignVerify(
1079
+ key: CryptoKey,
1080
+ data: BufferLike,
1081
+ signature?: BufferLike,
1082
+ ): ArrayBuffer | boolean {
1083
+ const isSign = signature === undefined;
1084
+ const expectedKeyType = isSign ? 'private' : 'public';
1085
+
1086
+ if (key.type !== expectedKeyType) {
1087
+ throw lazyDOMException(
1088
+ `Key must be a ${expectedKeyType} key`,
1089
+ 'InvalidAccessError',
1090
+ );
1091
+ }
1092
+
1093
+ // Get curve type from algorithm name (Ed25519 or Ed448)
1094
+ const algorithmName = key.algorithm.name;
1095
+ const curveType = algorithmName.toLowerCase() as 'ed25519' | 'ed448';
1096
+
1097
+ // Create Ed instance with the curve
1098
+ const ed = new Ed(curveType, {});
1099
+
1100
+ // Export raw key bytes (exportKey with no format returns raw for Ed keys)
1101
+ const rawKey = key.keyObject.handle.exportKey();
1102
+ const dataBuffer = bufferLikeToArrayBuffer(data);
1103
+
1104
+ if (isSign) {
1105
+ // Sign operation - use raw private key
1106
+ const sig = ed.signSync(dataBuffer, rawKey);
1107
+ return sig;
1108
+ } else {
1109
+ // Verify operation - use raw public key
1110
+ const signatureBuffer = bufferLikeToArrayBuffer(signature!);
1111
+ return ed.verifySync(signatureBuffer, dataBuffer, rawKey);
1112
+ }
1113
+ }
1114
+
1115
+ const signVerify = (
1116
+ algorithm: SubtleAlgorithm,
1117
+ key: CryptoKey,
1118
+ data: BufferLike,
1119
+ signature?: BufferLike,
1120
+ ): ArrayBuffer | boolean => {
1121
+ const usage: Operation = signature === undefined ? 'sign' : 'verify';
1122
+ algorithm = normalizeAlgorithm(algorithm, usage);
1123
+
1124
+ if (!key.usages.includes(usage) || algorithm.name !== key.algorithm.name) {
1125
+ throw lazyDOMException(
1126
+ `Unable to use this key to ${usage}`,
1127
+ 'InvalidAccessError',
1128
+ );
1129
+ }
1130
+
1131
+ switch (algorithm.name) {
1132
+ case 'ECDSA':
1133
+ return ecdsaSignVerify(key, data, algorithm, signature);
1134
+ case 'HMAC':
1135
+ return hmacSignVerify(key, data, signature);
1136
+ case 'RSASSA-PKCS1-v1_5':
1137
+ return rsaSignVerify(key, data, 'pkcs1', signature);
1138
+ case 'RSA-PSS':
1139
+ return rsaSignVerify(key, data, 'pss', signature, algorithm.saltLength);
1140
+ case 'Ed25519':
1141
+ case 'Ed448':
1142
+ return edSignVerify(key, data, signature);
1143
+ }
1144
+ throw lazyDOMException(
1145
+ `Unrecognized algorithm name '${algorithm.name}' for '${usage}'`,
1146
+ 'NotSupportedError',
1147
+ );
1148
+ };
1149
+
1150
+ const cipherOrWrap = async (
1151
+ mode: CipherOrWrapMode,
1152
+ algorithm: EncryptDecryptParams,
1153
+ key: CryptoKey,
1154
+ data: ArrayBuffer,
1155
+ op: Operation,
1156
+ ): Promise<ArrayBuffer> => {
1157
+ if (
1158
+ key.algorithm.name !== algorithm.name ||
1159
+ !key.usages.includes(op as KeyUsage)
1160
+ ) {
1161
+ throw lazyDOMException(
1162
+ 'The requested operation is not valid for the provided key',
1163
+ 'InvalidAccessError',
1164
+ );
1165
+ }
1166
+
1167
+ validateMaxBufferLength(data, 'data');
1168
+
1169
+ switch (algorithm.name) {
1170
+ case 'RSA-OAEP':
1171
+ return rsaCipher(mode, key, data, algorithm);
1172
+ case 'AES-CTR':
1173
+ // Fall through
1174
+ case 'AES-CBC':
1175
+ // Fall through
1176
+ case 'AES-GCM':
1177
+ return aesCipher(mode, key, data, algorithm);
1178
+ }
1179
+ };
1180
+
1181
+ export class Subtle {
1182
+ async decrypt(
1183
+ algorithm: EncryptDecryptParams,
1184
+ key: CryptoKey,
1185
+ data: BufferLike,
1186
+ ): Promise<ArrayBuffer> {
1187
+ const normalizedAlgorithm = normalizeAlgorithm(algorithm, 'decrypt');
1188
+ return cipherOrWrap(
1189
+ CipherOrWrapMode.kWebCryptoCipherDecrypt,
1190
+ normalizedAlgorithm as EncryptDecryptParams,
1191
+ key,
1192
+ bufferLikeToArrayBuffer(data),
1193
+ 'decrypt',
1194
+ );
1195
+ }
1196
+
1197
+ async digest(
1198
+ algorithm: SubtleAlgorithm | AnyAlgorithm,
1199
+ data: BufferLike,
1200
+ ): Promise<ArrayBuffer> {
1201
+ const normalizedAlgorithm = normalizeAlgorithm(
1202
+ algorithm,
1203
+ 'digest' as Operation,
1204
+ );
1205
+ return asyncDigest(normalizedAlgorithm, data);
1206
+ }
1207
+
1208
+ async deriveBits(
1209
+ algorithm: SubtleAlgorithm,
1210
+ baseKey: CryptoKey,
1211
+ length: number,
1212
+ ): Promise<ArrayBuffer> {
1213
+ if (!baseKey.keyUsages.includes('deriveBits')) {
1214
+ throw new Error('baseKey does not have deriveBits usage');
1215
+ }
1216
+ if (baseKey.algorithm.name !== algorithm.name)
1217
+ throw new Error('Key algorithm mismatch');
1218
+ switch (algorithm.name) {
1219
+ case 'PBKDF2':
1220
+ return pbkdf2DeriveBits(algorithm, baseKey, length);
1221
+ }
1222
+ throw new Error(
1223
+ `'subtle.deriveBits()' for ${algorithm.name} is not implemented.`,
1224
+ );
1225
+ }
1226
+
1227
+ async encrypt(
1228
+ algorithm: EncryptDecryptParams,
1229
+ key: CryptoKey,
1230
+ data: BufferLike,
1231
+ ): Promise<ArrayBuffer> {
1232
+ const normalizedAlgorithm = normalizeAlgorithm(algorithm, 'encrypt');
1233
+ return cipherOrWrap(
1234
+ CipherOrWrapMode.kWebCryptoCipherEncrypt,
1235
+ normalizedAlgorithm as EncryptDecryptParams,
1236
+ key,
1237
+ bufferLikeToArrayBuffer(data),
1238
+ 'encrypt',
1239
+ );
1240
+ }
1241
+
1242
+ async exportKey(
1243
+ format: ImportFormat,
1244
+ key: CryptoKey,
1245
+ ): Promise<ArrayBuffer | JWK> {
1246
+ if (!key.extractable) throw new Error('key is not extractable');
1247
+
1248
+ switch (format) {
1249
+ case 'spki':
1250
+ return (await exportKeySpki(key)) as ArrayBuffer;
1251
+ case 'pkcs8':
1252
+ return (await exportKeyPkcs8(key)) as ArrayBuffer;
1253
+ case 'jwk':
1254
+ return exportKeyJWK(key) as JWK;
1255
+ case 'raw':
1256
+ return exportKeyRaw(key) as ArrayBuffer;
1257
+ }
1258
+ }
1259
+
1260
+ async generateKey(
1261
+ algorithm: SubtleAlgorithm,
1262
+ extractable: boolean,
1263
+ keyUsages: KeyUsage[],
1264
+ ): Promise<CryptoKey | CryptoKeyPair> {
1265
+ algorithm = normalizeAlgorithm(algorithm, 'generateKey');
1266
+ let result: CryptoKey | CryptoKeyPair;
1267
+ switch (algorithm.name) {
1268
+ case 'RSASSA-PKCS1-v1_5':
1269
+ // Fall through
1270
+ case 'RSA-PSS':
1271
+ // Fall through
1272
+ case 'RSA-OAEP':
1273
+ result = await rsa_generateKeyPair(algorithm, extractable, keyUsages);
1274
+ break;
1275
+ case 'ECDSA':
1276
+ // Fall through
1277
+ case 'ECDH':
1278
+ result = await ec_generateKeyPair(
1279
+ algorithm.name,
1280
+ algorithm.namedCurve!,
1281
+ extractable,
1282
+ keyUsages,
1283
+ );
1284
+ checkCryptoKeyPairUsages(result as CryptoKeyPair);
1285
+ break;
1286
+ case 'AES-CTR':
1287
+ // Fall through
1288
+ case 'AES-CBC':
1289
+ // Fall through
1290
+ case 'AES-GCM':
1291
+ // Fall through
1292
+ case 'AES-KW':
1293
+ result = await aesGenerateKey(
1294
+ algorithm as AesKeyGenParams,
1295
+ extractable,
1296
+ keyUsages,
1297
+ );
1298
+ break;
1299
+ case 'HMAC':
1300
+ result = await hmacGenerateKey(algorithm, extractable, keyUsages);
1301
+ break;
1302
+ case 'Ed25519':
1303
+ // Fall through
1304
+ case 'Ed448':
1305
+ result = await ed_generateKeyPairWebCrypto(
1306
+ algorithm.name.toLowerCase() as 'ed25519' | 'ed448',
1307
+ extractable,
1308
+ keyUsages,
1309
+ );
1310
+ checkCryptoKeyPairUsages(result as CryptoKeyPair);
1311
+ break;
1312
+ default:
1313
+ throw new Error(
1314
+ `'subtle.generateKey()' is not implemented for ${algorithm.name}.
1315
+ Unrecognized algorithm name`,
1316
+ );
1317
+ }
1318
+
1319
+ return result;
1320
+ }
1321
+
1322
+ async importKey(
1323
+ format: ImportFormat,
1324
+ data: BufferLike | BinaryLike | JWK,
1325
+ algorithm: SubtleAlgorithm | AnyAlgorithm,
1326
+ extractable: boolean,
1327
+ keyUsages: KeyUsage[],
1328
+ ): Promise<CryptoKey> {
1329
+ const normalizedAlgorithm = normalizeAlgorithm(algorithm, 'importKey');
1330
+ let result: CryptoKey;
1331
+ switch (normalizedAlgorithm.name) {
1332
+ case 'RSASSA-PKCS1-v1_5':
1333
+ // Fall through
1334
+ case 'RSA-PSS':
1335
+ // Fall through
1336
+ case 'RSA-OAEP':
1337
+ result = rsaImportKey(
1338
+ format,
1339
+ data as BufferLike | JWK,
1340
+ normalizedAlgorithm,
1341
+ extractable,
1342
+ keyUsages,
1343
+ );
1344
+ break;
1345
+ case 'ECDSA':
1346
+ // Fall through
1347
+ case 'ECDH':
1348
+ result = ecImportKey(
1349
+ format,
1350
+ data,
1351
+ normalizedAlgorithm,
1352
+ extractable,
1353
+ keyUsages,
1354
+ );
1355
+ break;
1356
+ case 'HMAC':
1357
+ result = await hmacImportKey(
1358
+ normalizedAlgorithm,
1359
+ format,
1360
+ data as BufferLike | JWK,
1361
+ extractable,
1362
+ keyUsages,
1363
+ );
1364
+ break;
1365
+ case 'AES-CTR':
1366
+ // Fall through
1367
+ case 'AES-CBC':
1368
+ // Fall through
1369
+ case 'AES-GCM':
1370
+ // Fall through
1371
+ case 'AES-KW':
1372
+ result = await aesImportKey(
1373
+ normalizedAlgorithm,
1374
+ format,
1375
+ data as BufferLike | JWK,
1376
+ extractable,
1377
+ keyUsages,
1378
+ );
1379
+ break;
1380
+ case 'PBKDF2':
1381
+ result = await importGenericSecretKey(
1382
+ normalizedAlgorithm,
1383
+ format,
1384
+ data as BufferLike | BinaryLike,
1385
+ extractable,
1386
+ keyUsages,
1387
+ );
1388
+ break;
1389
+ case 'Ed25519':
1390
+ // Fall through
1391
+ case 'Ed448':
1392
+ result = edImportKey(
1393
+ format,
1394
+ data as BufferLike,
1395
+ normalizedAlgorithm,
1396
+ extractable,
1397
+ keyUsages,
1398
+ );
1399
+ break;
1400
+ default:
1401
+ throw new Error(
1402
+ `"subtle.importKey()" is not implemented for ${normalizedAlgorithm.name}`,
1403
+ );
1404
+ }
1405
+
1406
+ if (
1407
+ (result.type === 'secret' || result.type === 'private') &&
1408
+ result.usages.length === 0
1409
+ ) {
1410
+ throw new Error(
1411
+ `Usages cannot be empty when importing a ${result.type} key.`,
1412
+ );
1413
+ }
1414
+
1415
+ return result;
1416
+ }
1417
+
1418
+ async sign(
1419
+ algorithm: SubtleAlgorithm,
1420
+ key: CryptoKey,
1421
+ data: BufferLike,
1422
+ ): Promise<ArrayBuffer> {
1423
+ return signVerify(algorithm, key, data) as ArrayBuffer;
1424
+ }
1425
+
1426
+ async verify(
1427
+ algorithm: SubtleAlgorithm,
1428
+ key: CryptoKey,
1429
+ signature: BufferLike,
1430
+ data: BufferLike,
1431
+ ): Promise<ArrayBuffer> {
1432
+ return signVerify(algorithm, key, data, signature) as ArrayBuffer;
1433
+ }
1434
+ }
1435
+
1436
+ export const subtle = new Subtle();