@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,91 @@
1
+ /**
2
+ * @fileoverview KEM command handlers
3
+ */
4
+
5
+ import { mkdir } from 'node:fs/promises';
6
+ import { join } from 'node:path';
7
+ import { getKemFactory } from '../algorithms.js';
8
+ import { readInput, writeOutput } from '../io.js';
9
+
10
+ export async function handleKemCommand(parsed) {
11
+ const { subcommand, args, options } = parsed;
12
+
13
+ switch (subcommand) {
14
+ case 'keygen':
15
+ return await kemKeygen(args[0], options);
16
+ case 'encapsulate':
17
+ return await kemEncapsulate(args[0], args[1], options);
18
+ case 'decapsulate':
19
+ return await kemDecapsulate(args[0], args[1], args[2], options);
20
+ default:
21
+ throw new Error(`Unknown KEM subcommand: ${subcommand}`);
22
+ }
23
+ }
24
+
25
+ async function kemKeygen(algorithm, options) {
26
+ if (!algorithm) {
27
+ throw new Error('Algorithm name required');
28
+ }
29
+
30
+ const factory = getKemFactory(algorithm);
31
+ const kem = await factory();
32
+
33
+ try {
34
+ const { publicKey, secretKey } = kem.generateKeyPair();
35
+
36
+ if (options.outputDir) {
37
+ await mkdir(options.outputDir, { recursive: true });
38
+ await writeOutput(publicKey, options.format, join(options.outputDir, 'public.key'));
39
+ await writeOutput(secretKey, options.format, join(options.outputDir, 'secret.key'));
40
+ console.log(`Keypair saved to ${options.outputDir}/`);
41
+ } else {
42
+ console.log('Public Key:');
43
+ await writeOutput(publicKey, options.format, null);
44
+ console.log('\nSecret Key:');
45
+ await writeOutput(secretKey, options.format, null);
46
+ }
47
+ } finally {
48
+ kem.destroy();
49
+ }
50
+ }
51
+
52
+ async function kemEncapsulate(algorithm, publicKeyInput, options) {
53
+ if (!algorithm || !publicKeyInput) {
54
+ throw new Error('Algorithm and public key required');
55
+ }
56
+
57
+ const factory = getKemFactory(algorithm);
58
+ const kem = await factory();
59
+
60
+ try {
61
+ const publicKey = await readInput(publicKeyInput, options.inputFormat);
62
+ const { ciphertext, sharedSecret } = kem.encapsulate(publicKey);
63
+
64
+ console.log('Ciphertext:');
65
+ await writeOutput(ciphertext, options.format, options.output ? options.output + '.ct' : null);
66
+ console.log('\nShared Secret:');
67
+ await writeOutput(sharedSecret, options.format, options.output ? options.output + '.ss' : null);
68
+ } finally {
69
+ kem.destroy();
70
+ }
71
+ }
72
+
73
+ async function kemDecapsulate(algorithm, ciphertextInput, secretKeyInput, options) {
74
+ if (!algorithm || !ciphertextInput || !secretKeyInput) {
75
+ throw new Error('Algorithm, ciphertext, and secret key required');
76
+ }
77
+
78
+ const factory = getKemFactory(algorithm);
79
+ const kem = await factory();
80
+
81
+ try {
82
+ const ciphertext = await readInput(ciphertextInput, options.inputFormat);
83
+ const secretKey = await readInput(secretKeyInput, options.inputFormat);
84
+ const sharedSecret = kem.decapsulate(ciphertext, secretKey);
85
+
86
+ console.log('Shared Secret:');
87
+ await writeOutput(sharedSecret, options.format, options.output);
88
+ } finally {
89
+ kem.destroy();
90
+ }
91
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * @fileoverview List command handler
3
+ */
4
+
5
+ import { KEM_ALGORITHMS, SIG_ALGORITHMS } from '../algorithms.js';
6
+
7
+ export function handleListCommand(parsed) {
8
+ const { options } = parsed;
9
+
10
+ if (options.kem) {
11
+ console.log('KEM Algorithms:');
12
+ Object.keys(KEM_ALGORITHMS).sort((a, b) => a.localeCompare(b)).forEach(alg => {
13
+ console.log(` ${alg}`);
14
+ });
15
+ } else if (options.sig) {
16
+ console.log('Signature Algorithms:');
17
+ Object.keys(SIG_ALGORITHMS).sort((a, b) => a.localeCompare(b)).forEach(alg => {
18
+ console.log(` ${alg}`);
19
+ });
20
+ } else {
21
+ console.log('KEM Algorithms:');
22
+ Object.keys(KEM_ALGORITHMS).sort((a, b) => a.localeCompare(b)).forEach(alg => {
23
+ console.log(` ${alg}`);
24
+ });
25
+ console.log('\nSignature Algorithms:');
26
+ Object.keys(SIG_ALGORITHMS).sort((a, b) => a.localeCompare(b)).forEach(alg => {
27
+ console.log(` ${alg}`);
28
+ });
29
+ }
30
+ }
@@ -0,0 +1,98 @@
1
+ /**
2
+ * @fileoverview Signature command handlers
3
+ */
4
+
5
+ import { mkdir } from 'node:fs/promises';
6
+ import { join } from 'node:path';
7
+ import { getSigFactory } from '../algorithms.js';
8
+ import { readInput, writeOutput } from '../io.js';
9
+ import process from "node:process";
10
+
11
+ export async function handleSigCommand(parsed) {
12
+ const { subcommand, args, options } = parsed;
13
+
14
+ switch (subcommand) {
15
+ case 'keygen':
16
+ return await sigKeygen(args[0], options);
17
+ case 'sign':
18
+ return await sigSign(args[0], args[1], args[2], options);
19
+ case 'verify':
20
+ return await sigVerify(args[0], args[1], args[2], args[3], options);
21
+ default:
22
+ throw new Error(`Unknown SIG subcommand: ${subcommand}`);
23
+ }
24
+ }
25
+
26
+ async function sigKeygen(algorithm, options) {
27
+ if (!algorithm) {
28
+ throw new Error('Algorithm name required');
29
+ }
30
+
31
+ const factory = getSigFactory(algorithm);
32
+ const sig = await factory();
33
+
34
+ try {
35
+ const { publicKey, secretKey } = sig.generateKeyPair();
36
+
37
+ if (options.outputDir) {
38
+ await mkdir(options.outputDir, { recursive: true });
39
+ await writeOutput(publicKey, options.format, join(options.outputDir, 'public.key'));
40
+ await writeOutput(secretKey, options.format, join(options.outputDir, 'secret.key'));
41
+ console.log(`Keypair saved to ${options.outputDir}/`);
42
+ } else {
43
+ console.log('Public Key:');
44
+ await writeOutput(publicKey, options.format, null);
45
+ console.log('\nSecret Key:');
46
+ await writeOutput(secretKey, options.format, null);
47
+ }
48
+ } finally {
49
+ sig.destroy();
50
+ }
51
+ }
52
+
53
+ async function sigSign(algorithm, messageInput, secretKeyInput, options) {
54
+ if (!algorithm || !messageInput || !secretKeyInput) {
55
+ throw new Error('Algorithm, message, and secret key required');
56
+ }
57
+
58
+ const factory = getSigFactory(algorithm);
59
+ const sig = await factory();
60
+
61
+ try {
62
+ const message = await readInput(messageInput, options.inputFormat);
63
+ const secretKey = await readInput(secretKeyInput, options.inputFormat);
64
+ const signature = await sig.sign(message, secretKey);
65
+
66
+ console.log('Signature:');
67
+ await writeOutput(signature, options.format, options.output);
68
+ } finally {
69
+ sig.destroy();
70
+ }
71
+ }
72
+
73
+ async function sigVerify(algorithm, messageInput, signatureInput, publicKeyInput, options) {
74
+ if (!algorithm || !messageInput || !signatureInput || !publicKeyInput) {
75
+ throw new Error('Algorithm, message, signature, and public key required');
76
+ }
77
+
78
+ const factory = getSigFactory(algorithm);
79
+ const sig = await factory();
80
+
81
+ try {
82
+ const message = await readInput(messageInput, options.inputFormat);
83
+ const signature = await readInput(signatureInput, options.inputFormat);
84
+ const publicKey = await readInput(publicKeyInput, options.inputFormat);
85
+
86
+ const isValid = sig.verify(message, signature, publicKey);
87
+
88
+ if (isValid) {
89
+ console.log('✓ Signature is valid');
90
+ process.exit(0);
91
+ } else {
92
+ console.log('✗ Signature is invalid');
93
+ process.exit(1);
94
+ }
95
+ } finally {
96
+ sig.destroy();
97
+ }
98
+ }
@@ -0,0 +1,86 @@
1
+ /**
2
+ * @fileoverview CLI main module
3
+ */
4
+
5
+ import { parseArgs } from './parser.js';
6
+ import { handleKemCommand } from './commands/kem.js';
7
+ import { handleSigCommand } from './commands/sig.js';
8
+ import { handleListCommand } from './commands/list.js';
9
+ import { handleInfoCommand } from './commands/info.js';
10
+ import process from "node:process";
11
+
12
+ export function createCLI() {
13
+ return {
14
+ async parse(argv) {
15
+ const parsed = parseArgs(argv);
16
+
17
+ switch (parsed.command) {
18
+ case 'kem':
19
+ return await handleKemCommand(parsed);
20
+ case 'sig':
21
+ return await handleSigCommand(parsed);
22
+ case 'list':
23
+ return handleListCommand(parsed);
24
+ case 'info':
25
+ return handleInfoCommand(parsed);
26
+ case 'help':
27
+ printHelp();
28
+ break;
29
+ default:
30
+ printHelp();
31
+ process.exit(1);
32
+ }
33
+ }
34
+ };
35
+ }
36
+
37
+ function printHelp() {
38
+ console.log(`
39
+ liboqs - Post-quantum cryptography CLI
40
+
41
+ Usage:
42
+ liboqs <command> [options]
43
+
44
+ Commands:
45
+ kem keygen <algorithm> Generate KEM keypair
46
+ kem encapsulate <algorithm> <public-key> Encapsulate to create shared secret
47
+ kem decapsulate <algorithm> <ct> <sk> Decapsulate to recover shared secret
48
+
49
+ sig keygen <algorithm> Generate signature keypair
50
+ sig sign <algorithm> <message> <sk> Sign a message
51
+ sig verify <algorithm> <msg> <sig> <pk> Verify a signature
52
+
53
+ list [--kem|--sig] List available algorithms
54
+ info <algorithm> Show algorithm information
55
+
56
+ Options:
57
+ --format <hex|base64|raw> Output encoding (default: hex)
58
+ --input-format <hex|base64> Input encoding (default: auto)
59
+ --output <file> Write output to file
60
+ --output-dir <dir> Directory for keygen output
61
+ --help, -h Show this help
62
+
63
+ Input Methods:
64
+ - File path: ./path/to/file
65
+ - Direct string: "hello world"
66
+ - Hex/Base64: hex:a1b2c3... or base64:SGVsbG8=
67
+ - Stdin: - (dash for piped input)
68
+ - Env var: LIBOQS_SECRET_KEY or $LIBOQS_SECRET_KEY
69
+
70
+ Examples:
71
+ # Generate ML-KEM-768 keypair
72
+ liboqs kem keygen ml-kem-768 --output-dir ./keys
73
+
74
+ # Sign a message
75
+ liboqs sig sign ml-dsa-65 "Hello" ./secret.key --output sig.bin
76
+
77
+ # Verify with piped message
78
+ echo "Hello" | liboqs sig verify ml-dsa-65 - sig.bin ./public.key
79
+
80
+ # Use environment variables
81
+ export LIBOQS_SECRET_KEY="$(cat secret.key)"
82
+ liboqs sig sign ml-dsa-65 message.txt LIBOQS_SECRET_KEY
83
+
84
+ For more information: https://open-quantum-safe.github.io/liboqs-js
85
+ `);
86
+ }
package/src/cli/io.js ADDED
@@ -0,0 +1,147 @@
1
+ /**
2
+ * @fileoverview CLI input/output utilities
3
+ */
4
+
5
+ import { existsSync } from 'node:fs';
6
+ import { readFile, writeFile } from 'node:fs/promises';
7
+ import process from "node:process";
8
+ import { Buffer } from "node:buffer";
9
+
10
+ /**
11
+ * Read input from various sources
12
+ * @param {string} input - Input string (file path, hex:, base64:, -, or LIBOQS_* env var)
13
+ * @param {string} inputFormat - Format override (hex|base64|auto)
14
+ * @returns {Promise<Uint8Array>}
15
+ */
16
+ export async function readInput(input, inputFormat = 'auto') {
17
+ // Check for stdin
18
+ if (input === '-') {
19
+ return await readStdin();
20
+ }
21
+
22
+ // Check for env var reference (LIBOQS_* or $LIBOQS_*)
23
+ const envVarName = input.startsWith('$') ? input.slice(1) : input;
24
+ if (envVarName.startsWith('LIBOQS_')) {
25
+ const envValue = process.env[envVarName];
26
+ if (!envValue) {
27
+ throw new Error(`Environment variable ${envVarName} is not set`);
28
+ }
29
+ input = envValue;
30
+ }
31
+
32
+ // Check for explicit encoding prefix
33
+ if (input.startsWith('hex:')) {
34
+ return hexToBytes(input.slice(4));
35
+ }
36
+ if (input.startsWith('base64:')) {
37
+ return base64ToBytes(input.slice(7));
38
+ }
39
+
40
+ // Try to read as file
41
+ if (existsSync(input)) {
42
+ const buffer = await readFile(input);
43
+ // Convert Buffer to Uint8Array for compatibility with algorithm validation
44
+ return new Uint8Array(buffer);
45
+ }
46
+
47
+ // Auto-detect format or treat as raw string
48
+ if (inputFormat === 'hex' || (inputFormat === 'auto' && /^[0-9a-fA-F]+$/.test(input))) {
49
+ return hexToBytes(input);
50
+ }
51
+ if (inputFormat === 'base64' || (inputFormat === 'auto' && /^[A-Za-z0-9+/=]+$/.test(input))) {
52
+ return base64ToBytes(input);
53
+ }
54
+
55
+ // Treat as raw string
56
+ return new TextEncoder().encode(input);
57
+ }
58
+
59
+ /**
60
+ * Read from stdin
61
+ * @returns {Promise<Uint8Array>}
62
+ */
63
+ async function readStdin() {
64
+ const chunks = [];
65
+ for await (const chunk of process.stdin) {
66
+ chunks.push(chunk);
67
+ }
68
+ const buffer = Buffer.concat(chunks);
69
+ // Convert Buffer to Uint8Array for compatibility with algorithm validation
70
+ return new Uint8Array(buffer);
71
+ }
72
+
73
+ /**
74
+ * Write output to file or stdout
75
+ * @param {Uint8Array} data - Data to write
76
+ * @param {string} format - Output format (hex|base64|raw)
77
+ * @param {string|null} outputPath - Output file path or null for stdout
78
+ */
79
+ export async function writeOutput(data, format = 'hex', outputPath = null) {
80
+ let output;
81
+
82
+ switch (format) {
83
+ case 'hex':
84
+ output = bytesToHex(data);
85
+ break;
86
+ case 'base64':
87
+ output = bytesToBase64(data);
88
+ break;
89
+ case 'raw':
90
+ output = data;
91
+ break;
92
+ default:
93
+ throw new Error(`Unknown output format: ${format}`);
94
+ }
95
+
96
+ if (outputPath) {
97
+ if (typeof output === 'string') {
98
+ await writeFile(outputPath, output, 'utf8');
99
+ } else {
100
+ await writeFile(outputPath, output);
101
+ }
102
+ } else if (typeof output === 'string') {
103
+ console.log(output);
104
+ } else {
105
+ process.stdout.write(output);
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Convert hex string to Uint8Array
111
+ */
112
+ function hexToBytes(hex) {
113
+ const clean = hex.replaceAll(/\s/g, '');
114
+ if (clean.length % 2 !== 0) {
115
+ throw new Error('Invalid hex string length');
116
+ }
117
+ const bytes = new Uint8Array(clean.length / 2);
118
+ for (let i = 0; i < bytes.length; i++) {
119
+ bytes[i] = Number.parseInt(clean.substr(i * 2, 2), 16);
120
+ }
121
+ return bytes;
122
+ }
123
+
124
+ /**
125
+ * Convert base64 string to Uint8Array
126
+ */
127
+ function base64ToBytes(base64) {
128
+ const buffer = Buffer.from(base64, 'base64');
129
+ // Convert Buffer to Uint8Array for compatibility with algorithm validation
130
+ return new Uint8Array(buffer);
131
+ }
132
+
133
+ /**
134
+ * Convert Uint8Array to hex string
135
+ */
136
+ function bytesToHex(bytes) {
137
+ return Array.from(bytes)
138
+ .map(b => b.toString(16).padStart(2, '0'))
139
+ .join('');
140
+ }
141
+
142
+ /**
143
+ * Convert Uint8Array to base64 string
144
+ */
145
+ function bytesToBase64(bytes) {
146
+ return Buffer.from(bytes).toString('base64');
147
+ }
@@ -0,0 +1,64 @@
1
+ /**
2
+ * @fileoverview CLI argument parser
3
+ */
4
+
5
+ export function parseArgs(argv) {
6
+ if (argv.length === 0 || argv[0] === '--help' || argv[0] === '-h') {
7
+ return { command: 'help' };
8
+ }
9
+
10
+ const command = argv[0];
11
+
12
+ // Commands without subcommands: list, info
13
+ const noSubcommandCommands = ['list', 'info'];
14
+ const hasSubcommand = !noSubcommandCommands.includes(command) && argv[1] && !argv[1].startsWith('--');
15
+
16
+ const subcommand = hasSubcommand ? argv[1] : null;
17
+ const startIndex = hasSubcommand ? 2 : 1;
18
+
19
+ const args = [];
20
+ const options = {
21
+ format: 'hex',
22
+ inputFormat: 'auto',
23
+ output: null,
24
+ outputDir: null,
25
+ kem: false,
26
+ sig: false
27
+ };
28
+
29
+ // Parse arguments and flags
30
+ for (let i = startIndex; i < argv.length; i++) {
31
+ const arg = argv[i];
32
+
33
+ if (arg.startsWith('--')) {
34
+ const flag = arg.slice(2);
35
+
36
+ if (flag === 'format' || flag === 'input-format' || flag === 'output' || flag === 'output-dir') {
37
+ const value = argv[++i];
38
+ if (!value) {
39
+ throw new Error(`Missing value for --${flag}`);
40
+ }
41
+
42
+ if (flag === 'format') options.format = value;
43
+ else if (flag === 'input-format') options.inputFormat = value;
44
+ else if (flag === 'output') options.output = value;
45
+ else if (flag === 'output-dir') options.outputDir = value;
46
+ } else if (flag === 'kem') {
47
+ options.kem = true;
48
+ } else if (flag === 'sig') {
49
+ options.sig = true;
50
+ } else {
51
+ throw new Error(`Unknown option: --${flag}`);
52
+ }
53
+ } else {
54
+ args.push(arg);
55
+ }
56
+ }
57
+
58
+ return {
59
+ command,
60
+ subcommand,
61
+ args,
62
+ options
63
+ };
64
+ }
@@ -0,0 +1,75 @@
1
+ /**
2
+ * @fileoverview Error classes for LibOQS operations
3
+ * @module @oqs/liboqs-js/errors
4
+ */
5
+
6
+ /**
7
+ * Base error class for all LibOQS errors
8
+ * @extends Error
9
+ */
10
+ export class LibOQSError extends Error {
11
+ /**
12
+ * @param {string} message - Error message
13
+ * @param {string} [algorithm] - Algorithm name
14
+ * @param {string} [operation] - Operation name
15
+ */
16
+ constructor(message, algorithm, operation) {
17
+ super(message);
18
+ this.name = 'LibOQSError';
19
+ this.algorithm = algorithm;
20
+ this.operation = operation;
21
+
22
+ // Maintains proper stack trace for where our error was thrown (only available on V8)
23
+ if (Error.captureStackTrace) {
24
+ Error.captureStackTrace(this, this.constructor);
25
+ }
26
+ }
27
+ }
28
+
29
+ /**
30
+ * Error thrown during algorithm initialization
31
+ * @extends LibOQSError
32
+ */
33
+ export class LibOQSInitError extends LibOQSError {
34
+ /**
35
+ * @param {string} algorithm - Algorithm name
36
+ * @param {string} [details] - Additional error details
37
+ */
38
+ constructor(algorithm, details) {
39
+ const message = `Failed to initialize ${algorithm}${details ? ': ' + details : ''}`;
40
+ super(message, algorithm, 'init');
41
+ this.name = 'LibOQSInitError';
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Error thrown during cryptographic operations
47
+ * @extends LibOQSError
48
+ */
49
+ export class LibOQSOperationError extends LibOQSError {
50
+ /**
51
+ * @param {string} operation - Operation name (e.g., 'keypair', 'encaps', 'sign')
52
+ * @param {string} algorithm - Algorithm name
53
+ * @param {string} [details] - Additional error details
54
+ */
55
+ constructor(operation, algorithm, details) {
56
+ const message = `${operation} failed for ${algorithm}${details ? ': ' + details : ''}`;
57
+ super(message, algorithm, operation);
58
+ this.name = 'LibOQSOperationError';
59
+ }
60
+ }
61
+
62
+ /**
63
+ * Error thrown for validation failures
64
+ * @extends LibOQSError
65
+ */
66
+ export class LibOQSValidationError extends LibOQSError {
67
+ /**
68
+ * @param {string} message - Error message
69
+ * @param {string} [algorithm] - Algorithm name
70
+ */
71
+ constructor(message, algorithm) {
72
+ super(message, algorithm, 'validation');
73
+ this.name = 'LibOQSValidationError';
74
+ }
75
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * @fileoverview Cross-realm validation utilities
3
+ * @module core/validation
4
+ * @description
5
+ * Provides validation functions that work across different JavaScript realms
6
+ * (e.g., different iframes, workers, WASM contexts, jsdom vs real browser).
7
+ *
8
+ * Uses duck-typing instead of instanceof to avoid cross-realm issues.
9
+ */
10
+
11
+ /**
12
+ * Check if a value is a Uint8Array (cross-realm safe)
13
+ *
14
+ * @param {*} value - Value to check
15
+ * @returns {boolean} True if value is Uint8Array-like
16
+ *
17
+ * @example
18
+ * isUint8Array(new Uint8Array([1, 2, 3])); // true
19
+ * isUint8Array([1, 2, 3]); // false
20
+ * isUint8Array(null); // false
21
+ */
22
+ export function isUint8Array(value) {
23
+ // Check if value is a typed array view and specifically Uint8Array
24
+ return value != null &&
25
+ typeof value === 'object' &&
26
+ ArrayBuffer.isView(value) &&
27
+ value.constructor.name === 'Uint8Array';
28
+ }