@oqs/liboqs-js 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (317) hide show
  1. package/LICENSE.md +50 -0
  2. package/README.md +829 -0
  3. package/bin/cli.js +16 -0
  4. package/dist/classic-mceliece-348864.deno.js +0 -0
  5. package/dist/classic-mceliece-348864.min.js +0 -0
  6. package/dist/classic-mceliece-348864f.deno.js +0 -0
  7. package/dist/classic-mceliece-348864f.min.js +0 -0
  8. package/dist/classic-mceliece-460896.deno.js +0 -0
  9. package/dist/classic-mceliece-460896.min.js +0 -0
  10. package/dist/classic-mceliece-460896f.deno.js +0 -0
  11. package/dist/classic-mceliece-460896f.min.js +0 -0
  12. package/dist/classic-mceliece-6688128.deno.js +0 -0
  13. package/dist/classic-mceliece-6688128.min.js +0 -0
  14. package/dist/classic-mceliece-6688128f.deno.js +0 -0
  15. package/dist/classic-mceliece-6688128f.min.js +0 -0
  16. package/dist/classic-mceliece-6960119.deno.js +0 -0
  17. package/dist/classic-mceliece-6960119.min.js +0 -0
  18. package/dist/classic-mceliece-6960119f.deno.js +0 -0
  19. package/dist/classic-mceliece-6960119f.min.js +0 -0
  20. package/dist/classic-mceliece-8192128.deno.js +0 -0
  21. package/dist/classic-mceliece-8192128.min.js +0 -0
  22. package/dist/classic-mceliece-8192128f.deno.js +0 -0
  23. package/dist/classic-mceliece-8192128f.min.js +0 -0
  24. package/dist/cross-rsdp-128-balanced.deno.js +0 -0
  25. package/dist/cross-rsdp-128-balanced.min.js +0 -0
  26. package/dist/cross-rsdp-128-fast.deno.js +0 -0
  27. package/dist/cross-rsdp-128-fast.min.js +0 -0
  28. package/dist/cross-rsdp-128-small.deno.js +0 -0
  29. package/dist/cross-rsdp-128-small.min.js +0 -0
  30. package/dist/cross-rsdp-192-balanced.deno.js +0 -0
  31. package/dist/cross-rsdp-192-balanced.min.js +0 -0
  32. package/dist/cross-rsdp-192-fast.deno.js +0 -0
  33. package/dist/cross-rsdp-192-fast.min.js +0 -0
  34. package/dist/cross-rsdp-192-small.deno.js +0 -0
  35. package/dist/cross-rsdp-192-small.min.js +0 -0
  36. package/dist/cross-rsdp-256-balanced.deno.js +0 -0
  37. package/dist/cross-rsdp-256-balanced.min.js +0 -0
  38. package/dist/cross-rsdp-256-fast.deno.js +0 -0
  39. package/dist/cross-rsdp-256-fast.min.js +0 -0
  40. package/dist/cross-rsdp-256-small.deno.js +0 -0
  41. package/dist/cross-rsdp-256-small.min.js +0 -0
  42. package/dist/cross-rsdpg-128-balanced.deno.js +0 -0
  43. package/dist/cross-rsdpg-128-balanced.min.js +0 -0
  44. package/dist/cross-rsdpg-128-fast.deno.js +0 -0
  45. package/dist/cross-rsdpg-128-fast.min.js +0 -0
  46. package/dist/cross-rsdpg-128-small.deno.js +0 -0
  47. package/dist/cross-rsdpg-128-small.min.js +0 -0
  48. package/dist/cross-rsdpg-192-balanced.deno.js +0 -0
  49. package/dist/cross-rsdpg-192-balanced.min.js +0 -0
  50. package/dist/cross-rsdpg-192-fast.deno.js +0 -0
  51. package/dist/cross-rsdpg-192-fast.min.js +0 -0
  52. package/dist/cross-rsdpg-192-small.deno.js +0 -0
  53. package/dist/cross-rsdpg-192-small.min.js +0 -0
  54. package/dist/cross-rsdpg-256-balanced.deno.js +0 -0
  55. package/dist/cross-rsdpg-256-balanced.min.js +0 -0
  56. package/dist/cross-rsdpg-256-fast.deno.js +0 -0
  57. package/dist/cross-rsdpg-256-fast.min.js +0 -0
  58. package/dist/cross-rsdpg-256-small.deno.js +0 -0
  59. package/dist/cross-rsdpg-256-small.min.js +0 -0
  60. package/dist/falcon-1024.deno.js +0 -0
  61. package/dist/falcon-1024.min.js +0 -0
  62. package/dist/falcon-512.deno.js +0 -0
  63. package/dist/falcon-512.min.js +0 -0
  64. package/dist/falcon-padded-1024.deno.js +0 -0
  65. package/dist/falcon-padded-1024.min.js +0 -0
  66. package/dist/falcon-padded-512.deno.js +0 -0
  67. package/dist/falcon-padded-512.min.js +0 -0
  68. package/dist/frodokem-1344-aes.deno.js +0 -0
  69. package/dist/frodokem-1344-aes.min.js +0 -0
  70. package/dist/frodokem-1344-shake.deno.js +0 -0
  71. package/dist/frodokem-1344-shake.min.js +0 -0
  72. package/dist/frodokem-640-aes.deno.js +0 -0
  73. package/dist/frodokem-640-aes.min.js +0 -0
  74. package/dist/frodokem-640-shake.deno.js +0 -0
  75. package/dist/frodokem-640-shake.min.js +0 -0
  76. package/dist/frodokem-976-aes.deno.js +0 -0
  77. package/dist/frodokem-976-aes.min.js +0 -0
  78. package/dist/frodokem-976-shake.deno.js +0 -0
  79. package/dist/frodokem-976-shake.min.js +0 -0
  80. package/dist/hqc-128.deno.js +0 -0
  81. package/dist/hqc-128.min.js +0 -0
  82. package/dist/hqc-192.deno.js +0 -0
  83. package/dist/hqc-192.min.js +0 -0
  84. package/dist/hqc-256.deno.js +0 -0
  85. package/dist/hqc-256.min.js +0 -0
  86. package/dist/kyber-1024.deno.js +0 -0
  87. package/dist/kyber-1024.min.js +0 -0
  88. package/dist/kyber-512.deno.js +0 -0
  89. package/dist/kyber-512.min.js +0 -0
  90. package/dist/kyber-768.deno.js +0 -0
  91. package/dist/kyber-768.min.js +0 -0
  92. package/dist/mayo-1.deno.js +0 -0
  93. package/dist/mayo-1.min.js +0 -0
  94. package/dist/mayo-2.deno.js +0 -0
  95. package/dist/mayo-2.min.js +0 -0
  96. package/dist/mayo-3.deno.js +0 -0
  97. package/dist/mayo-3.min.js +0 -0
  98. package/dist/mayo-5.deno.js +0 -0
  99. package/dist/mayo-5.min.js +0 -0
  100. package/dist/ml-dsa-44.deno.js +0 -0
  101. package/dist/ml-dsa-44.min.js +0 -0
  102. package/dist/ml-dsa-65.deno.js +0 -0
  103. package/dist/ml-dsa-65.min.js +0 -0
  104. package/dist/ml-dsa-87.deno.js +0 -0
  105. package/dist/ml-dsa-87.min.js +0 -0
  106. package/dist/ml-kem-1024.deno.js +0 -0
  107. package/dist/ml-kem-1024.min.js +0 -0
  108. package/dist/ml-kem-512.deno.js +0 -0
  109. package/dist/ml-kem-512.min.js +0 -0
  110. package/dist/ml-kem-768.deno.js +0 -0
  111. package/dist/ml-kem-768.min.js +0 -0
  112. package/dist/ntru-hps-2048-509.deno.js +0 -0
  113. package/dist/ntru-hps-2048-509.min.js +0 -0
  114. package/dist/ntru-hps-2048-677.deno.js +0 -0
  115. package/dist/ntru-hps-2048-677.min.js +0 -0
  116. package/dist/ntru-hps-4096-1229.deno.js +0 -0
  117. package/dist/ntru-hps-4096-1229.min.js +0 -0
  118. package/dist/ntru-hps-4096-821.deno.js +0 -0
  119. package/dist/ntru-hps-4096-821.min.js +0 -0
  120. package/dist/ntru-hrss-1373.deno.js +0 -0
  121. package/dist/ntru-hrss-1373.min.js +0 -0
  122. package/dist/ntru-hrss-701.deno.js +0 -0
  123. package/dist/ntru-hrss-701.min.js +0 -0
  124. package/dist/ov-iii-pkc-skc.deno.js +0 -0
  125. package/dist/ov-iii-pkc-skc.min.js +0 -0
  126. package/dist/ov-iii-pkc.deno.js +0 -0
  127. package/dist/ov-iii-pkc.min.js +0 -0
  128. package/dist/ov-iii.deno.js +0 -0
  129. package/dist/ov-iii.min.js +0 -0
  130. package/dist/ov-ip-pkc-skc.deno.js +0 -0
  131. package/dist/ov-ip-pkc-skc.min.js +0 -0
  132. package/dist/ov-ip-pkc.deno.js +0 -0
  133. package/dist/ov-ip-pkc.min.js +0 -0
  134. package/dist/ov-ip.deno.js +0 -0
  135. package/dist/ov-ip.min.js +0 -0
  136. package/dist/ov-is-pkc-skc.deno.js +0 -0
  137. package/dist/ov-is-pkc-skc.min.js +0 -0
  138. package/dist/ov-is-pkc.deno.js +0 -0
  139. package/dist/ov-is-pkc.min.js +0 -0
  140. package/dist/ov-is.deno.js +0 -0
  141. package/dist/ov-is.min.js +0 -0
  142. package/dist/ov-v-pkc-skc.deno.js +0 -0
  143. package/dist/ov-v-pkc-skc.min.js +0 -0
  144. package/dist/ov-v-pkc.deno.js +0 -0
  145. package/dist/ov-v-pkc.min.js +0 -0
  146. package/dist/ov-v.deno.js +0 -0
  147. package/dist/ov-v.min.js +0 -0
  148. package/dist/slh-dsa-sha2-128f.deno.js +0 -0
  149. package/dist/slh-dsa-sha2-128f.min.js +0 -0
  150. package/dist/slh-dsa-sha2-128s.deno.js +0 -0
  151. package/dist/slh-dsa-sha2-128s.min.js +0 -0
  152. package/dist/slh-dsa-sha2-192f.deno.js +0 -0
  153. package/dist/slh-dsa-sha2-192f.min.js +0 -0
  154. package/dist/slh-dsa-sha2-192s.deno.js +0 -0
  155. package/dist/slh-dsa-sha2-192s.min.js +0 -0
  156. package/dist/slh-dsa-sha2-256f.deno.js +0 -0
  157. package/dist/slh-dsa-sha2-256f.min.js +0 -0
  158. package/dist/slh-dsa-sha2-256s.deno.js +0 -0
  159. package/dist/slh-dsa-sha2-256s.min.js +0 -0
  160. package/dist/slh-dsa-shake-128f.deno.js +0 -0
  161. package/dist/slh-dsa-shake-128f.min.js +0 -0
  162. package/dist/slh-dsa-shake-128s.deno.js +0 -0
  163. package/dist/slh-dsa-shake-128s.min.js +0 -0
  164. package/dist/slh-dsa-shake-192f.deno.js +0 -0
  165. package/dist/slh-dsa-shake-192f.min.js +0 -0
  166. package/dist/slh-dsa-shake-192s.deno.js +0 -0
  167. package/dist/slh-dsa-shake-192s.min.js +0 -0
  168. package/dist/slh-dsa-shake-256f.deno.js +0 -0
  169. package/dist/slh-dsa-shake-256f.min.js +0 -0
  170. package/dist/slh-dsa-shake-256s.deno.js +0 -0
  171. package/dist/slh-dsa-shake-256s.min.js +0 -0
  172. package/dist/snova-24-5-4-esk.deno.js +0 -0
  173. package/dist/snova-24-5-4-esk.min.js +0 -0
  174. package/dist/snova-24-5-4-shake-esk.deno.js +0 -0
  175. package/dist/snova-24-5-4-shake-esk.min.js +0 -0
  176. package/dist/snova-24-5-4-shake.deno.js +0 -0
  177. package/dist/snova-24-5-4-shake.min.js +0 -0
  178. package/dist/snova-24-5-4.deno.js +0 -0
  179. package/dist/snova-24-5-4.min.js +0 -0
  180. package/dist/snova-24-5-5.deno.js +0 -0
  181. package/dist/snova-24-5-5.min.js +0 -0
  182. package/dist/snova-25-8-3.deno.js +0 -0
  183. package/dist/snova-25-8-3.min.js +0 -0
  184. package/dist/snova-29-6-5.deno.js +0 -0
  185. package/dist/snova-29-6-5.min.js +0 -0
  186. package/dist/snova-37-17-2.deno.js +0 -0
  187. package/dist/snova-37-17-2.min.js +0 -0
  188. package/dist/snova-37-8-4.deno.js +0 -0
  189. package/dist/snova-37-8-4.min.js +0 -0
  190. package/dist/snova-49-11-3.deno.js +0 -0
  191. package/dist/snova-49-11-3.min.js +0 -0
  192. package/dist/snova-56-25-2.deno.js +0 -0
  193. package/dist/snova-56-25-2.min.js +0 -0
  194. package/dist/snova-60-10-4.deno.js +0 -0
  195. package/dist/snova-60-10-4.min.js +0 -0
  196. package/dist/sntrup761.deno.js +0 -0
  197. package/dist/sntrup761.min.js +0 -0
  198. package/package.json +108 -0
  199. package/src/algorithms/kem/classic-mceliece/classic-mceliece-348864.js +336 -0
  200. package/src/algorithms/kem/classic-mceliece/classic-mceliece-348864f.js +336 -0
  201. package/src/algorithms/kem/classic-mceliece/classic-mceliece-460896.js +336 -0
  202. package/src/algorithms/kem/classic-mceliece/classic-mceliece-460896f.js +336 -0
  203. package/src/algorithms/kem/classic-mceliece/classic-mceliece-6688128.js +336 -0
  204. package/src/algorithms/kem/classic-mceliece/classic-mceliece-6688128f.js +336 -0
  205. package/src/algorithms/kem/classic-mceliece/classic-mceliece-6960119.js +336 -0
  206. package/src/algorithms/kem/classic-mceliece/classic-mceliece-6960119f.js +336 -0
  207. package/src/algorithms/kem/classic-mceliece/classic-mceliece-8192128.js +336 -0
  208. package/src/algorithms/kem/classic-mceliece/classic-mceliece-8192128f.js +336 -0
  209. package/src/algorithms/kem/frodokem/efrodokem-1344-aes.js +366 -0
  210. package/src/algorithms/kem/frodokem/efrodokem-1344-shake.js +366 -0
  211. package/src/algorithms/kem/frodokem/efrodokem-640-aes.js +366 -0
  212. package/src/algorithms/kem/frodokem/efrodokem-640-shake.js +366 -0
  213. package/src/algorithms/kem/frodokem/efrodokem-976-aes.js +366 -0
  214. package/src/algorithms/kem/frodokem/efrodokem-976-shake.js +366 -0
  215. package/src/algorithms/kem/frodokem/frodokem-1344-aes.js +366 -0
  216. package/src/algorithms/kem/frodokem/frodokem-1344-shake.js +366 -0
  217. package/src/algorithms/kem/frodokem/frodokem-640-aes.js +366 -0
  218. package/src/algorithms/kem/frodokem/frodokem-640-shake.js +366 -0
  219. package/src/algorithms/kem/frodokem/frodokem-976-aes.js +366 -0
  220. package/src/algorithms/kem/frodokem/frodokem-976-shake.js +366 -0
  221. package/src/algorithms/kem/hqc/hqc-128.js +366 -0
  222. package/src/algorithms/kem/hqc/hqc-192.js +366 -0
  223. package/src/algorithms/kem/hqc/hqc-256.js +366 -0
  224. package/src/algorithms/kem/kyber/kyber-1024.js +349 -0
  225. package/src/algorithms/kem/kyber/kyber-512.js +347 -0
  226. package/src/algorithms/kem/kyber/kyber-768.js +348 -0
  227. package/src/algorithms/kem/ml-kem/ml-kem-1024.js +345 -0
  228. package/src/algorithms/kem/ml-kem/ml-kem-512.js +345 -0
  229. package/src/algorithms/kem/ml-kem/ml-kem-768.js +344 -0
  230. package/src/algorithms/kem/ntru/ntru-hps-2048-509.js +366 -0
  231. package/src/algorithms/kem/ntru/ntru-hps-2048-677.js +366 -0
  232. package/src/algorithms/kem/ntru/ntru-hps-4096-1229.js +366 -0
  233. package/src/algorithms/kem/ntru/ntru-hps-4096-821.js +366 -0
  234. package/src/algorithms/kem/ntru/ntru-hrss-1373.js +366 -0
  235. package/src/algorithms/kem/ntru/ntru-hrss-701.js +366 -0
  236. package/src/algorithms/kem/ntru/sntrup761.js +367 -0
  237. package/src/algorithms/sig/cross/cross-rsdp-128-balanced.js +391 -0
  238. package/src/algorithms/sig/cross/cross-rsdp-128-fast.js +391 -0
  239. package/src/algorithms/sig/cross/cross-rsdp-128-small.js +391 -0
  240. package/src/algorithms/sig/cross/cross-rsdp-192-balanced.js +391 -0
  241. package/src/algorithms/sig/cross/cross-rsdp-192-fast.js +391 -0
  242. package/src/algorithms/sig/cross/cross-rsdp-192-small.js +391 -0
  243. package/src/algorithms/sig/cross/cross-rsdp-256-balanced.js +391 -0
  244. package/src/algorithms/sig/cross/cross-rsdp-256-fast.js +391 -0
  245. package/src/algorithms/sig/cross/cross-rsdp-256-small.js +391 -0
  246. package/src/algorithms/sig/cross/cross-rsdpg-128-balanced.js +391 -0
  247. package/src/algorithms/sig/cross/cross-rsdpg-128-fast.js +391 -0
  248. package/src/algorithms/sig/cross/cross-rsdpg-128-small.js +391 -0
  249. package/src/algorithms/sig/cross/cross-rsdpg-192-balanced.js +391 -0
  250. package/src/algorithms/sig/cross/cross-rsdpg-192-fast.js +391 -0
  251. package/src/algorithms/sig/cross/cross-rsdpg-192-small.js +391 -0
  252. package/src/algorithms/sig/cross/cross-rsdpg-256-balanced.js +391 -0
  253. package/src/algorithms/sig/cross/cross-rsdpg-256-fast.js +391 -0
  254. package/src/algorithms/sig/cross/cross-rsdpg-256-small.js +391 -0
  255. package/src/algorithms/sig/falcon/falcon-1024.js +378 -0
  256. package/src/algorithms/sig/falcon/falcon-512.js +379 -0
  257. package/src/algorithms/sig/falcon/falcon-padded-1024.js +380 -0
  258. package/src/algorithms/sig/falcon/falcon-padded-512.js +380 -0
  259. package/src/algorithms/sig/mayo/mayo-1.js +390 -0
  260. package/src/algorithms/sig/mayo/mayo-2.js +390 -0
  261. package/src/algorithms/sig/mayo/mayo-3.js +390 -0
  262. package/src/algorithms/sig/mayo/mayo-5.js +390 -0
  263. package/src/algorithms/sig/ml-dsa/ml-dsa-44.js +338 -0
  264. package/src/algorithms/sig/ml-dsa/ml-dsa-65.js +338 -0
  265. package/src/algorithms/sig/ml-dsa/ml-dsa-87.js +338 -0
  266. package/src/algorithms/sig/slh-dsa/slh-dsa-sha2-128f.js +367 -0
  267. package/src/algorithms/sig/slh-dsa/slh-dsa-sha2-128s.js +367 -0
  268. package/src/algorithms/sig/slh-dsa/slh-dsa-sha2-192f.js +367 -0
  269. package/src/algorithms/sig/slh-dsa/slh-dsa-sha2-192s.js +367 -0
  270. package/src/algorithms/sig/slh-dsa/slh-dsa-sha2-256f.js +367 -0
  271. package/src/algorithms/sig/slh-dsa/slh-dsa-sha2-256s.js +367 -0
  272. package/src/algorithms/sig/slh-dsa/slh-dsa-shake-128f.js +367 -0
  273. package/src/algorithms/sig/slh-dsa/slh-dsa-shake-128s.js +367 -0
  274. package/src/algorithms/sig/slh-dsa/slh-dsa-shake-192f.js +367 -0
  275. package/src/algorithms/sig/slh-dsa/slh-dsa-shake-192s.js +367 -0
  276. package/src/algorithms/sig/slh-dsa/slh-dsa-shake-256f.js +367 -0
  277. package/src/algorithms/sig/slh-dsa/slh-dsa-shake-256s.js +367 -0
  278. package/src/algorithms/sig/snova/snova-24-5-4-esk.js +391 -0
  279. package/src/algorithms/sig/snova/snova-24-5-4-shake-esk.js +391 -0
  280. package/src/algorithms/sig/snova/snova-24-5-4-shake.js +391 -0
  281. package/src/algorithms/sig/snova/snova-24-5-4.js +391 -0
  282. package/src/algorithms/sig/snova/snova-24-5-5.js +391 -0
  283. package/src/algorithms/sig/snova/snova-25-8-3.js +391 -0
  284. package/src/algorithms/sig/snova/snova-29-6-5.js +391 -0
  285. package/src/algorithms/sig/snova/snova-37-17-2.js +391 -0
  286. package/src/algorithms/sig/snova/snova-37-8-4.js +391 -0
  287. package/src/algorithms/sig/snova/snova-49-11-3.js +391 -0
  288. package/src/algorithms/sig/snova/snova-56-25-2.js +391 -0
  289. package/src/algorithms/sig/snova/snova-60-10-4.js +391 -0
  290. package/src/algorithms/sig/uov/ov-iii-pkc-skc.js +390 -0
  291. package/src/algorithms/sig/uov/ov-iii-pkc.js +390 -0
  292. package/src/algorithms/sig/uov/ov-iii.js +390 -0
  293. package/src/algorithms/sig/uov/ov-ip-pkc-skc.js +390 -0
  294. package/src/algorithms/sig/uov/ov-ip-pkc.js +390 -0
  295. package/src/algorithms/sig/uov/ov-ip.js +390 -0
  296. package/src/algorithms/sig/uov/ov-is-pkc-skc.js +390 -0
  297. package/src/algorithms/sig/uov/ov-is-pkc.js +390 -0
  298. package/src/algorithms/sig/uov/ov-is.js +390 -0
  299. package/src/algorithms/sig/uov/ov-v-pkc-skc.js +390 -0
  300. package/src/algorithms/sig/uov/ov-v-pkc.js +390 -0
  301. package/src/algorithms/sig/uov/ov-v.js +390 -0
  302. package/src/cli/algorithms.js +254 -0
  303. package/src/cli/commands/info.js +35 -0
  304. package/src/cli/commands/kem.js +91 -0
  305. package/src/cli/commands/list.js +30 -0
  306. package/src/cli/commands/sig.js +98 -0
  307. package/src/cli/index.js +86 -0
  308. package/src/cli/io.js +147 -0
  309. package/src/cli/parser.js +64 -0
  310. package/src/core/errors.js +75 -0
  311. package/src/core/validation.js +28 -0
  312. package/src/index.js +164 -0
  313. package/src/kem.js +60 -0
  314. package/src/sig.js +87 -0
  315. package/src/types/algorithms.d.ts +1543 -0
  316. package/src/types/errors.d.ts +60 -0
  317. package/src/types/index.d.ts +9 -0
@@ -0,0 +1,344 @@
1
+ /**
2
+ * @fileoverview ML-KEM-768 KEM algorithm implementation
3
+ * @module algorithms/kem/ml-kem/ml-kem-768
4
+ * @description
5
+ * ML-KEM-768 is a lattice-based key encapsulation mechanism providing NIST security level 3.
6
+ * It is part of the NIST FIPS 203 standard (Module-Lattice-Based Key-Encapsulation Mechanism).
7
+ *
8
+ * Key features:
9
+ * - Lattice-based cryptography (Module-LWE problem)
10
+ * - Security Level 3 (192-bit classical, quantum-resistant)
11
+ * - NIST FIPS 203 standardized
12
+ * - IND-CCA2 security
13
+ * - Efficient key sizes and performance
14
+ *
15
+ * @see {@link https://csrc.nist.gov/pubs/fips/203/final} - NIST FIPS 203 specification
16
+ */
17
+
18
+ import { LibOQSError, LibOQSInitError, LibOQSOperationError, LibOQSValidationError } from '../../../core/errors.js';
19
+ import { isUint8Array } from '../../../core/validation.js';
20
+
21
+ // Dynamic module loading for cross-runtime compatibility
22
+ async function loadModule() {
23
+ const isDeno = typeof Deno !== 'undefined';
24
+ const modulePath = isDeno
25
+ ? `../../../../dist/ml-kem-768.deno.js`
26
+ : `../../../../dist/ml-kem-768.min.js`;
27
+
28
+ const module = await import(modulePath);
29
+ return module.default;
30
+ }
31
+
32
+ /**
33
+ * ML-KEM-768-INFO algorithm constants and metadata
34
+ * @type {{readonly name: 'ML-KEM-768', readonly identifier: 'ML-KEM-768', readonly type: 'kem', readonly securityLevel: 3, readonly standardized: true, readonly description: string, readonly keySize: {readonly publicKey: 1184, readonly secretKey: 2400, readonly ciphertext: 1088, readonly sharedSecret: 32}}}
35
+ */
36
+ export const ML_KEM_768_INFO = {
37
+ name: 'ML-KEM-768',
38
+ identifier: 'ML-KEM-768',
39
+ type: 'kem',
40
+ securityLevel: 3,
41
+ standardized: true,
42
+ description: 'NIST FIPS 203 ML-KEM-768 (192-bit quantum security)',
43
+ keySize: {
44
+ publicKey: 1184,
45
+ secretKey: 2400,
46
+ ciphertext: 1088,
47
+ sharedSecret: 32
48
+ }
49
+ };
50
+
51
+ /**
52
+ * Factory function to create an ML-KEM-768 KEM instance
53
+ *
54
+ * @async
55
+ * @function createMLKEM768
56
+ * @returns {Promise<MLKEM768>} Initialized ML-KEM-768 instance
57
+ * @throws {LibOQSInitError} If module initialization fails
58
+ *
59
+ * @example
60
+ * import { createMLKEM768 } from '@oqs/liboqs-js';
61
+ *
62
+ * const kem = await createMLKEM768();
63
+ * const { publicKey, secretKey } = kem.generateKeyPair();
64
+ * kem.destroy();
65
+ */
66
+ export async function createMLKEM768() {
67
+ const moduleFactory = await loadModule();
68
+ const wasmModule = await moduleFactory();
69
+ wasmModule._OQS_init();
70
+
71
+ const algoName = ML_KEM_768_INFO.identifier;
72
+ const nameLen = wasmModule.lengthBytesUTF8(algoName);
73
+ const namePtr = wasmModule._malloc(nameLen + 1);
74
+ wasmModule.stringToUTF8(algoName, namePtr, nameLen + 1);
75
+
76
+ const kemPtr = wasmModule._OQS_KEM_new(namePtr);
77
+ wasmModule._free(namePtr);
78
+
79
+ if (!kemPtr) {
80
+ throw new LibOQSInitError('ML-KEM-768', 'Failed to create KEM instance');
81
+ }
82
+
83
+ return new MLKEM768(wasmModule, kemPtr);
84
+ }
85
+
86
+ /**
87
+ * ML-KEM-768 wrapper class providing high-level KEM operations
88
+ *
89
+ * This class wraps the low-level WASM module to provide a user-friendly
90
+ * interface for ML-KEM-768 operations with automatic memory management
91
+ * and input validation.
92
+ *
93
+ * @class MLKEM768
94
+ * @example
95
+ * import { createMLKEM768 } from '@oqs/liboqs-js';
96
+ *
97
+ * const kem = await createMLKEM768();
98
+ * const { publicKey, secretKey } = kem.generateKeyPair();
99
+ * const { ciphertext, sharedSecret } = kem.encapsulate(publicKey);
100
+ * kem.destroy();
101
+ */
102
+ export class MLKEM768 {
103
+ /** @type {Object} @private */
104
+ #wasmModule;
105
+ /** @type {number} @private */
106
+ #kemPtr;
107
+ /** @type {boolean} @private */
108
+ #destroyed = false;
109
+
110
+ /**
111
+ * @param {Object} wasmModule - Emscripten WASM module
112
+ * @param {number} kemPtr - Pointer to KEM instance
113
+ * @private
114
+ */
115
+ constructor(wasmModule, kemPtr) {
116
+ this.#wasmModule = wasmModule;
117
+ this.#kemPtr = kemPtr;
118
+ }
119
+
120
+ /**
121
+ * Generate a new keypair for ML-KEM-768
122
+ *
123
+ * Generates a public/private keypair using the algorithm's internal
124
+ * random number generator. The secret key must be kept confidential.
125
+ *
126
+ * @returns {{publicKey: Uint8Array, secretKey: Uint8Array}}
127
+ * @throws {LibOQSOperationError} If keypair generation fails
128
+ * @throws {LibOQSError} If instance has been destroyed
129
+ * @example
130
+ * const { publicKey, secretKey } = kem.generateKeyPair();
131
+ * // publicKey: 1184 bytes
132
+ * // secretKey: 2400 bytes (keep confidential!)
133
+ */
134
+ generateKeyPair() {
135
+ this.#checkDestroyed();
136
+
137
+ const publicKeyPtr = this.#wasmModule._malloc(ML_KEM_768_INFO.keySize.publicKey);
138
+ const secretKeyPtr = this.#wasmModule._malloc(ML_KEM_768_INFO.keySize.secretKey);
139
+
140
+ try {
141
+ const result = this.#wasmModule._OQS_KEM_keypair(this.#kemPtr, publicKeyPtr, secretKeyPtr);
142
+
143
+ if (result !== 0) {
144
+ throw new LibOQSOperationError('keypair', 'ML-KEM-768', `Error code: ${result}`);
145
+ }
146
+
147
+ const publicKey = new Uint8Array(ML_KEM_768_INFO.keySize.publicKey);
148
+ const secretKey = new Uint8Array(ML_KEM_768_INFO.keySize.secretKey);
149
+
150
+ publicKey.set(this.#wasmModule.HEAPU8.subarray(publicKeyPtr, publicKeyPtr + ML_KEM_768_INFO.keySize.publicKey));
151
+ secretKey.set(this.#wasmModule.HEAPU8.subarray(secretKeyPtr, secretKeyPtr + ML_KEM_768_INFO.keySize.secretKey));
152
+
153
+ return { publicKey, secretKey };
154
+
155
+ } finally {
156
+ this.#wasmModule._free(publicKeyPtr);
157
+ this.#wasmModule._free(secretKeyPtr);
158
+ }
159
+ }
160
+
161
+ /**
162
+ * Encapsulate a shared secret using a public key
163
+ *
164
+ * Generates a random shared secret and encapsulates it using the
165
+ * provided public key. The shared secret can be used for symmetric
166
+ * encryption.
167
+ *
168
+ * @param {Uint8Array} publicKey - Recipient's public key (1184 bytes)
169
+ * @returns {{ciphertext: Uint8Array, sharedSecret: Uint8Array}}
170
+ * @throws {LibOQSValidationError} If public key is invalid
171
+ * @throws {LibOQSOperationError} If encapsulation fails
172
+ * @throws {LibOQSError} If instance has been destroyed
173
+ * @example
174
+ * const { ciphertext, sharedSecret } = kem.encapsulate(recipientPublicKey);
175
+ * // ciphertext: 1088 bytes (send to recipient)
176
+ * // sharedSecret: 32 bytes (use for symmetric encryption)
177
+ */
178
+ encapsulate(publicKey) {
179
+ this.#checkDestroyed();
180
+ this.#validatePublicKey(publicKey);
181
+
182
+ const publicKeyPtr = this.#wasmModule._malloc(ML_KEM_768_INFO.keySize.publicKey);
183
+ const ciphertextPtr = this.#wasmModule._malloc(ML_KEM_768_INFO.keySize.ciphertext);
184
+ const sharedSecretPtr = this.#wasmModule._malloc(ML_KEM_768_INFO.keySize.sharedSecret);
185
+
186
+ try {
187
+ this.#wasmModule.HEAPU8.set(publicKey, publicKeyPtr);
188
+
189
+ const result = this.#wasmModule._OQS_KEM_encaps(
190
+ this.#kemPtr,
191
+ ciphertextPtr,
192
+ sharedSecretPtr,
193
+ publicKeyPtr
194
+ );
195
+
196
+ if (result !== 0) {
197
+ throw new LibOQSOperationError('encaps', 'ML-KEM-768', `Error code: ${result}`);
198
+ }
199
+
200
+ const ciphertext = new Uint8Array(ML_KEM_768_INFO.keySize.ciphertext);
201
+ const sharedSecret = new Uint8Array(ML_KEM_768_INFO.keySize.sharedSecret);
202
+
203
+ ciphertext.set(this.#wasmModule.HEAPU8.subarray(ciphertextPtr, ciphertextPtr + ML_KEM_768_INFO.keySize.ciphertext));
204
+ sharedSecret.set(this.#wasmModule.HEAPU8.subarray(sharedSecretPtr, sharedSecretPtr + ML_KEM_768_INFO.keySize.sharedSecret));
205
+
206
+ return { ciphertext, sharedSecret };
207
+
208
+ } finally {
209
+ this.#wasmModule._free(publicKeyPtr);
210
+ this.#wasmModule._free(ciphertextPtr);
211
+ this.#wasmModule._free(sharedSecretPtr);
212
+ }
213
+ }
214
+
215
+ /**
216
+ * Decapsulate a shared secret using a secret key
217
+ *
218
+ * Recovers the shared secret from a ciphertext using the secret key.
219
+ * The recovered shared secret will match the one generated during
220
+ * encapsulation.
221
+ *
222
+ * @param {Uint8Array} ciphertext - Ciphertext received (1088 bytes)
223
+ * @param {Uint8Array} secretKey - Recipient's secret key (2400 bytes)
224
+ * @returns {Uint8Array} Recovered shared secret (32 bytes)
225
+ * @throws {LibOQSValidationError} If inputs are invalid
226
+ * @throws {LibOQSOperationError} If decapsulation fails
227
+ * @throws {LibOQSError} If instance has been destroyed
228
+ * @example
229
+ * const sharedSecret = kem.decapsulate(ciphertext, mySecretKey);
230
+ * // sharedSecret: 32 bytes (matches sender's shared secret)
231
+ */
232
+ decapsulate(ciphertext, secretKey) {
233
+ this.#checkDestroyed();
234
+ this.#validateCiphertext(ciphertext);
235
+ this.#validateSecretKey(secretKey);
236
+
237
+ const ciphertextPtr = this.#wasmModule._malloc(ML_KEM_768_INFO.keySize.ciphertext);
238
+ const secretKeyPtr = this.#wasmModule._malloc(ML_KEM_768_INFO.keySize.secretKey);
239
+ const sharedSecretPtr = this.#wasmModule._malloc(ML_KEM_768_INFO.keySize.sharedSecret);
240
+
241
+ try {
242
+ this.#wasmModule.HEAPU8.set(ciphertext, ciphertextPtr);
243
+ this.#wasmModule.HEAPU8.set(secretKey, secretKeyPtr);
244
+
245
+ const result = this.#wasmModule._OQS_KEM_decaps(
246
+ this.#kemPtr,
247
+ sharedSecretPtr,
248
+ ciphertextPtr,
249
+ secretKeyPtr
250
+ );
251
+
252
+ if (result !== 0) {
253
+ throw new LibOQSOperationError('decaps', 'ML-KEM-768', `Error code: ${result}`);
254
+ }
255
+
256
+ const sharedSecret = new Uint8Array(ML_KEM_768_INFO.keySize.sharedSecret);
257
+ sharedSecret.set(this.#wasmModule.HEAPU8.subarray(sharedSecretPtr, sharedSecretPtr + ML_KEM_768_INFO.keySize.sharedSecret));
258
+
259
+ return sharedSecret;
260
+
261
+ } finally {
262
+ this.#wasmModule._free(ciphertextPtr);
263
+ this.#wasmModule._free(secretKeyPtr);
264
+ this.#wasmModule._free(sharedSecretPtr);
265
+ }
266
+ }
267
+
268
+ /**
269
+ * Clean up resources and free WASM memory
270
+ *
271
+ * This method should be called when you're done using the instance
272
+ * to free WASM memory. After calling destroy(), the instance cannot
273
+ * be used for further operations.
274
+ *
275
+ * @example
276
+ * const kem = await createMLKEM768(LibOQS_ml_kem_768);
277
+ * // ... use kem ...
278
+ * kem.destroy();
279
+ */
280
+ destroy() {
281
+ if (!this.#destroyed) {
282
+ if (this.#kemPtr) {
283
+ this.#wasmModule._OQS_KEM_free(this.#kemPtr);
284
+ this.#kemPtr = null;
285
+ }
286
+ this.#destroyed = true;
287
+ }
288
+ }
289
+
290
+ /**
291
+ * Enables automatic cleanup via `using` declarations
292
+ * @example
293
+ * using instance = await create...();
294
+ * // automatically cleaned up at end of scope
295
+ */
296
+ [Symbol.dispose]() {
297
+ this.destroy();
298
+ }
299
+
300
+ /**
301
+ * Get algorithm information and constants
302
+ * @returns {typeof ML_KEM_768_INFO} Algorithm metadata (copy of ML_KEM_768_INFO)
303
+ * @example
304
+ * const info = kem.info;
305
+ * console.log(info.keySize.publicKey); // 1184
306
+ */
307
+ get info() {
308
+ return ML_KEM_768_INFO;
309
+ }
310
+
311
+ #checkDestroyed() {
312
+ if (this.#destroyed) {
313
+ throw new LibOQSError('Instance has been destroyed', 'ML-KEM-768');
314
+ }
315
+ }
316
+
317
+ #validatePublicKey(publicKey) {
318
+ if (!isUint8Array(publicKey) || publicKey.length !== ML_KEM_768_INFO.keySize.publicKey) {
319
+ throw new LibOQSValidationError(
320
+ `Invalid public key: expected ${ML_KEM_768_INFO.keySize.publicKey} bytes, got ${publicKey?.length ?? 'null'}`,
321
+ 'ML-KEM-768'
322
+ );
323
+ }
324
+ }
325
+
326
+ #validateSecretKey(secretKey) {
327
+ if (!isUint8Array(secretKey) || secretKey.length !== ML_KEM_768_INFO.keySize.secretKey) {
328
+ throw new LibOQSValidationError(
329
+ `Invalid secret key: expected ${ML_KEM_768_INFO.keySize.secretKey} bytes, got ${secretKey?.length ?? 'null'}`,
330
+ 'ML-KEM-768'
331
+ );
332
+ }
333
+ }
334
+
335
+ #validateCiphertext(ciphertext) {
336
+ if (!isUint8Array(ciphertext) || ciphertext.length !== ML_KEM_768_INFO.keySize.ciphertext) {
337
+ throw new LibOQSValidationError(
338
+ `Invalid ciphertext: expected ${ML_KEM_768_INFO.keySize.ciphertext} bytes, got ${ciphertext?.length ?? 'null'}`,
339
+ 'ML-KEM-768'
340
+ );
341
+ }
342
+ }
343
+ }
344
+
@@ -0,0 +1,366 @@
1
+ /**
2
+ * @fileoverview NTRU-HPS-2048-509 KEM algorithm implementation
3
+ * @module algorithms/kem/ntru/ntru-hps-2048-509
4
+ * @description
5
+ * NTRU-HPS-2048-509 is a lattice-based key encapsulation mechanism from the NTRU-HPS (Highest Performance Secure) family.
6
+ * It provides post-quantum security based on the NTRU problem.
7
+ *
8
+ * Key features:
9
+ * - Lattice-based cryptography (NTRU problem)
10
+ * - Security Level 1 (128-bit classical, quantum-resistant)
11
+ * - Optimized for performance
12
+ * - Compact ciphertext (699 bytes)
13
+ *
14
+ * @see {@link https://ntru.org/} - NTRU specification
15
+ */
16
+
17
+ import { LibOQSError, LibOQSInitError, LibOQSOperationError, LibOQSValidationError } from '../../../core/errors.js';
18
+ import { isUint8Array } from '../../../core/validation.js';
19
+
20
+ // Dynamic module loading for cross-runtime compatibility
21
+ async function loadModule() {
22
+ const isDeno = typeof Deno !== 'undefined';
23
+ const modulePath = isDeno
24
+ ? `../../../../dist/ntru-hps-2048-509.deno.js`
25
+ : `../../../../dist/ntru-hps-2048-509.min.js`;
26
+
27
+ const module = await import(modulePath);
28
+ return module.default;
29
+ }
30
+
31
+ /**
32
+ * NTRU-HPS-2048-509-INFO algorithm constants and metadata
33
+ * @type {{readonly name: 'NTRU-HPS-2048-509', readonly identifier: 'NTRU-HPS-2048-509', readonly type: 'kem', readonly securityLevel: 1, readonly standardized: false, readonly description: string, readonly keySize: {readonly publicKey: 699, readonly secretKey: 935, readonly ciphertext: 699, readonly sharedSecret: 32}}}
34
+ */
35
+ export const NTRU_HPS_2048_509_INFO = {
36
+ name: 'NTRU-HPS-2048-509',
37
+ identifier: 'NTRU-HPS-2048-509',
38
+ type: 'kem',
39
+ securityLevel: 1,
40
+ standardized: false,
41
+ description: 'NTRU-HPS-2048-509 NTRU-HPS (Highest Performance Secure) (NIST Level 1, 128-bit quantum security)',
42
+ keySize: {
43
+ publicKey: 699,
44
+ secretKey: 935,
45
+ ciphertext: 699,
46
+ sharedSecret: 32
47
+ }
48
+ };
49
+
50
+ /**
51
+ * Factory function to create a NTRU-HPS-2048-509 KEM instance
52
+ *
53
+ * @async
54
+ * @function createNTRUHps2048509
55
+ * @returns {Promise<NTRUHps2048509>} Initialized NTRU-HPS-2048-509 instance
56
+ * @throws {LibOQSInitError} If module initialization fails
57
+ *
58
+ * @example
59
+ * import { createNTRUHps2048509 } from '@oqs/liboqs-js';
60
+ *
61
+ * const kem = await createNTRUHps2048509();
62
+ * const { publicKey, secretKey } = kem.generateKeyPair();
63
+ * kem.destroy();
64
+ */
65
+ export async function createNTRUHps2048509() {
66
+ const moduleFactory = await loadModule();
67
+ const wasmModule = await moduleFactory();
68
+ wasmModule._OQS_init();
69
+
70
+ const algoName = NTRU_HPS_2048_509_INFO.identifier;
71
+ const nameLen = wasmModule.lengthBytesUTF8(algoName);
72
+ const namePtr = wasmModule._malloc(nameLen + 1);
73
+ wasmModule.stringToUTF8(algoName, namePtr, nameLen + 1);
74
+
75
+ const kemPtr = wasmModule._OQS_KEM_new(namePtr);
76
+ wasmModule._free(namePtr);
77
+
78
+ if (!kemPtr) {
79
+ throw new LibOQSInitError('NTRU-HPS-2048-509', 'Failed to create KEM instance');
80
+ }
81
+
82
+ return new NTRUHps2048509(wasmModule, kemPtr);
83
+ }
84
+
85
+ /**
86
+ * NTRU-HPS-2048-509 key encapsulation mechanism wrapper class
87
+ *
88
+ * @class NTRUHps2048509
89
+ * @description
90
+ * High-level wrapper for NTRU-HPS-2048-509 KEM operations. Provides secure key generation,
91
+ * encapsulation, and decapsulation with automatic memory management.
92
+ *
93
+ * Memory Management:
94
+ * - All WASM memory is managed internally
95
+ * - Call destroy() when finished to free resources
96
+ * - Do not use instance after calling destroy()
97
+ *
98
+ * @example
99
+ * const kem = await createNTRUHps2048509();
100
+ *
101
+ * // Generate keypair
102
+ * const { publicKey, secretKey } = kem.generateKeyPair();
103
+ *
104
+ * // Encapsulate
105
+ * const { ciphertext, sharedSecret: senderSecret } = kem.encapsulate(publicKey);
106
+ *
107
+ * // Decapsulate
108
+ * const receiverSecret = kem.decapsulate(ciphertext, secretKey);
109
+ *
110
+ * // Cleanup
111
+ * kem.destroy();
112
+ */
113
+ export class NTRUHps2048509 {
114
+ /** @type {Object} @private */ #wasmModule;
115
+ /** @type {number} @private */ #kemPtr;
116
+ /** @type {boolean} @private */ #destroyed = false;
117
+
118
+ /**
119
+ * @private
120
+ * @constructor
121
+ * @param {Object} wasmModule - Emscripten WASM module
122
+ * @param {number} kemPtr - Pointer to OQS_KEM structure
123
+ */
124
+ constructor(wasmModule, kemPtr) {
125
+ this.#wasmModule = wasmModule;
126
+ this.#kemPtr = kemPtr;
127
+ }
128
+
129
+ /**
130
+ * Generate a new NTRU-HPS-2048-509 keypair
131
+ *
132
+ * @async
133
+ * @returns {{publicKey: Uint8Array, secretKey: Uint8Array}}
134
+ * @throws {LibOQSError} If instance is destroyed
135
+ * @throws {LibOQSOperationError} If key generation fails
136
+ *
137
+ * @example
138
+ * const { publicKey, secretKey } = kem.generateKeyPair();
139
+ * console.log('Public key:', publicKey.length); // 699 bytes
140
+ * console.log('Secret key:', secretKey.length); // 935 bytes
141
+ */
142
+ generateKeyPair() {
143
+ this.#checkDestroyed();
144
+
145
+ const publicKey = new Uint8Array(NTRU_HPS_2048_509_INFO.keySize.publicKey);
146
+ const secretKey = new Uint8Array(NTRU_HPS_2048_509_INFO.keySize.secretKey);
147
+
148
+ const publicKeyPtr = this.#wasmModule._malloc(publicKey.length);
149
+ const secretKeyPtr = this.#wasmModule._malloc(secretKey.length);
150
+
151
+ try {
152
+ const result = this.#wasmModule._OQS_KEM_keypair(this.#kemPtr, publicKeyPtr, secretKeyPtr);
153
+
154
+ if (result !== 0) {
155
+ throw new LibOQSOperationError('generateKeyPair', 'NTRU-HPS-2048-509', 'Key generation failed');
156
+ }
157
+
158
+ publicKey.set(this.#wasmModule.HEAPU8.subarray(publicKeyPtr, publicKeyPtr + publicKey.length));
159
+ secretKey.set(this.#wasmModule.HEAPU8.subarray(secretKeyPtr, secretKeyPtr + secretKey.length));
160
+
161
+ return { publicKey, secretKey };
162
+ } finally {
163
+ this.#wasmModule._free(publicKeyPtr);
164
+ this.#wasmModule._free(secretKeyPtr);
165
+ }
166
+ }
167
+
168
+ /**
169
+ * Encapsulate a shared secret using the public key
170
+ *
171
+ * @async
172
+ * @param {Uint8Array} publicKey - Public key for encapsulation (699 bytes)
173
+ * @returns {{ciphertext: Uint8Array, sharedSecret: Uint8Array}}
174
+ * @returns {Uint8Array} returns.sharedSecret - Shared secret Ciphertext and shared secret
175
+ * @throws {LibOQSError} If instance is destroyed
176
+ * @throws {LibOQSValidationError} If public key is invalid
177
+ * @throws {LibOQSOperationError} If encapsulation fails
178
+ *
179
+ * @example
180
+ * const { ciphertext, sharedSecret } = kem.encapsulate(publicKey);
181
+ * console.log('Ciphertext:', ciphertext.length); // 699 bytes
182
+ * console.log('Shared secret:', sharedSecret.length); // 32 bytes
183
+ */
184
+ encapsulate(publicKey) {
185
+ this.#checkDestroyed();
186
+ this.#validatePublicKey(publicKey);
187
+
188
+ const ciphertext = new Uint8Array(NTRU_HPS_2048_509_INFO.keySize.ciphertext);
189
+ const sharedSecret = new Uint8Array(NTRU_HPS_2048_509_INFO.keySize.sharedSecret);
190
+
191
+ const ciphertextPtr = this.#wasmModule._malloc(ciphertext.length);
192
+ const sharedSecretPtr = this.#wasmModule._malloc(sharedSecret.length);
193
+ const publicKeyPtr = this.#wasmModule._malloc(publicKey.length);
194
+
195
+ try {
196
+ this.#wasmModule.HEAPU8.set(publicKey, publicKeyPtr);
197
+
198
+ const result = this.#wasmModule._OQS_KEM_encaps(
199
+ this.#kemPtr,
200
+ ciphertextPtr,
201
+ sharedSecretPtr,
202
+ publicKeyPtr
203
+ );
204
+
205
+ if (result !== 0) {
206
+ throw new LibOQSOperationError('encapsulate', 'NTRU-HPS-2048-509', 'Encapsulation failed');
207
+ }
208
+
209
+ ciphertext.set(this.#wasmModule.HEAPU8.subarray(ciphertextPtr, ciphertextPtr + ciphertext.length));
210
+ sharedSecret.set(this.#wasmModule.HEAPU8.subarray(sharedSecretPtr, sharedSecretPtr + sharedSecret.length));
211
+
212
+ return { ciphertext, sharedSecret };
213
+ } finally {
214
+ this.#wasmModule._free(ciphertextPtr);
215
+ this.#wasmModule._free(sharedSecretPtr);
216
+ this.#wasmModule._free(publicKeyPtr);
217
+ }
218
+ }
219
+
220
+ /**
221
+ * Decapsulate a shared secret using the secret key
222
+ *
223
+ * @async
224
+ * @param {Uint8Array} ciphertext - Ciphertext to decapsulate (699 bytes)
225
+ * @param {Uint8Array} secretKey - Secret key for decapsulation (935 bytes)
226
+ * @returns {Uint8Array} Shared secret (32 bytes)
227
+ * @throws {LibOQSError} If instance is destroyed
228
+ * @throws {LibOQSValidationError} If inputs are invalid
229
+ * @throws {LibOQSOperationError} If decapsulation fails
230
+ *
231
+ * @example
232
+ * const sharedSecret = kem.decapsulate(ciphertext, secretKey);
233
+ * console.log('Shared secret:', sharedSecret.length); // 32 bytes
234
+ */
235
+ decapsulate(ciphertext, secretKey) {
236
+ this.#checkDestroyed();
237
+ this.#validateCiphertext(ciphertext);
238
+ this.#validateSecretKey(secretKey);
239
+
240
+ const sharedSecret = new Uint8Array(NTRU_HPS_2048_509_INFO.keySize.sharedSecret);
241
+
242
+ const sharedSecretPtr = this.#wasmModule._malloc(sharedSecret.length);
243
+ const ciphertextPtr = this.#wasmModule._malloc(ciphertext.length);
244
+ const secretKeyPtr = this.#wasmModule._malloc(secretKey.length);
245
+
246
+ try {
247
+ this.#wasmModule.HEAPU8.set(ciphertext, ciphertextPtr);
248
+ this.#wasmModule.HEAPU8.set(secretKey, secretKeyPtr);
249
+
250
+ const result = this.#wasmModule._OQS_KEM_decaps(
251
+ this.#kemPtr,
252
+ sharedSecretPtr,
253
+ ciphertextPtr,
254
+ secretKeyPtr
255
+ );
256
+
257
+ if (result !== 0) {
258
+ throw new LibOQSOperationError('decapsulate', 'NTRU-HPS-2048-509', 'Decapsulation failed');
259
+ }
260
+
261
+ sharedSecret.set(this.#wasmModule.HEAPU8.subarray(sharedSecretPtr, sharedSecretPtr + sharedSecret.length));
262
+
263
+ return sharedSecret;
264
+ } finally {
265
+ this.#wasmModule._free(sharedSecretPtr);
266
+ this.#wasmModule._free(ciphertextPtr);
267
+ this.#wasmModule._free(secretKeyPtr);
268
+ }
269
+ }
270
+
271
+ /**
272
+ * Free WASM resources
273
+ *
274
+ * @description
275
+ * Releases all WASM memory associated with this instance.
276
+ * The instance cannot be used after calling destroy().
277
+ *
278
+ * @example
279
+ * kem.destroy();
280
+ * // kem is now unusable
281
+ */
282
+ destroy() {
283
+ if (!this.#destroyed && this.#kemPtr) {
284
+ this.#wasmModule._OQS_KEM_free(this.#kemPtr);
285
+ this.#kemPtr = null;
286
+ this.#destroyed = true;
287
+ }
288
+ }
289
+
290
+ /**
291
+ * Enables automatic cleanup via `using` declarations
292
+ * @example
293
+ * using instance = await create...();
294
+ * // automatically cleaned up at end of scope
295
+ */
296
+ [Symbol.dispose]() {
297
+ this.destroy();
298
+ }
299
+
300
+ /**
301
+ * Get algorithm information
302
+ *
303
+ * @readonly
304
+ * @returns {typeof NTRU_HPS_2048_509_INFO} Algorithm metadata
305
+ *
306
+ * @example
307
+ * console.log(kem.info.name); // 'NTRU-HPS-2048-509'
308
+ * console.log(kem.info.securityLevel); // 1
309
+ * console.log(kem.info.keySize); // { publicKey: 699, secretKey: 935, ciphertext: 699, sharedSecret: 32 }
310
+ */
311
+ get info() {
312
+ return NTRU_HPS_2048_509_INFO;
313
+ }
314
+
315
+ /**
316
+ * @private
317
+ * @throws {LibOQSError} If instance is destroyed
318
+ */
319
+ #checkDestroyed() {
320
+ if (this.#destroyed) {
321
+ throw new LibOQSError('Instance has been destroyed', 'NTRU-HPS-2048-509');
322
+ }
323
+ }
324
+
325
+ /**
326
+ * @private
327
+ * @param {Uint8Array} publicKey
328
+ * @throws {LibOQSValidationError} If public key size is invalid
329
+ */
330
+ #validatePublicKey(publicKey) {
331
+ if (!isUint8Array(publicKey) || publicKey.length !== NTRU_HPS_2048_509_INFO.keySize.publicKey) {
332
+ throw new LibOQSValidationError(
333
+ `Invalid public key: expected ${NTRU_HPS_2048_509_INFO.keySize.publicKey} bytes, got ${publicKey?.length ?? 'null'}`,
334
+ 'NTRU-HPS-2048-509'
335
+ );
336
+ }
337
+ }
338
+
339
+ /**
340
+ * @private
341
+ * @param {Uint8Array} secretKey
342
+ * @throws {LibOQSValidationError} If secret key size is invalid
343
+ */
344
+ #validateSecretKey(secretKey) {
345
+ if (!isUint8Array(secretKey) || secretKey.length !== NTRU_HPS_2048_509_INFO.keySize.secretKey) {
346
+ throw new LibOQSValidationError(
347
+ `Invalid secret key: expected ${NTRU_HPS_2048_509_INFO.keySize.secretKey} bytes, got ${secretKey?.length ?? 'null'}`,
348
+ 'NTRU-HPS-2048-509'
349
+ );
350
+ }
351
+ }
352
+
353
+ /**
354
+ * @private
355
+ * @param {Uint8Array} ciphertext
356
+ * @throws {LibOQSValidationError} If ciphertext size is invalid
357
+ */
358
+ #validateCiphertext(ciphertext) {
359
+ if (!isUint8Array(ciphertext) || ciphertext.length !== NTRU_HPS_2048_509_INFO.keySize.ciphertext) {
360
+ throw new LibOQSValidationError(
361
+ `Invalid ciphertext: expected ${NTRU_HPS_2048_509_INFO.keySize.ciphertext} bytes, got ${ciphertext?.length ?? 'null'}`,
362
+ 'NTRU-HPS-2048-509'
363
+ );
364
+ }
365
+ }
366
+ }