react-native-quick-crypto 1.0.10 → 1.0.12

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 (293) hide show
  1. package/android/CMakeLists.txt +16 -0
  2. package/cpp/argon2/HybridArgon2.cpp +103 -0
  3. package/cpp/argon2/HybridArgon2.hpp +32 -0
  4. package/cpp/certificate/HybridCertificate.cpp +42 -0
  5. package/cpp/certificate/HybridCertificate.hpp +16 -0
  6. package/cpp/cipher/CCMCipher.cpp +4 -1
  7. package/cpp/cipher/ChaCha20Cipher.cpp +3 -1
  8. package/cpp/cipher/ChaCha20Poly1305Cipher.cpp +5 -5
  9. package/cpp/cipher/ChaCha20Poly1305Cipher.hpp +1 -2
  10. package/cpp/cipher/HybridCipher.cpp +68 -1
  11. package/cpp/cipher/HybridCipher.hpp +6 -0
  12. package/cpp/cipher/HybridRsaCipher.cpp +0 -13
  13. package/cpp/cipher/XChaCha20Poly1305Cipher.cpp +7 -5
  14. package/cpp/cipher/XChaCha20Poly1305Cipher.hpp +1 -2
  15. package/cpp/cipher/XSalsa20Cipher.cpp +4 -0
  16. package/cpp/cipher/XSalsa20Poly1305Cipher.cpp +7 -5
  17. package/cpp/cipher/XSalsa20Poly1305Cipher.hpp +1 -2
  18. package/cpp/dh/HybridDhKeyPair.cpp +179 -0
  19. package/cpp/dh/HybridDhKeyPair.hpp +37 -0
  20. package/cpp/dsa/HybridDsaKeyPair.cpp +128 -0
  21. package/cpp/dsa/HybridDsaKeyPair.hpp +32 -0
  22. package/cpp/ecdh/HybridECDH.cpp +42 -120
  23. package/cpp/ecdh/HybridECDH.hpp +1 -0
  24. package/cpp/keys/HybridKeyObjectHandle.cpp +150 -128
  25. package/cpp/keys/HybridKeyObjectHandle.hpp +6 -3
  26. package/cpp/keys/KeyObjectData.hpp +2 -0
  27. package/cpp/kmac/HybridKmac.cpp +83 -0
  28. package/cpp/kmac/HybridKmac.hpp +31 -0
  29. package/cpp/mldsa/HybridMlDsaKeyPair.cpp +11 -20
  30. package/cpp/mldsa/HybridMlDsaKeyPair.hpp +4 -2
  31. package/cpp/mlkem/HybridMlKemKeyPair.cpp +319 -0
  32. package/cpp/mlkem/HybridMlKemKeyPair.hpp +48 -0
  33. package/cpp/prime/HybridPrime.cpp +81 -0
  34. package/cpp/prime/HybridPrime.hpp +20 -0
  35. package/cpp/sign/SignUtils.hpp +9 -26
  36. package/cpp/utils/QuickCryptoUtils.cpp +44 -0
  37. package/cpp/utils/QuickCryptoUtils.hpp +39 -0
  38. package/cpp/x509/HybridX509Certificate.cpp +174 -0
  39. package/cpp/x509/HybridX509Certificate.hpp +51 -0
  40. package/lib/commonjs/argon2.js +39 -0
  41. package/lib/commonjs/argon2.js.map +1 -0
  42. package/lib/commonjs/certificate.js +35 -0
  43. package/lib/commonjs/certificate.js.map +1 -0
  44. package/lib/commonjs/cipher.js +23 -2
  45. package/lib/commonjs/cipher.js.map +1 -1
  46. package/lib/commonjs/dhKeyPair.js +109 -0
  47. package/lib/commonjs/dhKeyPair.js.map +1 -0
  48. package/lib/commonjs/dsa.js +92 -0
  49. package/lib/commonjs/dsa.js.map +1 -0
  50. package/lib/commonjs/ec.js +18 -18
  51. package/lib/commonjs/ec.js.map +1 -1
  52. package/lib/commonjs/ecdh.js +37 -0
  53. package/lib/commonjs/ecdh.js.map +1 -1
  54. package/lib/commonjs/ed.js +9 -9
  55. package/lib/commonjs/ed.js.map +1 -1
  56. package/lib/commonjs/hash.js +17 -12
  57. package/lib/commonjs/hash.js.map +1 -1
  58. package/lib/commonjs/hkdf.js.map +1 -1
  59. package/lib/commonjs/index.js +57 -0
  60. package/lib/commonjs/index.js.map +1 -1
  61. package/lib/commonjs/keys/classes.js +11 -9
  62. package/lib/commonjs/keys/classes.js.map +1 -1
  63. package/lib/commonjs/keys/generateKeyPair.js +11 -0
  64. package/lib/commonjs/keys/generateKeyPair.js.map +1 -1
  65. package/lib/commonjs/keys/index.js +24 -0
  66. package/lib/commonjs/keys/index.js.map +1 -1
  67. package/lib/commonjs/keys/signVerify.js +0 -2
  68. package/lib/commonjs/keys/signVerify.js.map +1 -1
  69. package/lib/commonjs/mlkem.js +219 -0
  70. package/lib/commonjs/mlkem.js.map +1 -0
  71. package/lib/commonjs/pbkdf2.js +18 -1
  72. package/lib/commonjs/pbkdf2.js.map +1 -1
  73. package/lib/commonjs/prime.js +84 -0
  74. package/lib/commonjs/prime.js.map +1 -0
  75. package/lib/commonjs/rsa.js +7 -7
  76. package/lib/commonjs/rsa.js.map +1 -1
  77. package/lib/commonjs/specs/argon2.nitro.js +6 -0
  78. package/lib/commonjs/specs/argon2.nitro.js.map +1 -0
  79. package/lib/commonjs/specs/certificate.nitro.js +6 -0
  80. package/lib/commonjs/specs/certificate.nitro.js.map +1 -0
  81. package/lib/commonjs/specs/dhKeyPair.nitro.js +6 -0
  82. package/lib/commonjs/specs/dhKeyPair.nitro.js.map +1 -0
  83. package/lib/commonjs/specs/dsaKeyPair.nitro.js +6 -0
  84. package/lib/commonjs/specs/dsaKeyPair.nitro.js.map +1 -0
  85. package/lib/commonjs/specs/kmac.nitro.js +6 -0
  86. package/lib/commonjs/specs/kmac.nitro.js.map +1 -0
  87. package/lib/commonjs/specs/mlKemKeyPair.nitro.js +6 -0
  88. package/lib/commonjs/specs/mlKemKeyPair.nitro.js.map +1 -0
  89. package/lib/commonjs/specs/prime.nitro.js +6 -0
  90. package/lib/commonjs/specs/prime.nitro.js.map +1 -0
  91. package/lib/commonjs/specs/x509certificate.nitro.js +6 -0
  92. package/lib/commonjs/specs/x509certificate.nitro.js.map +1 -0
  93. package/lib/commonjs/subtle.js +385 -114
  94. package/lib/commonjs/subtle.js.map +1 -1
  95. package/lib/commonjs/utils/conversion.js +3 -3
  96. package/lib/commonjs/utils/conversion.js.map +1 -1
  97. package/lib/commonjs/utils/hashnames.js +31 -0
  98. package/lib/commonjs/utils/hashnames.js.map +1 -1
  99. package/lib/commonjs/utils/types.js.map +1 -1
  100. package/lib/commonjs/x509certificate.js +189 -0
  101. package/lib/commonjs/x509certificate.js.map +1 -0
  102. package/lib/module/argon2.js +34 -0
  103. package/lib/module/argon2.js.map +1 -0
  104. package/lib/module/certificate.js +30 -0
  105. package/lib/module/certificate.js.map +1 -0
  106. package/lib/module/cipher.js +23 -3
  107. package/lib/module/cipher.js.map +1 -1
  108. package/lib/module/dhKeyPair.js +102 -0
  109. package/lib/module/dhKeyPair.js.map +1 -0
  110. package/lib/module/dsa.js +85 -0
  111. package/lib/module/dsa.js.map +1 -0
  112. package/lib/module/ec.js +6 -6
  113. package/lib/module/ec.js.map +1 -1
  114. package/lib/module/ecdh.js +37 -0
  115. package/lib/module/ecdh.js.map +1 -1
  116. package/lib/module/ed.js +1 -1
  117. package/lib/module/ed.js.map +1 -1
  118. package/lib/module/hash.js +17 -12
  119. package/lib/module/hash.js.map +1 -1
  120. package/lib/module/hkdf.js.map +1 -1
  121. package/lib/module/index.js +15 -0
  122. package/lib/module/index.js.map +1 -1
  123. package/lib/module/keys/classes.js +11 -9
  124. package/lib/module/keys/classes.js.map +1 -1
  125. package/lib/module/keys/generateKeyPair.js +11 -0
  126. package/lib/module/keys/generateKeyPair.js.map +1 -1
  127. package/lib/module/keys/index.js +25 -1
  128. package/lib/module/keys/index.js.map +1 -1
  129. package/lib/module/keys/signVerify.js +0 -2
  130. package/lib/module/keys/signVerify.js.map +1 -1
  131. package/lib/module/mlkem.js +211 -0
  132. package/lib/module/mlkem.js.map +1 -0
  133. package/lib/module/pbkdf2.js +18 -1
  134. package/lib/module/pbkdf2.js.map +1 -1
  135. package/lib/module/prime.js +77 -0
  136. package/lib/module/prime.js.map +1 -0
  137. package/lib/module/rsa.js +1 -1
  138. package/lib/module/rsa.js.map +1 -1
  139. package/lib/module/specs/argon2.nitro.js +4 -0
  140. package/lib/module/specs/argon2.nitro.js.map +1 -0
  141. package/lib/module/specs/certificate.nitro.js +4 -0
  142. package/lib/module/specs/certificate.nitro.js.map +1 -0
  143. package/lib/module/specs/dhKeyPair.nitro.js +4 -0
  144. package/lib/module/specs/dhKeyPair.nitro.js.map +1 -0
  145. package/lib/module/specs/dsaKeyPair.nitro.js +4 -0
  146. package/lib/module/specs/dsaKeyPair.nitro.js.map +1 -0
  147. package/lib/module/specs/kmac.nitro.js +4 -0
  148. package/lib/module/specs/kmac.nitro.js.map +1 -0
  149. package/lib/module/specs/mlKemKeyPair.nitro.js +4 -0
  150. package/lib/module/specs/mlKemKeyPair.nitro.js.map +1 -0
  151. package/lib/module/specs/prime.nitro.js +4 -0
  152. package/lib/module/specs/prime.nitro.js.map +1 -0
  153. package/lib/module/specs/x509certificate.nitro.js +4 -0
  154. package/lib/module/specs/x509certificate.nitro.js.map +1 -0
  155. package/lib/module/subtle.js +386 -116
  156. package/lib/module/subtle.js.map +1 -1
  157. package/lib/module/utils/conversion.js +3 -4
  158. package/lib/module/utils/conversion.js.map +1 -1
  159. package/lib/module/utils/hashnames.js +31 -0
  160. package/lib/module/utils/hashnames.js.map +1 -1
  161. package/lib/module/utils/types.js.map +1 -1
  162. package/lib/module/x509certificate.js +184 -0
  163. package/lib/module/x509certificate.js.map +1 -0
  164. package/lib/tsconfig.tsbuildinfo +1 -1
  165. package/lib/typescript/argon2.d.ts +16 -0
  166. package/lib/typescript/argon2.d.ts.map +1 -0
  167. package/lib/typescript/certificate.d.ts +8 -0
  168. package/lib/typescript/certificate.d.ts.map +1 -0
  169. package/lib/typescript/cipher.d.ts +15 -0
  170. package/lib/typescript/cipher.d.ts.map +1 -1
  171. package/lib/typescript/dhKeyPair.d.ts +19 -0
  172. package/lib/typescript/dhKeyPair.d.ts.map +1 -0
  173. package/lib/typescript/dsa.d.ts +19 -0
  174. package/lib/typescript/dsa.d.ts.map +1 -0
  175. package/lib/typescript/ec.d.ts +1 -1
  176. package/lib/typescript/ec.d.ts.map +1 -1
  177. package/lib/typescript/ecdh.d.ts +3 -0
  178. package/lib/typescript/ecdh.d.ts.map +1 -1
  179. package/lib/typescript/ed.d.ts +1 -1
  180. package/lib/typescript/ed.d.ts.map +1 -1
  181. package/lib/typescript/hash.d.ts.map +1 -1
  182. package/lib/typescript/hkdf.d.ts +2 -6
  183. package/lib/typescript/hkdf.d.ts.map +1 -1
  184. package/lib/typescript/index.d.ts +32 -4
  185. package/lib/typescript/index.d.ts.map +1 -1
  186. package/lib/typescript/keys/classes.d.ts +7 -5
  187. package/lib/typescript/keys/classes.d.ts.map +1 -1
  188. package/lib/typescript/keys/generateKeyPair.d.ts.map +1 -1
  189. package/lib/typescript/keys/index.d.ts +2 -2
  190. package/lib/typescript/keys/index.d.ts.map +1 -1
  191. package/lib/typescript/keys/signVerify.d.ts.map +1 -1
  192. package/lib/typescript/mlkem.d.ts +30 -0
  193. package/lib/typescript/mlkem.d.ts.map +1 -0
  194. package/lib/typescript/pbkdf2.d.ts +2 -2
  195. package/lib/typescript/pbkdf2.d.ts.map +1 -1
  196. package/lib/typescript/prime.d.ts +19 -0
  197. package/lib/typescript/prime.d.ts.map +1 -0
  198. package/lib/typescript/rsa.d.ts +1 -1
  199. package/lib/typescript/rsa.d.ts.map +1 -1
  200. package/lib/typescript/specs/argon2.nitro.d.ts +9 -0
  201. package/lib/typescript/specs/argon2.nitro.d.ts.map +1 -0
  202. package/lib/typescript/specs/certificate.nitro.d.ts +10 -0
  203. package/lib/typescript/specs/certificate.nitro.d.ts.map +1 -0
  204. package/lib/typescript/specs/cipher.nitro.d.ts +9 -0
  205. package/lib/typescript/specs/cipher.nitro.d.ts.map +1 -1
  206. package/lib/typescript/specs/dhKeyPair.nitro.d.ts +14 -0
  207. package/lib/typescript/specs/dhKeyPair.nitro.d.ts.map +1 -0
  208. package/lib/typescript/specs/dsaKeyPair.nitro.d.ts +13 -0
  209. package/lib/typescript/specs/dsaKeyPair.nitro.d.ts.map +1 -0
  210. package/lib/typescript/specs/ecdh.nitro.d.ts +1 -0
  211. package/lib/typescript/specs/ecdh.nitro.d.ts.map +1 -1
  212. package/lib/typescript/specs/keyObjectHandle.nitro.d.ts +1 -0
  213. package/lib/typescript/specs/keyObjectHandle.nitro.d.ts.map +1 -1
  214. package/lib/typescript/specs/kmac.nitro.d.ts +10 -0
  215. package/lib/typescript/specs/kmac.nitro.d.ts.map +1 -0
  216. package/lib/typescript/specs/mlKemKeyPair.nitro.d.ts +18 -0
  217. package/lib/typescript/specs/mlKemKeyPair.nitro.d.ts.map +1 -0
  218. package/lib/typescript/specs/prime.nitro.d.ts +11 -0
  219. package/lib/typescript/specs/prime.nitro.d.ts.map +1 -0
  220. package/lib/typescript/specs/x509certificate.nitro.d.ts +34 -0
  221. package/lib/typescript/specs/x509certificate.nitro.d.ts.map +1 -0
  222. package/lib/typescript/subtle.d.ts +12 -0
  223. package/lib/typescript/subtle.d.ts.map +1 -1
  224. package/lib/typescript/utils/conversion.d.ts.map +1 -1
  225. package/lib/typescript/utils/hashnames.d.ts +1 -1
  226. package/lib/typescript/utils/hashnames.d.ts.map +1 -1
  227. package/lib/typescript/utils/types.d.ts +25 -9
  228. package/lib/typescript/utils/types.d.ts.map +1 -1
  229. package/lib/typescript/x509certificate.d.ts +64 -0
  230. package/lib/typescript/x509certificate.d.ts.map +1 -0
  231. package/nitrogen/generated/android/QuickCrypto+autolinking.cmake +8 -0
  232. package/nitrogen/generated/android/QuickCryptoOnLoad.cpp +80 -0
  233. package/nitrogen/generated/ios/QuickCryptoAutolinking.mm +80 -0
  234. package/nitrogen/generated/shared/c++/AsymmetricKeyType.hpp +12 -0
  235. package/nitrogen/generated/shared/c++/CipherInfo.hpp +104 -0
  236. package/nitrogen/generated/shared/c++/HybridArgon2Spec.cpp +22 -0
  237. package/nitrogen/generated/shared/c++/HybridArgon2Spec.hpp +66 -0
  238. package/nitrogen/generated/shared/c++/HybridCertificateSpec.cpp +23 -0
  239. package/nitrogen/generated/shared/c++/HybridCertificateSpec.hpp +64 -0
  240. package/nitrogen/generated/shared/c++/HybridCipherSpec.cpp +1 -0
  241. package/nitrogen/generated/shared/c++/HybridCipherSpec.hpp +4 -0
  242. package/nitrogen/generated/shared/c++/HybridDhKeyPairSpec.cpp +27 -0
  243. package/nitrogen/generated/shared/c++/HybridDhKeyPairSpec.hpp +69 -0
  244. package/nitrogen/generated/shared/c++/HybridDsaKeyPairSpec.cpp +26 -0
  245. package/nitrogen/generated/shared/c++/HybridDsaKeyPairSpec.hpp +68 -0
  246. package/nitrogen/generated/shared/c++/HybridECDHSpec.cpp +1 -0
  247. package/nitrogen/generated/shared/c++/HybridECDHSpec.hpp +1 -0
  248. package/nitrogen/generated/shared/c++/HybridKeyObjectHandleSpec.cpp +1 -0
  249. package/nitrogen/generated/shared/c++/HybridKeyObjectHandleSpec.hpp +1 -0
  250. package/nitrogen/generated/shared/c++/HybridKmacSpec.cpp +23 -0
  251. package/nitrogen/generated/shared/c++/HybridKmacSpec.hpp +66 -0
  252. package/nitrogen/generated/shared/c++/HybridMlKemKeyPairSpec.cpp +31 -0
  253. package/nitrogen/generated/shared/c++/HybridMlKemKeyPairSpec.hpp +74 -0
  254. package/nitrogen/generated/shared/c++/HybridPrimeSpec.cpp +24 -0
  255. package/nitrogen/generated/shared/c++/HybridPrimeSpec.hpp +67 -0
  256. package/nitrogen/generated/shared/c++/HybridX509CertificateHandleSpec.cpp +46 -0
  257. package/nitrogen/generated/shared/c++/HybridX509CertificateHandleSpec.hpp +96 -0
  258. package/package.json +4 -1
  259. package/src/argon2.ts +83 -0
  260. package/src/certificate.ts +41 -0
  261. package/src/cipher.ts +41 -3
  262. package/src/dhKeyPair.ts +156 -0
  263. package/src/dsa.ts +129 -0
  264. package/src/ec.ts +9 -9
  265. package/src/ecdh.ts +59 -0
  266. package/src/ed.ts +2 -2
  267. package/src/hash.ts +34 -11
  268. package/src/hkdf.ts +2 -7
  269. package/src/index.ts +16 -0
  270. package/src/keys/classes.ts +26 -14
  271. package/src/keys/generateKeyPair.ts +14 -0
  272. package/src/keys/index.ts +37 -2
  273. package/src/keys/signVerify.ts +0 -5
  274. package/src/mlkem.ts +350 -0
  275. package/src/pbkdf2.ts +34 -5
  276. package/src/prime.ts +134 -0
  277. package/src/rsa.ts +1 -1
  278. package/src/specs/argon2.nitro.ts +29 -0
  279. package/src/specs/certificate.nitro.ts +8 -0
  280. package/src/specs/cipher.nitro.ts +14 -0
  281. package/src/specs/dhKeyPair.nitro.ts +14 -0
  282. package/src/specs/dsaKeyPair.nitro.ts +13 -0
  283. package/src/specs/ecdh.nitro.ts +1 -0
  284. package/src/specs/keyObjectHandle.nitro.ts +5 -0
  285. package/src/specs/kmac.nitro.ts +12 -0
  286. package/src/specs/mlKemKeyPair.nitro.ts +32 -0
  287. package/src/specs/prime.nitro.ts +18 -0
  288. package/src/specs/x509certificate.nitro.ts +38 -0
  289. package/src/subtle.ts +821 -136
  290. package/src/utils/conversion.ts +10 -4
  291. package/src/utils/hashnames.ts +33 -2
  292. package/src/utils/types.ts +64 -8
  293. package/src/x509certificate.ts +277 -0
@@ -5,27 +5,24 @@ import { Buffer as SBuffer } from 'safe-buffer';
5
5
  import { KFormatType, KeyEncoding, KeyType } from './utils';
6
6
  import { CryptoKey, KeyObject, PublicKeyObject, PrivateKeyObject, SecretKeyObject } from './keys';
7
7
  import { bufferLikeToArrayBuffer } from './utils/conversion';
8
+ import { argon2Sync } from './argon2';
8
9
  import { lazyDOMException } from './utils/errors';
9
10
  import { normalizeHashName, HashContext } from './utils/hashnames';
10
11
  import { validateMaxBufferLength } from './utils/validation';
11
12
  import { asyncDigest } from './hash';
12
- import { createSecretKey } from './keys';
13
+ import { createSecretKey, createPublicKey } from './keys';
13
14
  import { NitroModules } from 'react-native-nitro-modules';
14
15
  import { pbkdf2DeriveBits } from './pbkdf2';
15
16
  import { ecImportKey, ecdsaSignVerify, ec_generateKeyPair, ecDeriveBits } from './ec';
16
17
  import { rsa_generateKeyPair } from './rsa';
17
18
  import { getRandomValues } from './random';
18
19
  import { createHmac } from './hmac';
20
+ import { timingSafeEqual } from './utils/timingSafeEqual';
19
21
  import { createSign, createVerify } from './keys/signVerify';
20
22
  import { ed_generateKeyPairWebCrypto, x_generateKeyPairWebCrypto, xDeriveBits, Ed } from './ed';
21
23
  import { mldsa_generateKeyPairWebCrypto } from './mldsa';
24
+ import { mlkem_generateKeyPairWebCrypto, MlKem } from './mlkem';
22
25
  import { hkdfDeriveBits } from './hkdf';
23
- // import { pbkdf2DeriveBits } from './pbkdf2';
24
- // import { aesCipher, aesGenerateKey, aesImportKey, getAlgorithmName } from './aes';
25
- // import { rsaCipher, rsaExportKey, rsaImportKey, rsaKeyGenerate } from './rsa';
26
- // import { normalizeAlgorithm, type Operation } from './algorithms';
27
- // import { hmacImportKey } from './mac';
28
-
29
26
  // Temporary enums that need to be defined
30
27
  var KWebCryptoKeyFormat = /*#__PURE__*/function (KWebCryptoKeyFormat) {
31
28
  KWebCryptoKeyFormat[KWebCryptoKeyFormat["kWebCryptoKeyFormatRaw"] = 0] = "kWebCryptoKeyFormatRaw";
@@ -71,15 +68,15 @@ function getAlgorithmName(name, length) {
71
68
  // Placeholder implementations for missing functions
72
69
  function ecExportKey(key, format) {
73
70
  const keyObject = key.keyObject;
74
- if (format === KWebCryptoKeyFormat.kWebCryptoKeyFormatSPKI) {
75
- // Export public key in SPKI format
71
+ if (format === KWebCryptoKeyFormat.kWebCryptoKeyFormatRaw) {
72
+ return bufferLikeToArrayBuffer(keyObject.handle.exportKey());
73
+ } else if (format === KWebCryptoKeyFormat.kWebCryptoKeyFormatSPKI) {
76
74
  const exported = keyObject.export({
77
75
  format: 'der',
78
76
  type: 'spki'
79
77
  });
80
78
  return bufferLikeToArrayBuffer(exported);
81
79
  } else if (format === KWebCryptoKeyFormat.kWebCryptoKeyFormatPKCS8) {
82
- // Export private key in PKCS8 format
83
80
  const exported = keyObject.export({
84
81
  format: 'der',
85
82
  type: 'pkcs8'
@@ -488,6 +485,100 @@ async function hmacGenerateKey(algorithm, extractable, keyUsages) {
488
485
  };
489
486
  return new CryptoKey(keyObject, keyAlgorithm, keyUsages, extractable);
490
487
  }
488
+ async function kmacGenerateKey(algorithm, extractable, keyUsages) {
489
+ const {
490
+ name
491
+ } = algorithm;
492
+ if (hasAnyNotIn(keyUsages, ['sign', 'verify'])) {
493
+ throw lazyDOMException(`Unsupported key usage for ${name} key`, 'SyntaxError');
494
+ }
495
+ const defaultLength = name === 'KMAC128' ? 128 : 256;
496
+ const length = algorithm.length ?? defaultLength;
497
+ if (length === 0) {
498
+ throw lazyDOMException('Zero-length key is not supported', 'OperationError');
499
+ }
500
+ const keyBytes = new Uint8Array(Math.ceil(length / 8));
501
+ getRandomValues(keyBytes);
502
+ const keyObject = createSecretKey(keyBytes);
503
+ const keyAlgorithm = {
504
+ name: name,
505
+ length
506
+ };
507
+ return new CryptoKey(keyObject, keyAlgorithm, keyUsages, extractable);
508
+ }
509
+ function kmacSignVerify(key, data, algorithm, signature) {
510
+ const {
511
+ name
512
+ } = algorithm;
513
+ const defaultLength = name === 'KMAC128' ? 256 : 512;
514
+ const outputLengthBits = algorithm.length ?? defaultLength;
515
+ if (outputLengthBits % 8 !== 0) {
516
+ throw lazyDOMException('KMAC output length must be a multiple of 8', 'OperationError');
517
+ }
518
+ const outputLengthBytes = outputLengthBits / 8;
519
+ const keyData = key.keyObject.export();
520
+ const kmac = NitroModules.createHybridObject('Kmac');
521
+ let customizationBuffer;
522
+ if (algorithm.customization !== undefined) {
523
+ customizationBuffer = bufferLikeToArrayBuffer(algorithm.customization);
524
+ }
525
+ kmac.createKmac(name, bufferLikeToArrayBuffer(keyData), outputLengthBytes, customizationBuffer);
526
+ kmac.update(bufferLikeToArrayBuffer(data));
527
+ const computed = kmac.digest();
528
+ if (signature === undefined) {
529
+ return computed;
530
+ }
531
+ const sigBuffer = bufferLikeToArrayBuffer(signature);
532
+ if (computed.byteLength !== sigBuffer.byteLength) {
533
+ return false;
534
+ }
535
+ return timingSafeEqual(new Uint8Array(computed), new Uint8Array(sigBuffer));
536
+ }
537
+ async function kmacImportKey(algorithm, format, data, extractable, keyUsages) {
538
+ const {
539
+ name
540
+ } = algorithm;
541
+ if (hasAnyNotIn(keyUsages, ['sign', 'verify'])) {
542
+ throw lazyDOMException(`Unsupported key usage for ${name} key`, 'SyntaxError');
543
+ }
544
+ let keyObject;
545
+ if (format === 'jwk') {
546
+ const jwk = data;
547
+ if (!jwk || typeof jwk !== 'object') {
548
+ throw lazyDOMException('Invalid keyData', 'DataError');
549
+ }
550
+ if (jwk.kty !== 'oct') {
551
+ throw lazyDOMException('Invalid JWK format for KMAC key', 'DataError');
552
+ }
553
+ const expectedAlg = name === 'KMAC128' ? 'K128' : 'K256';
554
+ if (jwk.alg !== undefined && jwk.alg !== expectedAlg) {
555
+ throw lazyDOMException('JWK "alg" does not match the requested algorithm', 'DataError');
556
+ }
557
+ const handle = NitroModules.createHybridObject('KeyObjectHandle');
558
+ const keyType = handle.initJwk(jwk, undefined);
559
+ if (keyType === undefined || keyType !== 0) {
560
+ throw lazyDOMException('Failed to import KMAC JWK', 'DataError');
561
+ }
562
+ keyObject = new SecretKeyObject(handle);
563
+ } else if (format === 'raw' || format === 'raw-secret') {
564
+ keyObject = createSecretKey(data);
565
+ } else {
566
+ throw lazyDOMException(`Unable to import ${name} key with format ${format}`, 'NotSupportedError');
567
+ }
568
+ const exported = keyObject.export();
569
+ const keyLength = exported.byteLength * 8;
570
+ if (keyLength === 0) {
571
+ throw lazyDOMException('Zero-length key is not supported', 'DataError');
572
+ }
573
+ if (algorithm.length !== undefined && algorithm.length !== keyLength) {
574
+ throw lazyDOMException('Invalid key length', 'DataError');
575
+ }
576
+ const keyAlgorithm = {
577
+ name: name,
578
+ length: keyLength
579
+ };
580
+ return new CryptoKey(keyObject, keyAlgorithm, keyUsages, extractable);
581
+ }
491
582
  function rsaImportKey(format, data, algorithm, extractable, keyUsages) {
492
583
  const {
493
584
  name
@@ -725,28 +816,48 @@ function edImportKey(format, data, algorithm, extractable, keyUsages) {
725
816
  name
726
817
  }, keyUsages, extractable);
727
818
  }
819
+ function pqcImportKeyObject(format, data, name) {
820
+ if (format === 'spki') {
821
+ return KeyObject.createKeyObject('public', bufferLikeToArrayBuffer(data), KFormatType.DER, KeyEncoding.SPKI);
822
+ } else if (format === 'pkcs8') {
823
+ return KeyObject.createKeyObject('private', bufferLikeToArrayBuffer(data), KFormatType.DER, KeyEncoding.PKCS8);
824
+ } else if (format === 'raw') {
825
+ const handle = NitroModules.createHybridObject('KeyObjectHandle');
826
+ if (!handle.initPqcRaw(name, bufferLikeToArrayBuffer(data), true)) {
827
+ throw lazyDOMException(`Failed to import ${name} raw public key`, 'DataError');
828
+ }
829
+ return new PublicKeyObject(handle);
830
+ } else if (format === 'raw-seed') {
831
+ const handle = NitroModules.createHybridObject('KeyObjectHandle');
832
+ if (!handle.initPqcRaw(name, bufferLikeToArrayBuffer(data), false)) {
833
+ throw lazyDOMException(`Failed to import ${name} raw seed`, 'DataError');
834
+ }
835
+ return new PrivateKeyObject(handle);
836
+ }
837
+ throw lazyDOMException(`Unsupported format for ${name} import: ${format}`, 'NotSupportedError');
838
+ }
728
839
  function mldsaImportKey(format, data, algorithm, extractable, keyUsages) {
729
840
  const {
730
841
  name
731
842
  } = algorithm;
732
-
733
- // Validate usages
734
- if (hasAnyNotIn(keyUsages, ['sign', 'verify'])) {
843
+ const isPublicFormat = format === 'spki' || format === 'raw';
844
+ if (hasAnyNotIn(keyUsages, isPublicFormat ? ['verify'] : ['sign'])) {
735
845
  throw lazyDOMException(`Unsupported key usage for ${name} key`, 'SyntaxError');
736
846
  }
737
- let keyObject;
738
- if (format === 'spki') {
739
- // Import public key
740
- const keyData = bufferLikeToArrayBuffer(data);
741
- keyObject = KeyObject.createKeyObject('public', keyData, KFormatType.DER, KeyEncoding.SPKI);
742
- } else if (format === 'pkcs8') {
743
- // Import private key
744
- const keyData = bufferLikeToArrayBuffer(data);
745
- keyObject = KeyObject.createKeyObject('private', keyData, KFormatType.DER, KeyEncoding.PKCS8);
746
- } else {
747
- throw lazyDOMException(`Unsupported format for ${name} import: ${format}`, 'NotSupportedError');
847
+ return new CryptoKey(pqcImportKeyObject(format, data, name), {
848
+ name
849
+ }, keyUsages, extractable);
850
+ }
851
+ function mlkemImportKey(format, data, algorithm, extractable, keyUsages) {
852
+ const {
853
+ name
854
+ } = algorithm;
855
+ const isPublicFormat = format === 'spki' || format === 'raw';
856
+ const allowedUsages = isPublicFormat ? ['encapsulateBits', 'encapsulateKey'] : ['decapsulateBits', 'decapsulateKey'];
857
+ if (hasAnyNotIn(keyUsages, allowedUsages)) {
858
+ throw lazyDOMException(`Unsupported key usage for ${name} key`, 'SyntaxError');
748
859
  }
749
- return new CryptoKey(keyObject, {
860
+ return new CryptoKey(pqcImportKeyObject(format, data, name), {
750
861
  name
751
862
  }, keyUsages, extractable);
752
863
  }
@@ -790,6 +901,15 @@ const exportKeySpki = async key => {
790
901
  return bufferLikeToArrayBuffer(key.keyObject.handle.exportKey(KFormatType.DER, KeyEncoding.SPKI));
791
902
  }
792
903
  break;
904
+ case 'ML-KEM-512':
905
+ // Fall through
906
+ case 'ML-KEM-768':
907
+ // Fall through
908
+ case 'ML-KEM-1024':
909
+ if (key.type === 'public') {
910
+ return bufferLikeToArrayBuffer(key.keyObject.handle.exportKey(KFormatType.DER, KeyEncoding.SPKI));
911
+ }
912
+ break;
793
913
  }
794
914
  throw new Error(`Unable to export a spki ${key.algorithm.name} ${key.type} key`);
795
915
  };
@@ -833,6 +953,15 @@ const exportKeyPkcs8 = async key => {
833
953
  return bufferLikeToArrayBuffer(key.keyObject.handle.exportKey(KFormatType.DER, KeyEncoding.PKCS8));
834
954
  }
835
955
  break;
956
+ case 'ML-KEM-512':
957
+ // Fall through
958
+ case 'ML-KEM-768':
959
+ // Fall through
960
+ case 'ML-KEM-1024':
961
+ if (key.type === 'private') {
962
+ return bufferLikeToArrayBuffer(key.keyObject.handle.exportKey(KFormatType.DER, KeyEncoding.PKCS8));
963
+ }
964
+ break;
836
965
  }
837
966
  throw new Error(`Unable to export a pkcs8 ${key.algorithm.name} ${key.type} key`);
838
967
  };
@@ -853,7 +982,22 @@ const exportKeyRaw = key => {
853
982
  // Fall through
854
983
  case 'X448':
855
984
  if (key.type === 'public') {
856
- // Export raw public key
985
+ const exported = key.keyObject.handle.exportKey();
986
+ return bufferLikeToArrayBuffer(exported);
987
+ }
988
+ break;
989
+ case 'ML-KEM-512':
990
+ // Fall through
991
+ case 'ML-KEM-768':
992
+ // Fall through
993
+ case 'ML-KEM-1024':
994
+ // Fall through
995
+ case 'ML-DSA-44':
996
+ // Fall through
997
+ case 'ML-DSA-65':
998
+ // Fall through
999
+ case 'ML-DSA-87':
1000
+ if (key.type === 'public') {
857
1001
  const exported = key.keyObject.handle.exportKey();
858
1002
  return bufferLikeToArrayBuffer(exported);
859
1003
  }
@@ -871,6 +1015,10 @@ const exportKeyRaw = key => {
871
1015
  case 'ChaCha20-Poly1305':
872
1016
  // Fall through
873
1017
  case 'HMAC':
1018
+ // Fall through
1019
+ case 'KMAC128':
1020
+ // Fall through
1021
+ case 'KMAC256':
874
1022
  {
875
1023
  const exported = key.keyObject.export();
876
1024
  // Convert Buffer to ArrayBuffer
@@ -897,6 +1045,12 @@ const exportKeyJWK = key => {
897
1045
  case 'HMAC':
898
1046
  jwk.alg = normalizeHashName(key.algorithm.hash, HashContext.JwkHmac);
899
1047
  return jwk;
1048
+ case 'KMAC128':
1049
+ jwk.alg = 'K128';
1050
+ return jwk;
1051
+ case 'KMAC256':
1052
+ jwk.alg = 'K256';
1053
+ return jwk;
900
1054
  case 'ECDSA':
901
1055
  // Fall through
902
1056
  case 'ECDH':
@@ -984,6 +1138,37 @@ const checkCryptoKeyPairUsages = pair => {
984
1138
  }
985
1139
  throw lazyDOMException('Usages cannot be empty when creating a key.', 'SyntaxError');
986
1140
  };
1141
+ function argon2DeriveBits(algorithm, baseKey, length) {
1142
+ if (length === 0 || length % 8 !== 0) {
1143
+ throw lazyDOMException('Invalid Argon2 derived key length', 'OperationError');
1144
+ }
1145
+ if (length < 32) {
1146
+ throw lazyDOMException('Argon2 derived key length must be at least 32 bits', 'OperationError');
1147
+ }
1148
+ const {
1149
+ nonce,
1150
+ parallelism,
1151
+ memory,
1152
+ passes,
1153
+ secretValue,
1154
+ associatedData
1155
+ } = algorithm;
1156
+ const tagLength = length / 8;
1157
+ const message = baseKey.keyObject.export();
1158
+ const algName = algorithm.name.toLowerCase();
1159
+ const result = argon2Sync(algName, {
1160
+ message,
1161
+ nonce: nonce ?? new Uint8Array(0),
1162
+ parallelism: parallelism ?? 1,
1163
+ tagLength,
1164
+ memory: memory ?? 65536,
1165
+ passes: passes ?? 3,
1166
+ secret: secretValue,
1167
+ associatedData,
1168
+ version: algorithm.version
1169
+ });
1170
+ return bufferLikeToArrayBuffer(result);
1171
+ }
987
1172
 
988
1173
  // Type guard to check if result is CryptoKeyPair
989
1174
  export function isCryptoKeyPair(result) {
@@ -1004,20 +1189,12 @@ function hmacSignVerify(key, data, signature) {
1004
1189
  // Sign operation - return the HMAC as ArrayBuffer
1005
1190
  return computed.buffer.slice(computed.byteOffset, computed.byteOffset + computed.byteLength);
1006
1191
  }
1007
-
1008
- // Verify operation - compare computed HMAC with provided signature
1009
- const sigBytes = new Uint8Array(bufferLikeToArrayBuffer(signature));
1010
- const computedBytes = new Uint8Array(computed.buffer, computed.byteOffset, computed.byteLength);
1011
- if (computedBytes.length !== sigBytes.length) {
1192
+ const sigBuffer = bufferLikeToArrayBuffer(signature);
1193
+ const computedBuffer = computed.buffer.slice(computed.byteOffset, computed.byteOffset + computed.byteLength);
1194
+ if (computedBuffer.byteLength !== sigBuffer.byteLength) {
1012
1195
  return false;
1013
1196
  }
1014
-
1015
- // Constant-time comparison to prevent timing attacks
1016
- let result = 0;
1017
- for (let i = 0; i < computedBytes.length; i++) {
1018
- result |= computedBytes[i] ^ sigBytes[i];
1019
- }
1020
- return result === 0;
1197
+ return timingSafeEqual(new Uint8Array(computedBuffer), new Uint8Array(sigBuffer));
1021
1198
  }
1022
1199
  function rsaSignVerify(key, data, padding, signature, saltLength) {
1023
1200
  // Get hash algorithm from key
@@ -1120,6 +1297,9 @@ const signVerify = (algorithm, key, data, signature) => {
1120
1297
  case 'ML-DSA-65':
1121
1298
  case 'ML-DSA-87':
1122
1299
  return mldsaSignVerify(key, data, signature);
1300
+ case 'KMAC128':
1301
+ case 'KMAC256':
1302
+ return kmacSignVerify(key, data, algorithm, signature);
1123
1303
  }
1124
1304
  throw lazyDOMException(`Unrecognized algorithm name '${algorithm.name}' for '${usage}'`, 'NotSupportedError');
1125
1305
  };
@@ -1145,7 +1325,53 @@ const cipherOrWrap = async (mode, algorithm, key, data, op) => {
1145
1325
  return chaCha20Poly1305Cipher(mode, key, data, algorithm);
1146
1326
  }
1147
1327
  };
1328
+ const SUPPORTED_ALGORITHMS = {
1329
+ encrypt: new Set(['RSA-OAEP', 'AES-CTR', 'AES-CBC', 'AES-GCM', 'AES-OCB', 'ChaCha20-Poly1305']),
1330
+ decrypt: new Set(['RSA-OAEP', 'AES-CTR', 'AES-CBC', 'AES-GCM', 'AES-OCB', 'ChaCha20-Poly1305']),
1331
+ sign: new Set(['RSASSA-PKCS1-v1_5', 'RSA-PSS', 'ECDSA', 'HMAC', 'KMAC128', 'KMAC256', 'Ed25519', 'Ed448', 'ML-DSA-44', 'ML-DSA-65', 'ML-DSA-87']),
1332
+ verify: new Set(['RSASSA-PKCS1-v1_5', 'RSA-PSS', 'ECDSA', 'HMAC', 'KMAC128', 'KMAC256', 'Ed25519', 'Ed448', 'ML-DSA-44', 'ML-DSA-65', 'ML-DSA-87']),
1333
+ digest: new Set(['SHA-1', 'SHA-256', 'SHA-384', 'SHA-512', 'SHA3-256', 'SHA3-384', 'SHA3-512', 'cSHAKE128', 'cSHAKE256']),
1334
+ generateKey: new Set(['RSASSA-PKCS1-v1_5', 'RSA-PSS', 'RSA-OAEP', 'ECDSA', 'ECDH', 'Ed25519', 'Ed448', 'X25519', 'X448', 'AES-CTR', 'AES-CBC', 'AES-GCM', 'AES-KW', 'AES-OCB', 'ChaCha20-Poly1305', 'HMAC', 'KMAC128', 'KMAC256', 'ML-DSA-44', 'ML-DSA-65', 'ML-DSA-87', 'ML-KEM-512', 'ML-KEM-768', 'ML-KEM-1024']),
1335
+ importKey: new Set(['RSASSA-PKCS1-v1_5', 'RSA-PSS', 'RSA-OAEP', 'ECDSA', 'ECDH', 'Ed25519', 'Ed448', 'X25519', 'X448', 'AES-CTR', 'AES-CBC', 'AES-GCM', 'AES-KW', 'AES-OCB', 'ChaCha20-Poly1305', 'HMAC', 'KMAC128', 'KMAC256', 'HKDF', 'PBKDF2', 'Argon2d', 'Argon2i', 'Argon2id', 'ML-DSA-44', 'ML-DSA-65', 'ML-DSA-87', 'ML-KEM-512', 'ML-KEM-768', 'ML-KEM-1024']),
1336
+ exportKey: new Set(['RSASSA-PKCS1-v1_5', 'RSA-PSS', 'RSA-OAEP', 'ECDSA', 'ECDH', 'Ed25519', 'Ed448', 'X25519', 'X448', 'AES-CTR', 'AES-CBC', 'AES-GCM', 'AES-KW', 'AES-OCB', 'ChaCha20-Poly1305', 'HMAC', 'KMAC128', 'KMAC256', 'ML-DSA-44', 'ML-DSA-65', 'ML-DSA-87', 'ML-KEM-512', 'ML-KEM-768', 'ML-KEM-1024']),
1337
+ deriveBits: new Set(['PBKDF2', 'HKDF', 'ECDH', 'X25519', 'X448', 'Argon2d', 'Argon2i', 'Argon2id']),
1338
+ wrapKey: new Set(['AES-CTR', 'AES-CBC', 'AES-GCM', 'AES-KW', 'AES-OCB', 'ChaCha20-Poly1305', 'RSA-OAEP']),
1339
+ unwrapKey: new Set(['AES-CTR', 'AES-CBC', 'AES-GCM', 'AES-KW', 'AES-OCB', 'ChaCha20-Poly1305', 'RSA-OAEP']),
1340
+ encapsulateBits: new Set(['ML-KEM-512', 'ML-KEM-768', 'ML-KEM-1024']),
1341
+ decapsulateBits: new Set(['ML-KEM-512', 'ML-KEM-768', 'ML-KEM-1024']),
1342
+ encapsulateKey: new Set(['ML-KEM-512', 'ML-KEM-768', 'ML-KEM-1024']),
1343
+ decapsulateKey: new Set(['ML-KEM-512', 'ML-KEM-768', 'ML-KEM-1024'])
1344
+ };
1345
+ const ASYMMETRIC_ALGORITHMS = new Set(['RSASSA-PKCS1-v1_5', 'RSA-PSS', 'RSA-OAEP', 'ECDSA', 'ECDH', 'Ed25519', 'Ed448', 'X25519', 'X448', 'ML-DSA-44', 'ML-DSA-65', 'ML-DSA-87', 'ML-KEM-512', 'ML-KEM-768', 'ML-KEM-1024']);
1148
1346
  export class Subtle {
1347
+ static supports(operation, algorithm, _lengthOrAdditionalAlgorithm) {
1348
+ let normalizedAlgorithm;
1349
+ try {
1350
+ normalizedAlgorithm = normalizeAlgorithm(algorithm, operation === 'getPublicKey' ? 'exportKey' : operation);
1351
+ } catch {
1352
+ return false;
1353
+ }
1354
+ const name = normalizedAlgorithm.name;
1355
+ if (operation === 'getPublicKey') {
1356
+ return ASYMMETRIC_ALGORITHMS.has(name);
1357
+ }
1358
+ if (operation === 'deriveKey') {
1359
+ // deriveKey decomposes to deriveBits + importKey of additional algorithm
1360
+ if (!SUPPORTED_ALGORITHMS.deriveBits?.has(name)) return false;
1361
+ if (_lengthOrAdditionalAlgorithm != null) {
1362
+ try {
1363
+ const additionalAlg = normalizeAlgorithm(_lengthOrAdditionalAlgorithm, 'importKey');
1364
+ return SUPPORTED_ALGORITHMS.importKey?.has(additionalAlg.name) ?? false;
1365
+ } catch {
1366
+ return false;
1367
+ }
1368
+ }
1369
+ return true;
1370
+ }
1371
+ const supported = SUPPORTED_ALGORITHMS[operation];
1372
+ if (!supported) return false;
1373
+ return supported.has(name);
1374
+ }
1149
1375
  async decrypt(algorithm, key, data) {
1150
1376
  const normalizedAlgorithm = normalizeAlgorithm(algorithm, 'decrypt');
1151
1377
  return cipherOrWrap(CipherOrWrapMode.kWebCryptoCipherDecrypt, normalizedAlgorithm, key, bufferLikeToArrayBuffer(data), 'decrypt');
@@ -1171,6 +1397,10 @@ export class Subtle {
1171
1397
  return ecDeriveBits(algorithm, baseKey, length);
1172
1398
  case 'HKDF':
1173
1399
  return hkdfDeriveBits(algorithm, baseKey, length);
1400
+ case 'Argon2d':
1401
+ case 'Argon2i':
1402
+ case 'Argon2id':
1403
+ return argon2DeriveBits(algorithm, baseKey, length);
1174
1404
  }
1175
1405
  throw new Error(`'subtle.deriveBits()' for ${algorithm.name} is not implemented.`);
1176
1406
  }
@@ -1201,6 +1431,11 @@ export class Subtle {
1201
1431
  case 'HKDF':
1202
1432
  derivedBits = hkdfDeriveBits(algorithm, baseKey, length);
1203
1433
  break;
1434
+ case 'Argon2d':
1435
+ case 'Argon2i':
1436
+ case 'Argon2id':
1437
+ derivedBits = argon2DeriveBits(algorithm, baseKey, length);
1438
+ break;
1204
1439
  default:
1205
1440
  throw new Error(`'subtle.deriveKey()' for ${algorithm.name} is not implemented.`);
1206
1441
  }
@@ -1214,7 +1449,19 @@ export class Subtle {
1214
1449
  }
1215
1450
  async exportKey(format, key) {
1216
1451
  if (!key.extractable) throw new Error('key is not extractable');
1217
- if (format === 'raw-secret') format = 'raw';
1452
+ if (format === 'raw-seed') {
1453
+ const pqcAlgos = ['ML-KEM-512', 'ML-KEM-768', 'ML-KEM-1024', 'ML-DSA-44', 'ML-DSA-65', 'ML-DSA-87'];
1454
+ if (!pqcAlgos.includes(key.algorithm.name)) {
1455
+ throw lazyDOMException('raw-seed export only supported for PQC keys', 'NotSupportedError');
1456
+ }
1457
+ if (key.type !== 'private') {
1458
+ throw lazyDOMException('raw-seed export requires a private key', 'InvalidAccessError');
1459
+ }
1460
+ return bufferLikeToArrayBuffer(key.keyObject.handle.exportKey());
1461
+ }
1462
+
1463
+ // Note: 'raw-seed' is handled above; do NOT normalize it here
1464
+ if (format === 'raw-secret' || format === 'raw-public') format = 'raw';
1218
1465
  switch (format) {
1219
1466
  case 'spki':
1220
1467
  return await exportKeySpki(key);
@@ -1339,6 +1586,11 @@ export class Subtle {
1339
1586
  case 'HMAC':
1340
1587
  result = await hmacGenerateKey(algorithm, extractable, keyUsages);
1341
1588
  break;
1589
+ case 'KMAC128':
1590
+ // Fall through
1591
+ case 'KMAC256':
1592
+ result = await kmacGenerateKey(algorithm, extractable, keyUsages);
1593
+ break;
1342
1594
  case 'Ed25519':
1343
1595
  // Fall through
1344
1596
  case 'Ed448':
@@ -1359,14 +1611,33 @@ export class Subtle {
1359
1611
  result = await x_generateKeyPairWebCrypto(algorithm.name.toLowerCase(), extractable, keyUsages);
1360
1612
  checkCryptoKeyPairUsages(result);
1361
1613
  break;
1614
+ case 'ML-KEM-512':
1615
+ // Fall through
1616
+ case 'ML-KEM-768':
1617
+ // Fall through
1618
+ case 'ML-KEM-1024':
1619
+ result = await mlkem_generateKeyPairWebCrypto(algorithm.name, extractable, keyUsages);
1620
+ checkCryptoKeyPairUsages(result);
1621
+ break;
1362
1622
  default:
1363
1623
  throw new Error(`'subtle.generateKey()' is not implemented for ${algorithm.name}.
1364
1624
  Unrecognized algorithm name`);
1365
1625
  }
1366
1626
  return result;
1367
1627
  }
1628
+ async getPublicKey(key, keyUsages) {
1629
+ if (key.type === 'secret') {
1630
+ throw lazyDOMException('key must be a private key', 'NotSupportedError');
1631
+ }
1632
+ if (key.type !== 'private') {
1633
+ throw lazyDOMException('key must be a private key', 'InvalidAccessError');
1634
+ }
1635
+ const publicKeyObject = createPublicKey(key.keyObject);
1636
+ return publicKeyObject.toCryptoKey(key.algorithm, true, keyUsages);
1637
+ }
1368
1638
  async importKey(format, data, algorithm, extractable, keyUsages) {
1369
- if (format === 'raw-secret') format = 'raw';
1639
+ // Note: 'raw-seed' is NOT normalized — PQC import functions handle it directly
1640
+ if (format === 'raw-secret' || format === 'raw-public') format = 'raw';
1370
1641
  const normalizedAlgorithm = normalizeAlgorithm(algorithm, 'importKey');
1371
1642
  let result;
1372
1643
  switch (normalizedAlgorithm.name) {
@@ -1385,6 +1656,11 @@ export class Subtle {
1385
1656
  case 'HMAC':
1386
1657
  result = await hmacImportKey(normalizedAlgorithm, format, data, extractable, keyUsages);
1387
1658
  break;
1659
+ case 'KMAC128':
1660
+ // Fall through
1661
+ case 'KMAC256':
1662
+ result = await kmacImportKey(normalizedAlgorithm, format, data, extractable, keyUsages);
1663
+ break;
1388
1664
  case 'AES-CTR':
1389
1665
  // Fall through
1390
1666
  case 'AES-CBC':
@@ -1399,6 +1675,9 @@ export class Subtle {
1399
1675
  result = await aesImportKey(normalizedAlgorithm, format, data, extractable, keyUsages);
1400
1676
  break;
1401
1677
  case 'PBKDF2':
1678
+ case 'Argon2d':
1679
+ case 'Argon2i':
1680
+ case 'Argon2id':
1402
1681
  result = await importGenericSecretKey(normalizedAlgorithm, format, data, extractable, keyUsages);
1403
1682
  break;
1404
1683
  case 'HKDF':
@@ -1420,6 +1699,13 @@ export class Subtle {
1420
1699
  case 'ML-DSA-87':
1421
1700
  result = mldsaImportKey(format, data, normalizedAlgorithm, extractable, keyUsages);
1422
1701
  break;
1702
+ case 'ML-KEM-512':
1703
+ // Fall through
1704
+ case 'ML-KEM-768':
1705
+ // Fall through
1706
+ case 'ML-KEM-1024':
1707
+ result = mlkemImportKey(format, data, normalizedAlgorithm, extractable, keyUsages);
1708
+ break;
1423
1709
  default:
1424
1710
  throw new Error(`"subtle.importKey()" is not implemented for ${normalizedAlgorithm.name}`);
1425
1711
  }
@@ -1429,85 +1715,65 @@ export class Subtle {
1429
1715
  return result;
1430
1716
  }
1431
1717
  async sign(algorithm, key, data) {
1432
- const normalizedAlgorithm = normalizeAlgorithm(algorithm, 'sign');
1433
- if (normalizedAlgorithm.name === 'HMAC') {
1434
- // Validate key usage
1435
- if (!key.usages.includes('sign')) {
1436
- throw lazyDOMException('Key does not have sign usage', 'InvalidAccessError');
1437
- }
1438
-
1439
- // Get hash algorithm from key or algorithm params
1440
- // Hash can be either a string or an object with name property
1441
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1442
- const alg = normalizedAlgorithm;
1443
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1444
- const keyAlg = key.algorithm;
1445
- let hashAlgorithm = 'SHA-256';
1446
- if (typeof alg.hash === 'string') {
1447
- hashAlgorithm = alg.hash;
1448
- } else if (alg.hash?.name) {
1449
- hashAlgorithm = alg.hash.name;
1450
- } else if (typeof keyAlg.hash === 'string') {
1451
- hashAlgorithm = keyAlg.hash;
1452
- } else if (keyAlg.hash?.name) {
1453
- hashAlgorithm = keyAlg.hash.name;
1454
- }
1455
-
1456
- // Create HMAC and sign
1457
- const keyData = key.keyObject.export();
1458
- const hmac = createHmac(hashAlgorithm, keyData);
1459
- hmac.update(bufferLikeToArrayBuffer(data));
1460
- return bufferLikeToArrayBuffer(hmac.digest());
1461
- }
1462
- return signVerify(normalizedAlgorithm, key, data);
1718
+ return signVerify(normalizeAlgorithm(algorithm, 'sign'), key, data);
1463
1719
  }
1464
1720
  async verify(algorithm, key, signature, data) {
1465
- const normalizedAlgorithm = normalizeAlgorithm(algorithm, 'verify');
1466
- if (normalizedAlgorithm.name === 'HMAC') {
1467
- // Validate key usage
1468
- if (!key.usages.includes('verify')) {
1469
- throw lazyDOMException('Key does not have verify usage', 'InvalidAccessError');
1470
- }
1471
-
1472
- // Get hash algorithm
1473
- // Hash can be either a string or an object with name property
1474
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1475
- const alg = normalizedAlgorithm;
1476
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1477
- const keyAlg = key.algorithm;
1478
- let hashAlgorithm = 'SHA-256';
1479
- if (typeof alg.hash === 'string') {
1480
- hashAlgorithm = alg.hash;
1481
- } else if (alg.hash?.name) {
1482
- hashAlgorithm = alg.hash.name;
1483
- } else if (typeof keyAlg.hash === 'string') {
1484
- hashAlgorithm = keyAlg.hash;
1485
- } else if (keyAlg.hash?.name) {
1486
- hashAlgorithm = keyAlg.hash.name;
1487
- }
1488
-
1489
- // Create HMAC and compute expected signature
1490
- const keyData = key.keyObject.export();
1491
- const hmac = createHmac(hashAlgorithm, keyData);
1492
- const dataBuffer = bufferLikeToArrayBuffer(data);
1493
- hmac.update(dataBuffer);
1494
- const expectedDigest = hmac.digest();
1495
- const expected = new Uint8Array(bufferLikeToArrayBuffer(expectedDigest));
1496
-
1497
- // Constant-time comparison
1498
- const signatureArray = new Uint8Array(bufferLikeToArrayBuffer(signature));
1499
- if (expected.length !== signatureArray.length) {
1500
- return false;
1501
- }
1502
-
1503
- // Manual constant-time comparison
1504
- let result = 0;
1505
- for (let i = 0; i < expected.length; i++) {
1506
- result |= expected[i] ^ signatureArray[i];
1507
- }
1508
- return result === 0;
1721
+ return signVerify(normalizeAlgorithm(algorithm, 'verify'), key, data, signature);
1722
+ }
1723
+ _encapsulateCore(algorithm, key) {
1724
+ const normalizedAlgorithm = normalizeAlgorithm(algorithm, 'encapsulateBits');
1725
+ if (key.algorithm.name !== normalizedAlgorithm.name) {
1726
+ throw lazyDOMException('Key algorithm mismatch', 'InvalidAccessError');
1509
1727
  }
1510
- return signVerify(normalizedAlgorithm, key, data, signature);
1728
+ const variant = normalizedAlgorithm.name;
1729
+ const mlkem = new MlKem(variant);
1730
+ const keyData = key.keyObject.handle.exportKey(KFormatType.DER, KeyEncoding.SPKI);
1731
+ mlkem.setPublicKey(bufferLikeToArrayBuffer(keyData), KFormatType.DER, KeyEncoding.SPKI);
1732
+ return mlkem.encapsulateSync();
1733
+ }
1734
+ _decapsulateCore(algorithm, key, ciphertext) {
1735
+ const normalizedAlgorithm = normalizeAlgorithm(algorithm, 'decapsulateBits');
1736
+ if (key.algorithm.name !== normalizedAlgorithm.name) {
1737
+ throw lazyDOMException('Key algorithm mismatch', 'InvalidAccessError');
1738
+ }
1739
+ const variant = normalizedAlgorithm.name;
1740
+ const mlkem = new MlKem(variant);
1741
+ const keyData = key.keyObject.handle.exportKey(KFormatType.DER, KeyEncoding.PKCS8);
1742
+ mlkem.setPrivateKey(bufferLikeToArrayBuffer(keyData), KFormatType.DER, KeyEncoding.PKCS8);
1743
+ return mlkem.decapsulateSync(bufferLikeToArrayBuffer(ciphertext));
1744
+ }
1745
+ async encapsulateBits(algorithm, key) {
1746
+ if (!key.usages.includes('encapsulateBits')) {
1747
+ throw lazyDOMException('Key does not have encapsulateBits usage', 'InvalidAccessError');
1748
+ }
1749
+ return this._encapsulateCore(algorithm, key);
1750
+ }
1751
+ async encapsulateKey(algorithm, key, sharedKeyAlgorithm, extractable, usages) {
1752
+ if (!key.usages.includes('encapsulateKey')) {
1753
+ throw lazyDOMException('Key does not have encapsulateKey usage', 'InvalidAccessError');
1754
+ }
1755
+ const {
1756
+ sharedKey,
1757
+ ciphertext
1758
+ } = this._encapsulateCore(algorithm, key);
1759
+ const importedKey = await this.importKey('raw', sharedKey, sharedKeyAlgorithm, extractable, usages);
1760
+ return {
1761
+ key: importedKey,
1762
+ ciphertext
1763
+ };
1764
+ }
1765
+ async decapsulateBits(algorithm, key, ciphertext) {
1766
+ if (!key.usages.includes('decapsulateBits')) {
1767
+ throw lazyDOMException('Key does not have decapsulateBits usage', 'InvalidAccessError');
1768
+ }
1769
+ return this._decapsulateCore(algorithm, key, ciphertext);
1770
+ }
1771
+ async decapsulateKey(algorithm, key, ciphertext, sharedKeyAlgorithm, extractable, usages) {
1772
+ if (!key.usages.includes('decapsulateKey')) {
1773
+ throw lazyDOMException('Key does not have decapsulateKey usage', 'InvalidAccessError');
1774
+ }
1775
+ const sharedKey = this._decapsulateCore(algorithm, key, ciphertext);
1776
+ return this.importKey('raw', sharedKey, sharedKeyAlgorithm, extractable, usages);
1511
1777
  }
1512
1778
  }
1513
1779
  export const subtle = new Subtle();
@@ -1526,6 +1792,10 @@ function getKeyLength(algorithm) {
1526
1792
  const hmacAlg = algorithm;
1527
1793
  return hmacAlg.length || 256;
1528
1794
  }
1795
+ case 'KMAC128':
1796
+ return algorithm.length || 128;
1797
+ case 'KMAC256':
1798
+ return algorithm.length || 256;
1529
1799
  default:
1530
1800
  throw lazyDOMException(`Cannot determine key length for ${name}`, 'NotSupportedError');
1531
1801
  }