@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-44 signature algorithm implementation
3
+ * @module algorithms/sig/ml-dsa/ml-dsa-44
4
+ * @description
5
+ * ML-DSA-44 is a lattice-based digital signature algorithm providing NIST security level 2.
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 2 (128-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-44.deno.js`
26
+ : `../../../../dist/ml-dsa-44.min.js`;
27
+
28
+ const module = await import(modulePath);
29
+ return module.default;
30
+ }
31
+
32
+ /**
33
+ * ML-DSA-44-INFO algorithm constants and metadata
34
+ * @type {{readonly name: 'ML-DSA-44', readonly identifier: 'ML-DSA-44', readonly type: 'sig', readonly securityLevel: 2, readonly standardized: true, readonly description: string, readonly keySize: {readonly publicKey: 1312, readonly secretKey: 2560, readonly signature: 2420}}}
35
+ */
36
+ export const ML_DSA_44_INFO = {
37
+ name: 'ML-DSA-44',
38
+ identifier: 'ML-DSA-44',
39
+ type: 'sig',
40
+ securityLevel: 2,
41
+ standardized: true,
42
+ description: 'NIST FIPS 204 ML-DSA-44 lattice-based signature (NIST Level 2, 128-bit quantum security)',
43
+ keySize: {
44
+ publicKey: 1312,
45
+ secretKey: 2560,
46
+ signature: 2420
47
+ }
48
+ };
49
+
50
+ /**
51
+ * Load and initialize ML-DSA-44 module
52
+ * @returns {Promise<MLDSA44>} Initialized ML-DSA-44 instance
53
+ * @throws {LibOQSInitError} If initialization fails
54
+ * @example
55
+ * import { createMLDSA44 } from '@oqs/liboqs-js';
56
+ * const sig = await createMLDSA44();
57
+ */
58
+ export async function createMLDSA44() {
59
+ const moduleFactory = await loadModule();
60
+ const wasmModule = await moduleFactory();
61
+ wasmModule._OQS_init();
62
+
63
+ const algoName = ML_DSA_44_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-44', 'Failed to create SIG instance');
73
+ }
74
+
75
+ return new MLDSA44(wasmModule, sigPtr);
76
+ }
77
+
78
+ /**
79
+ * ML-DSA-44 digital signature wrapper class
80
+ *
81
+ * Provides high-level interface for ML-DSA-44 digital signature operations.
82
+ * Automatically manages WASM memory and validates inputs.
83
+ *
84
+ * @class MLDSA44
85
+ * @example
86
+ * const sig = await createMLDSA44();
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 MLDSA44 {
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-44 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_44_INFO.keySize.publicKey);
127
+ const secretKey = new Uint8Array(ML_DSA_44_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-44', '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 (2560 bytes)
157
+ * @returns {Uint8Array} Digital signature (up to 2420 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_44_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-44', '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 (1312 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_44_INFO} Algorithm metadata
285
+ */
286
+ get info() {
287
+ return ML_DSA_44_INFO;
288
+ }
289
+
290
+ #checkDestroyed() {
291
+ if (this.#destroyed) {
292
+ throw new LibOQSError('Instance has been destroyed', 'ML-DSA-44');
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-44'
301
+ );
302
+ }
303
+ }
304
+
305
+ #validatePublicKey(publicKey) {
306
+ if (!isUint8Array(publicKey) || publicKey.length !== ML_DSA_44_INFO.keySize.publicKey) {
307
+ throw new LibOQSValidationError(
308
+ `Invalid public key: expected ${ML_DSA_44_INFO.keySize.publicKey} bytes, got ${publicKey?.length ?? 'null'}`,
309
+ 'ML-DSA-44'
310
+ );
311
+ }
312
+ }
313
+
314
+ #validateSecretKey(secretKey) {
315
+ if (!isUint8Array(secretKey) || secretKey.length !== ML_DSA_44_INFO.keySize.secretKey) {
316
+ throw new LibOQSValidationError(
317
+ `Invalid secret key: expected ${ML_DSA_44_INFO.keySize.secretKey} bytes, got ${secretKey?.length ?? 'null'}`,
318
+ 'ML-DSA-44'
319
+ );
320
+ }
321
+ }
322
+
323
+ #validateSignature(signature) {
324
+ if (!isUint8Array(signature)) {
325
+ throw new LibOQSValidationError(
326
+ 'Signature must be Uint8Array',
327
+ 'ML-DSA-44'
328
+ );
329
+ }
330
+ if (signature.length === 0 || signature.length > ML_DSA_44_INFO.keySize.signature) {
331
+ throw new LibOQSValidationError(
332
+ `Invalid signature length: expected up to ${ML_DSA_44_INFO.keySize.signature} bytes, got ${signature.length}`,
333
+ 'ML-DSA-44'
334
+ );
335
+ }
336
+ }
337
+ }
338
+
@@ -0,0 +1,338 @@
1
+ /**
2
+ * @fileoverview ML-DSA-65 signature algorithm implementation
3
+ * @module algorithms/sig/ml-dsa/ml-dsa-65
4
+ * @description
5
+ * ML-DSA-65 is a lattice-based digital signature algorithm providing NIST security level 3.
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 3 (192-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-65.deno.js`
26
+ : `../../../../dist/ml-dsa-65.min.js`;
27
+
28
+ const module = await import(modulePath);
29
+ return module.default;
30
+ }
31
+
32
+ /**
33
+ * ML-DSA-65-INFO algorithm constants and metadata
34
+ * @type {{readonly name: 'ML-DSA-65', readonly identifier: 'ML-DSA-65', readonly type: 'sig', readonly securityLevel: 3, readonly standardized: true, readonly description: string, readonly keySize: {readonly publicKey: 1952, readonly secretKey: 4032, readonly signature: 3309}}}
35
+ */
36
+ export const ML_DSA_65_INFO = {
37
+ name: 'ML-DSA-65',
38
+ identifier: 'ML-DSA-65',
39
+ type: 'sig',
40
+ securityLevel: 3,
41
+ standardized: true,
42
+ description: 'NIST FIPS 204 ML-DSA-65 lattice-based signature (NIST Level 3, 192-bit quantum security)',
43
+ keySize: {
44
+ publicKey: 1952,
45
+ secretKey: 4032,
46
+ signature: 3309
47
+ }
48
+ };
49
+
50
+ /**
51
+ * Load and initialize ML-DSA-65 module
52
+ * @returns {Promise<MLDSA65>} Initialized ML-DSA-65 instance
53
+ * @throws {LibOQSInitError} If initialization fails
54
+ * @example
55
+ * import { createMLDSA65 } from '@oqs/liboqs-js';
56
+ * const sig = await createMLDSA65();
57
+ */
58
+ export async function createMLDSA65() {
59
+ const moduleFactory = await loadModule();
60
+ const wasmModule = await moduleFactory();
61
+ wasmModule._OQS_init();
62
+
63
+ const algoName = ML_DSA_65_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-65', 'Failed to create SIG instance');
73
+ }
74
+
75
+ return new MLDSA65(wasmModule, sigPtr);
76
+ }
77
+
78
+ /**
79
+ * ML-DSA-65 digital signature wrapper class
80
+ *
81
+ * Provides high-level interface for ML-DSA-65 digital signature operations.
82
+ * Automatically manages WASM memory and validates inputs.
83
+ *
84
+ * @class MLDSA65
85
+ * @example
86
+ * const sig = await createMLDSA65();
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 MLDSA65 {
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-65 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_65_INFO.keySize.publicKey);
127
+ const secretKey = new Uint8Array(ML_DSA_65_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-65', '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 (4032 bytes)
157
+ * @returns {Uint8Array} Digital signature (up to 3309 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_65_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-65', '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 (1952 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_65_INFO} Algorithm metadata
285
+ */
286
+ get info() {
287
+ return ML_DSA_65_INFO;
288
+ }
289
+
290
+ #checkDestroyed() {
291
+ if (this.#destroyed) {
292
+ throw new LibOQSError('Instance has been destroyed', 'ML-DSA-65');
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-65'
301
+ );
302
+ }
303
+ }
304
+
305
+ #validatePublicKey(publicKey) {
306
+ if (!isUint8Array(publicKey) || publicKey.length !== ML_DSA_65_INFO.keySize.publicKey) {
307
+ throw new LibOQSValidationError(
308
+ `Invalid public key: expected ${ML_DSA_65_INFO.keySize.publicKey} bytes, got ${publicKey?.length ?? 'null'}`,
309
+ 'ML-DSA-65'
310
+ );
311
+ }
312
+ }
313
+
314
+ #validateSecretKey(secretKey) {
315
+ if (!isUint8Array(secretKey) || secretKey.length !== ML_DSA_65_INFO.keySize.secretKey) {
316
+ throw new LibOQSValidationError(
317
+ `Invalid secret key: expected ${ML_DSA_65_INFO.keySize.secretKey} bytes, got ${secretKey?.length ?? 'null'}`,
318
+ 'ML-DSA-65'
319
+ );
320
+ }
321
+ }
322
+
323
+ #validateSignature(signature) {
324
+ if (!isUint8Array(signature)) {
325
+ throw new LibOQSValidationError(
326
+ 'Signature must be Uint8Array',
327
+ 'ML-DSA-65'
328
+ );
329
+ }
330
+ if (signature.length === 0 || signature.length > ML_DSA_65_INFO.keySize.signature) {
331
+ throw new LibOQSValidationError(
332
+ `Invalid signature length: expected up to ${ML_DSA_65_INFO.keySize.signature} bytes, got ${signature.length}`,
333
+ 'ML-DSA-65'
334
+ );
335
+ }
336
+ }
337
+ }
338
+