react-native-quick-crypto 1.1.0 → 1.1.2

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 (815) hide show
  1. package/QuickCrypto.podspec +1 -0
  2. package/android/CMakeLists.txt +4 -0
  3. package/android/build.gradle +5 -1
  4. package/cpp/argon2/HybridArgon2.cpp +10 -3
  5. package/cpp/blake3/HybridBlake3.cpp +5 -3
  6. package/cpp/cipher/CCMCipher.cpp +35 -26
  7. package/cpp/cipher/CCMCipher.hpp +2 -4
  8. package/cpp/cipher/ChaCha20Cipher.cpp +19 -27
  9. package/cpp/cipher/ChaCha20Cipher.hpp +2 -4
  10. package/cpp/cipher/ChaCha20Poly1305Cipher.cpp +41 -36
  11. package/cpp/cipher/ChaCha20Poly1305Cipher.hpp +2 -4
  12. package/cpp/cipher/GCMCipher.cpp +17 -20
  13. package/cpp/cipher/HybridCipher.cpp +44 -47
  14. package/cpp/cipher/HybridCipher.hpp +17 -1
  15. package/cpp/cipher/HybridRsaCipher.cpp +93 -56
  16. package/cpp/cipher/OCBCipher.cpp +5 -5
  17. package/cpp/cipher/XChaCha20Poly1305Cipher.cpp +27 -32
  18. package/cpp/cipher/XSalsa20Cipher.cpp +78 -16
  19. package/cpp/cipher/XSalsa20Cipher.hpp +25 -3
  20. package/cpp/cipher/XSalsa20Poly1305Cipher.cpp +32 -41
  21. package/cpp/dh/HybridDiffieHellman.cpp +29 -0
  22. package/cpp/ec/HybridEcKeyPair.cpp +35 -33
  23. package/cpp/ec/HybridEcKeyPair.hpp +3 -7
  24. package/cpp/ecdh/HybridECDH.cpp +23 -0
  25. package/cpp/ed25519/HybridEdKeyPair.cpp +73 -117
  26. package/cpp/ed25519/HybridEdKeyPair.hpp +5 -9
  27. package/cpp/hash/HybridHash.cpp +5 -7
  28. package/cpp/hkdf/HybridHkdf.cpp +6 -4
  29. package/cpp/hmac/HybridHmac.cpp +4 -6
  30. package/cpp/keys/HybridKeyObjectHandle.cpp +630 -2
  31. package/cpp/keys/HybridKeyObjectHandle.hpp +21 -1
  32. package/cpp/kmac/HybridKmac.cpp +4 -4
  33. package/cpp/mldsa/HybridMlDsaKeyPair.cpp +37 -49
  34. package/cpp/mlkem/HybridMlKemKeyPair.cpp +39 -43
  35. package/cpp/pbkdf2/HybridPbkdf2.cpp +7 -8
  36. package/cpp/rsa/HybridRsaKeyPair.cpp +5 -8
  37. package/cpp/rsa/HybridRsaKeyPair.hpp +4 -7
  38. package/cpp/scrypt/HybridScrypt.cpp +6 -4
  39. package/cpp/sign/HybridSignHandle.cpp +47 -72
  40. package/cpp/sign/HybridVerifyHandle.cpp +47 -67
  41. package/cpp/slhdsa/HybridSlhDsaKeyPair.cpp +245 -0
  42. package/cpp/slhdsa/HybridSlhDsaKeyPair.hpp +48 -0
  43. package/cpp/turboshake/HybridTurboShake.cpp +379 -0
  44. package/cpp/turboshake/HybridTurboShake.hpp +28 -0
  45. package/cpp/utils/HybridUtils.cpp +195 -43
  46. package/cpp/utils/HybridUtils.hpp +9 -2
  47. package/cpp/utils/QuickCryptoUtils.hpp +72 -0
  48. package/deps/blake3/README.md +6 -7
  49. package/deps/blake3/c/blake3.c +3 -2
  50. package/deps/blake3/c/blake3.h +2 -2
  51. package/deps/blake3/c/blake3_dispatch.c +2 -2
  52. package/deps/blake3/c/blake3_impl.h +1 -1
  53. package/deps/blake3/c/blake3_neon.c +5 -4
  54. package/deps/ncrypto/include/ncrypto/version.h +2 -2
  55. package/deps/ncrypto/include/ncrypto.h +9 -2
  56. package/deps/ncrypto/src/ncrypto.cpp +130 -35
  57. package/lib/commonjs/argon2.js +51 -2
  58. package/lib/commonjs/argon2.js.map +1 -1
  59. package/lib/commonjs/cipher.js +109 -11
  60. package/lib/commonjs/cipher.js.map +1 -1
  61. package/lib/commonjs/dhKeyPair.js +3 -0
  62. package/lib/commonjs/dhKeyPair.js.map +1 -1
  63. package/lib/commonjs/dsa.js +11 -2
  64. package/lib/commonjs/dsa.js.map +1 -1
  65. package/lib/commonjs/ec.js +37 -30
  66. package/lib/commonjs/ec.js.map +1 -1
  67. package/lib/commonjs/ed.js +60 -6
  68. package/lib/commonjs/ed.js.map +1 -1
  69. package/lib/commonjs/hash.js +67 -10
  70. package/lib/commonjs/hash.js.map +1 -1
  71. package/lib/commonjs/hkdf.js +33 -6
  72. package/lib/commonjs/hkdf.js.map +1 -1
  73. package/lib/commonjs/hmac.js +15 -5
  74. package/lib/commonjs/hmac.js.map +1 -1
  75. package/lib/commonjs/keys/classes.js +33 -7
  76. package/lib/commonjs/keys/classes.js.map +1 -1
  77. package/lib/commonjs/keys/generateKeyPair.js +85 -4
  78. package/lib/commonjs/keys/generateKeyPair.js.map +1 -1
  79. package/lib/commonjs/keys/index.js +50 -2
  80. package/lib/commonjs/keys/index.js.map +1 -1
  81. package/lib/commonjs/keys/publicCipher.js +10 -4
  82. package/lib/commonjs/keys/publicCipher.js.map +1 -1
  83. package/lib/commonjs/keys/signVerify.js +9 -2
  84. package/lib/commonjs/keys/signVerify.js.map +1 -1
  85. package/lib/commonjs/keys/utils.js +59 -1
  86. package/lib/commonjs/keys/utils.js.map +1 -1
  87. package/lib/commonjs/random.js +74 -11
  88. package/lib/commonjs/random.js.map +1 -1
  89. package/lib/commonjs/rsa.js +15 -5
  90. package/lib/commonjs/rsa.js.map +1 -1
  91. package/lib/commonjs/scrypt.js +47 -6
  92. package/lib/commonjs/scrypt.js.map +1 -1
  93. package/lib/commonjs/slhdsa.js +70 -0
  94. package/lib/commonjs/slhdsa.js.map +1 -0
  95. package/lib/commonjs/specs/slhDsaKeyPair.nitro.js +6 -0
  96. package/lib/commonjs/specs/slhDsaKeyPair.nitro.js.map +1 -0
  97. package/lib/commonjs/specs/turboshake.nitro.js +6 -0
  98. package/lib/commonjs/specs/turboshake.nitro.js.map +1 -0
  99. package/lib/commonjs/subtle.js +975 -253
  100. package/lib/commonjs/subtle.js.map +1 -1
  101. package/lib/commonjs/utils/cipher.js +18 -7
  102. package/lib/commonjs/utils/cipher.js.map +1 -1
  103. package/lib/commonjs/utils/conversion.js +86 -28
  104. package/lib/commonjs/utils/conversion.js.map +1 -1
  105. package/lib/commonjs/utils/errors.js +63 -4
  106. package/lib/commonjs/utils/errors.js.map +1 -1
  107. package/lib/commonjs/utils/timingSafeEqual.js +7 -2
  108. package/lib/commonjs/utils/timingSafeEqual.js.map +1 -1
  109. package/lib/commonjs/utils/types.js.map +1 -1
  110. package/lib/commonjs/utils/validation.js +46 -0
  111. package/lib/commonjs/utils/validation.js.map +1 -1
  112. package/lib/commonjs/x509certificate.js +6 -6
  113. package/lib/commonjs/x509certificate.js.map +1 -1
  114. package/lib/module/argon2.js +51 -2
  115. package/lib/module/argon2.js.map +1 -1
  116. package/lib/module/cipher.js +109 -11
  117. package/lib/module/cipher.js.map +1 -1
  118. package/lib/module/dhKeyPair.js +3 -0
  119. package/lib/module/dhKeyPair.js.map +1 -1
  120. package/lib/module/dsa.js +11 -2
  121. package/lib/module/dsa.js.map +1 -1
  122. package/lib/module/ec.js +38 -31
  123. package/lib/module/ec.js.map +1 -1
  124. package/lib/module/ed.js +61 -7
  125. package/lib/module/ed.js.map +1 -1
  126. package/lib/module/hash.js +67 -10
  127. package/lib/module/hash.js.map +1 -1
  128. package/lib/module/hkdf.js +33 -6
  129. package/lib/module/hkdf.js.map +1 -1
  130. package/lib/module/hmac.js +15 -5
  131. package/lib/module/hmac.js.map +1 -1
  132. package/lib/module/keys/classes.js +31 -5
  133. package/lib/module/keys/classes.js.map +1 -1
  134. package/lib/module/keys/generateKeyPair.js +86 -5
  135. package/lib/module/keys/generateKeyPair.js.map +1 -1
  136. package/lib/module/keys/index.js +50 -2
  137. package/lib/module/keys/index.js.map +1 -1
  138. package/lib/module/keys/publicCipher.js +10 -4
  139. package/lib/module/keys/publicCipher.js.map +1 -1
  140. package/lib/module/keys/signVerify.js +9 -2
  141. package/lib/module/keys/signVerify.js.map +1 -1
  142. package/lib/module/keys/utils.js +57 -1
  143. package/lib/module/keys/utils.js.map +1 -1
  144. package/lib/module/random.js +74 -12
  145. package/lib/module/random.js.map +1 -1
  146. package/lib/module/rsa.js +14 -4
  147. package/lib/module/rsa.js.map +1 -1
  148. package/lib/module/scrypt.js +47 -6
  149. package/lib/module/scrypt.js.map +1 -1
  150. package/lib/module/slhdsa.js +64 -0
  151. package/lib/module/slhdsa.js.map +1 -0
  152. package/lib/module/specs/slhDsaKeyPair.nitro.js +4 -0
  153. package/lib/module/specs/slhDsaKeyPair.nitro.js.map +1 -0
  154. package/lib/module/specs/turboshake.nitro.js +4 -0
  155. package/lib/module/specs/turboshake.nitro.js.map +1 -0
  156. package/lib/module/subtle.js +976 -254
  157. package/lib/module/subtle.js.map +1 -1
  158. package/lib/module/utils/cipher.js +18 -7
  159. package/lib/module/utils/cipher.js.map +1 -1
  160. package/lib/module/utils/conversion.js +84 -28
  161. package/lib/module/utils/conversion.js.map +1 -1
  162. package/lib/module/utils/errors.js +61 -4
  163. package/lib/module/utils/errors.js.map +1 -1
  164. package/lib/module/utils/timingSafeEqual.js +8 -3
  165. package/lib/module/utils/timingSafeEqual.js.map +1 -1
  166. package/lib/module/utils/types.js.map +1 -1
  167. package/lib/module/utils/validation.js +44 -0
  168. package/lib/module/utils/validation.js.map +1 -1
  169. package/lib/module/x509certificate.js +6 -6
  170. package/lib/module/x509certificate.js.map +1 -1
  171. package/lib/typescript/argon2.d.ts.map +1 -1
  172. package/lib/typescript/cipher.d.ts +2 -2
  173. package/lib/typescript/cipher.d.ts.map +1 -1
  174. package/lib/typescript/dhKeyPair.d.ts.map +1 -1
  175. package/lib/typescript/dsa.d.ts.map +1 -1
  176. package/lib/typescript/ec.d.ts.map +1 -1
  177. package/lib/typescript/ed.d.ts.map +1 -1
  178. package/lib/typescript/hash.d.ts +2 -2
  179. package/lib/typescript/hash.d.ts.map +1 -1
  180. package/lib/typescript/hkdf.d.ts.map +1 -1
  181. package/lib/typescript/hmac.d.ts +2 -2
  182. package/lib/typescript/hmac.d.ts.map +1 -1
  183. package/lib/typescript/index.d.ts +13 -8
  184. package/lib/typescript/index.d.ts.map +1 -1
  185. package/lib/typescript/keys/classes.d.ts +10 -1
  186. package/lib/typescript/keys/classes.d.ts.map +1 -1
  187. package/lib/typescript/keys/generateKeyPair.d.ts +12 -1
  188. package/lib/typescript/keys/generateKeyPair.d.ts.map +1 -1
  189. package/lib/typescript/keys/index.d.ts +3 -1
  190. package/lib/typescript/keys/index.d.ts.map +1 -1
  191. package/lib/typescript/keys/publicCipher.d.ts.map +1 -1
  192. package/lib/typescript/keys/signVerify.d.ts.map +1 -1
  193. package/lib/typescript/keys/utils.d.ts +21 -4
  194. package/lib/typescript/keys/utils.d.ts.map +1 -1
  195. package/lib/typescript/random.d.ts +5 -1
  196. package/lib/typescript/random.d.ts.map +1 -1
  197. package/lib/typescript/rsa.d.ts.map +1 -1
  198. package/lib/typescript/scrypt.d.ts.map +1 -1
  199. package/lib/typescript/slhdsa.d.ts +19 -0
  200. package/lib/typescript/slhdsa.d.ts.map +1 -0
  201. package/lib/typescript/specs/keyObjectHandle.nitro.d.ts +9 -0
  202. package/lib/typescript/specs/keyObjectHandle.nitro.d.ts.map +1 -1
  203. package/lib/typescript/specs/slhDsaKeyPair.nitro.d.ts +16 -0
  204. package/lib/typescript/specs/slhDsaKeyPair.nitro.d.ts.map +1 -0
  205. package/lib/typescript/specs/turboshake.nitro.d.ts +11 -0
  206. package/lib/typescript/specs/turboshake.nitro.d.ts.map +1 -0
  207. package/lib/typescript/specs/utils.nitro.d.ts +0 -2
  208. package/lib/typescript/specs/utils.nitro.d.ts.map +1 -1
  209. package/lib/typescript/subtle.d.ts +3 -2
  210. package/lib/typescript/subtle.d.ts.map +1 -1
  211. package/lib/typescript/utils/cipher.d.ts +13 -1
  212. package/lib/typescript/utils/cipher.d.ts.map +1 -1
  213. package/lib/typescript/utils/conversion.d.ts +13 -9
  214. package/lib/typescript/utils/conversion.d.ts.map +1 -1
  215. package/lib/typescript/utils/errors.d.ts +12 -0
  216. package/lib/typescript/utils/errors.d.ts.map +1 -1
  217. package/lib/typescript/utils/timingSafeEqual.d.ts.map +1 -1
  218. package/lib/typescript/utils/types.d.ts +32 -15
  219. package/lib/typescript/utils/types.d.ts.map +1 -1
  220. package/lib/typescript/utils/validation.d.ts +3 -1
  221. package/lib/typescript/utils/validation.d.ts.map +1 -1
  222. package/lib/typescript/x509certificate.d.ts.map +1 -1
  223. package/nitrogen/generated/android/QuickCrypto+autolinking.cmake +2 -0
  224. package/nitrogen/generated/android/QuickCryptoOnLoad.cpp +20 -0
  225. package/nitrogen/generated/ios/QuickCryptoAutolinking.mm +20 -0
  226. package/nitrogen/generated/shared/c++/AsymmetricKeyType.hpp +48 -0
  227. package/nitrogen/generated/shared/c++/HybridKeyObjectHandleSpec.cpp +9 -0
  228. package/nitrogen/generated/shared/c++/HybridKeyObjectHandleSpec.hpp +9 -0
  229. package/nitrogen/generated/shared/c++/HybridSlhDsaKeyPairSpec.cpp +29 -0
  230. package/nitrogen/generated/shared/c++/HybridSlhDsaKeyPairSpec.hpp +72 -0
  231. package/nitrogen/generated/shared/c++/HybridTurboShakeSpec.cpp +22 -0
  232. package/nitrogen/generated/shared/c++/HybridTurboShakeSpec.hpp +70 -0
  233. package/nitrogen/generated/shared/c++/HybridUtilsSpec.cpp +0 -2
  234. package/nitrogen/generated/shared/c++/HybridUtilsSpec.hpp +0 -3
  235. package/nitrogen/generated/shared/c++/JWK.hpp +9 -1
  236. package/nitrogen/generated/shared/c++/JWKkty.hpp +4 -0
  237. package/nitrogen/generated/shared/c++/KangarooTwelveVariant.hpp +76 -0
  238. package/nitrogen/generated/shared/c++/TurboShakeVariant.hpp +76 -0
  239. package/package.json +38 -7
  240. package/src/argon2.ts +80 -2
  241. package/src/cipher.ts +139 -15
  242. package/src/dhKeyPair.ts +8 -0
  243. package/src/dsa.ts +19 -2
  244. package/src/ec.ts +52 -29
  245. package/src/ed.ts +95 -16
  246. package/src/hash.ts +125 -12
  247. package/src/hkdf.ts +44 -6
  248. package/src/hmac.ts +17 -7
  249. package/src/keys/classes.ts +46 -5
  250. package/src/keys/generateKeyPair.ts +151 -5
  251. package/src/keys/index.ts +73 -3
  252. package/src/keys/publicCipher.ts +10 -4
  253. package/src/keys/signVerify.ts +13 -2
  254. package/src/keys/utils.ts +78 -5
  255. package/src/random.ts +104 -11
  256. package/src/rsa.ts +26 -4
  257. package/src/scrypt.ts +73 -6
  258. package/src/slhdsa.ts +146 -0
  259. package/src/specs/keyObjectHandle.nitro.ts +17 -0
  260. package/src/specs/slhDsaKeyPair.nitro.ts +29 -0
  261. package/src/specs/turboshake.nitro.ts +21 -0
  262. package/src/specs/utils.nitro.ts +0 -2
  263. package/src/subtle.ts +1246 -333
  264. package/src/utils/cipher.ts +30 -8
  265. package/src/utils/conversion.ts +129 -40
  266. package/src/utils/errors.ts +72 -4
  267. package/src/utils/timingSafeEqual.ts +8 -3
  268. package/src/utils/types.ts +80 -15
  269. package/src/utils/validation.ts +70 -1
  270. package/src/x509certificate.ts +5 -6
  271. package/deps/blake3/.cargo/config.toml +0 -2
  272. package/deps/blake3/.git-blame-ignore-revs +0 -2
  273. package/deps/blake3/.github/workflows/build_b3sum.py +0 -38
  274. package/deps/blake3/.github/workflows/ci.yml +0 -491
  275. package/deps/blake3/.github/workflows/tag.yml +0 -43
  276. package/deps/blake3/.github/workflows/upload_github_release_asset.py +0 -73
  277. package/deps/blake3/CONTRIBUTING.md +0 -31
  278. package/deps/blake3/Cargo.toml +0 -135
  279. package/deps/blake3/b3sum/Cargo.lock +0 -513
  280. package/deps/blake3/b3sum/Cargo.toml +0 -26
  281. package/deps/blake3/b3sum/README.md +0 -72
  282. package/deps/blake3/b3sum/src/main.rs +0 -564
  283. package/deps/blake3/b3sum/src/unit_tests.rs +0 -235
  284. package/deps/blake3/b3sum/tests/cli_tests.rs +0 -680
  285. package/deps/blake3/b3sum/what_does_check_do.md +0 -176
  286. package/deps/blake3/benches/bench.rs +0 -623
  287. package/deps/blake3/build.rs +0 -389
  288. package/deps/blake3/c/CMakeLists.txt +0 -383
  289. package/deps/blake3/c/CMakePresets.json +0 -73
  290. package/deps/blake3/c/Makefile.testing +0 -82
  291. package/deps/blake3/c/blake3-config.cmake.in +0 -14
  292. package/deps/blake3/c/blake3_avx2.c +0 -326
  293. package/deps/blake3/c/blake3_avx2_x86-64_unix.S +0 -1815
  294. package/deps/blake3/c/blake3_avx2_x86-64_windows_gnu.S +0 -1817
  295. package/deps/blake3/c/blake3_avx2_x86-64_windows_msvc.asm +0 -1828
  296. package/deps/blake3/c/blake3_avx512.c +0 -1388
  297. package/deps/blake3/c/blake3_avx512_x86-64_unix.S +0 -4824
  298. package/deps/blake3/c/blake3_avx512_x86-64_windows_gnu.S +0 -2615
  299. package/deps/blake3/c/blake3_avx512_x86-64_windows_msvc.asm +0 -2634
  300. package/deps/blake3/c/blake3_c_rust_bindings/Cargo.toml +0 -32
  301. package/deps/blake3/c/blake3_c_rust_bindings/README.md +0 -4
  302. package/deps/blake3/c/blake3_c_rust_bindings/benches/bench.rs +0 -477
  303. package/deps/blake3/c/blake3_c_rust_bindings/build.rs +0 -253
  304. package/deps/blake3/c/blake3_c_rust_bindings/cross_test.sh +0 -31
  305. package/deps/blake3/c/blake3_c_rust_bindings/src/lib.rs +0 -333
  306. package/deps/blake3/c/blake3_c_rust_bindings/src/test.rs +0 -696
  307. package/deps/blake3/c/blake3_sse2.c +0 -566
  308. package/deps/blake3/c/blake3_sse2_x86-64_unix.S +0 -2291
  309. package/deps/blake3/c/blake3_sse2_x86-64_windows_gnu.S +0 -2332
  310. package/deps/blake3/c/blake3_sse2_x86-64_windows_msvc.asm +0 -2350
  311. package/deps/blake3/c/blake3_sse41.c +0 -560
  312. package/deps/blake3/c/blake3_sse41_x86-64_unix.S +0 -2028
  313. package/deps/blake3/c/blake3_sse41_x86-64_windows_gnu.S +0 -2069
  314. package/deps/blake3/c/blake3_sse41_x86-64_windows_msvc.asm +0 -2089
  315. package/deps/blake3/c/blake3_tbb.cpp +0 -37
  316. package/deps/blake3/c/dependencies/CMakeLists.txt +0 -3
  317. package/deps/blake3/c/dependencies/tbb/CMakeLists.txt +0 -28
  318. package/deps/blake3/c/example.c +0 -36
  319. package/deps/blake3/c/example_tbb.c +0 -57
  320. package/deps/blake3/c/libblake3.pc.in +0 -12
  321. package/deps/blake3/c/main.c +0 -166
  322. package/deps/blake3/c/test.py +0 -97
  323. package/deps/blake3/media/B3.svg +0 -70
  324. package/deps/blake3/media/BLAKE3.svg +0 -85
  325. package/deps/blake3/media/speed.svg +0 -1474
  326. package/deps/blake3/reference_impl/Cargo.toml +0 -8
  327. package/deps/blake3/reference_impl/README.md +0 -14
  328. package/deps/blake3/reference_impl/reference_impl.rs +0 -374
  329. package/deps/blake3/src/ffi_avx2.rs +0 -65
  330. package/deps/blake3/src/ffi_avx512.rs +0 -169
  331. package/deps/blake3/src/ffi_neon.rs +0 -82
  332. package/deps/blake3/src/ffi_sse2.rs +0 -126
  333. package/deps/blake3/src/ffi_sse41.rs +0 -126
  334. package/deps/blake3/src/guts.rs +0 -60
  335. package/deps/blake3/src/hazmat.rs +0 -704
  336. package/deps/blake3/src/io.rs +0 -64
  337. package/deps/blake3/src/join.rs +0 -92
  338. package/deps/blake3/src/lib.rs +0 -1835
  339. package/deps/blake3/src/platform.rs +0 -587
  340. package/deps/blake3/src/portable.rs +0 -198
  341. package/deps/blake3/src/rust_avx2.rs +0 -474
  342. package/deps/blake3/src/rust_sse2.rs +0 -775
  343. package/deps/blake3/src/rust_sse41.rs +0 -766
  344. package/deps/blake3/src/test.rs +0 -1049
  345. package/deps/blake3/src/traits.rs +0 -227
  346. package/deps/blake3/src/wasm32_simd.rs +0 -794
  347. package/deps/blake3/test_vectors/Cargo.toml +0 -19
  348. package/deps/blake3/test_vectors/cross_test.sh +0 -25
  349. package/deps/blake3/test_vectors/src/bin/generate.rs +0 -4
  350. package/deps/blake3/test_vectors/src/lib.rs +0 -350
  351. package/deps/blake3/test_vectors/test_vectors.json +0 -217
  352. package/deps/blake3/tools/compiler_version/Cargo.toml +0 -7
  353. package/deps/blake3/tools/compiler_version/build.rs +0 -6
  354. package/deps/blake3/tools/compiler_version/src/main.rs +0 -27
  355. package/deps/blake3/tools/instruction_set_support/Cargo.toml +0 -6
  356. package/deps/blake3/tools/instruction_set_support/src/main.rs +0 -10
  357. package/deps/blake3/tools/release.md +0 -16
  358. package/deps/ncrypto/.bazelignore +0 -4
  359. package/deps/ncrypto/.bazelrc +0 -1
  360. package/deps/ncrypto/.bazelversion +0 -1
  361. package/deps/ncrypto/.clang-format +0 -111
  362. package/deps/ncrypto/.github/workflows/bazel.yml +0 -58
  363. package/deps/ncrypto/.github/workflows/commitlint.yml +0 -16
  364. package/deps/ncrypto/.github/workflows/linter.yml +0 -38
  365. package/deps/ncrypto/.github/workflows/macos.yml +0 -43
  366. package/deps/ncrypto/.github/workflows/release-please.yml +0 -16
  367. package/deps/ncrypto/.github/workflows/ubuntu.yml +0 -128
  368. package/deps/ncrypto/.github/workflows/visual-studio.yml +0 -49
  369. package/deps/ncrypto/.python-version +0 -1
  370. package/deps/ncrypto/.release-please-manifest.json +0 -3
  371. package/deps/ncrypto/BUILD.bazel +0 -44
  372. package/deps/ncrypto/CHANGELOG.md +0 -37
  373. package/deps/ncrypto/CMakeLists.txt +0 -79
  374. package/deps/ncrypto/MODULE.bazel +0 -16
  375. package/deps/ncrypto/MODULE.bazel.lock +0 -461
  376. package/deps/ncrypto/cmake/CPM.cmake +0 -1225
  377. package/deps/ncrypto/cmake/ncrypto-flags.cmake +0 -17
  378. package/deps/ncrypto/ncrypto.pc.in +0 -10
  379. package/deps/ncrypto/patches/0001-Expose-libdecrepit-so-NodeJS-can-use-it-for-ncrypto.patch +0 -28
  380. package/deps/ncrypto/pyproject.toml +0 -38
  381. package/deps/ncrypto/release-please-config.json +0 -11
  382. package/deps/ncrypto/src/CMakeLists.txt +0 -40
  383. package/deps/ncrypto/tests/BUILD.bazel +0 -11
  384. package/deps/ncrypto/tests/CMakeLists.txt +0 -7
  385. package/deps/ncrypto/tests/basic.cpp +0 -856
  386. package/deps/ncrypto/tools/run-clang-format.sh +0 -42
  387. package/deps/simdutf/.clang-format +0 -4
  388. package/deps/simdutf/.github/ISSUE_TEMPLATE/bug_report.md +0 -62
  389. package/deps/simdutf/.github/ISSUE_TEMPLATE/config.yml +0 -1
  390. package/deps/simdutf/.github/ISSUE_TEMPLATE/feature_request.md +0 -35
  391. package/deps/simdutf/.github/ISSUE_TEMPLATE/standard-issue-template.md +0 -29
  392. package/deps/simdutf/.github/pull_request_template.md +0 -51
  393. package/deps/simdutf/.github/workflows/aarch64.yml +0 -39
  394. package/deps/simdutf/.github/workflows/alpine.yml +0 -27
  395. package/deps/simdutf/.github/workflows/amalgamation_demos.yml +0 -34
  396. package/deps/simdutf/.github/workflows/armv7.yml +0 -32
  397. package/deps/simdutf/.github/workflows/atomic_fuzz.yml +0 -25
  398. package/deps/simdutf/.github/workflows/cifuzz.yml +0 -37
  399. package/deps/simdutf/.github/workflows/clangformat.yml +0 -36
  400. package/deps/simdutf/.github/workflows/debian-latestcxxstandards.yml +0 -40
  401. package/deps/simdutf/.github/workflows/debian.yml +0 -33
  402. package/deps/simdutf/.github/workflows/documentation.yml +0 -36
  403. package/deps/simdutf/.github/workflows/emscripten.yml +0 -19
  404. package/deps/simdutf/.github/workflows/loongarch64-gcc-14.2.yml +0 -39
  405. package/deps/simdutf/.github/workflows/macos-latest.yml +0 -29
  406. package/deps/simdutf/.github/workflows/msys2-clang.yml +0 -48
  407. package/deps/simdutf/.github/workflows/msys2.yml +0 -50
  408. package/deps/simdutf/.github/workflows/ppc64le.yml +0 -29
  409. package/deps/simdutf/.github/workflows/rvv-1024-clang-18.yml +0 -35
  410. package/deps/simdutf/.github/workflows/rvv-128-clang-17.yml +0 -35
  411. package/deps/simdutf/.github/workflows/rvv-256-gcc-14.yml +0 -31
  412. package/deps/simdutf/.github/workflows/s390x.yml +0 -29
  413. package/deps/simdutf/.github/workflows/selective-amalgamation.yml +0 -29
  414. package/deps/simdutf/.github/workflows/typos.yml +0 -19
  415. package/deps/simdutf/.github/workflows/ubuntu22-cxx20.yml +0 -30
  416. package/deps/simdutf/.github/workflows/ubuntu22.yml +0 -32
  417. package/deps/simdutf/.github/workflows/ubuntu22_gcc12.yml +0 -27
  418. package/deps/simdutf/.github/workflows/ubuntu22sani.yml +0 -29
  419. package/deps/simdutf/.github/workflows/ubuntu24-cxxstandards.yml +0 -34
  420. package/deps/simdutf/.github/workflows/ubuntu24-unsignedchar.yml +0 -34
  421. package/deps/simdutf/.github/workflows/ubuntu24.yml +0 -32
  422. package/deps/simdutf/.github/workflows/ubuntu24sani.yml +0 -36
  423. package/deps/simdutf/.github/workflows/ubuntu24sani_clang.yml +0 -29
  424. package/deps/simdutf/.github/workflows/vs17-arm-ci.yml +0 -21
  425. package/deps/simdutf/.github/workflows/vs17-ci-cxx20.yml +0 -41
  426. package/deps/simdutf/.github/workflows/vs17-ci.yml +0 -41
  427. package/deps/simdutf/.github/workflows/vs17-clang-ci.yml +0 -41
  428. package/deps/simdutf/.github/workflows/vs17-cxxstandards.yml +0 -36
  429. package/deps/simdutf/AI_USAGE_POLICY.md +0 -56
  430. package/deps/simdutf/AUTHORS +0 -6
  431. package/deps/simdutf/CMakeLists.txt +0 -231
  432. package/deps/simdutf/CONTRIBUTING.md +0 -214
  433. package/deps/simdutf/CONTRIBUTORS +0 -1
  434. package/deps/simdutf/Doxyfile +0 -2584
  435. package/deps/simdutf/Makefile.crosscompile +0 -54
  436. package/deps/simdutf/README-RVV.md +0 -16
  437. package/deps/simdutf/SECURITY.md +0 -8
  438. package/deps/simdutf/benchmarks/CMakeLists.txt +0 -101
  439. package/deps/simdutf/benchmarks/alignment.cpp +0 -150
  440. package/deps/simdutf/benchmarks/base64/CMakeLists.txt +0 -30
  441. package/deps/simdutf/benchmarks/base64/benchmark_base64.cpp +0 -875
  442. package/deps/simdutf/benchmarks/base64/libbase64_spaces.h +0 -49
  443. package/deps/simdutf/benchmarks/base64/node_base64.h +0 -227
  444. package/deps/simdutf/benchmarks/base64/openssl3_base64.h +0 -334
  445. package/deps/simdutf/benchmarks/benchmark.cpp +0 -65
  446. package/deps/simdutf/benchmarks/benchmark_to_well_formed_utf16.cpp +0 -347
  447. package/deps/simdutf/benchmarks/competition/.clang-format-ignore +0 -5
  448. package/deps/simdutf/benchmarks/competition/CppCon2018/utf_utils.cpp +0 -1276
  449. package/deps/simdutf/benchmarks/competition/CppCon2018/utf_utils.h +0 -595
  450. package/deps/simdutf/benchmarks/competition/README.md +0 -7
  451. package/deps/simdutf/benchmarks/competition/hoehrmann/hoehrmann.h +0 -91
  452. package/deps/simdutf/benchmarks/competition/inoue2008/inoue_utf8_to_utf16.h +0 -444
  453. package/deps/simdutf/benchmarks/competition/inoue2008/inoue_utf8_to_utf16_tables.h +0 -13183
  454. package/deps/simdutf/benchmarks/competition/inoue2008/script.py +0 -73
  455. package/deps/simdutf/benchmarks/competition/llvm/ConvertUTF.cpp +0 -738
  456. package/deps/simdutf/benchmarks/competition/llvm/ConvertUTF.h +0 -293
  457. package/deps/simdutf/benchmarks/competition/u8u16/COPYRIGHT +0 -8
  458. package/deps/simdutf/benchmarks/competition/u8u16/Makefile +0 -44
  459. package/deps/simdutf/benchmarks/competition/u8u16/OSL3.0.txt +0 -169
  460. package/deps/simdutf/benchmarks/competition/u8u16/Profiling/BOM_Profiler.h +0 -148
  461. package/deps/simdutf/benchmarks/competition/u8u16/Profiling/i386_timer.h +0 -45
  462. package/deps/simdutf/benchmarks/competition/u8u16/Profiling/ppc_timer.c +0 -34
  463. package/deps/simdutf/benchmarks/competition/u8u16/README +0 -56
  464. package/deps/simdutf/benchmarks/competition/u8u16/config/config_defs.h +0 -43
  465. package/deps/simdutf/benchmarks/competition/u8u16/config/g4_config.h +0 -27
  466. package/deps/simdutf/benchmarks/competition/u8u16/config/mmx_config.h +0 -16
  467. package/deps/simdutf/benchmarks/competition/u8u16/config/p4_config.h +0 -18
  468. package/deps/simdutf/benchmarks/competition/u8u16/config/p4_ideal_config.h +0 -16
  469. package/deps/simdutf/benchmarks/competition/u8u16/config/spu_config.h +0 -28
  470. package/deps/simdutf/benchmarks/competition/u8u16/config/ssse3_config.h +0 -20
  471. package/deps/simdutf/benchmarks/competition/u8u16/iconv_u8u16.c +0 -2
  472. package/deps/simdutf/benchmarks/competition/u8u16/lib/altivec_simd.h +0 -440
  473. package/deps/simdutf/benchmarks/competition/u8u16/lib/libgen/make_basic_ops.py +0 -121
  474. package/deps/simdutf/benchmarks/competition/u8u16/lib/libgen/make_half_operand_versions.py +0 -158
  475. package/deps/simdutf/benchmarks/competition/u8u16/lib/libgen/make_test.py +0 -270
  476. package/deps/simdutf/benchmarks/competition/u8u16/lib/mmx_simd.h +0 -141
  477. package/deps/simdutf/benchmarks/competition/u8u16/lib/mmx_simd_basic.h +0 -216
  478. package/deps/simdutf/benchmarks/competition/u8u16/lib/mmx_simd_built_in.h +0 -119
  479. package/deps/simdutf/benchmarks/competition/u8u16/lib/mmx_simd_modified.h +0 -2430
  480. package/deps/simdutf/benchmarks/competition/u8u16/lib/outline.txt +0 -39
  481. package/deps/simdutf/benchmarks/competition/u8u16/lib/spu_simd.h +0 -421
  482. package/deps/simdutf/benchmarks/competition/u8u16/lib/sse_simd.h +0 -836
  483. package/deps/simdutf/benchmarks/competition/u8u16/lib/stdint.h +0 -222
  484. package/deps/simdutf/benchmarks/competition/u8u16/libu8u16_BE.c +0 -4
  485. package/deps/simdutf/benchmarks/competition/u8u16/libu8u16_LE.c +0 -5
  486. package/deps/simdutf/benchmarks/competition/u8u16/proto/u8u16.py +0 -390
  487. package/deps/simdutf/benchmarks/competition/u8u16/src/Makefile +0 -18
  488. package/deps/simdutf/benchmarks/competition/u8u16/src/bytelex.h +0 -448
  489. package/deps/simdutf/benchmarks/competition/u8u16/src/charsets/ASCII_EBCDIC.h +0 -284
  490. package/deps/simdutf/benchmarks/competition/u8u16/src/libu8u16.c +0 -1975
  491. package/deps/simdutf/benchmarks/competition/u8u16/src/libu8u16.pdf +0 -0
  492. package/deps/simdutf/benchmarks/competition/u8u16/src/libu8u16.w +0 -2263
  493. package/deps/simdutf/benchmarks/competition/u8u16/src/multiliteral.h +0 -239
  494. package/deps/simdutf/benchmarks/competition/u8u16/src/u8u16.c +0 -232
  495. package/deps/simdutf/benchmarks/competition/u8u16/src/x8x16.c +0 -194
  496. package/deps/simdutf/benchmarks/competition/u8u16/src/xml_error.c +0 -193
  497. package/deps/simdutf/benchmarks/competition/u8u16/src/xml_error.h +0 -167
  498. package/deps/simdutf/benchmarks/competition/u8u16/src/xmldecl.c +0 -288
  499. package/deps/simdutf/benchmarks/competition/u8u16/src/xmldecl.h +0 -117
  500. package/deps/simdutf/benchmarks/competition/u8u16/u8u16_g4.c +0 -2
  501. package/deps/simdutf/benchmarks/competition/u8u16/u8u16_mmx.c +0 -2
  502. package/deps/simdutf/benchmarks/competition/u8u16/u8u16_p4.c +0 -3
  503. package/deps/simdutf/benchmarks/competition/u8u16/u8u16_p4_ideal.c +0 -2
  504. package/deps/simdutf/benchmarks/competition/u8u16/u8u16_spu.c +0 -2
  505. package/deps/simdutf/benchmarks/competition/u8u16/u8u16_ssse3.c +0 -3
  506. package/deps/simdutf/benchmarks/competition/u8u16/x8x16_p4.c +0 -2
  507. package/deps/simdutf/benchmarks/competition/utf8lut/LICENSE +0 -23
  508. package/deps/simdutf/benchmarks/competition/utf8lut/data/test_minimal.txt +0 -44
  509. package/deps/simdutf/benchmarks/competition/utf8lut/readme.md +0 -106
  510. package/deps/simdutf/benchmarks/competition/utf8lut/scripts/build_clang_corr_tests.cmd +0 -11
  511. package/deps/simdutf/benchmarks/competition/utf8lut/scripts/build_clang_corr_tests.sh +0 -13
  512. package/deps/simdutf/benchmarks/competition/utf8lut/scripts/build_gcc_corr_tests.sh +0 -13
  513. package/deps/simdutf/benchmarks/competition/utf8lut/scripts/build_gcc_example.sh +0 -13
  514. package/deps/simdutf/benchmarks/competition/utf8lut/scripts/build_gcc_file_conv.sh +0 -14
  515. package/deps/simdutf/benchmarks/competition/utf8lut/scripts/build_gcc_iconv_lib.sh +0 -11
  516. package/deps/simdutf/benchmarks/competition/utf8lut/scripts/build_gcc_iconv_sample.sh +0 -8
  517. package/deps/simdutf/benchmarks/competition/utf8lut/scripts/build_mingw_corr_tests.cmd +0 -12
  518. package/deps/simdutf/benchmarks/competition/utf8lut/scripts/build_mingw_example.cmd +0 -13
  519. package/deps/simdutf/benchmarks/competition/utf8lut/scripts/build_mingw_file_conv.cmd +0 -14
  520. package/deps/simdutf/benchmarks/competition/utf8lut/scripts/build_mingw_iconv_lib.cmd +0 -11
  521. package/deps/simdutf/benchmarks/competition/utf8lut/scripts/build_mingw_iconv_sample.cmd +0 -8
  522. package/deps/simdutf/benchmarks/competition/utf8lut/scripts/build_msvc_corr_tests.cmd +0 -11
  523. package/deps/simdutf/benchmarks/competition/utf8lut/scripts/build_msvc_example.cmd +0 -12
  524. package/deps/simdutf/benchmarks/competition/utf8lut/scripts/build_msvc_file_conv.cmd +0 -13
  525. package/deps/simdutf/benchmarks/competition/utf8lut/scripts/build_msvc_iconv_lib.cmd +0 -10
  526. package/deps/simdutf/benchmarks/competition/utf8lut/scripts/build_msvc_iconv_sample.cmd +0 -9
  527. package/deps/simdutf/benchmarks/competition/utf8lut/scripts/html_table.py +0 -25
  528. package/deps/simdutf/benchmarks/competition/utf8lut/scripts/measure.py +0 -94
  529. package/deps/simdutf/benchmarks/competition/utf8lut/scripts/resize.py +0 -20
  530. package/deps/simdutf/benchmarks/competition/utf8lut/scripts/wipe_all.cmd +0 -2
  531. package/deps/simdutf/benchmarks/competition/utf8lut/scripts/wipe_interm.cmd +0 -1
  532. package/deps/simdutf/benchmarks/competition/utf8lut/src/base/CustomMemcpy.h +0 -75
  533. package/deps/simdutf/benchmarks/competition/utf8lut/src/base/PerfDefs.h +0 -47
  534. package/deps/simdutf/benchmarks/competition/utf8lut/src/base/Timing.cpp +0 -17
  535. package/deps/simdutf/benchmarks/competition/utf8lut/src/base/Timing.h +0 -76
  536. package/deps/simdutf/benchmarks/competition/utf8lut/src/buffer/AllProcessors.cpp +0 -35
  537. package/deps/simdutf/benchmarks/competition/utf8lut/src/buffer/BaseBufferProcessor.cpp +0 -117
  538. package/deps/simdutf/benchmarks/competition/utf8lut/src/buffer/BaseBufferProcessor.h +0 -210
  539. package/deps/simdutf/benchmarks/competition/utf8lut/src/buffer/BufferDecoder.h +0 -158
  540. package/deps/simdutf/benchmarks/competition/utf8lut/src/buffer/BufferEncoder.h +0 -104
  541. package/deps/simdutf/benchmarks/competition/utf8lut/src/buffer/ProcessorPlugins.h +0 -334
  542. package/deps/simdutf/benchmarks/competition/utf8lut/src/buffer/ProcessorSelector.h +0 -186
  543. package/deps/simdutf/benchmarks/competition/utf8lut/src/core/DecoderLut.cpp +0 -140
  544. package/deps/simdutf/benchmarks/competition/utf8lut/src/core/DecoderLut.h +0 -42
  545. package/deps/simdutf/benchmarks/competition/utf8lut/src/core/DecoderProcess.h +0 -100
  546. package/deps/simdutf/benchmarks/competition/utf8lut/src/core/Dfa.h +0 -57
  547. package/deps/simdutf/benchmarks/competition/utf8lut/src/core/EncoderLut.cpp +0 -85
  548. package/deps/simdutf/benchmarks/competition/utf8lut/src/core/EncoderLut.h +0 -27
  549. package/deps/simdutf/benchmarks/competition/utf8lut/src/core/EncoderProcess.h +0 -126
  550. package/deps/simdutf/benchmarks/competition/utf8lut/src/core/ProcessTrivial.h +0 -108
  551. package/deps/simdutf/benchmarks/competition/utf8lut/src/iconv/iconv.cpp +0 -139
  552. package/deps/simdutf/benchmarks/competition/utf8lut/src/iconv/iconv.h +0 -74
  553. package/deps/simdutf/benchmarks/competition/utf8lut/src/message/MessageConverter.cpp +0 -65
  554. package/deps/simdutf/benchmarks/competition/utf8lut/src/message/MessageConverter.h +0 -91
  555. package/deps/simdutf/benchmarks/competition/utf8lut/src/tests/CorrectnessTests.cpp +0 -772
  556. package/deps/simdutf/benchmarks/competition/utf8lut/src/tests/Example.cpp +0 -12
  557. package/deps/simdutf/benchmarks/competition/utf8lut/src/tests/FileConverter.cpp +0 -486
  558. package/deps/simdutf/benchmarks/competition/utf8lut/src/tests/iconv_sample.c +0 -162
  559. package/deps/simdutf/benchmarks/competition/utf8lut/src/utf8lut.h +0 -15
  560. package/deps/simdutf/benchmarks/competition/utf8sse4/fromutf8-sse.cpp +0 -292
  561. package/deps/simdutf/benchmarks/competition/utfcpp/LICENSE +0 -23
  562. package/deps/simdutf/benchmarks/competition/utfcpp/README.md +0 -1503
  563. package/deps/simdutf/benchmarks/competition/utfcpp/source/utf8/checked.h +0 -335
  564. package/deps/simdutf/benchmarks/competition/utfcpp/source/utf8/core.h +0 -338
  565. package/deps/simdutf/benchmarks/competition/utfcpp/source/utf8/cpp11.h +0 -103
  566. package/deps/simdutf/benchmarks/competition/utfcpp/source/utf8/cpp17.h +0 -103
  567. package/deps/simdutf/benchmarks/competition/utfcpp/source/utf8/unchecked.h +0 -274
  568. package/deps/simdutf/benchmarks/competition/utfcpp/source/utf8.h +0 -34
  569. package/deps/simdutf/benchmarks/dataset/README.md +0 -155
  570. package/deps/simdutf/benchmarks/dataset/emoji.txt +0 -204
  571. package/deps/simdutf/benchmarks/dataset/scripts/utf8type.py +0 -40
  572. package/deps/simdutf/benchmarks/dataset/wikipedia_mars/Makefile +0 -80
  573. package/deps/simdutf/benchmarks/dataset/wikipedia_mars/convert_to_utf6.py +0 -20
  574. package/deps/simdutf/benchmarks/find/CMakeLists.txt +0 -6
  575. package/deps/simdutf/benchmarks/find/findbenchmark.cpp +0 -63
  576. package/deps/simdutf/benchmarks/find/findbenchmarker.h +0 -46
  577. package/deps/simdutf/benchmarks/shortbench.cpp +0 -555
  578. package/deps/simdutf/benchmarks/src/CMakeLists.txt +0 -52
  579. package/deps/simdutf/benchmarks/src/apple_arm_events.h +0 -1104
  580. package/deps/simdutf/benchmarks/src/benchmark.cpp +0 -3899
  581. package/deps/simdutf/benchmarks/src/benchmark.h +0 -317
  582. package/deps/simdutf/benchmarks/src/benchmark_base.cpp +0 -144
  583. package/deps/simdutf/benchmarks/src/benchmark_base.h +0 -98
  584. package/deps/simdutf/benchmarks/src/cmdline.cpp +0 -176
  585. package/deps/simdutf/benchmarks/src/cmdline.h +0 -35
  586. package/deps/simdutf/benchmarks/src/event_counter.h +0 -162
  587. package/deps/simdutf/benchmarks/src/linux-perf-events.h +0 -104
  588. package/deps/simdutf/benchmarks/stream.cpp +0 -209
  589. package/deps/simdutf/benchmarks/threaded.cpp +0 -123
  590. package/deps/simdutf/cmake/CPM.cmake +0 -1363
  591. package/deps/simdutf/cmake/JoinPaths.cmake +0 -23
  592. package/deps/simdutf/cmake/add_cpp_test.cmake +0 -68
  593. package/deps/simdutf/cmake/simdutf-config.cmake.in +0 -2
  594. package/deps/simdutf/cmake/simdutf-flags.cmake +0 -26
  595. package/deps/simdutf/cmake/toolchains-ci/riscv64-linux-gnu.cmake +0 -4
  596. package/deps/simdutf/cmake/toolchains-dev/README.md +0 -32
  597. package/deps/simdutf/cmake/toolchains-dev/aarch64.cmake +0 -14
  598. package/deps/simdutf/cmake/toolchains-dev/loongarch64.cmake +0 -22
  599. package/deps/simdutf/cmake/toolchains-dev/powerpc64.cmake +0 -16
  600. package/deps/simdutf/cmake/toolchains-dev/powerpc64le.cmake +0 -16
  601. package/deps/simdutf/cmake/toolchains-dev/riscv64.cmake +0 -16
  602. package/deps/simdutf/cmake/toolchains-dev/rvv-spike.cmake +0 -38
  603. package/deps/simdutf/doc/avx512.png +0 -0
  604. package/deps/simdutf/doc/logo.png +0 -0
  605. package/deps/simdutf/doc/logo.svg +0 -165
  606. package/deps/simdutf/doc/node2023.png +0 -0
  607. package/deps/simdutf/doc/shortinput.md +0 -78
  608. package/deps/simdutf/doc/utf16utf8.png +0 -0
  609. package/deps/simdutf/doc/utf8utf16.png +0 -0
  610. package/deps/simdutf/doc/widelogo.png +0 -0
  611. package/deps/simdutf/doxygen.py +0 -50
  612. package/deps/simdutf/fuzz/.clang-format +0 -9
  613. package/deps/simdutf/fuzz/CMakeLists.txt +0 -45
  614. package/deps/simdutf/fuzz/README.md +0 -168
  615. package/deps/simdutf/fuzz/atomic_base64.cpp +0 -448
  616. package/deps/simdutf/fuzz/base64.cpp +0 -278
  617. package/deps/simdutf/fuzz/build.sh +0 -83
  618. package/deps/simdutf/fuzz/conversion.cpp +0 -669
  619. package/deps/simdutf/fuzz/helpers/.clang-format-ignore +0 -1
  620. package/deps/simdutf/fuzz/helpers/common.h +0 -135
  621. package/deps/simdutf/fuzz/helpers/nameof.hpp +0 -1258
  622. package/deps/simdutf/fuzz/main.cpp +0 -72
  623. package/deps/simdutf/fuzz/minimize_and_cleanse.sh +0 -87
  624. package/deps/simdutf/fuzz/misc.cpp +0 -216
  625. package/deps/simdutf/fuzz/random_fuzz.sh +0 -154
  626. package/deps/simdutf/fuzz/roundtrip.cpp +0 -588
  627. package/deps/simdutf/fuzz/safe_conversion.cpp +0 -104
  628. package/deps/simdutf/riscv/Dockerfile +0 -16
  629. package/deps/simdutf/riscv/README.md +0 -24
  630. package/deps/simdutf/riscv/remove-docker-station +0 -8
  631. package/deps/simdutf/riscv/run-docker-station +0 -31
  632. package/deps/simdutf/scripts/.flake8 +0 -2
  633. package/deps/simdutf/scripts/Makefile +0 -2
  634. package/deps/simdutf/scripts/README_ADD_FUNCTION.md +0 -49
  635. package/deps/simdutf/scripts/add_function.py +0 -330
  636. package/deps/simdutf/scripts/amalgamation_tests.py +0 -156
  637. package/deps/simdutf/scripts/base64/Makefile +0 -2
  638. package/deps/simdutf/scripts/base64/README.md +0 -2
  639. package/deps/simdutf/scripts/base64/avx512.py +0 -76
  640. package/deps/simdutf/scripts/base64/neon_decode.py +0 -143
  641. package/deps/simdutf/scripts/base64/neon_generate_lut.py +0 -101
  642. package/deps/simdutf/scripts/base64/sse.py +0 -252
  643. package/deps/simdutf/scripts/base64/sseregular.py +0 -160
  644. package/deps/simdutf/scripts/base64/sseurl.py +0 -283
  645. package/deps/simdutf/scripts/base64/table.py +0 -59
  646. package/deps/simdutf/scripts/base64bench_print.py +0 -145
  647. package/deps/simdutf/scripts/benchmark-all.py +0 -119
  648. package/deps/simdutf/scripts/benchmark_print.py +0 -324
  649. package/deps/simdutf/scripts/check_feature_macros.py +0 -156
  650. package/deps/simdutf/scripts/check_typos.sh +0 -13
  651. package/deps/simdutf/scripts/clang_format.sh +0 -35
  652. package/deps/simdutf/scripts/clang_format_docker.sh +0 -38
  653. package/deps/simdutf/scripts/common.py +0 -24
  654. package/deps/simdutf/scripts/compilation_benchmark.py +0 -55
  655. package/deps/simdutf/scripts/compile_many_variations.sh +0 -64
  656. package/deps/simdutf/scripts/create_latex_table.py +0 -62
  657. package/deps/simdutf/scripts/docker/Dockerfile +0 -14
  658. package/deps/simdutf/scripts/docker/Makefile +0 -9
  659. package/deps/simdutf/scripts/docker/README.md +0 -30
  660. package/deps/simdutf/scripts/docker/llvm.gpg +0 -0
  661. package/deps/simdutf/scripts/ppc64_convert_utf16_to_utf8.py +0 -155
  662. package/deps/simdutf/scripts/prepare_doxygen.sh +0 -21
  663. package/deps/simdutf/scripts/release.py +0 -197
  664. package/deps/simdutf/scripts/shortinputplots.py +0 -97
  665. package/deps/simdutf/scripts/sse_convert_utf16_to_utf8.py +0 -422
  666. package/deps/simdutf/scripts/sse_convert_utf32_to_utf16.py +0 -105
  667. package/deps/simdutf/scripts/sse_utf8_utf16_decode.py +0 -186
  668. package/deps/simdutf/scripts/sse_validate_utf16le_proof.py +0 -137
  669. package/deps/simdutf/scripts/sse_validate_utf16le_testcases.py +0 -129
  670. package/deps/simdutf/scripts/table.py +0 -207
  671. package/deps/simdutf/scripts/tests/new.txt +0 -33
  672. package/deps/simdutf/scripts/tests/old.txt +0 -33
  673. package/deps/simdutf/scripts/tests/results.txt +0 -272
  674. package/deps/simdutf/simdutf.pc.in +0 -11
  675. package/deps/simdutf/singleheader/.flake8 +0 -2
  676. package/deps/simdutf/singleheader/CMakeLists.txt +0 -64
  677. package/deps/simdutf/singleheader/README-dev.md +0 -81
  678. package/deps/simdutf/singleheader/README.md +0 -19
  679. package/deps/simdutf/singleheader/amalgamate.py +0 -513
  680. package/deps/simdutf/singleheader/amalgamation_demo.c +0 -59
  681. package/deps/simdutf/singleheader/amalgamation_demo.cpp +0 -54
  682. package/deps/simdutf/singleheader/test-features.py +0 -262
  683. package/deps/simdutf/src/CMakeLists.txt +0 -78
  684. package/deps/simdutf/tests/CMakeLists.txt +0 -483
  685. package/deps/simdutf/tests/atomic_base64_tests.cpp +0 -2845
  686. package/deps/simdutf/tests/base64_tests.cpp +0 -3617
  687. package/deps/simdutf/tests/basic_fuzzer.cpp +0 -805
  688. package/deps/simdutf/tests/bele_tests.cpp +0 -182
  689. package/deps/simdutf/tests/constexpr_base64_tests.cpp +0 -387
  690. package/deps/simdutf/tests/convert_latin1_to_utf16be_tests.cpp +0 -52
  691. package/deps/simdutf/tests/convert_latin1_to_utf16le_tests.cpp +0 -80
  692. package/deps/simdutf/tests/convert_latin1_to_utf32_tests.cpp +0 -66
  693. package/deps/simdutf/tests/convert_latin1_to_utf8_tests.cpp +0 -120
  694. package/deps/simdutf/tests/convert_utf16_to_utf8_safe_tests.cpp +0 -203
  695. package/deps/simdutf/tests/convert_utf16_to_utf8_with_replacement_tests.cpp +0 -276
  696. package/deps/simdutf/tests/convert_utf16be_to_latin1_tests.cpp +0 -109
  697. package/deps/simdutf/tests/convert_utf16be_to_latin1_tests_with_errors.cpp +0 -136
  698. package/deps/simdutf/tests/convert_utf16be_to_utf32_tests.cpp +0 -193
  699. package/deps/simdutf/tests/convert_utf16be_to_utf32_with_errors_tests.cpp +0 -381
  700. package/deps/simdutf/tests/convert_utf16be_to_utf8_tests.cpp +0 -259
  701. package/deps/simdutf/tests/convert_utf16be_to_utf8_with_errors_tests.cpp +0 -266
  702. package/deps/simdutf/tests/convert_utf16le_to_latin1_tests.cpp +0 -148
  703. package/deps/simdutf/tests/convert_utf16le_to_latin1_tests_with_errors.cpp +0 -176
  704. package/deps/simdutf/tests/convert_utf16le_to_utf32_tests.cpp +0 -213
  705. package/deps/simdutf/tests/convert_utf16le_to_utf32_with_errors_tests.cpp +0 -318
  706. package/deps/simdutf/tests/convert_utf16le_to_utf8_tests.cpp +0 -343
  707. package/deps/simdutf/tests/convert_utf16le_to_utf8_with_errors_tests.cpp +0 -271
  708. package/deps/simdutf/tests/convert_utf32_to_latin1_tests.cpp +0 -111
  709. package/deps/simdutf/tests/convert_utf32_to_latin1_with_errors_tests.cpp +0 -96
  710. package/deps/simdutf/tests/convert_utf32_to_utf16be_tests.cpp +0 -148
  711. package/deps/simdutf/tests/convert_utf32_to_utf16be_with_errors_tests.cpp +0 -192
  712. package/deps/simdutf/tests/convert_utf32_to_utf16le_tests.cpp +0 -166
  713. package/deps/simdutf/tests/convert_utf32_to_utf16le_with_errors_tests.cpp +0 -215
  714. package/deps/simdutf/tests/convert_utf32_to_utf8_tests.cpp +0 -181
  715. package/deps/simdutf/tests/convert_utf32_to_utf8_with_errors_tests.cpp +0 -261
  716. package/deps/simdutf/tests/convert_utf8_to_latin1_tests.cpp +0 -516
  717. package/deps/simdutf/tests/convert_utf8_to_latin1_with_errors_tests.cpp +0 -579
  718. package/deps/simdutf/tests/convert_utf8_to_utf16be_tests.cpp +0 -412
  719. package/deps/simdutf/tests/convert_utf8_to_utf16be_with_errors_tests.cpp +0 -480
  720. package/deps/simdutf/tests/convert_utf8_to_utf16le_tests.cpp +0 -671
  721. package/deps/simdutf/tests/convert_utf8_to_utf16le_with_errors_tests.cpp +0 -455
  722. package/deps/simdutf/tests/convert_utf8_to_utf32_tests.cpp +0 -1204
  723. package/deps/simdutf/tests/convert_utf8_to_utf32_with_errors_tests.cpp +0 -337
  724. package/deps/simdutf/tests/convert_valid_utf16be_to_latin1_tests.cpp +0 -37
  725. package/deps/simdutf/tests/convert_valid_utf16be_to_utf32_tests.cpp +0 -97
  726. package/deps/simdutf/tests/convert_valid_utf16be_to_utf8_tests.cpp +0 -126
  727. package/deps/simdutf/tests/convert_valid_utf16le_to_latin1_tests.cpp +0 -71
  728. package/deps/simdutf/tests/convert_valid_utf16le_to_utf32_tests.cpp +0 -122
  729. package/deps/simdutf/tests/convert_valid_utf16le_to_utf8_tests.cpp +0 -244
  730. package/deps/simdutf/tests/convert_valid_utf32_to_latin1_tests.cpp +0 -49
  731. package/deps/simdutf/tests/convert_valid_utf32_to_utf16be_tests.cpp +0 -92
  732. package/deps/simdutf/tests/convert_valid_utf32_to_utf16le_tests.cpp +0 -114
  733. package/deps/simdutf/tests/convert_valid_utf32_to_utf8_tests.cpp +0 -109
  734. package/deps/simdutf/tests/convert_valid_utf8_to_latin1_tests.cpp +0 -84
  735. package/deps/simdutf/tests/convert_valid_utf8_to_utf16be_tests.cpp +0 -124
  736. package/deps/simdutf/tests/convert_valid_utf8_to_utf16le_tests.cpp +0 -221
  737. package/deps/simdutf/tests/convert_valid_utf8_to_utf32_tests.cpp +0 -155
  738. package/deps/simdutf/tests/count_utf16be.cpp +0 -64
  739. package/deps/simdutf/tests/count_utf16le.cpp +0 -61
  740. package/deps/simdutf/tests/count_utf8.cpp +0 -87
  741. package/deps/simdutf/tests/detect_encodings_tests.cpp +0 -312
  742. package/deps/simdutf/tests/embed/valid_utf8.txt +0 -1
  743. package/deps/simdutf/tests/embed_tests.cpp +0 -22
  744. package/deps/simdutf/tests/find_tests.cpp +0 -77
  745. package/deps/simdutf/tests/fixed_string_tests.cpp +0 -153
  746. package/deps/simdutf/tests/helpers/CMakeLists.txt +0 -25
  747. package/deps/simdutf/tests/helpers/compiletime_conversions.h +0 -222
  748. package/deps/simdutf/tests/helpers/fixed_string.h +0 -267
  749. package/deps/simdutf/tests/helpers/random_int.cpp +0 -30
  750. package/deps/simdutf/tests/helpers/random_int.h +0 -39
  751. package/deps/simdutf/tests/helpers/random_utf16.cpp +0 -123
  752. package/deps/simdutf/tests/helpers/random_utf16.h +0 -52
  753. package/deps/simdutf/tests/helpers/random_utf32.cpp +0 -41
  754. package/deps/simdutf/tests/helpers/random_utf32.h +0 -40
  755. package/deps/simdutf/tests/helpers/random_utf8.cpp +0 -93
  756. package/deps/simdutf/tests/helpers/random_utf8.h +0 -36
  757. package/deps/simdutf/tests/helpers/test.cpp +0 -231
  758. package/deps/simdutf/tests/helpers/test.h +0 -193
  759. package/deps/simdutf/tests/helpers/transcode_test_base.cpp +0 -1257
  760. package/deps/simdutf/tests/helpers/transcode_test_base.h +0 -683
  761. package/deps/simdutf/tests/helpers/utf16.h +0 -27
  762. package/deps/simdutf/tests/installation_tests/find/CMakeLists.txt +0 -43
  763. package/deps/simdutf/tests/installation_tests/from_fetch/CMakeLists.txt +0 -47
  764. package/deps/simdutf/tests/internal_tests.cpp +0 -27
  765. package/deps/simdutf/tests/null_safety_tests.cpp +0 -94
  766. package/deps/simdutf/tests/random_fuzzer.cpp +0 -779
  767. package/deps/simdutf/tests/readme_tests.cpp +0 -274
  768. package/deps/simdutf/tests/reference/CMakeLists.txt +0 -23
  769. package/deps/simdutf/tests/reference/decode_utf16.h +0 -81
  770. package/deps/simdutf/tests/reference/decode_utf32.h +0 -47
  771. package/deps/simdutf/tests/reference/encode_latin1.cpp +0 -1
  772. package/deps/simdutf/tests/reference/encode_latin1.h +0 -32
  773. package/deps/simdutf/tests/reference/encode_utf16.cpp +0 -49
  774. package/deps/simdutf/tests/reference/encode_utf16.h +0 -20
  775. package/deps/simdutf/tests/reference/encode_utf32.cpp +0 -1
  776. package/deps/simdutf/tests/reference/encode_utf32.h +0 -36
  777. package/deps/simdutf/tests/reference/encode_utf8.cpp +0 -1
  778. package/deps/simdutf/tests/reference/encode_utf8.h +0 -40
  779. package/deps/simdutf/tests/reference/validate_utf16.cpp +0 -60
  780. package/deps/simdutf/tests/reference/validate_utf16.h +0 -14
  781. package/deps/simdutf/tests/reference/validate_utf16_to_latin1.cpp +0 -35
  782. package/deps/simdutf/tests/reference/validate_utf16_to_latin1.h +0 -13
  783. package/deps/simdutf/tests/reference/validate_utf32.cpp +0 -27
  784. package/deps/simdutf/tests/reference/validate_utf32.h +0 -12
  785. package/deps/simdutf/tests/reference/validate_utf32_to_latin1.cpp +0 -27
  786. package/deps/simdutf/tests/reference/validate_utf32_to_latin1.h +0 -12
  787. package/deps/simdutf/tests/reference/validate_utf8.cpp +0 -82
  788. package/deps/simdutf/tests/reference/validate_utf8.h +0 -11
  789. package/deps/simdutf/tests/reference/validate_utf8_to_latin1.cpp +0 -43
  790. package/deps/simdutf/tests/reference/validate_utf8_to_latin1.h +0 -12
  791. package/deps/simdutf/tests/select_implementation.cpp +0 -43
  792. package/deps/simdutf/tests/simdutf_c_tests.cpp +0 -244
  793. package/deps/simdutf/tests/span_tests.cpp +0 -401
  794. package/deps/simdutf/tests/special_tests.cpp +0 -559
  795. package/deps/simdutf/tests/straight_c_test.c +0 -187
  796. package/deps/simdutf/tests/text_encoding_tests.cpp +0 -77
  797. package/deps/simdutf/tests/to_well_formed_utf16_tests.cpp +0 -377
  798. package/deps/simdutf/tests/utf8_length_from_utf16_tests.cpp +0 -202
  799. package/deps/simdutf/tests/validate_ascii_basic_tests.cpp +0 -165
  800. package/deps/simdutf/tests/validate_ascii_with_errors_tests.cpp +0 -77
  801. package/deps/simdutf/tests/validate_utf16be_basic_tests.cpp +0 -175
  802. package/deps/simdutf/tests/validate_utf16be_with_errors_tests.cpp +0 -188
  803. package/deps/simdutf/tests/validate_utf16le_basic_tests.cpp +0 -268
  804. package/deps/simdutf/tests/validate_utf16le_with_errors_tests.cpp +0 -274
  805. package/deps/simdutf/tests/validate_utf32_basic_tests.cpp +0 -92
  806. package/deps/simdutf/tests/validate_utf32_with_errors_tests.cpp +0 -114
  807. package/deps/simdutf/tests/validate_utf8_basic_tests.cpp +0 -178
  808. package/deps/simdutf/tests/validate_utf8_brute_force_tests.cpp +0 -88
  809. package/deps/simdutf/tests/validate_utf8_puzzler_tests.cpp +0 -33
  810. package/deps/simdutf/tests/validate_utf8_with_errors_tests.cpp +0 -228
  811. package/deps/simdutf/tools/CMakeLists.txt +0 -85
  812. package/deps/simdutf/tools/fastbase64.cpp +0 -250
  813. package/deps/simdutf/tools/sutf.cpp +0 -556
  814. package/deps/simdutf/tools/sutf.h +0 -40
  815. package/lib/tsconfig.tsbuildinfo +0 -1
package/src/subtle.ts CHANGED
@@ -18,7 +18,8 @@ import type {
18
18
  RsaOaepParams,
19
19
  ChaCha20Poly1305Params,
20
20
  } from './utils';
21
- import { KFormatType, KeyEncoding, KeyType } from './utils';
21
+ import { KFormatType, KeyEncoding, KeyType, kNamedCurveAliases } from './utils';
22
+ import { Buffer } from '@craftzdog/react-native-buffer';
22
23
  import {
23
24
  CryptoKey,
24
25
  KeyObject,
@@ -31,7 +32,10 @@ import { bufferLikeToArrayBuffer } from './utils/conversion';
31
32
  import { argon2Sync } from './argon2';
32
33
  import { lazyDOMException } from './utils/errors';
33
34
  import { normalizeHashName, HashContext } from './utils/hashnames';
34
- import { validateMaxBufferLength } from './utils/validation';
35
+ import {
36
+ validateJwkStructure,
37
+ validateMaxBufferLength,
38
+ } from './utils/validation';
35
39
  import { asyncDigest } from './hash';
36
40
  import { createSecretKey, createPublicKey } from './keys';
37
41
  import { NitroModules } from 'react-native-nitro-modules';
@@ -58,6 +62,11 @@ import {
58
62
  Ed,
59
63
  } from './ed';
60
64
  import { mldsa_generateKeyPairWebCrypto, type MlDsaVariant } from './mldsa';
65
+ import {
66
+ slhdsa_generateKeyPairWebCrypto,
67
+ SLH_DSA_VARIANTS,
68
+ type SlhDsaVariant,
69
+ } from './slhdsa';
61
70
  import {
62
71
  mlkem_generateKeyPairWebCrypto,
63
72
  type MlKemVariant,
@@ -83,12 +92,55 @@ function hasAnyNotIn(usages: KeyUsage[], allowed: KeyUsage[]): boolean {
83
92
  return usages.some(usage => !allowed.includes(usage));
84
93
  }
85
94
 
95
+ // Mirrors webidl.requiredArguments. Node throws TypeError when a SubtleCrypto
96
+ // method is called with fewer than the spec-required number of arguments
97
+ // (webcrypto.js:866 etc.); we relied on TypeScript types alone, which apps
98
+ // catching `instanceof TypeError` could not see at runtime.
99
+ function requireArgs(actual: number, required: number, method: string): void {
100
+ if (actual < required) {
101
+ throw new TypeError(
102
+ `Failed to execute '${method}' on 'SubtleCrypto': ${required} arguments required, but only ${actual} present.`,
103
+ );
104
+ }
105
+ }
106
+
107
+ // WebCrypto §18.4.4: algorithm name lookup is case-insensitive, but the
108
+ // canonical mixed-case form is preserved in the resulting `name` field
109
+ // (e.g. "aes-gcm" → "AES-GCM"). This map is built lazily on first call so
110
+ // the registry of canonical names below can stay declared after the
111
+ // function. Without this, callers who pass lowercase strings bypass the
112
+ // downstream `SUPPORTED_ALGORITHMS` set comparisons silently.
113
+ //
114
+ // The map's value type is `AnyAlgorithm` so callers can use the lookup
115
+ // result directly without re-asserting. The `as AnyAlgorithm` at insertion
116
+ // is the single contract boundary: every name in `SUPPORTED_ALGORITHMS` is
117
+ // already a member of `AnyAlgorithm` by construction.
118
+ let _canonicalAlgorithmNames: Map<string, AnyAlgorithm> | null = null;
119
+ function getCanonicalAlgorithmNames(): Map<string, AnyAlgorithm> {
120
+ if (_canonicalAlgorithmNames === null) {
121
+ const map = new Map<string, AnyAlgorithm>();
122
+ for (const set of Object.values(SUPPORTED_ALGORITHMS)) {
123
+ if (!set) continue;
124
+ for (const name of set) {
125
+ map.set(name.toLowerCase(), name as AnyAlgorithm);
126
+ }
127
+ }
128
+ _canonicalAlgorithmNames = map;
129
+ }
130
+ return _canonicalAlgorithmNames;
131
+ }
132
+
86
133
  function normalizeAlgorithm(
87
134
  algorithm: SubtleAlgorithm | AnyAlgorithm,
88
135
  _operation: Operation,
89
136
  ): SubtleAlgorithm {
137
+ const map = getCanonicalAlgorithmNames();
90
138
  if (typeof algorithm === 'string') {
91
- return { name: algorithm };
139
+ return { name: map.get(algorithm.toLowerCase()) ?? algorithm };
140
+ }
141
+ if (typeof algorithm.name === 'string') {
142
+ const canonical = map.get(algorithm.name.toLowerCase()) ?? algorithm.name;
143
+ return { ...algorithm, name: canonical };
92
144
  }
93
145
  return algorithm as SubtleAlgorithm;
94
146
  }
@@ -112,15 +164,70 @@ function getAlgorithmName(name: string, length: number): string {
112
164
  }
113
165
  }
114
166
 
115
- // Placeholder implementations for missing functions
167
+ // Mirrors Node's aliasKeyFormat (lib/internal/crypto/webcrypto.js): for
168
+ // algorithms whose import/export accepts both 'raw' and the disambiguated
169
+ // 'raw-secret' / 'raw-public', collapse the latter to 'raw'. Used per-algorithm
170
+ // — algorithms that demand the disambiguated form (KMAC, AES-OCB,
171
+ // ChaCha20-Poly1305, Argon2*, ML-DSA, ML-KEM) MUST NOT alias.
172
+ function aliasKeyFormat(format: ImportFormat): ImportFormat {
173
+ if (format === 'raw-secret' || format === 'raw-public') return 'raw';
174
+ return format;
175
+ }
176
+
177
+ const kUncompressedSpkiLength: Record<string, number> = {
178
+ 'P-256': 91,
179
+ 'P-384': 120,
180
+ 'P-521': 158,
181
+ };
182
+
116
183
  function ecExportKey(key: CryptoKey, format: KWebCryptoKeyFormat): ArrayBuffer {
117
184
  const keyObject = key.keyObject;
118
185
 
119
186
  if (format === KWebCryptoKeyFormat.kWebCryptoKeyFormatRaw) {
120
187
  return bufferLikeToArrayBuffer(keyObject.handle.exportKey());
121
188
  } else if (format === KWebCryptoKeyFormat.kWebCryptoKeyFormatSPKI) {
122
- const exported = keyObject.export({ format: 'der', type: 'spki' });
123
- return bufferLikeToArrayBuffer(exported);
189
+ const exported = bufferLikeToArrayBuffer(
190
+ keyObject.export({ format: 'der', type: 'spki' }),
191
+ );
192
+
193
+ // WebCrypto requires uncompressed point format for SPKI exports.
194
+ // If the key was imported in compressed form, re-export as uncompressed
195
+ // by reconstructing the point from the JWK x,y coordinates and
196
+ // round-tripping through initECRaw.
197
+ const namedCurve = key.algorithm.namedCurve;
198
+ const expected =
199
+ namedCurve === undefined
200
+ ? undefined
201
+ : kUncompressedSpkiLength[namedCurve];
202
+ if (expected !== undefined && exported.byteLength !== expected) {
203
+ const jwk = keyObject.handle.exportJwk({}, false);
204
+ if (!jwk.x || !jwk.y) {
205
+ throw lazyDOMException(
206
+ 'Failed to re-export EC public key as uncompressed SPKI',
207
+ 'OperationError',
208
+ );
209
+ }
210
+ const x = Buffer.from(jwk.x, 'base64url');
211
+ const y = Buffer.from(jwk.y, 'base64url');
212
+ const raw = new Uint8Array(1 + x.length + y.length);
213
+ raw[0] = 0x04;
214
+ raw.set(x, 1);
215
+ raw.set(y, 1 + x.length);
216
+ const tmp =
217
+ NitroModules.createHybridObject<KeyObjectHandle>('KeyObjectHandle');
218
+ const curveAlias =
219
+ kNamedCurveAliases[namedCurve as keyof typeof kNamedCurveAliases];
220
+ if (!tmp.initECRaw(curveAlias, raw.buffer as ArrayBuffer)) {
221
+ throw lazyDOMException(
222
+ 'Failed to re-export EC public key as uncompressed SPKI',
223
+ 'OperationError',
224
+ );
225
+ }
226
+ return bufferLikeToArrayBuffer(
227
+ tmp.exportKey(KFormatType.DER, KeyEncoding.SPKI),
228
+ );
229
+ }
230
+ return exported;
124
231
  } else if (format === KWebCryptoKeyFormat.kWebCryptoKeyFormatPKCS8) {
125
232
  const exported = keyObject.export({ format: 'der', type: 'pkcs8' });
126
233
  return bufferLikeToArrayBuffer(exported);
@@ -749,13 +856,22 @@ function kmacSignVerify(
749
856
  ): ArrayBuffer | boolean {
750
857
  const { name } = algorithm;
751
858
 
752
- const defaultLength = name === 'KMAC128' ? 256 : 512;
753
- const outputLengthBits = algorithm.length ?? defaultLength;
859
+ // KmacParams.outputLength is required per
860
+ // https://wicg.github.io/webcrypto-modern-algos/#KmacParams-dictionary
861
+ // and the rename from `length` (commit ab8dc2b84c2). Mirror Node's
862
+ // mac.js:213-223 by reading `outputLength` (in bits).
863
+ if (typeof algorithm.outputLength !== 'number') {
864
+ throw lazyDOMException(
865
+ `${name}Params.outputLength is required`,
866
+ 'OperationError',
867
+ );
868
+ }
869
+ const outputLengthBits = algorithm.outputLength;
754
870
 
755
871
  if (outputLengthBits % 8 !== 0) {
756
872
  throw lazyDOMException(
757
- 'KMAC output length must be a multiple of 8',
758
- 'OperationError',
873
+ `Unsupported ${name}Params outputLength`,
874
+ 'NotSupportedError',
759
875
  );
760
876
  }
761
877
 
@@ -800,13 +916,6 @@ async function kmacImportKey(
800
916
  ): Promise<CryptoKey> {
801
917
  const { name } = algorithm;
802
918
 
803
- if (hasAnyNotIn(keyUsages, ['sign', 'verify'])) {
804
- throw lazyDOMException(
805
- `Unsupported key usage for ${name} key`,
806
- 'SyntaxError',
807
- );
808
- }
809
-
810
919
  let keyObject: KeyObject;
811
920
 
812
921
  if (format === 'jwk') {
@@ -815,29 +924,51 @@ async function kmacImportKey(
815
924
  if (!jwk || typeof jwk !== 'object') {
816
925
  throw lazyDOMException('Invalid keyData', 'DataError');
817
926
  }
818
-
819
927
  if (jwk.kty !== 'oct') {
820
- throw lazyDOMException('Invalid JWK format for KMAC key', 'DataError');
928
+ throw lazyDOMException('Invalid JWK "kty" Parameter', 'DataError');
821
929
  }
930
+ validateJwkStructure(jwk, extractable, keyUsages, 'sig');
822
931
 
823
932
  const expectedAlg = name === 'KMAC128' ? 'K128' : 'K256';
824
933
  if (jwk.alg !== undefined && jwk.alg !== expectedAlg) {
825
934
  throw lazyDOMException(
826
- 'JWK "alg" does not match the requested algorithm',
935
+ 'JWK "alg" Parameter and algorithm name mismatch',
827
936
  'DataError',
828
937
  );
829
938
  }
830
939
 
940
+ if (hasAnyNotIn(keyUsages, ['sign', 'verify'])) {
941
+ throw lazyDOMException(
942
+ `Unsupported key usage for ${name} key`,
943
+ 'SyntaxError',
944
+ );
945
+ }
946
+
831
947
  const handle =
832
948
  NitroModules.createHybridObject<KeyObjectHandle>('KeyObjectHandle');
833
- const keyType = handle.initJwk(jwk, undefined);
834
-
949
+ let keyType: KeyType | undefined;
950
+ try {
951
+ keyType = handle.initJwk(jwk, undefined);
952
+ } catch (err) {
953
+ throw lazyDOMException('Invalid keyData', {
954
+ name: 'DataError',
955
+ cause: err,
956
+ });
957
+ }
835
958
  if (keyType === undefined || keyType !== 0) {
836
- throw lazyDOMException('Failed to import KMAC JWK', 'DataError');
959
+ throw lazyDOMException('Invalid keyData', 'DataError');
837
960
  }
838
961
 
839
962
  keyObject = new SecretKeyObject(handle);
840
- } else if (format === 'raw' || format === 'raw-secret') {
963
+ } else if (format === 'raw-secret') {
964
+ // KMAC accepts only the disambiguated 'raw-secret' form (Node mac.js:141-145
965
+ // returns undefined for plain 'raw' when not HMAC).
966
+ if (hasAnyNotIn(keyUsages, ['sign', 'verify'])) {
967
+ throw lazyDOMException(
968
+ `Unsupported key usage for ${name} key`,
969
+ 'SyntaxError',
970
+ );
971
+ }
841
972
  keyObject = createSecretKey(data as BinaryLike);
842
973
  } else {
843
974
  throw lazyDOMException(
@@ -874,7 +1005,6 @@ function rsaImportKey(
874
1005
  ): CryptoKey {
875
1006
  const { name } = algorithm;
876
1007
 
877
- // Validate usages
878
1008
  let checkSet: KeyUsage[];
879
1009
  switch (name) {
880
1010
  case 'RSASSA-PKCS1-v1_5':
@@ -887,38 +1017,75 @@ function rsaImportKey(
887
1017
  default:
888
1018
  throw new Error(`Unsupported RSA algorithm: ${name}`);
889
1019
  }
890
-
891
- if (hasAnyNotIn(keyUsages, checkSet)) {
892
- throw new Error(`Unsupported key usage for ${name}`);
893
- }
1020
+ const checkUsages = (): void => {
1021
+ if (hasAnyNotIn(keyUsages, checkSet)) {
1022
+ throw lazyDOMException(
1023
+ `Unsupported key usage for ${name} key`,
1024
+ 'SyntaxError',
1025
+ );
1026
+ }
1027
+ };
894
1028
 
895
1029
  let keyObject: KeyObject;
896
1030
 
897
1031
  if (format === 'jwk') {
898
1032
  const jwk = data as JWK;
899
1033
 
900
- // Validate JWK
1034
+ if (!jwk || typeof jwk !== 'object') {
1035
+ throw lazyDOMException('Invalid keyData', 'DataError');
1036
+ }
901
1037
  if (jwk.kty !== 'RSA') {
902
- throw new Error('Invalid JWK format for RSA key');
1038
+ throw lazyDOMException('Invalid JWK "kty" Parameter', 'DataError');
1039
+ }
1040
+ const expectedUse = name === 'RSA-OAEP' ? 'enc' : 'sig';
1041
+ validateJwkStructure(jwk, extractable, keyUsages, expectedUse);
1042
+ checkUsages();
1043
+
1044
+ if (jwk.alg !== undefined) {
1045
+ let jwkContext: HashContext;
1046
+ switch (name) {
1047
+ case 'RSASSA-PKCS1-v1_5':
1048
+ jwkContext = HashContext.JwkRsa;
1049
+ break;
1050
+ case 'RSA-PSS':
1051
+ jwkContext = HashContext.JwkRsaPss;
1052
+ break;
1053
+ default:
1054
+ jwkContext = HashContext.JwkRsaOaep;
1055
+ }
1056
+ const expectedAlg = normalizeHashName(algorithm.hash, jwkContext);
1057
+ if (jwk.alg !== expectedAlg) {
1058
+ throw lazyDOMException(
1059
+ 'JWK "alg" does not match the requested algorithm',
1060
+ 'DataError',
1061
+ );
1062
+ }
903
1063
  }
904
1064
 
905
1065
  const handle =
906
1066
  NitroModules.createHybridObject<KeyObjectHandle>('KeyObjectHandle');
907
- const keyType = handle.initJwk(jwk, undefined);
908
-
1067
+ let keyType: KeyType | undefined;
1068
+ try {
1069
+ keyType = handle.initJwk(jwk, undefined);
1070
+ } catch (err) {
1071
+ throw lazyDOMException('Invalid keyData', {
1072
+ name: 'DataError',
1073
+ cause: err,
1074
+ });
1075
+ }
909
1076
  if (keyType === undefined) {
910
- throw new Error('Failed to import RSA JWK');
1077
+ throw lazyDOMException('Invalid keyData', 'DataError');
911
1078
  }
912
1079
 
913
- // Create the appropriate KeyObject based on type
914
- if (keyType === 1) {
1080
+ if (keyType === KeyType.PUBLIC) {
915
1081
  keyObject = new PublicKeyObject(handle);
916
- } else if (keyType === 2) {
1082
+ } else if (keyType === KeyType.PRIVATE) {
917
1083
  keyObject = new PrivateKeyObject(handle);
918
1084
  } else {
919
- throw new Error('Unexpected key type from RSA JWK import');
1085
+ throw lazyDOMException('Invalid keyData', 'DataError');
920
1086
  }
921
1087
  } else if (format === 'spki') {
1088
+ checkUsages();
922
1089
  const keyData = bufferLikeToArrayBuffer(data as BufferLike);
923
1090
  keyObject = KeyObject.createKeyObject(
924
1091
  'public',
@@ -927,6 +1094,7 @@ function rsaImportKey(
927
1094
  KeyEncoding.SPKI,
928
1095
  );
929
1096
  } else if (format === 'pkcs8') {
1097
+ checkUsages();
930
1098
  const keyData = bufferLikeToArrayBuffer(data as BufferLike);
931
1099
  keyObject = KeyObject.createKeyObject(
932
1100
  'private',
@@ -935,7 +1103,10 @@ function rsaImportKey(
935
1103
  KeyEncoding.PKCS8,
936
1104
  );
937
1105
  } else {
938
- throw new Error(`Unsupported format for RSA import: ${format}`);
1106
+ throw lazyDOMException(
1107
+ `Unsupported format for ${name} import: ${format}`,
1108
+ 'NotSupportedError',
1109
+ );
939
1110
  }
940
1111
 
941
1112
  // Get the modulus length from the key and add it to the algorithm
@@ -977,31 +1148,30 @@ async function hmacImportKey(
977
1148
  extractable: boolean,
978
1149
  keyUsages: KeyUsage[],
979
1150
  ): Promise<CryptoKey> {
980
- // Validate usages
981
- if (hasAnyNotIn(keyUsages, ['sign', 'verify'])) {
982
- throw new Error('Unsupported key usage for an HMAC key');
983
- }
1151
+ const checkUsages = (): void => {
1152
+ if (hasAnyNotIn(keyUsages, ['sign', 'verify'])) {
1153
+ throw new Error('Unsupported key usage for an HMAC key');
1154
+ }
1155
+ };
984
1156
 
985
1157
  let keyObject: KeyObject;
986
1158
 
987
1159
  if (format === 'jwk') {
988
1160
  const jwk = data as JWK;
989
1161
 
990
- // Validate JWK
991
1162
  if (!jwk || typeof jwk !== 'object') {
992
1163
  throw new Error('Invalid keyData');
993
1164
  }
994
-
995
1165
  if (jwk.kty !== 'oct') {
996
1166
  throw new Error('Invalid JWK format for HMAC key');
997
1167
  }
1168
+ validateJwkStructure(jwk, extractable, keyUsages, 'sig');
1169
+ checkUsages();
998
1170
 
999
- // Validate key length if specified
1000
1171
  if (algorithm.length !== undefined) {
1001
1172
  if (!jwk.k) {
1002
1173
  throw new Error('JWK missing key data');
1003
1174
  }
1004
- // Decode to check length
1005
1175
  const decoded = SBuffer.from(jwk.k, 'base64');
1006
1176
  const keyBitLength = decoded.length * 8;
1007
1177
  if (algorithm.length === 0) {
@@ -1014,17 +1184,29 @@ async function hmacImportKey(
1014
1184
 
1015
1185
  const handle =
1016
1186
  NitroModules.createHybridObject<KeyObjectHandle>('KeyObjectHandle');
1017
- const keyType = handle.initJwk(jwk, undefined);
1018
-
1187
+ let keyType: KeyType | undefined;
1188
+ try {
1189
+ keyType = handle.initJwk(jwk, undefined);
1190
+ } catch (err) {
1191
+ throw lazyDOMException('Invalid keyData', {
1192
+ name: 'DataError',
1193
+ cause: err,
1194
+ });
1195
+ }
1019
1196
  if (keyType === undefined || keyType !== 0) {
1020
- throw new Error('Failed to import HMAC JWK');
1197
+ throw lazyDOMException('Invalid keyData', 'DataError');
1021
1198
  }
1022
1199
 
1023
1200
  keyObject = new SecretKeyObject(handle);
1024
- } else if (format === 'raw') {
1201
+ } else if (format === 'raw' || format === 'raw-secret') {
1202
+ // HMAC accepts both 'raw' and 'raw-secret' (Node mac.js:141-145).
1203
+ checkUsages();
1025
1204
  keyObject = createSecretKey(data as BinaryLike);
1026
1205
  } else {
1027
- throw new Error(`Unable to import HMAC key with format ${format}`);
1206
+ throw lazyDOMException(
1207
+ `Unable to import HMAC key with format ${format}`,
1208
+ 'NotSupportedError',
1209
+ );
1028
1210
  }
1029
1211
 
1030
1212
  // Normalize hash to { name: string } format per WebCrypto spec
@@ -1047,16 +1229,24 @@ async function aesImportKey(
1047
1229
  ): Promise<CryptoKey> {
1048
1230
  const { name, length } = algorithm;
1049
1231
 
1050
- // Validate usages
1051
1232
  const validUsages: KeyUsage[] = [
1052
1233
  'encrypt',
1053
1234
  'decrypt',
1054
1235
  'wrapKey',
1055
1236
  'unwrapKey',
1056
1237
  ];
1057
- if (hasAnyNotIn(keyUsages, validUsages)) {
1058
- throw new Error(`Unsupported key usage for ${name}`);
1059
- }
1238
+ const checkUsages = (): void => {
1239
+ if (hasAnyNotIn(keyUsages, validUsages)) {
1240
+ throw new Error(`Unsupported key usage for ${name}`);
1241
+ }
1242
+ };
1243
+
1244
+ // AES-OCB and ChaCha20-Poly1305 require the disambiguated 'raw-secret' form
1245
+ // and reject 'raw' (Node aes.js:243-249, chacha20_poly1305.js:104-134).
1246
+ // Other AES variants accept both 'raw' and 'raw-secret'.
1247
+ const requiresRawSecret = name === 'AES-OCB' || name === 'ChaCha20-Poly1305';
1248
+ const acceptsRaw =
1249
+ format === 'raw-secret' || (format === 'raw' && !requiresRawSecret);
1060
1250
 
1061
1251
  let keyObject: KeyObject;
1062
1252
  let actualLength: number;
@@ -1064,36 +1254,53 @@ async function aesImportKey(
1064
1254
  if (format === 'jwk') {
1065
1255
  const jwk = data as JWK;
1066
1256
 
1067
- // Validate JWK
1068
1257
  if (jwk.kty !== 'oct') {
1069
1258
  throw new Error('Invalid JWK format for AES key');
1070
1259
  }
1260
+ validateJwkStructure(jwk, extractable, keyUsages, 'enc');
1261
+ checkUsages();
1071
1262
 
1072
1263
  const handle =
1073
1264
  NitroModules.createHybridObject<KeyObjectHandle>('KeyObjectHandle');
1074
- const keyType = handle.initJwk(jwk, undefined);
1075
-
1265
+ let keyType: KeyType | undefined;
1266
+ try {
1267
+ keyType = handle.initJwk(jwk, undefined);
1268
+ } catch (err) {
1269
+ throw lazyDOMException('Invalid keyData', {
1270
+ name: 'DataError',
1271
+ cause: err,
1272
+ });
1273
+ }
1076
1274
  if (keyType === undefined || keyType !== 0) {
1077
- throw new Error('Failed to import AES JWK');
1275
+ throw lazyDOMException('Invalid keyData', 'DataError');
1078
1276
  }
1079
1277
 
1080
1278
  keyObject = new SecretKeyObject(handle);
1081
1279
 
1082
- // Get actual key length from imported key
1083
1280
  const exported = keyObject.export();
1084
1281
  actualLength = exported.byteLength * 8;
1085
- } else if (format === 'raw') {
1282
+ } else if (acceptsRaw) {
1283
+ checkUsages();
1086
1284
  const keyData = bufferLikeToArrayBuffer(data as BufferLike);
1087
1285
  actualLength = keyData.byteLength * 8;
1088
1286
 
1089
- // Validate key length
1090
- if (![128, 192, 256].includes(actualLength)) {
1287
+ if (name === 'ChaCha20-Poly1305') {
1288
+ if (actualLength !== 256) {
1289
+ throw lazyDOMException(
1290
+ 'Invalid ChaCha20-Poly1305 key length',
1291
+ 'DataError',
1292
+ );
1293
+ }
1294
+ } else if (![128, 192, 256].includes(actualLength)) {
1091
1295
  throw new Error('Invalid AES key length');
1092
1296
  }
1093
1297
 
1094
1298
  keyObject = createSecretKey(keyData);
1095
1299
  } else {
1096
- throw new Error(`Unsupported format for AES import: ${format}`);
1300
+ throw lazyDOMException(
1301
+ `Unable to import ${name} key with format ${format}`,
1302
+ 'NotSupportedError',
1303
+ );
1097
1304
  }
1098
1305
 
1099
1306
  // Validate length if specified
@@ -1120,23 +1327,23 @@ function edImportKey(
1120
1327
  ): CryptoKey {
1121
1328
  const { name } = algorithm;
1122
1329
 
1123
- // Validate usages
1124
1330
  const isX = name === 'X25519' || name === 'X448';
1125
1331
  const allowedUsages: KeyUsage[] = isX
1126
1332
  ? ['deriveKey', 'deriveBits']
1127
1333
  : ['sign', 'verify'];
1128
-
1129
- if (hasAnyNotIn(keyUsages, allowedUsages)) {
1130
- throw lazyDOMException(
1131
- `Unsupported key usage for ${name} key`,
1132
- 'SyntaxError',
1133
- );
1134
- }
1334
+ const checkUsages = (): void => {
1335
+ if (hasAnyNotIn(keyUsages, allowedUsages)) {
1336
+ throw lazyDOMException(
1337
+ `Unsupported key usage for ${name} key`,
1338
+ 'SyntaxError',
1339
+ );
1340
+ }
1341
+ };
1135
1342
 
1136
1343
  let keyObject: KeyObject;
1137
1344
 
1138
1345
  if (format === 'spki') {
1139
- // Import public key
1346
+ checkUsages();
1140
1347
  const keyData = bufferLikeToArrayBuffer(data as BufferLike);
1141
1348
  keyObject = KeyObject.createKeyObject(
1142
1349
  'public',
@@ -1145,7 +1352,7 @@ function edImportKey(
1145
1352
  KeyEncoding.SPKI,
1146
1353
  );
1147
1354
  } else if (format === 'pkcs8') {
1148
- // Import private key
1355
+ checkUsages();
1149
1356
  const keyData = bufferLikeToArrayBuffer(data as BufferLike);
1150
1357
  keyObject = KeyObject.createKeyObject(
1151
1358
  'private',
@@ -1154,19 +1361,51 @@ function edImportKey(
1154
1361
  KeyEncoding.PKCS8,
1155
1362
  );
1156
1363
  } else if (format === 'raw') {
1157
- // Raw format - public key only for Ed keys
1364
+ checkUsages();
1158
1365
  const keyData = bufferLikeToArrayBuffer(data as BufferLike);
1159
1366
  const handle =
1160
1367
  NitroModules.createHybridObject<KeyObjectHandle>('KeyObjectHandle');
1161
- // For raw Ed keys, we need to create them differently
1162
- // Raw public keys are just the key bytes
1163
- handle.init(1, keyData); // 1 = public key type
1368
+ handle.init(1, keyData);
1164
1369
  keyObject = new PublicKeyObject(handle);
1165
1370
  } else if (format === 'jwk') {
1166
1371
  const jwkData = data as JWK;
1372
+ if (!jwkData || typeof jwkData !== 'object') {
1373
+ throw lazyDOMException('Invalid keyData', 'DataError');
1374
+ }
1375
+ if (jwkData.kty !== 'OKP') {
1376
+ throw lazyDOMException('Invalid JWK "kty" Parameter', 'DataError');
1377
+ }
1378
+ const expectedUse = isX ? 'enc' : 'sig';
1379
+ validateJwkStructure(jwkData, extractable, keyUsages, expectedUse);
1380
+
1381
+ if (jwkData.crv !== name) {
1382
+ throw lazyDOMException(
1383
+ 'JWK "crv" Parameter and algorithm name mismatch',
1384
+ 'DataError',
1385
+ );
1386
+ }
1387
+
1388
+ if (!isX && jwkData.alg !== undefined) {
1389
+ if (jwkData.alg !== name && jwkData.alg !== 'EdDSA') {
1390
+ throw lazyDOMException(
1391
+ 'JWK "alg" does not match the requested algorithm',
1392
+ 'DataError',
1393
+ );
1394
+ }
1395
+ }
1396
+
1397
+ checkUsages();
1167
1398
  const handle =
1168
1399
  NitroModules.createHybridObject<KeyObjectHandle>('KeyObjectHandle');
1169
- const keyType = handle.initJwk(jwkData);
1400
+ let keyType: KeyType | undefined;
1401
+ try {
1402
+ keyType = handle.initJwk(jwkData);
1403
+ } catch (err) {
1404
+ throw lazyDOMException('Invalid JWK data', {
1405
+ name: 'DataError',
1406
+ cause: err,
1407
+ });
1408
+ }
1170
1409
  if (keyType === undefined) {
1171
1410
  throw lazyDOMException('Invalid JWK data', 'DataError');
1172
1411
  }
@@ -1185,42 +1424,133 @@ function edImportKey(
1185
1424
  return new CryptoKey(keyObject, { name }, keyUsages, extractable);
1186
1425
  }
1187
1426
 
1427
+ // Lengths (in bytes) of seedless ML-DSA / ML-KEM PKCS#8 encodings. A PKCS#8
1428
+ // blob of exactly this length contains only the expanded private key with no
1429
+ // seed; Node rejects these to keep cross-implementation interop intact.
1430
+ // Refs: node lib/internal/crypto/ml_dsa.js (mlDsaImportKey, pkcs8 case)
1431
+ // node lib/internal/crypto/ml_kem.js (mlKemImportKey, pkcs8 case)
1432
+ export const PQC_SEEDLESS_PKCS8_LENGTHS: Readonly<Record<string, number>> = {
1433
+ 'ML-DSA-44': 2588,
1434
+ 'ML-DSA-65': 4060,
1435
+ 'ML-DSA-87': 4924,
1436
+ 'ML-KEM-512': 1660,
1437
+ 'ML-KEM-768': 2428,
1438
+ 'ML-KEM-1024': 3196,
1439
+ };
1440
+
1441
+ // Map from PQC algorithm name to display family. Used to render the
1442
+ // import-rejection error message in the same form Node emits.
1443
+ const PQC_FAMILY: Readonly<Record<string, 'ML-DSA' | 'ML-KEM' | 'SLH-DSA'>> = {
1444
+ 'ML-DSA-44': 'ML-DSA',
1445
+ 'ML-DSA-65': 'ML-DSA',
1446
+ 'ML-DSA-87': 'ML-DSA',
1447
+ 'ML-KEM-512': 'ML-KEM',
1448
+ 'ML-KEM-768': 'ML-KEM',
1449
+ 'ML-KEM-1024': 'ML-KEM',
1450
+ 'SLH-DSA-SHA2-128s': 'SLH-DSA',
1451
+ 'SLH-DSA-SHA2-128f': 'SLH-DSA',
1452
+ 'SLH-DSA-SHA2-192s': 'SLH-DSA',
1453
+ 'SLH-DSA-SHA2-192f': 'SLH-DSA',
1454
+ 'SLH-DSA-SHA2-256s': 'SLH-DSA',
1455
+ 'SLH-DSA-SHA2-256f': 'SLH-DSA',
1456
+ 'SLH-DSA-SHAKE-128s': 'SLH-DSA',
1457
+ 'SLH-DSA-SHAKE-128f': 'SLH-DSA',
1458
+ 'SLH-DSA-SHAKE-192s': 'SLH-DSA',
1459
+ 'SLH-DSA-SHAKE-192f': 'SLH-DSA',
1460
+ 'SLH-DSA-SHAKE-256s': 'SLH-DSA',
1461
+ 'SLH-DSA-SHAKE-256f': 'SLH-DSA',
1462
+ };
1463
+
1188
1464
  function pqcImportKeyObject(
1189
1465
  format: ImportFormat,
1190
- data: BufferLike,
1466
+ data: BufferLike | JWK,
1191
1467
  name: string,
1192
- ): KeyObject {
1468
+ ): { keyObject: KeyObject; isPublic: boolean } {
1193
1469
  if (format === 'spki') {
1194
- return KeyObject.createKeyObject(
1195
- 'public',
1196
- bufferLikeToArrayBuffer(data),
1197
- KFormatType.DER,
1198
- KeyEncoding.SPKI,
1199
- );
1470
+ return {
1471
+ keyObject: KeyObject.createKeyObject(
1472
+ 'public',
1473
+ bufferLikeToArrayBuffer(data as BufferLike),
1474
+ KFormatType.DER,
1475
+ KeyEncoding.SPKI,
1476
+ ),
1477
+ isPublic: true,
1478
+ };
1200
1479
  } else if (format === 'pkcs8') {
1201
- return KeyObject.createKeyObject(
1202
- 'private',
1203
- bufferLikeToArrayBuffer(data),
1204
- KFormatType.DER,
1205
- KeyEncoding.PKCS8,
1206
- );
1207
- } else if (format === 'raw') {
1480
+ const ab = bufferLikeToArrayBuffer(data as BufferLike);
1481
+ const family = PQC_FAMILY[name];
1482
+ if (
1483
+ family !== undefined &&
1484
+ ab.byteLength === PQC_SEEDLESS_PKCS8_LENGTHS[name]
1485
+ ) {
1486
+ throw lazyDOMException(
1487
+ `Importing an ${family} PKCS#8 key without a seed is not supported`,
1488
+ 'NotSupportedError',
1489
+ );
1490
+ }
1491
+ return {
1492
+ keyObject: KeyObject.createKeyObject(
1493
+ 'private',
1494
+ ab,
1495
+ KFormatType.DER,
1496
+ KeyEncoding.PKCS8,
1497
+ ),
1498
+ isPublic: false,
1499
+ };
1500
+ } else if (format === 'raw-public') {
1501
+ // ML-DSA / ML-KEM reject plain 'raw' — only 'raw-public' is accepted for
1502
+ // public-key import (Node webcrypto.js:493-499, 506-511).
1208
1503
  const handle =
1209
1504
  NitroModules.createHybridObject<KeyObjectHandle>('KeyObjectHandle');
1210
- if (!handle.initPqcRaw(name, bufferLikeToArrayBuffer(data), true)) {
1505
+ if (
1506
+ !handle.initPqcRaw(
1507
+ name,
1508
+ bufferLikeToArrayBuffer(data as BufferLike),
1509
+ true,
1510
+ )
1511
+ ) {
1211
1512
  throw lazyDOMException(
1212
1513
  `Failed to import ${name} raw public key`,
1213
1514
  'DataError',
1214
1515
  );
1215
1516
  }
1216
- return new PublicKeyObject(handle);
1517
+ return { keyObject: new PublicKeyObject(handle), isPublic: true };
1217
1518
  } else if (format === 'raw-seed') {
1218
1519
  const handle =
1219
1520
  NitroModules.createHybridObject<KeyObjectHandle>('KeyObjectHandle');
1220
- if (!handle.initPqcRaw(name, bufferLikeToArrayBuffer(data), false)) {
1521
+ if (
1522
+ !handle.initPqcRaw(
1523
+ name,
1524
+ bufferLikeToArrayBuffer(data as BufferLike),
1525
+ false,
1526
+ )
1527
+ ) {
1221
1528
  throw lazyDOMException(`Failed to import ${name} raw seed`, 'DataError');
1222
1529
  }
1223
- return new PrivateKeyObject(handle);
1530
+ return { keyObject: new PrivateKeyObject(handle), isPublic: false };
1531
+ } else if (format === 'jwk') {
1532
+ const jwkData = data as JWK;
1533
+ const isPublic = jwkData.priv === undefined;
1534
+ const handle =
1535
+ NitroModules.createHybridObject<KeyObjectHandle>('KeyObjectHandle');
1536
+ let keyType: KeyType | undefined;
1537
+ try {
1538
+ keyType = handle.initJwk(jwkData);
1539
+ } catch (err) {
1540
+ throw lazyDOMException('Invalid JWK data', {
1541
+ name: 'DataError',
1542
+ cause: err,
1543
+ });
1544
+ }
1545
+ if (keyType === undefined) {
1546
+ throw lazyDOMException('Invalid JWK data', 'DataError');
1547
+ }
1548
+ return {
1549
+ keyObject: isPublic
1550
+ ? new PublicKeyObject(handle)
1551
+ : new PrivateKeyObject(handle),
1552
+ isPublic,
1553
+ };
1224
1554
  }
1225
1555
  throw lazyDOMException(
1226
1556
  `Unsupported format for ${name} import: ${format}`,
@@ -1228,39 +1558,109 @@ function pqcImportKeyObject(
1228
1558
  );
1229
1559
  }
1230
1560
 
1561
+ // Per WebCrypto AKP JWK rules, public-vs-private is determined by the presence
1562
+ // of `priv`. For binary formats it follows from the format itself.
1563
+ function pqcIsPublicImport(
1564
+ format: ImportFormat,
1565
+ data: BufferLike | JWK,
1566
+ ): boolean {
1567
+ if (format === 'jwk') {
1568
+ return (
1569
+ typeof data === 'object' &&
1570
+ data !== null &&
1571
+ (data as JWK).priv === undefined
1572
+ );
1573
+ }
1574
+ return format === 'spki' || format === 'raw-public';
1575
+ }
1576
+
1577
+ function validatePqcJwk(
1578
+ data: BufferLike | JWK,
1579
+ name: string,
1580
+ extractable: boolean,
1581
+ keyUsages: KeyUsage[],
1582
+ expectedUse: 'sig' | 'enc',
1583
+ ): void {
1584
+ if (typeof data !== 'object' || data === null) {
1585
+ throw lazyDOMException('Invalid keyData', 'DataError');
1586
+ }
1587
+ const jwk = data as JWK;
1588
+ if (jwk.kty !== 'AKP') {
1589
+ throw lazyDOMException('Invalid JWK "kty" Parameter', 'DataError');
1590
+ }
1591
+ validateJwkStructure(jwk, extractable, keyUsages, expectedUse);
1592
+ if (jwk.alg !== name) {
1593
+ throw lazyDOMException(
1594
+ 'JWK "alg" Parameter and algorithm name mismatch',
1595
+ 'DataError',
1596
+ );
1597
+ }
1598
+ }
1599
+
1600
+ // Validates that `format` is one of the formats PQC algorithms accept; rejects
1601
+ // plain 'raw' early so the format error wins over usage-based errors.
1602
+ function validatePqcFormat(format: ImportFormat, name: string): void {
1603
+ if (
1604
+ format !== 'spki' &&
1605
+ format !== 'pkcs8' &&
1606
+ format !== 'raw-public' &&
1607
+ format !== 'raw-seed' &&
1608
+ format !== 'jwk'
1609
+ ) {
1610
+ throw lazyDOMException(
1611
+ `Unsupported format for ${name} import: ${format}`,
1612
+ 'NotSupportedError',
1613
+ );
1614
+ }
1615
+ }
1616
+
1231
1617
  function mldsaImportKey(
1232
1618
  format: ImportFormat,
1233
- data: BufferLike,
1619
+ data: BufferLike | JWK,
1234
1620
  algorithm: SubtleAlgorithm,
1235
1621
  extractable: boolean,
1236
1622
  keyUsages: KeyUsage[],
1237
1623
  ): CryptoKey {
1238
1624
  const { name } = algorithm;
1239
- const isPublicFormat = format === 'spki' || format === 'raw';
1240
- if (hasAnyNotIn(keyUsages, isPublicFormat ? ['verify'] : ['sign'])) {
1625
+ validatePqcFormat(format, name);
1626
+ if (format === 'jwk') {
1627
+ validatePqcJwk(data, name, extractable, keyUsages, 'sig');
1628
+ }
1629
+ const isPublic = pqcIsPublicImport(format, data);
1630
+ if (hasAnyNotIn(keyUsages, isPublic ? ['verify'] : ['sign'])) {
1241
1631
  throw lazyDOMException(
1242
1632
  `Unsupported key usage for ${name} key`,
1243
1633
  'SyntaxError',
1244
1634
  );
1245
1635
  }
1246
- return new CryptoKey(
1247
- pqcImportKeyObject(format, data, name),
1248
- { name },
1249
- keyUsages,
1250
- extractable,
1251
- );
1636
+ const { keyObject } = pqcImportKeyObject(format, data, name);
1637
+ return new CryptoKey(keyObject, { name }, keyUsages, extractable);
1638
+ }
1639
+
1640
+ function slhdsaImportKey(
1641
+ format: ImportFormat,
1642
+ data: BufferLike | JWK,
1643
+ algorithm: SubtleAlgorithm,
1644
+ extractable: boolean,
1645
+ keyUsages: KeyUsage[],
1646
+ ): CryptoKey {
1647
+ return mldsaImportKey(format, data, algorithm, extractable, keyUsages);
1252
1648
  }
1253
1649
 
1254
1650
  function mlkemImportKey(
1255
1651
  format: ImportFormat,
1256
- data: BufferLike,
1652
+ data: BufferLike | JWK,
1257
1653
  algorithm: SubtleAlgorithm,
1258
1654
  extractable: boolean,
1259
1655
  keyUsages: KeyUsage[],
1260
1656
  ): CryptoKey {
1261
1657
  const { name } = algorithm;
1262
- const isPublicFormat = format === 'spki' || format === 'raw';
1263
- const allowedUsages: KeyUsage[] = isPublicFormat
1658
+ validatePqcFormat(format, name);
1659
+ if (format === 'jwk') {
1660
+ validatePqcJwk(data, name, extractable, keyUsages, 'enc');
1661
+ }
1662
+ const isPublic = pqcIsPublicImport(format, data);
1663
+ const allowedUsages: KeyUsage[] = isPublic
1264
1664
  ? ['encapsulateBits', 'encapsulateKey']
1265
1665
  : ['decapsulateBits', 'decapsulateKey'];
1266
1666
  if (hasAnyNotIn(keyUsages, allowedUsages)) {
@@ -1269,12 +1669,8 @@ function mlkemImportKey(
1269
1669
  'SyntaxError',
1270
1670
  );
1271
1671
  }
1272
- return new CryptoKey(
1273
- pqcImportKeyObject(format, data, name),
1274
- { name },
1275
- keyUsages,
1276
- extractable,
1277
- );
1672
+ const { keyObject } = pqcImportKeyObject(format, data, name);
1673
+ return new CryptoKey(keyObject, { name }, keyUsages, extractable);
1278
1674
  }
1279
1675
 
1280
1676
  const exportKeySpki = async (
@@ -1316,8 +1712,21 @@ const exportKeySpki = async (
1316
1712
  case 'ML-DSA-65':
1317
1713
  // Fall through
1318
1714
  case 'ML-DSA-87':
1715
+ // Fall through
1716
+ case 'SLH-DSA-SHA2-128s':
1717
+ case 'SLH-DSA-SHA2-128f':
1718
+ case 'SLH-DSA-SHA2-192s':
1719
+ case 'SLH-DSA-SHA2-192f':
1720
+ case 'SLH-DSA-SHA2-256s':
1721
+ case 'SLH-DSA-SHA2-256f':
1722
+ case 'SLH-DSA-SHAKE-128s':
1723
+ case 'SLH-DSA-SHAKE-128f':
1724
+ case 'SLH-DSA-SHAKE-192s':
1725
+ case 'SLH-DSA-SHAKE-192f':
1726
+ case 'SLH-DSA-SHAKE-256s':
1727
+ case 'SLH-DSA-SHAKE-256f':
1319
1728
  if (key.type === 'public') {
1320
- // Export ML-DSA key in SPKI DER format
1729
+ // Export ML-DSA / SLH-DSA key in SPKI DER format
1321
1730
  return bufferLikeToArrayBuffer(
1322
1731
  key.keyObject.handle.exportKey(KFormatType.DER, KeyEncoding.SPKI),
1323
1732
  );
@@ -1380,18 +1789,40 @@ const exportKeyPkcs8 = async (
1380
1789
  case 'ML-DSA-65':
1381
1790
  // Fall through
1382
1791
  case 'ML-DSA-87':
1383
- if (key.type === 'private') {
1384
- // Export ML-DSA key in PKCS8 DER format
1385
- return bufferLikeToArrayBuffer(
1386
- key.keyObject.handle.exportKey(KFormatType.DER, KeyEncoding.PKCS8),
1387
- );
1388
- }
1389
- break;
1792
+ // Fall through
1390
1793
  case 'ML-KEM-512':
1391
1794
  // Fall through
1392
1795
  case 'ML-KEM-768':
1393
1796
  // Fall through
1394
1797
  case 'ML-KEM-1024':
1798
+ if (key.type === 'private') {
1799
+ const ab = bufferLikeToArrayBuffer(
1800
+ key.keyObject.handle.exportKey(KFormatType.DER, KeyEncoding.PKCS8),
1801
+ );
1802
+ // 22 bytes of PKCS#8 ASN.1 + seed (32 ML-DSA, 64 ML-KEM). Guards
1803
+ // against a seedless KeyObject that was wrapped via toCryptoKey.
1804
+ const expected = key.algorithm.name.startsWith('ML-DSA') ? 54 : 86;
1805
+ if (ab.byteLength !== expected) {
1806
+ throw lazyDOMException(
1807
+ 'The operation failed for an operation-specific reason',
1808
+ 'OperationError',
1809
+ );
1810
+ }
1811
+ return ab;
1812
+ }
1813
+ break;
1814
+ case 'SLH-DSA-SHA2-128s':
1815
+ case 'SLH-DSA-SHA2-128f':
1816
+ case 'SLH-DSA-SHA2-192s':
1817
+ case 'SLH-DSA-SHA2-192f':
1818
+ case 'SLH-DSA-SHA2-256s':
1819
+ case 'SLH-DSA-SHA2-256f':
1820
+ case 'SLH-DSA-SHAKE-128s':
1821
+ case 'SLH-DSA-SHAKE-128f':
1822
+ case 'SLH-DSA-SHAKE-192s':
1823
+ case 'SLH-DSA-SHAKE-192f':
1824
+ case 'SLH-DSA-SHAKE-256s':
1825
+ case 'SLH-DSA-SHAKE-256f':
1395
1826
  if (key.type === 'private') {
1396
1827
  return bufferLikeToArrayBuffer(
1397
1828
  key.keyObject.handle.exportKey(KFormatType.DER, KeyEncoding.PKCS8),
@@ -1405,79 +1836,101 @@ const exportKeyPkcs8 = async (
1405
1836
  );
1406
1837
  };
1407
1838
 
1408
- const exportKeyRaw = (key: CryptoKey): ArrayBuffer | unknown => {
1409
- switch (key.algorithm.name) {
1839
+ // Mirrors Node's export key matrix (lib/internal/crypto/webcrypto.js
1840
+ // exportKeyRawSecret / exportKeyRawPublic, lines 472-563):
1841
+ //
1842
+ // raw — AES-CTR/CBC/GCM/KW + HMAC (secret); ECDSA/ECDH/Ed/X (public)
1843
+ // raw-secret — AES-CTR/CBC/GCM/KW + HMAC + AES-OCB + KMAC + ChaCha20-Poly1305
1844
+ // raw-public — ECDSA/ECDH + Ed/X + ML-DSA + ML-KEM (public)
1845
+ const exportKeyRaw = (
1846
+ key: CryptoKey,
1847
+ format: 'raw' | 'raw-secret' | 'raw-public',
1848
+ ): ArrayBuffer => {
1849
+ const name = key.algorithm.name;
1850
+ const isPublic = key.type === 'public';
1851
+ const isSecret = key.type === 'secret';
1852
+
1853
+ const exportSecret = (): ArrayBuffer => {
1854
+ const exported = key.keyObject.export();
1855
+ return exported.buffer.slice(
1856
+ exported.byteOffset,
1857
+ exported.byteOffset + exported.byteLength,
1858
+ ) as ArrayBuffer;
1859
+ };
1860
+ const exportRawPublic = (): ArrayBuffer =>
1861
+ bufferLikeToArrayBuffer(key.keyObject.handle.exportKey());
1862
+
1863
+ const fail = (): never => {
1864
+ throw lazyDOMException(
1865
+ `Unable to export ${name} ${key.type} key using ${format} format`,
1866
+ 'NotSupportedError',
1867
+ );
1868
+ };
1869
+
1870
+ // Symmetric: AES-CTR/CBC/GCM/KW and HMAC accept both 'raw' and 'raw-secret';
1871
+ // AES-OCB / KMAC* / ChaCha20-Poly1305 only 'raw-secret'.
1872
+ switch (name) {
1873
+ case 'AES-CTR':
1874
+ case 'AES-CBC':
1875
+ case 'AES-GCM':
1876
+ case 'AES-KW':
1877
+ case 'HMAC':
1878
+ if (!isSecret) return fail();
1879
+ if (format === 'raw' || format === 'raw-secret') return exportSecret();
1880
+ return fail();
1881
+ case 'AES-OCB':
1882
+ case 'KMAC128':
1883
+ case 'KMAC256':
1884
+ case 'ChaCha20-Poly1305':
1885
+ if (!isSecret) return fail();
1886
+ if (format === 'raw-secret') return exportSecret();
1887
+ return fail();
1410
1888
  case 'ECDSA':
1411
- // Fall through
1412
1889
  case 'ECDH':
1413
- if (key.type === 'public') {
1890
+ if (!isPublic) return fail();
1891
+ if (format === 'raw' || format === 'raw-public') {
1414
1892
  return ecExportKey(key, KWebCryptoKeyFormat.kWebCryptoKeyFormatRaw);
1415
1893
  }
1416
- break;
1894
+ return fail();
1417
1895
  case 'Ed25519':
1418
- // Fall through
1419
1896
  case 'Ed448':
1420
- // Fall through
1421
1897
  case 'X25519':
1422
- // Fall through
1423
1898
  case 'X448':
1424
- if (key.type === 'public') {
1425
- const exported = key.keyObject.handle.exportKey();
1426
- return bufferLikeToArrayBuffer(exported);
1427
- }
1428
- break;
1429
- case 'ML-KEM-512':
1430
- // Fall through
1431
- case 'ML-KEM-768':
1432
- // Fall through
1433
- case 'ML-KEM-1024':
1434
- // Fall through
1899
+ if (!isPublic) return fail();
1900
+ if (format === 'raw' || format === 'raw-public') return exportRawPublic();
1901
+ return fail();
1435
1902
  case 'ML-DSA-44':
1436
- // Fall through
1437
1903
  case 'ML-DSA-65':
1438
- // Fall through
1439
1904
  case 'ML-DSA-87':
1440
- if (key.type === 'public') {
1441
- const exported = key.keyObject.handle.exportKey();
1442
- return bufferLikeToArrayBuffer(exported);
1443
- }
1444
- break;
1445
- case 'AES-CTR':
1446
- // Fall through
1447
- case 'AES-CBC':
1448
- // Fall through
1449
- case 'AES-GCM':
1450
- // Fall through
1451
- case 'AES-KW':
1452
- // Fall through
1453
- case 'AES-OCB':
1454
- // Fall through
1455
- case 'ChaCha20-Poly1305':
1456
- // Fall through
1457
- case 'HMAC':
1458
- // Fall through
1459
- case 'KMAC128':
1460
- // Fall through
1461
- case 'KMAC256': {
1462
- const exported = key.keyObject.export();
1463
- // Convert Buffer to ArrayBuffer
1464
- return exported.buffer.slice(
1465
- exported.byteOffset,
1466
- exported.byteOffset + exported.byteLength,
1467
- );
1468
- }
1469
- }
1470
-
1471
- throw lazyDOMException(
1472
- `Unable to export a raw ${key.algorithm.name} ${key.type} key`,
1473
- 'InvalidAccessError',
1474
- );
1905
+ case 'ML-KEM-512':
1906
+ case 'ML-KEM-768':
1907
+ case 'ML-KEM-1024':
1908
+ case 'SLH-DSA-SHA2-128s':
1909
+ case 'SLH-DSA-SHA2-128f':
1910
+ case 'SLH-DSA-SHA2-192s':
1911
+ case 'SLH-DSA-SHA2-192f':
1912
+ case 'SLH-DSA-SHA2-256s':
1913
+ case 'SLH-DSA-SHA2-256f':
1914
+ case 'SLH-DSA-SHAKE-128s':
1915
+ case 'SLH-DSA-SHAKE-128f':
1916
+ case 'SLH-DSA-SHAKE-192s':
1917
+ case 'SLH-DSA-SHAKE-192f':
1918
+ case 'SLH-DSA-SHAKE-256s':
1919
+ case 'SLH-DSA-SHAKE-256f':
1920
+ // ML-DSA / ML-KEM / SLH-DSA keys do not recognize plain 'raw' (Node
1921
+ // webcrypto.js lines 488-510).
1922
+ if (!isPublic) return fail();
1923
+ if (format === 'raw-public') return exportRawPublic();
1924
+ return fail();
1925
+ }
1926
+
1927
+ return fail();
1475
1928
  };
1476
1929
 
1477
1930
  const exportKeyJWK = (key: CryptoKey): ArrayBuffer | unknown => {
1478
1931
  const jwk = key.keyObject.handle.exportJwk(
1479
1932
  {
1480
- key_ops: key.usages,
1933
+ key_ops: [...key.usages],
1481
1934
  ext: key.extractable,
1482
1935
  },
1483
1936
  true,
@@ -1503,16 +1956,41 @@ const exportKeyJWK = (key: CryptoKey): ArrayBuffer | unknown => {
1503
1956
  return jwk;
1504
1957
  case 'ECDSA':
1505
1958
  // Fall through
1506
- case 'ECDH':
1507
- jwk.crv ||= key.algorithm.namedCurve;
1508
- return jwk;
1509
- case 'Ed25519':
1959
+ case 'ECDH':
1960
+ jwk.crv ||= key.algorithm.namedCurve;
1961
+ return jwk;
1962
+ case 'Ed25519':
1963
+ // Fall through
1964
+ case 'Ed448':
1965
+ // Fall through
1966
+ case 'X25519':
1967
+ // Fall through
1968
+ case 'X448':
1969
+ return jwk;
1970
+ case 'ML-DSA-44':
1971
+ // Fall through
1972
+ case 'ML-DSA-65':
1973
+ // Fall through
1974
+ case 'ML-DSA-87':
1510
1975
  // Fall through
1511
- case 'Ed448':
1976
+ case 'ML-KEM-512':
1512
1977
  // Fall through
1513
- case 'X25519':
1978
+ case 'ML-KEM-768':
1514
1979
  // Fall through
1515
- case 'X448':
1980
+ case 'ML-KEM-1024':
1981
+ // Fall through
1982
+ case 'SLH-DSA-SHA2-128s':
1983
+ case 'SLH-DSA-SHA2-128f':
1984
+ case 'SLH-DSA-SHA2-192s':
1985
+ case 'SLH-DSA-SHA2-192f':
1986
+ case 'SLH-DSA-SHA2-256s':
1987
+ case 'SLH-DSA-SHA2-256f':
1988
+ case 'SLH-DSA-SHAKE-128s':
1989
+ case 'SLH-DSA-SHAKE-128f':
1990
+ case 'SLH-DSA-SHAKE-192s':
1991
+ case 'SLH-DSA-SHAKE-192f':
1992
+ case 'SLH-DSA-SHAKE-256s':
1993
+ case 'SLH-DSA-SHAKE-256f':
1516
1994
  return jwk;
1517
1995
  case 'AES-CTR':
1518
1996
  // Fall through
@@ -1543,7 +2021,11 @@ const exportKeyJWK = (key: CryptoKey): ArrayBuffer | unknown => {
1543
2021
  );
1544
2022
  };
1545
2023
 
1546
- const importGenericSecretKey = async (
2024
+ // PBKDF2 import. Mirrors Node's importGenericSecretKey ordering
2025
+ // (keys.js:945-971): extractable → usage → format → length. Callers pre-alias
2026
+ // 'raw-secret' / 'raw-public' to 'raw' via aliasKeyFormat
2027
+ // (webcrypto.js:798-808).
2028
+ const pbkdf2ImportKey = async (
1547
2029
  { name, length }: SubtleAlgorithm,
1548
2030
  format: ImportFormat,
1549
2031
  keyData: BufferLike | BinaryLike,
@@ -1551,33 +2033,70 @@ const importGenericSecretKey = async (
1551
2033
  keyUsages: KeyUsage[],
1552
2034
  ): Promise<CryptoKey> => {
1553
2035
  if (extractable) {
1554
- throw new Error(`${name} keys are not extractable`);
2036
+ throw lazyDOMException(`${name} keys are not extractable`, 'SyntaxError');
1555
2037
  }
1556
2038
  if (hasAnyNotIn(keyUsages, ['deriveKey', 'deriveBits'])) {
1557
- throw new Error(`Unsupported key usage for a ${name} key`);
2039
+ throw lazyDOMException(
2040
+ `Unsupported key usage for a ${name} key`,
2041
+ 'SyntaxError',
2042
+ );
2043
+ }
2044
+ if (format !== 'raw') {
2045
+ throw lazyDOMException(
2046
+ `Unable to import ${name} key with format ${format}`,
2047
+ 'NotSupportedError',
2048
+ );
1558
2049
  }
1559
2050
 
1560
- switch (format) {
1561
- case 'raw': {
1562
- if (hasAnyNotIn(keyUsages, ['deriveKey', 'deriveBits'])) {
1563
- throw new Error(`Unsupported key usage for a ${name} key`);
1564
- }
2051
+ const checkLength =
2052
+ typeof keyData === 'string' || SBuffer.isBuffer(keyData)
2053
+ ? keyData.length * 8
2054
+ : keyData.byteLength * 8;
2055
+ if (length !== undefined && length !== checkLength) {
2056
+ throw lazyDOMException('Invalid key length', 'DataError');
2057
+ }
1565
2058
 
1566
- const checkLength =
1567
- typeof keyData === 'string' || SBuffer.isBuffer(keyData)
1568
- ? keyData.length * 8
1569
- : keyData.byteLength * 8;
2059
+ const keyObject = createSecretKey(keyData as BinaryLike);
2060
+ return new CryptoKey(keyObject, { name }, keyUsages, false);
2061
+ };
1570
2062
 
1571
- if (length !== undefined && length !== checkLength) {
1572
- throw new Error('Invalid key length');
1573
- }
2063
+ // Argon2 import. Node gates the format at the dispatcher level — only
2064
+ // 'raw-secret' enters importGenericSecretKey (webcrypto.js:813-822). To match
2065
+ // that, format is the first check here; remaining ordering matches Node's
2066
+ // importGenericSecretKey.
2067
+ const argon2ImportKey = async (
2068
+ { name, length }: SubtleAlgorithm,
2069
+ format: ImportFormat,
2070
+ keyData: BufferLike | BinaryLike,
2071
+ extractable: boolean,
2072
+ keyUsages: KeyUsage[],
2073
+ ): Promise<CryptoKey> => {
2074
+ if (format !== 'raw-secret') {
2075
+ throw lazyDOMException(
2076
+ `Unable to import ${name} key with format ${format}`,
2077
+ 'NotSupportedError',
2078
+ );
2079
+ }
2080
+ if (extractable) {
2081
+ throw lazyDOMException(`${name} keys are not extractable`, 'SyntaxError');
2082
+ }
2083
+ if (hasAnyNotIn(keyUsages, ['deriveKey', 'deriveBits'])) {
2084
+ throw lazyDOMException(
2085
+ `Unsupported key usage for a ${name} key`,
2086
+ 'SyntaxError',
2087
+ );
2088
+ }
1574
2089
 
1575
- const keyObject = createSecretKey(keyData as BinaryLike);
1576
- return new CryptoKey(keyObject, { name }, keyUsages, false);
1577
- }
2090
+ const checkLength =
2091
+ typeof keyData === 'string' || SBuffer.isBuffer(keyData)
2092
+ ? keyData.length * 8
2093
+ : keyData.byteLength * 8;
2094
+ if (length !== undefined && length !== checkLength) {
2095
+ throw lazyDOMException('Invalid key length', 'DataError');
1578
2096
  }
1579
2097
 
1580
- throw new Error(`Unable to import ${name} key with format ${format}`);
2098
+ const keyObject = createSecretKey(keyData as BinaryLike);
2099
+ return new CryptoKey(keyObject, { name }, keyUsages, false);
1581
2100
  };
1582
2101
 
1583
2102
  const hkdfImportKey = async (
@@ -1588,6 +2107,13 @@ const hkdfImportKey = async (
1588
2107
  keyUsages: KeyUsage[],
1589
2108
  ): Promise<CryptoKey> => {
1590
2109
  const { name } = algorithm;
2110
+ // WebCrypto §28.7.6: HKDF keys are never extractable. The previous
2111
+ // implementation passed `extractable` through verbatim, allowing callers
2112
+ // to round-trip the input keying material via `exportKey` — defeating
2113
+ // the whole point of the deriveBits-only usage.
2114
+ if (extractable) {
2115
+ throw lazyDOMException(`${name} keys are not extractable`, 'SyntaxError');
2116
+ }
1591
2117
  if (hasAnyNotIn(keyUsages, ['deriveKey', 'deriveBits'])) {
1592
2118
  throw new Error(`Unsupported key usage for a ${name} key`);
1593
2119
  }
@@ -1595,7 +2121,7 @@ const hkdfImportKey = async (
1595
2121
  switch (format) {
1596
2122
  case 'raw': {
1597
2123
  const keyObject = createSecretKey(keyData as BinaryLike);
1598
- return new CryptoKey(keyObject, { name }, keyUsages, extractable);
2124
+ return new CryptoKey(keyObject, { name }, keyUsages, false);
1599
2125
  }
1600
2126
  default:
1601
2127
  throw new Error(`Unable to import ${name} key with format ${format}`);
@@ -1820,7 +2346,11 @@ const signVerify = (
1820
2346
  const usage: Operation = signature === undefined ? 'sign' : 'verify';
1821
2347
  algorithm = normalizeAlgorithm(algorithm, usage);
1822
2348
 
1823
- if (!key.usages.includes(usage) || algorithm.name !== key.algorithm.name) {
2349
+ if (algorithm.name !== key.algorithm.name) {
2350
+ throw lazyDOMException('Key algorithm mismatch', 'InvalidAccessError');
2351
+ }
2352
+
2353
+ if (!key.usages.includes(usage)) {
1824
2354
  throw lazyDOMException(
1825
2355
  `Unable to use this key to ${usage}`,
1826
2356
  'InvalidAccessError',
@@ -1842,6 +2372,18 @@ const signVerify = (
1842
2372
  case 'ML-DSA-44':
1843
2373
  case 'ML-DSA-65':
1844
2374
  case 'ML-DSA-87':
2375
+ case 'SLH-DSA-SHA2-128s':
2376
+ case 'SLH-DSA-SHA2-128f':
2377
+ case 'SLH-DSA-SHA2-192s':
2378
+ case 'SLH-DSA-SHA2-192f':
2379
+ case 'SLH-DSA-SHA2-256s':
2380
+ case 'SLH-DSA-SHA2-256f':
2381
+ case 'SLH-DSA-SHAKE-128s':
2382
+ case 'SLH-DSA-SHAKE-128f':
2383
+ case 'SLH-DSA-SHAKE-192s':
2384
+ case 'SLH-DSA-SHAKE-192f':
2385
+ case 'SLH-DSA-SHAKE-256s':
2386
+ case 'SLH-DSA-SHAKE-256f':
1845
2387
  return mldsaSignVerify(key, data, signature);
1846
2388
  case 'KMAC128':
1847
2389
  case 'KMAC256':
@@ -1853,23 +2395,16 @@ const signVerify = (
1853
2395
  );
1854
2396
  };
1855
2397
 
2398
+ // Algorithm-mismatch and usage checks live at the public-method call sites
2399
+ // (encrypt / decrypt / wrapKey / unwrapKey) so spec-mandated message and
2400
+ // ordering — algorithm-mismatch first, then usage — is preserved
2401
+ // (Node webcrypto.js, commit 4cb1f284136).
1856
2402
  const cipherOrWrap = async (
1857
2403
  mode: CipherOrWrapMode,
1858
2404
  algorithm: EncryptDecryptParams,
1859
2405
  key: CryptoKey,
1860
2406
  data: ArrayBuffer,
1861
- op: Operation,
1862
2407
  ): Promise<ArrayBuffer> => {
1863
- if (
1864
- key.algorithm.name !== algorithm.name ||
1865
- !key.usages.includes(op as KeyUsage)
1866
- ) {
1867
- throw lazyDOMException(
1868
- 'The requested operation is not valid for the provided key',
1869
- 'InvalidAccessError',
1870
- );
1871
- }
1872
-
1873
2408
  validateMaxBufferLength(data, 'data');
1874
2409
 
1875
2410
  switch (algorithm.name) {
@@ -1924,6 +2459,7 @@ const SUPPORTED_ALGORITHMS: Record<string, Set<string>> = {
1924
2459
  'ML-DSA-44',
1925
2460
  'ML-DSA-65',
1926
2461
  'ML-DSA-87',
2462
+ ...SLH_DSA_VARIANTS,
1927
2463
  ]),
1928
2464
  verify: new Set([
1929
2465
  'RSASSA-PKCS1-v1_5',
@@ -1937,6 +2473,7 @@ const SUPPORTED_ALGORITHMS: Record<string, Set<string>> = {
1937
2473
  'ML-DSA-44',
1938
2474
  'ML-DSA-65',
1939
2475
  'ML-DSA-87',
2476
+ ...SLH_DSA_VARIANTS,
1940
2477
  ]),
1941
2478
  digest: new Set([
1942
2479
  'SHA-1',
@@ -1948,6 +2485,10 @@ const SUPPORTED_ALGORITHMS: Record<string, Set<string>> = {
1948
2485
  'SHA3-512',
1949
2486
  'cSHAKE128',
1950
2487
  'cSHAKE256',
2488
+ 'TurboSHAKE128',
2489
+ 'TurboSHAKE256',
2490
+ 'KT128',
2491
+ 'KT256',
1951
2492
  ]),
1952
2493
  generateKey: new Set([
1953
2494
  'RSASSA-PKCS1-v1_5',
@@ -1974,6 +2515,7 @@ const SUPPORTED_ALGORITHMS: Record<string, Set<string>> = {
1974
2515
  'ML-KEM-512',
1975
2516
  'ML-KEM-768',
1976
2517
  'ML-KEM-1024',
2518
+ ...SLH_DSA_VARIANTS,
1977
2519
  ]),
1978
2520
  importKey: new Set([
1979
2521
  'RSASSA-PKCS1-v1_5',
@@ -2005,6 +2547,7 @@ const SUPPORTED_ALGORITHMS: Record<string, Set<string>> = {
2005
2547
  'ML-KEM-512',
2006
2548
  'ML-KEM-768',
2007
2549
  'ML-KEM-1024',
2550
+ ...SLH_DSA_VARIANTS,
2008
2551
  ]),
2009
2552
  exportKey: new Set([
2010
2553
  'RSASSA-PKCS1-v1_5',
@@ -2031,6 +2574,7 @@ const SUPPORTED_ALGORITHMS: Record<string, Set<string>> = {
2031
2574
  'ML-KEM-512',
2032
2575
  'ML-KEM-768',
2033
2576
  'ML-KEM-1024',
2577
+ ...SLH_DSA_VARIANTS,
2034
2578
  ]),
2035
2579
  deriveBits: new Set([
2036
2580
  'PBKDF2',
@@ -2066,7 +2610,7 @@ const SUPPORTED_ALGORITHMS: Record<string, Set<string>> = {
2066
2610
  decapsulateKey: new Set(['ML-KEM-512', 'ML-KEM-768', 'ML-KEM-1024']),
2067
2611
  };
2068
2612
 
2069
- const ASYMMETRIC_ALGORITHMS = new Set([
2613
+ const ASYMMETRIC_ALGORITHMS = new Set<string>([
2070
2614
  'RSASSA-PKCS1-v1_5',
2071
2615
  'RSA-PSS',
2072
2616
  'RSA-OAEP',
@@ -2082,52 +2626,230 @@ const ASYMMETRIC_ALGORITHMS = new Set([
2082
2626
  'ML-KEM-512',
2083
2627
  'ML-KEM-768',
2084
2628
  'ML-KEM-1024',
2629
+ ...SLH_DSA_VARIANTS,
2085
2630
  ]);
2086
2631
 
2087
- export class Subtle {
2088
- static supports(
2089
- operation: string,
2090
- algorithm: SubtleAlgorithm | AnyAlgorithm,
2091
- _lengthOrAdditionalAlgorithm?: unknown,
2092
- ): boolean {
2093
- let normalizedAlgorithm: SubtleAlgorithm;
2094
- try {
2095
- normalizedAlgorithm = normalizeAlgorithm(
2096
- algorithm,
2097
- (operation === 'getPublicKey' ? 'exportKey' : operation) as Operation,
2098
- );
2099
- } catch {
2632
+ // Per-algorithm validators for deriveBits (mirrors Node's hkdf.js:141-149,
2633
+ // pbkdf2.js:96-105, argon2.js:194-209). Used by Subtle.supports to reject
2634
+ // length values that the actual deriveBits implementation would reject.
2635
+ function validateKdfDeriveBitsLength(
2636
+ length: number | null | undefined,
2637
+ algName: string,
2638
+ ): void {
2639
+ if (length === null || length === undefined) {
2640
+ throw lazyDOMException('length cannot be null', 'OperationError');
2641
+ }
2642
+ if (length % 8) {
2643
+ throw lazyDOMException('length must be a multiple of 8', 'OperationError');
2644
+ }
2645
+ if (algName.startsWith('Argon2') && length < 32) {
2646
+ throw lazyDOMException('length must be >= 32', 'OperationError');
2647
+ }
2648
+ }
2649
+
2650
+ // Mirrors Node's webcrypto.js:1652-1731 `check`. Normalizes the algorithm,
2651
+ // looks it up in SUPPORTED_ALGORITHMS, and runs per-algorithm validation
2652
+ // (deriveBits length validators, HMAC+SHA3 generateKey rejection).
2653
+ // `op` is the operation key in SUPPORTED_ALGORITHMS — wrapKey/unwrapKey fall
2654
+ // back to encrypt/decrypt to mirror Node's normalize fallback.
2655
+ function supportsCheck(
2656
+ op: string,
2657
+ alg: SubtleAlgorithm | AnyAlgorithm,
2658
+ length?: number | null,
2659
+ ): boolean {
2660
+ let normalizedAlgorithm: SubtleAlgorithm;
2661
+ try {
2662
+ normalizedAlgorithm = normalizeAlgorithm(alg, op as Operation);
2663
+ } catch {
2664
+ if (op === 'wrapKey') return supportsCheck('encrypt', alg);
2665
+ if (op === 'unwrapKey') return supportsCheck('decrypt', alg);
2666
+ return false;
2667
+ }
2668
+
2669
+ const supported = SUPPORTED_ALGORITHMS[op];
2670
+ if (!supported || !supported.has(normalizedAlgorithm.name)) {
2671
+ if (op === 'wrapKey') return supportsCheck('encrypt', alg);
2672
+ if (op === 'unwrapKey') return supportsCheck('decrypt', alg);
2673
+ return false;
2674
+ }
2675
+
2676
+ if (op === 'deriveBits') {
2677
+ const name = normalizedAlgorithm.name;
2678
+ if (name === 'HKDF' || name === 'PBKDF2' || name.startsWith('Argon2')) {
2679
+ try {
2680
+ validateKdfDeriveBitsLength(length, name);
2681
+ } catch {
2682
+ return false;
2683
+ }
2684
+ }
2685
+ }
2686
+
2687
+ if (op === 'generateKey' && normalizedAlgorithm.name === 'HMAC') {
2688
+ const hashName =
2689
+ typeof normalizedAlgorithm.hash === 'string'
2690
+ ? normalizedAlgorithm.hash
2691
+ : (normalizedAlgorithm.hash as { name?: string } | undefined)?.name;
2692
+ if (
2693
+ normalizedAlgorithm.length === undefined &&
2694
+ typeof hashName === 'string' &&
2695
+ hashName.startsWith('SHA3-')
2696
+ ) {
2100
2697
  return false;
2101
2698
  }
2699
+ }
2102
2700
 
2103
- const name = normalizedAlgorithm.name;
2701
+ return true;
2702
+ }
2703
+
2704
+ function supportsImpl(
2705
+ operation: string,
2706
+ algorithm: SubtleAlgorithm | AnyAlgorithm,
2707
+ lengthOrAdditionalAlgorithm: unknown,
2708
+ ): boolean {
2709
+ switch (operation) {
2710
+ case 'decapsulateBits':
2711
+ case 'decapsulateKey':
2712
+ case 'decrypt':
2713
+ case 'deriveBits':
2714
+ case 'deriveKey':
2715
+ case 'digest':
2716
+ case 'encapsulateBits':
2717
+ case 'encapsulateKey':
2718
+ case 'encrypt':
2719
+ case 'exportKey':
2720
+ case 'generateKey':
2721
+ case 'getPublicKey':
2722
+ case 'importKey':
2723
+ case 'sign':
2724
+ case 'unwrapKey':
2725
+ case 'verify':
2726
+ case 'wrapKey':
2727
+ break;
2728
+ default:
2729
+ return false;
2730
+ }
2104
2731
 
2105
- if (operation === 'getPublicKey') {
2106
- return ASYMMETRIC_ALGORITHMS.has(name);
2732
+ let length: number | null | undefined;
2733
+
2734
+ if (operation === 'deriveKey') {
2735
+ // deriveKey decomposes to importKey of derived alg + deriveBits with that
2736
+ // alg's key length. Node webcrypto.js:1547-1563.
2737
+ if (lengthOrAdditionalAlgorithm != null) {
2738
+ const additional = lengthOrAdditionalAlgorithm as
2739
+ | SubtleAlgorithm
2740
+ | AnyAlgorithm;
2741
+ if (!supportsCheck('importKey', additional)) return false;
2742
+ try {
2743
+ length = getKeyLength(normalizeAlgorithm(additional, 'get key length'));
2744
+ } catch {
2745
+ return false;
2746
+ }
2747
+ return supportsCheck('deriveBits', algorithm, length);
2107
2748
  }
2749
+ // No additional algorithm given — only check the deriveBits side.
2750
+ return supportsCheck('deriveBits', algorithm);
2751
+ }
2752
+
2753
+ if (operation === 'wrapKey') {
2754
+ // wrapKey decomposes to encrypt of wrapping alg + exportKey of wrapped alg.
2755
+ // Node webcrypto.js:1564-1572.
2756
+ if (lengthOrAdditionalAlgorithm != null) {
2757
+ const additional = lengthOrAdditionalAlgorithm as
2758
+ | SubtleAlgorithm
2759
+ | AnyAlgorithm;
2760
+ if (!supportsCheck('exportKey', additional)) return false;
2761
+ }
2762
+ return supportsCheck('wrapKey', algorithm);
2763
+ }
2108
2764
 
2109
- if (operation === 'deriveKey') {
2110
- // deriveKey decomposes to deriveBits + importKey of additional algorithm
2111
- if (!SUPPORTED_ALGORITHMS.deriveBits?.has(name)) return false;
2112
- if (_lengthOrAdditionalAlgorithm != null) {
2113
- try {
2114
- const additionalAlg = normalizeAlgorithm(
2115
- _lengthOrAdditionalAlgorithm as SubtleAlgorithm | AnyAlgorithm,
2116
- 'importKey',
2117
- );
2118
- return (
2119
- SUPPORTED_ALGORITHMS.importKey?.has(additionalAlg.name) ?? false
2120
- );
2121
- } catch {
2122
- return false;
2123
- }
2765
+ if (operation === 'unwrapKey') {
2766
+ // unwrapKey decomposes to decrypt of wrapping alg + importKey of wrapped
2767
+ // alg. Node webcrypto.js:1573-1581.
2768
+ if (lengthOrAdditionalAlgorithm != null) {
2769
+ const additional = lengthOrAdditionalAlgorithm as
2770
+ | SubtleAlgorithm
2771
+ | AnyAlgorithm;
2772
+ if (!supportsCheck('importKey', additional)) return false;
2773
+ }
2774
+ return supportsCheck('unwrapKey', algorithm);
2775
+ }
2776
+
2777
+ if (operation === 'deriveBits') {
2778
+ if (lengthOrAdditionalAlgorithm == null) {
2779
+ length = null;
2780
+ } else if (typeof lengthOrAdditionalAlgorithm === 'number') {
2781
+ length = lengthOrAdditionalAlgorithm;
2782
+ } else {
2783
+ return false;
2784
+ }
2785
+ return supportsCheck('deriveBits', algorithm, length);
2786
+ }
2787
+
2788
+ if (operation === 'getPublicKey') {
2789
+ let normalized: SubtleAlgorithm;
2790
+ try {
2791
+ normalized = normalizeAlgorithm(algorithm, 'exportKey');
2792
+ } catch {
2793
+ return false;
2794
+ }
2795
+ return ASYMMETRIC_ALGORITHMS.has(normalized.name);
2796
+ }
2797
+
2798
+ if (operation === 'encapsulateKey' || operation === 'decapsulateKey') {
2799
+ // sharedKeyAlgorithm must support importKey, with HMAC/KMAC limited to
2800
+ // length === undefined or 256 (Node webcrypto.js:1610-1645).
2801
+ const additional = lengthOrAdditionalAlgorithm as
2802
+ | SubtleAlgorithm
2803
+ | AnyAlgorithm;
2804
+ let normalizedAdd: SubtleAlgorithm;
2805
+ try {
2806
+ normalizedAdd = normalizeAlgorithm(additional, 'importKey');
2807
+ } catch {
2808
+ return false;
2809
+ }
2810
+ switch (normalizedAdd.name) {
2811
+ case 'AES-OCB':
2812
+ case 'AES-KW':
2813
+ case 'AES-GCM':
2814
+ case 'AES-CTR':
2815
+ case 'AES-CBC':
2816
+ case 'ChaCha20-Poly1305':
2817
+ case 'HKDF':
2818
+ case 'PBKDF2':
2819
+ case 'Argon2i':
2820
+ case 'Argon2d':
2821
+ case 'Argon2id':
2822
+ break;
2823
+ case 'HMAC':
2824
+ case 'KMAC128':
2825
+ case 'KMAC256': {
2826
+ const addLen = normalizedAdd.length;
2827
+ if (addLen !== undefined && addLen !== 256) return false;
2828
+ break;
2124
2829
  }
2125
- return true;
2830
+ default:
2831
+ return false;
2126
2832
  }
2833
+ return supportsCheck(operation, algorithm);
2834
+ }
2127
2835
 
2128
- const supported = SUPPORTED_ALGORITHMS[operation];
2129
- if (!supported) return false;
2130
- return supported.has(name);
2836
+ return supportsCheck(operation, algorithm);
2837
+ }
2838
+
2839
+ export class Subtle {
2840
+ // Spec-compliant capability detector. Mirrors Node's webcrypto.js:1506-1649
2841
+ // `SubtleCrypto.supports`, including:
2842
+ // • composed-operation decomposition (deriveKey, wrapKey, unwrapKey,
2843
+ // encapsulateKey, decapsulateKey, getPublicKey)
2844
+ // • per-algorithm length validators for deriveBits (HKDF/PBKDF2/Argon2)
2845
+ // • HMAC + SHA3 generateKey with no length → false
2846
+ // Static-only per the WICG spec.
2847
+ static supports(
2848
+ operation: string,
2849
+ algorithm: SubtleAlgorithm | AnyAlgorithm,
2850
+ lengthOrAdditionalAlgorithm: unknown = null,
2851
+ ): boolean {
2852
+ return supportsImpl(operation, algorithm, lengthOrAdditionalAlgorithm);
2131
2853
  }
2132
2854
 
2133
2855
  async decrypt(
@@ -2135,13 +2857,25 @@ export class Subtle {
2135
2857
  key: CryptoKey,
2136
2858
  data: BufferLike,
2137
2859
  ): Promise<ArrayBuffer> {
2138
- const normalizedAlgorithm = normalizeAlgorithm(algorithm, 'decrypt');
2860
+ requireArgs(arguments.length, 3, 'decrypt');
2861
+ const normalizedAlgorithm = normalizeAlgorithm(
2862
+ algorithm,
2863
+ 'decrypt',
2864
+ ) as EncryptDecryptParams;
2865
+ if (normalizedAlgorithm.name !== key.algorithm.name) {
2866
+ throw lazyDOMException('Key algorithm mismatch', 'InvalidAccessError');
2867
+ }
2868
+ if (!key.usages.includes('decrypt')) {
2869
+ throw lazyDOMException(
2870
+ 'Unable to use this key to decrypt',
2871
+ 'InvalidAccessError',
2872
+ );
2873
+ }
2139
2874
  return cipherOrWrap(
2140
2875
  CipherOrWrapMode.kWebCryptoCipherDecrypt,
2141
- normalizedAlgorithm as EncryptDecryptParams,
2876
+ normalizedAlgorithm,
2142
2877
  key,
2143
2878
  bufferLikeToArrayBuffer(data),
2144
- 'decrypt',
2145
2879
  );
2146
2880
  }
2147
2881
 
@@ -2149,6 +2883,7 @@ export class Subtle {
2149
2883
  algorithm: SubtleAlgorithm | AnyAlgorithm,
2150
2884
  data: BufferLike,
2151
2885
  ): Promise<ArrayBuffer> {
2886
+ requireArgs(arguments.length, 2, 'digest');
2152
2887
  const normalizedAlgorithm = normalizeAlgorithm(
2153
2888
  algorithm,
2154
2889
  'digest' as Operation,
@@ -2159,39 +2894,56 @@ export class Subtle {
2159
2894
  async deriveBits(
2160
2895
  algorithm: SubtleAlgorithm,
2161
2896
  baseKey: CryptoKey,
2162
- length: number,
2897
+ length: number | null = null,
2163
2898
  ): Promise<ArrayBuffer> {
2164
- // Allow either deriveBits OR deriveKey usage (WebCrypto spec allows both)
2165
- if (
2166
- !baseKey.keyUsages.includes('deriveBits') &&
2167
- !baseKey.keyUsages.includes('deriveKey')
2168
- ) {
2169
- throw new Error('baseKey does not have deriveBits or deriveKey usage');
2899
+ requireArgs(arguments.length, 2, 'deriveBits');
2900
+ const normalizedAlgorithm = normalizeAlgorithm(algorithm, 'deriveBits');
2901
+ // WebCrypto §SubtleCrypto.deriveBits step 11: throw InvalidAccessError
2902
+ // unless `baseKey.[[usages]]` contains "deriveBits" specifically. The
2903
+ // previous `deriveBits || deriveKey` accept-either branch silently
2904
+ // promoted deriveKey-only keys into deriveBits use, contradicting the
2905
+ // spec usage gate.
2906
+ if (!baseKey.usages.includes('deriveBits')) {
2907
+ throw lazyDOMException(
2908
+ 'baseKey does not have deriveBits usage',
2909
+ 'InvalidAccessError',
2910
+ );
2170
2911
  }
2171
- if (baseKey.algorithm.name !== algorithm.name)
2172
- throw new Error('Key algorithm mismatch');
2173
- switch (algorithm.name) {
2912
+ if (baseKey.algorithm.name !== normalizedAlgorithm.name) {
2913
+ throw lazyDOMException('Key algorithm mismatch', 'InvalidAccessError');
2914
+ }
2915
+ switch (normalizedAlgorithm.name) {
2174
2916
  case 'PBKDF2':
2175
- return pbkdf2DeriveBits(algorithm, baseKey, length);
2917
+ if (length === null) {
2918
+ throw lazyDOMException('length cannot be null', 'OperationError');
2919
+ }
2920
+ return pbkdf2DeriveBits(normalizedAlgorithm, baseKey, length);
2176
2921
  case 'X25519':
2177
2922
  // Fall through
2178
2923
  case 'X448':
2179
- return xDeriveBits(algorithm, baseKey, length);
2924
+ return xDeriveBits(normalizedAlgorithm, baseKey, length);
2180
2925
  case 'ECDH':
2181
- return ecDeriveBits(algorithm, baseKey, length);
2926
+ return ecDeriveBits(normalizedAlgorithm, baseKey, length);
2182
2927
  case 'HKDF':
2928
+ if (length === null) {
2929
+ throw lazyDOMException('length cannot be null', 'OperationError');
2930
+ }
2183
2931
  return hkdfDeriveBits(
2184
- algorithm as unknown as HkdfAlgorithm,
2932
+ normalizedAlgorithm as unknown as HkdfAlgorithm,
2185
2933
  baseKey,
2186
2934
  length,
2187
2935
  );
2188
2936
  case 'Argon2d':
2189
2937
  case 'Argon2i':
2190
2938
  case 'Argon2id':
2191
- return argon2DeriveBits(algorithm, baseKey, length);
2939
+ if (length === null) {
2940
+ throw lazyDOMException('length cannot be null', 'OperationError');
2941
+ }
2942
+ return argon2DeriveBits(normalizedAlgorithm, baseKey, length);
2192
2943
  }
2193
- throw new Error(
2194
- `'subtle.deriveBits()' for ${algorithm.name} is not implemented.`,
2944
+ throw lazyDOMException(
2945
+ `'subtle.deriveBits()' for ${normalizedAlgorithm.name} is not implemented.`,
2946
+ 'NotSupportedError',
2195
2947
  );
2196
2948
  }
2197
2949
 
@@ -2202,40 +2954,55 @@ export class Subtle {
2202
2954
  extractable: boolean,
2203
2955
  keyUsages: KeyUsage[],
2204
2956
  ): Promise<CryptoKey> {
2957
+ requireArgs(arguments.length, 5, 'deriveKey');
2958
+ const normalizedAlgorithm = normalizeAlgorithm(algorithm, 'deriveBits');
2959
+ const normalizedDerivedKeyAlgorithm = normalizeAlgorithm(
2960
+ derivedKeyAlgorithm,
2961
+ 'importKey',
2962
+ );
2963
+
2205
2964
  // Validate baseKey usage
2206
- if (
2207
- !baseKey.usages.includes('deriveKey') &&
2208
- !baseKey.usages.includes('deriveBits')
2209
- ) {
2965
+ if (!baseKey.usages.includes('deriveKey')) {
2210
2966
  throw lazyDOMException(
2211
- 'baseKey does not have deriveKey or deriveBits usage',
2967
+ 'baseKey does not have deriveKey usage',
2212
2968
  'InvalidAccessError',
2213
2969
  );
2214
2970
  }
2215
2971
 
2216
- // Calculate required key length
2217
- const length = getKeyLength(derivedKeyAlgorithm);
2972
+ if (baseKey.algorithm.name !== normalizedAlgorithm.name) {
2973
+ throw lazyDOMException('Key algorithm mismatch', 'InvalidAccessError');
2974
+ }
2975
+
2976
+ // Calculate required key length (may be null for KDF-derived material).
2977
+ const length = getKeyLength(normalizedDerivedKeyAlgorithm);
2218
2978
 
2219
2979
  // Step 1: Derive bits
2220
2980
  let derivedBits: ArrayBuffer;
2221
- if (baseKey.algorithm.name !== algorithm.name)
2222
- throw new Error('Key algorithm mismatch');
2223
-
2224
- switch (algorithm.name) {
2981
+ switch (normalizedAlgorithm.name) {
2225
2982
  case 'PBKDF2':
2226
- derivedBits = await pbkdf2DeriveBits(algorithm, baseKey, length);
2983
+ if (length === null) {
2984
+ throw lazyDOMException('length cannot be null', 'OperationError');
2985
+ }
2986
+ derivedBits = await pbkdf2DeriveBits(
2987
+ normalizedAlgorithm,
2988
+ baseKey,
2989
+ length,
2990
+ );
2227
2991
  break;
2228
2992
  case 'X25519':
2229
2993
  // Fall through
2230
2994
  case 'X448':
2231
- derivedBits = await xDeriveBits(algorithm, baseKey, length);
2995
+ derivedBits = await xDeriveBits(normalizedAlgorithm, baseKey, length);
2232
2996
  break;
2233
2997
  case 'ECDH':
2234
- derivedBits = await ecDeriveBits(algorithm, baseKey, length);
2998
+ derivedBits = await ecDeriveBits(normalizedAlgorithm, baseKey, length);
2235
2999
  break;
2236
3000
  case 'HKDF':
3001
+ if (length === null) {
3002
+ throw lazyDOMException('length cannot be null', 'OperationError');
3003
+ }
2237
3004
  derivedBits = hkdfDeriveBits(
2238
- algorithm as unknown as HkdfAlgorithm,
3005
+ normalizedAlgorithm as unknown as HkdfAlgorithm,
2239
3006
  baseKey,
2240
3007
  length,
2241
3008
  );
@@ -2243,17 +3010,22 @@ export class Subtle {
2243
3010
  case 'Argon2d':
2244
3011
  case 'Argon2i':
2245
3012
  case 'Argon2id':
2246
- derivedBits = argon2DeriveBits(algorithm, baseKey, length);
3013
+ if (length === null) {
3014
+ throw lazyDOMException('length cannot be null', 'OperationError');
3015
+ }
3016
+ derivedBits = argon2DeriveBits(normalizedAlgorithm, baseKey, length);
2247
3017
  break;
2248
3018
  default:
2249
- throw new Error(
2250
- `'subtle.deriveKey()' for ${algorithm.name} is not implemented.`,
3019
+ throw lazyDOMException(
3020
+ `'subtle.deriveKey()' for ${normalizedAlgorithm.name} is not implemented.`,
3021
+ 'NotSupportedError',
2251
3022
  );
2252
3023
  }
2253
3024
 
2254
- // Step 2: Import as key
3025
+ // Step 2: Import as key. Use 'raw-secret' so derived material flows into
3026
+ // AEADs / KMAC correctly — they reject plain 'raw' (Node webcrypto.js:381-385).
2255
3027
  return this.importKey(
2256
- 'raw',
3028
+ 'raw-secret',
2257
3029
  derivedBits,
2258
3030
  derivedKeyAlgorithm,
2259
3031
  extractable,
@@ -2266,13 +3038,25 @@ export class Subtle {
2266
3038
  key: CryptoKey,
2267
3039
  data: BufferLike,
2268
3040
  ): Promise<ArrayBuffer> {
2269
- const normalizedAlgorithm = normalizeAlgorithm(algorithm, 'encrypt');
3041
+ requireArgs(arguments.length, 3, 'encrypt');
3042
+ const normalizedAlgorithm = normalizeAlgorithm(
3043
+ algorithm,
3044
+ 'encrypt',
3045
+ ) as EncryptDecryptParams;
3046
+ if (normalizedAlgorithm.name !== key.algorithm.name) {
3047
+ throw lazyDOMException('Key algorithm mismatch', 'InvalidAccessError');
3048
+ }
3049
+ if (!key.usages.includes('encrypt')) {
3050
+ throw lazyDOMException(
3051
+ 'Unable to use this key to encrypt',
3052
+ 'InvalidAccessError',
3053
+ );
3054
+ }
2270
3055
  return cipherOrWrap(
2271
3056
  CipherOrWrapMode.kWebCryptoCipherEncrypt,
2272
- normalizedAlgorithm as EncryptDecryptParams,
3057
+ normalizedAlgorithm,
2273
3058
  key,
2274
3059
  bufferLikeToArrayBuffer(data),
2275
- 'encrypt',
2276
3060
  );
2277
3061
  }
2278
3062
 
@@ -2280,16 +3064,19 @@ export class Subtle {
2280
3064
  format: ImportFormat,
2281
3065
  key: CryptoKey,
2282
3066
  ): Promise<ArrayBuffer | JWK> {
2283
- if (!key.extractable) throw new Error('key is not extractable');
3067
+ requireArgs(arguments.length, 2, 'exportKey');
3068
+ if (!key.extractable)
3069
+ throw lazyDOMException('key is not extractable', 'InvalidAccessError');
2284
3070
 
2285
3071
  if (format === 'raw-seed') {
2286
- const pqcAlgos = [
3072
+ const pqcAlgos: string[] = [
2287
3073
  'ML-KEM-512',
2288
3074
  'ML-KEM-768',
2289
3075
  'ML-KEM-1024',
2290
3076
  'ML-DSA-44',
2291
3077
  'ML-DSA-65',
2292
3078
  'ML-DSA-87',
3079
+ ...SLH_DSA_VARIANTS,
2293
3080
  ];
2294
3081
  if (!pqcAlgos.includes(key.algorithm.name)) {
2295
3082
  throw lazyDOMException(
@@ -2306,9 +3093,6 @@ export class Subtle {
2306
3093
  return bufferLikeToArrayBuffer(key.keyObject.handle.exportKey());
2307
3094
  }
2308
3095
 
2309
- // Note: 'raw-seed' is handled above; do NOT normalize it here
2310
- if (format === 'raw-secret' || format === 'raw-public') format = 'raw';
2311
-
2312
3096
  switch (format) {
2313
3097
  case 'spki':
2314
3098
  return (await exportKeySpki(key)) as ArrayBuffer;
@@ -2317,7 +3101,9 @@ export class Subtle {
2317
3101
  case 'jwk':
2318
3102
  return exportKeyJWK(key) as JWK;
2319
3103
  case 'raw':
2320
- return exportKeyRaw(key) as ArrayBuffer;
3104
+ case 'raw-secret':
3105
+ case 'raw-public':
3106
+ return exportKeyRaw(key, format) as ArrayBuffer;
2321
3107
  }
2322
3108
  }
2323
3109
 
@@ -2327,10 +3113,18 @@ export class Subtle {
2327
3113
  wrappingKey: CryptoKey,
2328
3114
  wrapAlgorithm: EncryptDecryptParams,
2329
3115
  ): Promise<ArrayBuffer> {
2330
- // Validate wrappingKey usage
3116
+ requireArgs(arguments.length, 4, 'wrapKey');
3117
+ const normalizedWrapAlgorithm = normalizeAlgorithm(
3118
+ wrapAlgorithm,
3119
+ 'wrapKey',
3120
+ ) as EncryptDecryptParams;
3121
+
3122
+ if (normalizedWrapAlgorithm.name !== wrappingKey.algorithm.name) {
3123
+ throw lazyDOMException('Key algorithm mismatch', 'InvalidAccessError');
3124
+ }
2331
3125
  if (!wrappingKey.usages.includes('wrapKey')) {
2332
3126
  throw lazyDOMException(
2333
- 'wrappingKey does not have wrapKey usage',
3127
+ 'Unable to use this key to wrapKey',
2334
3128
  'InvalidAccessError',
2335
3129
  );
2336
3130
  }
@@ -2345,7 +3139,7 @@ export class Subtle {
2345
3139
  const buffer = SBuffer.from(jwkString, 'utf8');
2346
3140
 
2347
3141
  // For AES-KW, pad to multiple of 8 bytes (accounting for null terminator)
2348
- if (wrapAlgorithm.name === 'AES-KW') {
3142
+ if (normalizedWrapAlgorithm.name === 'AES-KW') {
2349
3143
  const length = buffer.length;
2350
3144
  // Add 1 for null terminator, then pad to multiple of 8
2351
3145
  const paddedLength = Math.ceil((length + 1) / 8) * 8;
@@ -2364,10 +3158,9 @@ export class Subtle {
2364
3158
  // Step 3: Encrypt the exported key
2365
3159
  return cipherOrWrap(
2366
3160
  CipherOrWrapMode.kWebCryptoCipherEncrypt,
2367
- wrapAlgorithm,
3161
+ normalizedWrapAlgorithm,
2368
3162
  wrappingKey,
2369
3163
  keyData,
2370
- 'wrapKey',
2371
3164
  );
2372
3165
  }
2373
3166
 
@@ -2380,10 +3173,18 @@ export class Subtle {
2380
3173
  extractable: boolean,
2381
3174
  keyUsages: KeyUsage[],
2382
3175
  ): Promise<CryptoKey> {
2383
- // Validate unwrappingKey usage
3176
+ requireArgs(arguments.length, 7, 'unwrapKey');
3177
+ const normalizedUnwrapAlgorithm = normalizeAlgorithm(
3178
+ unwrapAlgorithm,
3179
+ 'unwrapKey',
3180
+ ) as EncryptDecryptParams;
3181
+
3182
+ if (normalizedUnwrapAlgorithm.name !== unwrappingKey.algorithm.name) {
3183
+ throw lazyDOMException('Key algorithm mismatch', 'InvalidAccessError');
3184
+ }
2384
3185
  if (!unwrappingKey.usages.includes('unwrapKey')) {
2385
3186
  throw lazyDOMException(
2386
- 'unwrappingKey does not have unwrapKey usage',
3187
+ 'Unable to use this key to unwrapKey',
2387
3188
  'InvalidAccessError',
2388
3189
  );
2389
3190
  }
@@ -2391,10 +3192,9 @@ export class Subtle {
2391
3192
  // Step 1: Decrypt the wrapped key
2392
3193
  const decrypted = await cipherOrWrap(
2393
3194
  CipherOrWrapMode.kWebCryptoCipherDecrypt,
2394
- unwrapAlgorithm,
3195
+ normalizedUnwrapAlgorithm,
2395
3196
  unwrappingKey,
2396
3197
  bufferLikeToArrayBuffer(wrappedKey),
2397
- 'unwrapKey',
2398
3198
  );
2399
3199
 
2400
3200
  // Step 2: Convert to appropriate format
@@ -2403,7 +3203,7 @@ export class Subtle {
2403
3203
  const buffer = SBuffer.from(decrypted);
2404
3204
  // For AES-KW, the data may be padded - find the null terminator
2405
3205
  let jwkString: string;
2406
- if (unwrapAlgorithm.name === 'AES-KW') {
3206
+ if (normalizedUnwrapAlgorithm.name === 'AES-KW') {
2407
3207
  // Find the null terminator (if present) to get the original string
2408
3208
  const nullIndex = buffer.indexOf(0);
2409
3209
  if (nullIndex !== -1) {
@@ -2435,6 +3235,7 @@ export class Subtle {
2435
3235
  extractable: boolean,
2436
3236
  keyUsages: KeyUsage[],
2437
3237
  ): Promise<CryptoKey | CryptoKeyPair> {
3238
+ requireArgs(arguments.length, 3, 'generateKey');
2438
3239
  algorithm = normalizeAlgorithm(algorithm, 'generateKey');
2439
3240
  let result: CryptoKey | CryptoKeyPair;
2440
3241
  switch (algorithm.name) {
@@ -2521,6 +3322,25 @@ export class Subtle {
2521
3322
  );
2522
3323
  checkCryptoKeyPairUsages(result as CryptoKeyPair);
2523
3324
  break;
3325
+ case 'SLH-DSA-SHA2-128s':
3326
+ case 'SLH-DSA-SHA2-128f':
3327
+ case 'SLH-DSA-SHA2-192s':
3328
+ case 'SLH-DSA-SHA2-192f':
3329
+ case 'SLH-DSA-SHA2-256s':
3330
+ case 'SLH-DSA-SHA2-256f':
3331
+ case 'SLH-DSA-SHAKE-128s':
3332
+ case 'SLH-DSA-SHAKE-128f':
3333
+ case 'SLH-DSA-SHAKE-192s':
3334
+ case 'SLH-DSA-SHAKE-192f':
3335
+ case 'SLH-DSA-SHAKE-256s':
3336
+ case 'SLH-DSA-SHAKE-256f':
3337
+ result = await slhdsa_generateKeyPairWebCrypto(
3338
+ algorithm.name as SlhDsaVariant,
3339
+ extractable,
3340
+ keyUsages,
3341
+ );
3342
+ checkCryptoKeyPairUsages(result as CryptoKeyPair);
3343
+ break;
2524
3344
  case 'X25519':
2525
3345
  // Fall through
2526
3346
  case 'X448':
@@ -2557,6 +3377,7 @@ export class Subtle {
2557
3377
  key: CryptoKey,
2558
3378
  keyUsages: KeyUsage[],
2559
3379
  ): Promise<CryptoKey> {
3380
+ requireArgs(arguments.length, 2, 'getPublicKey');
2560
3381
  if (key.type === 'secret') {
2561
3382
  throw lazyDOMException('key must be a private key', 'NotSupportedError');
2562
3383
  }
@@ -2575,8 +3396,11 @@ export class Subtle {
2575
3396
  extractable: boolean,
2576
3397
  keyUsages: KeyUsage[],
2577
3398
  ): Promise<CryptoKey> {
2578
- // Note: 'raw-seed' is NOT normalized — PQC import functions handle it directly
2579
- if (format === 'raw-secret' || format === 'raw-public') format = 'raw';
3399
+ requireArgs(arguments.length, 5, 'importKey');
3400
+ // Per-algorithm format handling. Some algorithms alias raw-secret/raw-public
3401
+ // to 'raw' (RSA, EC, Ed/X, HMAC, HKDF, PBKDF2); others demand the
3402
+ // disambiguated form (KMAC, AES-OCB, ChaCha20-Poly1305, Argon2, ML-DSA,
3403
+ // ML-KEM). 'raw-seed' is never normalized — PQC import handles it directly.
2580
3404
  const normalizedAlgorithm = normalizeAlgorithm(algorithm, 'importKey');
2581
3405
  let result: CryptoKey;
2582
3406
  switch (normalizedAlgorithm.name) {
@@ -2586,7 +3410,7 @@ export class Subtle {
2586
3410
  // Fall through
2587
3411
  case 'RSA-OAEP':
2588
3412
  result = rsaImportKey(
2589
- format,
3413
+ aliasKeyFormat(format),
2590
3414
  data as BufferLike | JWK,
2591
3415
  normalizedAlgorithm,
2592
3416
  extractable,
@@ -2597,7 +3421,7 @@ export class Subtle {
2597
3421
  // Fall through
2598
3422
  case 'ECDH':
2599
3423
  result = ecImportKey(
2600
- format,
3424
+ aliasKeyFormat(format),
2601
3425
  data,
2602
3426
  normalizedAlgorithm,
2603
3427
  extractable,
@@ -2605,6 +3429,9 @@ export class Subtle {
2605
3429
  );
2606
3430
  break;
2607
3431
  case 'HMAC':
3432
+ // No aliasing — Node routes HMAC straight into mac.js, which accepts
3433
+ // 'raw' / 'raw-secret' / 'jwk' and rejects everything else
3434
+ // (webcrypto.js:774-781, mac.js:136-174).
2608
3435
  result = await hmacImportKey(
2609
3436
  normalizedAlgorithm,
2610
3437
  format,
@@ -2644,10 +3471,18 @@ export class Subtle {
2644
3471
  );
2645
3472
  break;
2646
3473
  case 'PBKDF2':
3474
+ result = await pbkdf2ImportKey(
3475
+ normalizedAlgorithm,
3476
+ aliasKeyFormat(format),
3477
+ data as BufferLike | BinaryLike,
3478
+ extractable,
3479
+ keyUsages,
3480
+ );
3481
+ break;
2647
3482
  case 'Argon2d':
2648
3483
  case 'Argon2i':
2649
3484
  case 'Argon2id':
2650
- result = await importGenericSecretKey(
3485
+ result = await argon2ImportKey(
2651
3486
  normalizedAlgorithm,
2652
3487
  format,
2653
3488
  data as BufferLike | BinaryLike,
@@ -2657,7 +3492,7 @@ export class Subtle {
2657
3492
  break;
2658
3493
  case 'HKDF':
2659
3494
  result = await hkdfImportKey(
2660
- format,
3495
+ aliasKeyFormat(format),
2661
3496
  data as BufferLike | BinaryLike,
2662
3497
  normalizedAlgorithm,
2663
3498
  extractable,
@@ -2672,6 +3507,26 @@ export class Subtle {
2672
3507
  // Fall through
2673
3508
  case 'Ed448':
2674
3509
  result = edImportKey(
3510
+ aliasKeyFormat(format),
3511
+ data as BufferLike | JWK,
3512
+ normalizedAlgorithm,
3513
+ extractable,
3514
+ keyUsages,
3515
+ );
3516
+ break;
3517
+ case 'SLH-DSA-SHA2-128s':
3518
+ case 'SLH-DSA-SHA2-128f':
3519
+ case 'SLH-DSA-SHA2-192s':
3520
+ case 'SLH-DSA-SHA2-192f':
3521
+ case 'SLH-DSA-SHA2-256s':
3522
+ case 'SLH-DSA-SHA2-256f':
3523
+ case 'SLH-DSA-SHAKE-128s':
3524
+ case 'SLH-DSA-SHAKE-128f':
3525
+ case 'SLH-DSA-SHAKE-192s':
3526
+ case 'SLH-DSA-SHAKE-192f':
3527
+ case 'SLH-DSA-SHAKE-256s':
3528
+ case 'SLH-DSA-SHAKE-256f':
3529
+ result = slhdsaImportKey(
2675
3530
  format,
2676
3531
  data as BufferLike | JWK,
2677
3532
  normalizedAlgorithm,
@@ -2686,7 +3541,7 @@ export class Subtle {
2686
3541
  case 'ML-DSA-87':
2687
3542
  result = mldsaImportKey(
2688
3543
  format,
2689
- data as BufferLike,
3544
+ data as BufferLike | JWK,
2690
3545
  normalizedAlgorithm,
2691
3546
  extractable,
2692
3547
  keyUsages,
@@ -2699,7 +3554,7 @@ export class Subtle {
2699
3554
  case 'ML-KEM-1024':
2700
3555
  result = mlkemImportKey(
2701
3556
  format,
2702
- data as BufferLike,
3557
+ data as BufferLike | JWK,
2703
3558
  normalizedAlgorithm,
2704
3559
  extractable,
2705
3560
  keyUsages,
@@ -2728,6 +3583,7 @@ export class Subtle {
2728
3583
  key: CryptoKey,
2729
3584
  data: BufferLike,
2730
3585
  ): Promise<ArrayBuffer> {
3586
+ requireArgs(arguments.length, 3, 'sign');
2731
3587
  return signVerify(
2732
3588
  normalizeAlgorithm(algorithm, 'sign'),
2733
3589
  key,
@@ -2741,6 +3597,7 @@ export class Subtle {
2741
3597
  signature: BufferLike,
2742
3598
  data: BufferLike,
2743
3599
  ): Promise<boolean> {
3600
+ requireArgs(arguments.length, 4, 'verify');
2744
3601
  return signVerify(
2745
3602
  normalizeAlgorithm(algorithm, 'verify'),
2746
3603
  key,
@@ -2812,6 +3669,7 @@ export class Subtle {
2812
3669
  algorithm: SubtleAlgorithm,
2813
3670
  key: CryptoKey,
2814
3671
  ): Promise<EncapsulateResult> {
3672
+ requireArgs(arguments.length, 2, 'encapsulateBits');
2815
3673
  if (!key.usages.includes('encapsulateBits')) {
2816
3674
  throw lazyDOMException(
2817
3675
  'Key does not have encapsulateBits usage',
@@ -2829,6 +3687,7 @@ export class Subtle {
2829
3687
  extractable: boolean,
2830
3688
  usages: KeyUsage[],
2831
3689
  ): Promise<{ key: CryptoKey; ciphertext: ArrayBuffer }> {
3690
+ requireArgs(arguments.length, 5, 'encapsulateKey');
2832
3691
  if (!key.usages.includes('encapsulateKey')) {
2833
3692
  throw lazyDOMException(
2834
3693
  'Key does not have encapsulateKey usage',
@@ -2837,8 +3696,10 @@ export class Subtle {
2837
3696
  }
2838
3697
 
2839
3698
  const { sharedKey, ciphertext } = this._encapsulateCore(algorithm, key);
3699
+ // Node imports the encapsulated shared bits as 'raw-secret'
3700
+ // (webcrypto.js:1370-1374) so AEADs / KMAC accept the result.
2840
3701
  const importedKey = await this.importKey(
2841
- 'raw',
3702
+ 'raw-secret',
2842
3703
  sharedKey,
2843
3704
  sharedKeyAlgorithm,
2844
3705
  extractable,
@@ -2853,6 +3714,7 @@ export class Subtle {
2853
3714
  key: CryptoKey,
2854
3715
  ciphertext: BufferLike,
2855
3716
  ): Promise<ArrayBuffer> {
3717
+ requireArgs(arguments.length, 3, 'decapsulateBits');
2856
3718
  if (!key.usages.includes('decapsulateBits')) {
2857
3719
  throw lazyDOMException(
2858
3720
  'Key does not have decapsulateBits usage',
@@ -2871,6 +3733,7 @@ export class Subtle {
2871
3733
  extractable: boolean,
2872
3734
  usages: KeyUsage[],
2873
3735
  ): Promise<CryptoKey> {
3736
+ requireArgs(arguments.length, 6, 'decapsulateKey');
2874
3737
  if (!key.usages.includes('decapsulateKey')) {
2875
3738
  throw lazyDOMException(
2876
3739
  'Key does not have decapsulateKey usage',
@@ -2879,8 +3742,10 @@ export class Subtle {
2879
3742
  }
2880
3743
 
2881
3744
  const sharedKey = this._decapsulateCore(algorithm, key, ciphertext);
3745
+ // Node imports the decapsulated shared bits as 'raw-secret'
3746
+ // (webcrypto.js:1490-1494).
2882
3747
  return this.importKey(
2883
- 'raw',
3748
+ 'raw-secret',
2884
3749
  sharedKey,
2885
3750
  sharedKeyAlgorithm,
2886
3751
  extractable,
@@ -2891,8 +3756,14 @@ export class Subtle {
2891
3756
 
2892
3757
  export const subtle = new Subtle();
2893
3758
 
2894
- function getKeyLength(algorithm: SubtleAlgorithm): number {
3759
+ // Returns the number of bits to derive for an `importKey` algorithm, mirroring
3760
+ // Node's webcrypto.js:269-306 `getKeyLength`. Returns null for KDF algorithms
3761
+ // (HKDF / PBKDF2 / Argon2) — those carry their full derived secret without a
3762
+ // fixed key length. Throws OperationError on invalid AES / HMAC inputs rather
3763
+ // than silently coercing to a default (Node commit 4cb1f284136 behavior).
3764
+ function getKeyLength(algorithm: SubtleAlgorithm): number | null {
2895
3765
  const name = algorithm.name;
3766
+ const length = (algorithm as { length?: number }).length;
2896
3767
 
2897
3768
  switch (name) {
2898
3769
  case 'AES-CTR':
@@ -2900,18 +3771,38 @@ function getKeyLength(algorithm: SubtleAlgorithm): number {
2900
3771
  case 'AES-GCM':
2901
3772
  case 'AES-KW':
2902
3773
  case 'AES-OCB':
2903
- case 'ChaCha20-Poly1305':
2904
- return (algorithm as AesKeyGenParams).length || 256;
3774
+ if (length !== 128 && length !== 192 && length !== 256) {
3775
+ throw lazyDOMException('Invalid key length', 'OperationError');
3776
+ }
3777
+ return length;
2905
3778
 
2906
3779
  case 'HMAC': {
2907
- const hmacAlg = algorithm as { length?: number };
2908
- return hmacAlg.length || 256;
3780
+ if (length === undefined) {
3781
+ return getHmacBlockSize(
3782
+ (algorithm.hash as { name?: string } | undefined)?.name ??
3783
+ (algorithm.hash as string | undefined),
3784
+ );
3785
+ }
3786
+ if (typeof length === 'number' && length !== 0) {
3787
+ return length;
3788
+ }
3789
+ throw lazyDOMException('Invalid key length', 'OperationError');
2909
3790
  }
2910
3791
 
2911
3792
  case 'KMAC128':
2912
- return algorithm.length || 128;
3793
+ return typeof length === 'number' ? length : 128;
2913
3794
  case 'KMAC256':
2914
- return algorithm.length || 256;
3795
+ return typeof length === 'number' ? length : 256;
3796
+
3797
+ case 'ChaCha20-Poly1305':
3798
+ return 256;
3799
+
3800
+ case 'HKDF':
3801
+ case 'PBKDF2':
3802
+ case 'Argon2d':
3803
+ case 'Argon2i':
3804
+ case 'Argon2id':
3805
+ return null;
2915
3806
 
2916
3807
  default:
2917
3808
  throw lazyDOMException(
@@ -2920,3 +3811,25 @@ function getKeyLength(algorithm: SubtleAlgorithm): number {
2920
3811
  );
2921
3812
  }
2922
3813
  }
3814
+
3815
+ function getHmacBlockSize(name: string | undefined): number {
3816
+ switch (name) {
3817
+ case 'SHA-1':
3818
+ case 'SHA-256':
3819
+ return 512;
3820
+ case 'SHA-384':
3821
+ case 'SHA-512':
3822
+ return 1024;
3823
+ case 'SHA3-256':
3824
+ case 'SHA3-384':
3825
+ case 'SHA3-512':
3826
+ // SHA-3 / HMAC interaction undefined — Node throws here too
3827
+ // (webcrypto-modern-algos issue #23).
3828
+ throw lazyDOMException(
3829
+ 'Explicit algorithm length member is required',
3830
+ 'NotSupportedError',
3831
+ );
3832
+ default:
3833
+ throw lazyDOMException('Invalid key length', 'OperationError');
3834
+ }
3835
+ }