@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,338 @@
1
+ /**
2
+ * @fileoverview ML-DSA-87 signature algorithm implementation
3
+ * @module algorithms/sig/ml-dsa/ml-dsa-87
4
+ * @description
5
+ * ML-DSA-87 is a lattice-based digital signature algorithm providing NIST security level 5.
6
+ * It is part of the NIST FIPS 204 standard (Module-Lattice-Based Digital Signature Algorithm).
7
+ *
8
+ * Key features:
9
+ * - Lattice-based cryptography (Module-LWE and Module-SIS problems)
10
+ * - Security Level 5 (256-bit classical, quantum-resistant)
11
+ * - NIST FIPS 204 standardized
12
+ * - Strong existential unforgeability under chosen message attack (SUF-CMA)
13
+ * - Deterministic signing with optional hedged mode
14
+ *
15
+ * @see {@link https://csrc.nist.gov/pubs/fips/204/final} - NIST FIPS 204 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-dsa-87.deno.js`
26
+ : `../../../../dist/ml-dsa-87.min.js`;
27
+
28
+ const module = await import(modulePath);
29
+ return module.default;
30
+ }
31
+
32
+ /**
33
+ * ML-DSA-87-INFO algorithm constants and metadata
34
+ * @type {{readonly name: 'ML-DSA-87', readonly identifier: 'ML-DSA-87', readonly type: 'sig', readonly securityLevel: 5, readonly standardized: true, readonly description: string, readonly keySize: {readonly publicKey: 2592, readonly secretKey: 4896, readonly signature: 4627}}}
35
+ */
36
+ export const ML_DSA_87_INFO = {
37
+ name: 'ML-DSA-87',
38
+ identifier: 'ML-DSA-87',
39
+ type: 'sig',
40
+ securityLevel: 5,
41
+ standardized: true,
42
+ description: 'NIST FIPS 204 ML-DSA-87 lattice-based signature (NIST Level 5, 256-bit quantum security)',
43
+ keySize: {
44
+ publicKey: 2592,
45
+ secretKey: 4896,
46
+ signature: 4627
47
+ }
48
+ };
49
+
50
+ /**
51
+ * Load and initialize ML-DSA-87 module
52
+ * @returns {Promise<MLDSA87>} Initialized ML-DSA-87 instance
53
+ * @throws {LibOQSInitError} If initialization fails
54
+ * @example
55
+ * import { createMLDSA87 } from '@oqs/liboqs-js';
56
+ * const sig = await createMLDSA87();
57
+ */
58
+ export async function createMLDSA87() {
59
+ const moduleFactory = await loadModule();
60
+ const wasmModule = await moduleFactory();
61
+ wasmModule._OQS_init();
62
+
63
+ const algoName = ML_DSA_87_INFO.identifier;
64
+ const nameLen = wasmModule.lengthBytesUTF8(algoName);
65
+ const namePtr = wasmModule._malloc(nameLen + 1);
66
+ wasmModule.stringToUTF8(algoName, namePtr, nameLen + 1);
67
+
68
+ const sigPtr = wasmModule._OQS_SIG_new(namePtr);
69
+ wasmModule._free(namePtr);
70
+
71
+ if (!sigPtr) {
72
+ throw new LibOQSInitError('ML-DSA-87', 'Failed to create SIG instance');
73
+ }
74
+
75
+ return new MLDSA87(wasmModule, sigPtr);
76
+ }
77
+
78
+ /**
79
+ * ML-DSA-87 digital signature wrapper class
80
+ *
81
+ * Provides high-level interface for ML-DSA-87 digital signature operations.
82
+ * Automatically manages WASM memory and validates inputs.
83
+ *
84
+ * @class MLDSA87
85
+ * @example
86
+ * const sig = await createMLDSA87();
87
+ * const { publicKey, secretKey } = sig.generateKeyPair();
88
+ *
89
+ * const message = new TextEncoder().encode('Hello, quantum world!');
90
+ * const signature = sig.sign(message, secretKey);
91
+ *
92
+ * const isValid = sig.verify(message, signature, publicKey);
93
+ * console.log('Valid:', isValid); // true
94
+ *
95
+ * sig.destroy();
96
+ */
97
+ export class MLDSA87 {
98
+ #wasmModule;
99
+ #sigPtr;
100
+ #destroyed = false;
101
+
102
+ /**
103
+ * @param {Object} wasmModule - Emscripten WASM module
104
+ * @param {number} sigPtr - Pointer to OQS_SIG structure
105
+ * @private
106
+ */
107
+ constructor(wasmModule, sigPtr) {
108
+ this.#wasmModule = wasmModule;
109
+ this.#sigPtr = sigPtr;
110
+ }
111
+
112
+ /**
113
+ * Generate a new ML-DSA-87 keypair
114
+ *
115
+ * Creates a new public/private keypair for digital signatures.
116
+ * The secret key must be kept confidential.
117
+ *
118
+ * @returns {{publicKey: Uint8Array, secretKey: Uint8Array}}
119
+ * @throws {LibOQSOperationError} If key generation fails
120
+ * @example
121
+ * const { publicKey, secretKey } = sig.generateKeyPair();
122
+ */
123
+ generateKeyPair() {
124
+ this.#checkDestroyed();
125
+
126
+ const publicKey = new Uint8Array(ML_DSA_87_INFO.keySize.publicKey);
127
+ const secretKey = new Uint8Array(ML_DSA_87_INFO.keySize.secretKey);
128
+
129
+ const pkPtr = this.#wasmModule._malloc(publicKey.length);
130
+ const skPtr = this.#wasmModule._malloc(secretKey.length);
131
+
132
+ try {
133
+ const result = this.#wasmModule._OQS_SIG_keypair(this.#sigPtr, pkPtr, skPtr);
134
+
135
+ if (result !== 0) {
136
+ throw new LibOQSOperationError('generateKeyPair', 'ML-DSA-87', 'Key generation failed');
137
+ }
138
+
139
+ publicKey.set(this.#wasmModule.HEAPU8.subarray(pkPtr, pkPtr + publicKey.length));
140
+ secretKey.set(this.#wasmModule.HEAPU8.subarray(skPtr, skPtr + secretKey.length));
141
+
142
+ return { publicKey, secretKey };
143
+ } finally {
144
+ this.#wasmModule._free(pkPtr);
145
+ this.#wasmModule._free(skPtr);
146
+ }
147
+ }
148
+
149
+ /**
150
+ * Sign a message using the secret key
151
+ *
152
+ * Generates a digital signature for the provided message.
153
+ * The signature can be verified using the corresponding public key.
154
+ *
155
+ * @param {Uint8Array} message - Message to sign (arbitrary length)
156
+ * @param {Uint8Array} secretKey - Secret key for signing (4896 bytes)
157
+ * @returns {Uint8Array} Digital signature (up to 4627 bytes)
158
+ * @throws {LibOQSValidationError} If inputs are invalid
159
+ * @throws {LibOQSOperationError} If signing fails
160
+ * @example
161
+ * const message = new TextEncoder().encode('Hello!');
162
+ * const signature = sig.sign(message, secretKey);
163
+ */
164
+ sign(message, secretKey) {
165
+ this.#checkDestroyed();
166
+ this.#validateMessage(message);
167
+ this.#validateSecretKey(secretKey);
168
+
169
+ const signature = new Uint8Array(ML_DSA_87_INFO.keySize.signature);
170
+ const sigPtr = this.#wasmModule._malloc(signature.length);
171
+ const sigLenPtr = this.#wasmModule._malloc(8); // size_t
172
+ const msgPtr = this.#wasmModule._malloc(message.length);
173
+ const skPtr = this.#wasmModule._malloc(secretKey.length);
174
+
175
+ try {
176
+ this.#wasmModule.HEAPU8.set(message, msgPtr);
177
+ this.#wasmModule.HEAPU8.set(secretKey, skPtr);
178
+ this.#wasmModule.setValue(sigLenPtr, signature.length, 'i64');
179
+
180
+ const result = this.#wasmModule._OQS_SIG_sign(
181
+ this.#sigPtr,
182
+ sigPtr,
183
+ sigLenPtr,
184
+ msgPtr,
185
+ message.length,
186
+ skPtr
187
+ );
188
+
189
+ if (result !== 0) {
190
+ throw new LibOQSOperationError('sign', 'ML-DSA-87', 'Signing failed');
191
+ }
192
+
193
+ const actualSigLen = this.#wasmModule.getValue(sigLenPtr, 'i32');
194
+ const actualSignature = new Uint8Array(actualSigLen);
195
+ actualSignature.set(this.#wasmModule.HEAPU8.subarray(sigPtr, sigPtr + actualSigLen));
196
+
197
+ return actualSignature;
198
+ } finally {
199
+ this.#wasmModule._free(sigPtr);
200
+ this.#wasmModule._free(sigLenPtr);
201
+ this.#wasmModule._free(msgPtr);
202
+ this.#wasmModule._free(skPtr);
203
+ }
204
+ }
205
+
206
+ /**
207
+ * Verify a signature against a message using the public key
208
+ *
209
+ * Verifies that the signature is valid for the given message and public key.
210
+ *
211
+ * @param {Uint8Array} message - Original message that was signed
212
+ * @param {Uint8Array} signature - Signature to verify
213
+ * @param {Uint8Array} publicKey - Public key for verification (2592 bytes)
214
+ * @returns {boolean} True if signature is valid, false otherwise
215
+ * @throws {LibOQSValidationError} If inputs are invalid
216
+ * @example
217
+ * const isValid = sig.verify(message, signature, publicKey);
218
+ * if (isValid) {
219
+ * console.log('Signature is valid!');
220
+ * }
221
+ */
222
+ verify(message, signature, publicKey) {
223
+ this.#checkDestroyed();
224
+ this.#validateMessage(message);
225
+ this.#validateSignature(signature);
226
+ this.#validatePublicKey(publicKey);
227
+
228
+ const msgPtr = this.#wasmModule._malloc(message.length);
229
+ const sigPtr = this.#wasmModule._malloc(signature.length);
230
+ const pkPtr = this.#wasmModule._malloc(publicKey.length);
231
+
232
+ try {
233
+ this.#wasmModule.HEAPU8.set(message, msgPtr);
234
+ this.#wasmModule.HEAPU8.set(signature, sigPtr);
235
+ this.#wasmModule.HEAPU8.set(publicKey, pkPtr);
236
+
237
+ const result = this.#wasmModule._OQS_SIG_verify(
238
+ this.#sigPtr,
239
+ msgPtr,
240
+ message.length,
241
+ sigPtr,
242
+ signature.length,
243
+ pkPtr
244
+ );
245
+
246
+ return result === 0;
247
+ } finally {
248
+ this.#wasmModule._free(msgPtr);
249
+ this.#wasmModule._free(sigPtr);
250
+ this.#wasmModule._free(pkPtr);
251
+ }
252
+ }
253
+
254
+ /**
255
+ * Clean up WASM resources
256
+ *
257
+ * Frees the native signature structure. The instance cannot be used after calling destroy().
258
+ *
259
+ * @example
260
+ * sig.destroy();
261
+ */
262
+ destroy() {
263
+ if (!this.#destroyed) {
264
+ if (this.#sigPtr) {
265
+ this.#wasmModule._OQS_SIG_free(this.#sigPtr);
266
+ this.#sigPtr = null;
267
+ }
268
+ this.#destroyed = true;
269
+ }
270
+ }
271
+
272
+ /**
273
+ * Enables automatic cleanup via `using` declarations
274
+ * @example
275
+ * using instance = await create...();
276
+ * // automatically cleaned up at end of scope
277
+ */
278
+ [Symbol.dispose]() {
279
+ this.destroy();
280
+ }
281
+
282
+ /**
283
+ * Get algorithm information
284
+ * @returns {typeof ML_DSA_87_INFO} Algorithm metadata
285
+ */
286
+ get info() {
287
+ return ML_DSA_87_INFO;
288
+ }
289
+
290
+ #checkDestroyed() {
291
+ if (this.#destroyed) {
292
+ throw new LibOQSError('Instance has been destroyed', 'ML-DSA-87');
293
+ }
294
+ }
295
+
296
+ #validateMessage(message) {
297
+ if (!ArrayBuffer.isView(message) || message.constructor.name !== 'Uint8Array') {
298
+ throw new LibOQSValidationError(
299
+ 'Message must be Uint8Array',
300
+ 'ML-DSA-87'
301
+ );
302
+ }
303
+ }
304
+
305
+ #validatePublicKey(publicKey) {
306
+ if (!isUint8Array(publicKey) || publicKey.length !== ML_DSA_87_INFO.keySize.publicKey) {
307
+ throw new LibOQSValidationError(
308
+ `Invalid public key: expected ${ML_DSA_87_INFO.keySize.publicKey} bytes, got ${publicKey?.length ?? 'null'}`,
309
+ 'ML-DSA-87'
310
+ );
311
+ }
312
+ }
313
+
314
+ #validateSecretKey(secretKey) {
315
+ if (!isUint8Array(secretKey) || secretKey.length !== ML_DSA_87_INFO.keySize.secretKey) {
316
+ throw new LibOQSValidationError(
317
+ `Invalid secret key: expected ${ML_DSA_87_INFO.keySize.secretKey} bytes, got ${secretKey?.length ?? 'null'}`,
318
+ 'ML-DSA-87'
319
+ );
320
+ }
321
+ }
322
+
323
+ #validateSignature(signature) {
324
+ if (!isUint8Array(signature)) {
325
+ throw new LibOQSValidationError(
326
+ 'Signature must be Uint8Array',
327
+ 'ML-DSA-87'
328
+ );
329
+ }
330
+ if (signature.length === 0 || signature.length > ML_DSA_87_INFO.keySize.signature) {
331
+ throw new LibOQSValidationError(
332
+ `Invalid signature length: expected up to ${ML_DSA_87_INFO.keySize.signature} bytes, got ${signature.length}`,
333
+ 'ML-DSA-87'
334
+ );
335
+ }
336
+ }
337
+ }
338
+
@@ -0,0 +1,367 @@
1
+ /**
2
+ * @fileoverview SLH-DSA-SHA2-128f signature algorithm implementation
3
+ * @module algorithms/sig/slh-dsa/slh-dsa-sha2-128f
4
+ * @description
5
+ * SLH-DSA-SHA2-128f is a stateless hash-based signature scheme providing NIST security level 1.
6
+ * This variant uses SHA2 for hashing and is optimized for speed (fast mode).
7
+ *
8
+ * Key features:
9
+ * - Stateless hash-based signatures
10
+ * - Security Level 1 (128-bit classical, quantum-resistant)
11
+ * - SHA2 hash function
12
+ * - Fast signing/verification
13
+ * - FIPS 205 standardized
14
+ *
15
+ * @see {@link https://csrc.nist.gov/pubs/fips/205/final} - FIPS 205: SLH-DSA 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/slh-dsa-sha2-128f.deno.js`
26
+ : `../../../../dist/slh-dsa-sha2-128f.min.js`;
27
+
28
+ const module = await import(modulePath);
29
+ return module.default;
30
+ }
31
+
32
+ /**
33
+ * SLH-DSA-SHA2-128F-INFO algorithm constants and metadata
34
+ * @type {{readonly name: 'SLH-DSA-SHA2-128f', readonly identifier: 'SLH_DSA_PURE_SHA2_128F', readonly type: 'sig', readonly securityLevel: 1, readonly standardized: true, readonly description: string, readonly keySize: {readonly publicKey: 32, readonly secretKey: 64, readonly signature: 17088}}}
35
+ */
36
+ export const SLH_DSA_SHA2_128F_INFO = {
37
+ name: 'SLH-DSA-SHA2-128f',
38
+ identifier: 'SLH_DSA_PURE_SHA2_128F',
39
+ type: 'sig',
40
+ securityLevel: 1,
41
+ standardized: true,
42
+ description: 'SLH-DSA-SHA2-128f hash-based signature (NIST Level 1, 128-bit quantum security, SHA2, fast, FIPS 205)',
43
+ keySize: {
44
+ publicKey: 32,
45
+ secretKey: 64,
46
+ signature: 17088
47
+ }
48
+ };
49
+
50
+ /**
51
+ * Factory function to create a SLH-DSA-SHA2-128f signature instance
52
+ *
53
+ * @async
54
+ * @function createSlhDsaSha2128f
55
+ * @returns {Promise<SlhDsaSha2128f>} Initialized SLH-DSA-SHA2-128f instance
56
+ * @throws {LibOQSInitError} If module initialization fails
57
+ *
58
+ * @example
59
+ * import { createSlhDsaSha2128f } from '@oqs/liboqs-js';
60
+ *
61
+ * const sig = await createSlhDsaSha2128f();
62
+ * const { publicKey, secretKey } = sig.generateKeyPair();
63
+ * sig.destroy();
64
+ */
65
+ export async function createSlhDsaSha2128f() {
66
+ const moduleFactory = await loadModule();
67
+ const wasmModule = await moduleFactory();
68
+ wasmModule._OQS_init();
69
+
70
+ const algoName = SLH_DSA_SHA2_128F_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 sigPtr = wasmModule._OQS_SIG_new(namePtr);
76
+ wasmModule._free(namePtr);
77
+
78
+ if (!sigPtr) {
79
+ throw new LibOQSInitError('SLH-DSA-SHA2-128f', 'Failed to create SIG instance');
80
+ }
81
+
82
+ return new SlhDsaSha2128f(wasmModule, sigPtr);
83
+ }
84
+
85
+ /**
86
+ * SLH-DSA-SHA2-128f signature scheme wrapper class
87
+ *
88
+ * @class SlhDsaSha2128f
89
+ * @description
90
+ * High-level wrapper for SLH-DSA-SHA2-128f signature operations. Provides secure key generation,
91
+ * signing, and verification 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 sig = await createSlhDsaSha2128f();
100
+ *
101
+ * // Generate keypair
102
+ * const { publicKey, secretKey } = sig.generateKeyPair();
103
+ *
104
+ * // Sign message
105
+ * const message = new TextEncoder().encode('Hello, world!');
106
+ * const signature = sig.sign(message, secretKey);
107
+ *
108
+ * // Verify signature
109
+ * const isValid = sig.verify(message, signature, publicKey);
110
+ *
111
+ * // Cleanup
112
+ * sig.destroy();
113
+ */
114
+ export class SlhDsaSha2128f {
115
+ /** @type {Object} @private */ #wasmModule;
116
+ /** @type {number} @private */ #sigPtr;
117
+ /** @type {boolean} @private */ #destroyed = false;
118
+
119
+ /**
120
+ * @private
121
+ * @constructor
122
+ * @param {Object} wasmModule - Emscripten WASM module
123
+ * @param {number} sigPtr - Pointer to OQS_SIG structure
124
+ */
125
+ constructor(wasmModule, sigPtr) {
126
+ this.#wasmModule = wasmModule;
127
+ this.#sigPtr = sigPtr;
128
+ }
129
+
130
+ /**
131
+ * Generate a new SLH-DSA-SHA2-128f keypair
132
+ *
133
+ * @async
134
+ * @returns {{publicKey: Uint8Array, secretKey: Uint8Array}}
135
+ * @throws {LibOQSError} If instance is destroyed
136
+ * @throws {LibOQSOperationError} If key generation fails
137
+ *
138
+ * @example
139
+ * const { publicKey, secretKey } = sig.generateKeyPair();
140
+ * console.log('Public key:', publicKey.length); // 32 bytes
141
+ * console.log('Secret key:', secretKey.length); // 64 bytes
142
+ */
143
+ generateKeyPair() {
144
+ this.#checkDestroyed();
145
+
146
+ const publicKey = new Uint8Array(SLH_DSA_SHA2_128F_INFO.keySize.publicKey);
147
+ const secretKey = new Uint8Array(SLH_DSA_SHA2_128F_INFO.keySize.secretKey);
148
+
149
+ const publicKeyPtr = this.#wasmModule._malloc(publicKey.length);
150
+ const secretKeyPtr = this.#wasmModule._malloc(secretKey.length);
151
+
152
+ try {
153
+ const result = this.#wasmModule._OQS_SIG_keypair(this.#sigPtr, publicKeyPtr, secretKeyPtr);
154
+
155
+ if (result !== 0) {
156
+ throw new LibOQSOperationError('generateKeyPair', 'SLH-DSA-SHA2-128f', 'Key generation failed');
157
+ }
158
+
159
+ publicKey.set(this.#wasmModule.HEAPU8.subarray(publicKeyPtr, publicKeyPtr + publicKey.length));
160
+ secretKey.set(this.#wasmModule.HEAPU8.subarray(secretKeyPtr, secretKeyPtr + secretKey.length));
161
+
162
+ return { publicKey, secretKey };
163
+ } finally {
164
+ this.#wasmModule._free(publicKeyPtr);
165
+ this.#wasmModule._free(secretKeyPtr);
166
+ }
167
+ }
168
+
169
+ /**
170
+ * Sign a message using a secret key
171
+ *
172
+ * @async
173
+ * @param {Uint8Array} message - Message to sign (any length)
174
+ * @param {Uint8Array} secretKey - Secret key (64 bytes)
175
+ * @returns {Uint8Array} Signature (17088 bytes)
176
+ * @throws {LibOQSError} If instance is destroyed
177
+ * @throws {LibOQSValidationError} If secret key size is invalid
178
+ * @throws {LibOQSOperationError} If signing fails
179
+ *
180
+ * @example
181
+ * const message = new TextEncoder().encode('Hello, world!');
182
+ * const signature = sig.sign(message, secretKey);
183
+ * console.log('Signature:', signature.length); // 17088 bytes
184
+ */
185
+ sign(message, secretKey) {
186
+ this.#checkDestroyed();
187
+ this.#validateSecretKey(secretKey);
188
+
189
+ const signatureMaxLen = SLH_DSA_SHA2_128F_INFO.keySize.signature;
190
+ const signature = new Uint8Array(signatureMaxLen);
191
+
192
+ const messagePtr = this.#wasmModule._malloc(message.length);
193
+ const secretKeyPtr = this.#wasmModule._malloc(secretKey.length);
194
+ const signaturePtr = this.#wasmModule._malloc(signatureMaxLen);
195
+ const signatureLenPtr = this.#wasmModule._malloc(8);
196
+
197
+ try {
198
+ this.#wasmModule.HEAPU8.set(message, messagePtr);
199
+ this.#wasmModule.HEAPU8.set(secretKey, secretKeyPtr);
200
+
201
+ const result = this.#wasmModule._OQS_SIG_sign(
202
+ this.#sigPtr,
203
+ signaturePtr,
204
+ signatureLenPtr,
205
+ messagePtr,
206
+ message.length,
207
+ secretKeyPtr
208
+ );
209
+
210
+ if (result !== 0) {
211
+ throw new LibOQSOperationError('sign', 'SLH-DSA-SHA2-128f', 'Signing failed');
212
+ }
213
+
214
+ const actualSignatureLen = this.#wasmModule.getValue(signatureLenPtr, 'i32');
215
+ signature.set(this.#wasmModule.HEAPU8.subarray(signaturePtr, signaturePtr + actualSignatureLen));
216
+
217
+ return signature.slice(0, actualSignatureLen);
218
+ } finally {
219
+ this.#wasmModule._free(messagePtr);
220
+ this.#wasmModule._free(secretKeyPtr);
221
+ this.#wasmModule._free(signaturePtr);
222
+ this.#wasmModule._free(signatureLenPtr);
223
+ }
224
+ }
225
+
226
+ /**
227
+ * Verify a signature using a public key
228
+ *
229
+ * @async
230
+ * @param {Uint8Array} message - Original message (any length)
231
+ * @param {Uint8Array} signature - Signature to verify
232
+ * @param {Uint8Array} publicKey - Public key (32 bytes)
233
+ * @returns {boolean} True if signature is valid, false otherwise
234
+ * @throws {LibOQSError} If instance is destroyed
235
+ * @throws {LibOQSValidationError} If public key or signature size is invalid
236
+ *
237
+ * @example
238
+ * const isValid = sig.verify(message, signature, publicKey);
239
+ * console.log('Signature valid:', isValid);
240
+ */
241
+ verify(message, signature, publicKey) {
242
+ this.#checkDestroyed();
243
+ this.#validatePublicKey(publicKey);
244
+ this.#validateSignature(signature);
245
+
246
+ const messagePtr = this.#wasmModule._malloc(message.length);
247
+ const signaturePtr = this.#wasmModule._malloc(signature.length);
248
+ const publicKeyPtr = this.#wasmModule._malloc(publicKey.length);
249
+
250
+ try {
251
+ this.#wasmModule.HEAPU8.set(message, messagePtr);
252
+ this.#wasmModule.HEAPU8.set(signature, signaturePtr);
253
+ this.#wasmModule.HEAPU8.set(publicKey, publicKeyPtr);
254
+
255
+ const result = this.#wasmModule._OQS_SIG_verify(
256
+ this.#sigPtr,
257
+ messagePtr,
258
+ message.length,
259
+ signaturePtr,
260
+ signature.length,
261
+ publicKeyPtr
262
+ );
263
+
264
+ return result === 0;
265
+ } finally {
266
+ this.#wasmModule._free(messagePtr);
267
+ this.#wasmModule._free(signaturePtr);
268
+ this.#wasmModule._free(publicKeyPtr);
269
+ }
270
+ }
271
+
272
+ /**
273
+ * Free WASM resources
274
+ *
275
+ * @description
276
+ * Releases all WASM memory associated with this instance.
277
+ * The instance cannot be used after calling destroy().
278
+ *
279
+ * @example
280
+ * sig.destroy();
281
+ * // sig is now unusable
282
+ */
283
+ destroy() {
284
+ if (!this.#destroyed && this.#sigPtr) {
285
+ this.#wasmModule._OQS_SIG_free(this.#sigPtr);
286
+ this.#sigPtr = null;
287
+ this.#destroyed = true;
288
+ }
289
+ }
290
+
291
+ /**
292
+ * Enables automatic cleanup via `using` declarations
293
+ * @example
294
+ * using instance = await create...();
295
+ * // automatically cleaned up at end of scope
296
+ */
297
+ [Symbol.dispose]() {
298
+ this.destroy();
299
+ }
300
+
301
+ /**
302
+ * Get algorithm information
303
+ *
304
+ * @readonly
305
+ * @returns {typeof SLH_DSA_SHA2_128F_INFO} Algorithm metadata
306
+ *
307
+ * @example
308
+ * console.log(sig.info.name); // 'SLH-DSA-SHA2-128f'
309
+ * console.log(sig.info.securityLevel); // 1
310
+ * console.log(sig.info.keySize); // { publicKey: 32, secretKey: 64, signature: 17088 }
311
+ */
312
+ get info() {
313
+ return SLH_DSA_SHA2_128F_INFO;
314
+ }
315
+
316
+ /**
317
+ * @private
318
+ * @throws {LibOQSError} If instance is destroyed
319
+ */
320
+ #checkDestroyed() {
321
+ if (this.#destroyed) {
322
+ throw new LibOQSError('Instance has been destroyed', 'SLH-DSA-SHA2-128f');
323
+ }
324
+ }
325
+
326
+ /**
327
+ * @private
328
+ * @param {Uint8Array} publicKey
329
+ * @throws {LibOQSValidationError} If public key size is invalid
330
+ */
331
+ #validatePublicKey(publicKey) {
332
+ if (!isUint8Array(publicKey) || publicKey.length !== SLH_DSA_SHA2_128F_INFO.keySize.publicKey) {
333
+ throw new LibOQSValidationError(
334
+ `Invalid public key: expected ${SLH_DSA_SHA2_128F_INFO.keySize.publicKey} bytes, got ${publicKey?.length ?? 'null'}`,
335
+ 'SLH-DSA-SHA2-128f'
336
+ );
337
+ }
338
+ }
339
+
340
+ /**
341
+ * @private
342
+ * @param {Uint8Array} secretKey
343
+ * @throws {LibOQSValidationError} If secret key size is invalid
344
+ */
345
+ #validateSecretKey(secretKey) {
346
+ if (!isUint8Array(secretKey) || secretKey.length !== SLH_DSA_SHA2_128F_INFO.keySize.secretKey) {
347
+ throw new LibOQSValidationError(
348
+ `Invalid secret key: expected ${SLH_DSA_SHA2_128F_INFO.keySize.secretKey} bytes, got ${secretKey?.length ?? 'null'}`,
349
+ 'SLH-DSA-SHA2-128f'
350
+ );
351
+ }
352
+ }
353
+
354
+ /**
355
+ * @private
356
+ * @param {Uint8Array} signature
357
+ * @throws {LibOQSValidationError} If signature size is invalid
358
+ */
359
+ #validateSignature(signature) {
360
+ if (!isUint8Array(signature) || signature.length === 0 || signature.length > SLH_DSA_SHA2_128F_INFO.keySize.signature) {
361
+ throw new LibOQSValidationError(
362
+ `Invalid signature: expected 0 < length <= ${SLH_DSA_SHA2_128F_INFO.keySize.signature} bytes, got ${signature?.length ?? 'null'}`,
363
+ 'SLH-DSA-SHA2-128f'
364
+ );
365
+ }
366
+ }
367
+ }