@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.
- package/LICENSE.md +50 -0
- package/README.md +829 -0
- package/bin/cli.js +16 -0
- package/dist/classic-mceliece-348864.deno.js +0 -0
- package/dist/classic-mceliece-348864.min.js +0 -0
- package/dist/classic-mceliece-348864f.deno.js +0 -0
- package/dist/classic-mceliece-348864f.min.js +0 -0
- package/dist/classic-mceliece-460896.deno.js +0 -0
- package/dist/classic-mceliece-460896.min.js +0 -0
- package/dist/classic-mceliece-460896f.deno.js +0 -0
- package/dist/classic-mceliece-460896f.min.js +0 -0
- package/dist/classic-mceliece-6688128.deno.js +0 -0
- package/dist/classic-mceliece-6688128.min.js +0 -0
- package/dist/classic-mceliece-6688128f.deno.js +0 -0
- package/dist/classic-mceliece-6688128f.min.js +0 -0
- package/dist/classic-mceliece-6960119.deno.js +0 -0
- package/dist/classic-mceliece-6960119.min.js +0 -0
- package/dist/classic-mceliece-6960119f.deno.js +0 -0
- package/dist/classic-mceliece-6960119f.min.js +0 -0
- package/dist/classic-mceliece-8192128.deno.js +0 -0
- package/dist/classic-mceliece-8192128.min.js +0 -0
- package/dist/classic-mceliece-8192128f.deno.js +0 -0
- package/dist/classic-mceliece-8192128f.min.js +0 -0
- package/dist/cross-rsdp-128-balanced.deno.js +0 -0
- package/dist/cross-rsdp-128-balanced.min.js +0 -0
- package/dist/cross-rsdp-128-fast.deno.js +0 -0
- package/dist/cross-rsdp-128-fast.min.js +0 -0
- package/dist/cross-rsdp-128-small.deno.js +0 -0
- package/dist/cross-rsdp-128-small.min.js +0 -0
- package/dist/cross-rsdp-192-balanced.deno.js +0 -0
- package/dist/cross-rsdp-192-balanced.min.js +0 -0
- package/dist/cross-rsdp-192-fast.deno.js +0 -0
- package/dist/cross-rsdp-192-fast.min.js +0 -0
- package/dist/cross-rsdp-192-small.deno.js +0 -0
- package/dist/cross-rsdp-192-small.min.js +0 -0
- package/dist/cross-rsdp-256-balanced.deno.js +0 -0
- package/dist/cross-rsdp-256-balanced.min.js +0 -0
- package/dist/cross-rsdp-256-fast.deno.js +0 -0
- package/dist/cross-rsdp-256-fast.min.js +0 -0
- package/dist/cross-rsdp-256-small.deno.js +0 -0
- package/dist/cross-rsdp-256-small.min.js +0 -0
- package/dist/cross-rsdpg-128-balanced.deno.js +0 -0
- package/dist/cross-rsdpg-128-balanced.min.js +0 -0
- package/dist/cross-rsdpg-128-fast.deno.js +0 -0
- package/dist/cross-rsdpg-128-fast.min.js +0 -0
- package/dist/cross-rsdpg-128-small.deno.js +0 -0
- package/dist/cross-rsdpg-128-small.min.js +0 -0
- package/dist/cross-rsdpg-192-balanced.deno.js +0 -0
- package/dist/cross-rsdpg-192-balanced.min.js +0 -0
- package/dist/cross-rsdpg-192-fast.deno.js +0 -0
- package/dist/cross-rsdpg-192-fast.min.js +0 -0
- package/dist/cross-rsdpg-192-small.deno.js +0 -0
- package/dist/cross-rsdpg-192-small.min.js +0 -0
- package/dist/cross-rsdpg-256-balanced.deno.js +0 -0
- package/dist/cross-rsdpg-256-balanced.min.js +0 -0
- package/dist/cross-rsdpg-256-fast.deno.js +0 -0
- package/dist/cross-rsdpg-256-fast.min.js +0 -0
- package/dist/cross-rsdpg-256-small.deno.js +0 -0
- package/dist/cross-rsdpg-256-small.min.js +0 -0
- package/dist/falcon-1024.deno.js +0 -0
- package/dist/falcon-1024.min.js +0 -0
- package/dist/falcon-512.deno.js +0 -0
- package/dist/falcon-512.min.js +0 -0
- package/dist/falcon-padded-1024.deno.js +0 -0
- package/dist/falcon-padded-1024.min.js +0 -0
- package/dist/falcon-padded-512.deno.js +0 -0
- package/dist/falcon-padded-512.min.js +0 -0
- package/dist/frodokem-1344-aes.deno.js +0 -0
- package/dist/frodokem-1344-aes.min.js +0 -0
- package/dist/frodokem-1344-shake.deno.js +0 -0
- package/dist/frodokem-1344-shake.min.js +0 -0
- package/dist/frodokem-640-aes.deno.js +0 -0
- package/dist/frodokem-640-aes.min.js +0 -0
- package/dist/frodokem-640-shake.deno.js +0 -0
- package/dist/frodokem-640-shake.min.js +0 -0
- package/dist/frodokem-976-aes.deno.js +0 -0
- package/dist/frodokem-976-aes.min.js +0 -0
- package/dist/frodokem-976-shake.deno.js +0 -0
- package/dist/frodokem-976-shake.min.js +0 -0
- package/dist/hqc-128.deno.js +0 -0
- package/dist/hqc-128.min.js +0 -0
- package/dist/hqc-192.deno.js +0 -0
- package/dist/hqc-192.min.js +0 -0
- package/dist/hqc-256.deno.js +0 -0
- package/dist/hqc-256.min.js +0 -0
- package/dist/kyber-1024.deno.js +0 -0
- package/dist/kyber-1024.min.js +0 -0
- package/dist/kyber-512.deno.js +0 -0
- package/dist/kyber-512.min.js +0 -0
- package/dist/kyber-768.deno.js +0 -0
- package/dist/kyber-768.min.js +0 -0
- package/dist/mayo-1.deno.js +0 -0
- package/dist/mayo-1.min.js +0 -0
- package/dist/mayo-2.deno.js +0 -0
- package/dist/mayo-2.min.js +0 -0
- package/dist/mayo-3.deno.js +0 -0
- package/dist/mayo-3.min.js +0 -0
- package/dist/mayo-5.deno.js +0 -0
- package/dist/mayo-5.min.js +0 -0
- package/dist/ml-dsa-44.deno.js +0 -0
- package/dist/ml-dsa-44.min.js +0 -0
- package/dist/ml-dsa-65.deno.js +0 -0
- package/dist/ml-dsa-65.min.js +0 -0
- package/dist/ml-dsa-87.deno.js +0 -0
- package/dist/ml-dsa-87.min.js +0 -0
- package/dist/ml-kem-1024.deno.js +0 -0
- package/dist/ml-kem-1024.min.js +0 -0
- package/dist/ml-kem-512.deno.js +0 -0
- package/dist/ml-kem-512.min.js +0 -0
- package/dist/ml-kem-768.deno.js +0 -0
- package/dist/ml-kem-768.min.js +0 -0
- package/dist/ntru-hps-2048-509.deno.js +0 -0
- package/dist/ntru-hps-2048-509.min.js +0 -0
- package/dist/ntru-hps-2048-677.deno.js +0 -0
- package/dist/ntru-hps-2048-677.min.js +0 -0
- package/dist/ntru-hps-4096-1229.deno.js +0 -0
- package/dist/ntru-hps-4096-1229.min.js +0 -0
- package/dist/ntru-hps-4096-821.deno.js +0 -0
- package/dist/ntru-hps-4096-821.min.js +0 -0
- package/dist/ntru-hrss-1373.deno.js +0 -0
- package/dist/ntru-hrss-1373.min.js +0 -0
- package/dist/ntru-hrss-701.deno.js +0 -0
- package/dist/ntru-hrss-701.min.js +0 -0
- package/dist/ov-iii-pkc-skc.deno.js +0 -0
- package/dist/ov-iii-pkc-skc.min.js +0 -0
- package/dist/ov-iii-pkc.deno.js +0 -0
- package/dist/ov-iii-pkc.min.js +0 -0
- package/dist/ov-iii.deno.js +0 -0
- package/dist/ov-iii.min.js +0 -0
- package/dist/ov-ip-pkc-skc.deno.js +0 -0
- package/dist/ov-ip-pkc-skc.min.js +0 -0
- package/dist/ov-ip-pkc.deno.js +0 -0
- package/dist/ov-ip-pkc.min.js +0 -0
- package/dist/ov-ip.deno.js +0 -0
- package/dist/ov-ip.min.js +0 -0
- package/dist/ov-is-pkc-skc.deno.js +0 -0
- package/dist/ov-is-pkc-skc.min.js +0 -0
- package/dist/ov-is-pkc.deno.js +0 -0
- package/dist/ov-is-pkc.min.js +0 -0
- package/dist/ov-is.deno.js +0 -0
- package/dist/ov-is.min.js +0 -0
- package/dist/ov-v-pkc-skc.deno.js +0 -0
- package/dist/ov-v-pkc-skc.min.js +0 -0
- package/dist/ov-v-pkc.deno.js +0 -0
- package/dist/ov-v-pkc.min.js +0 -0
- package/dist/ov-v.deno.js +0 -0
- package/dist/ov-v.min.js +0 -0
- package/dist/slh-dsa-sha2-128f.deno.js +0 -0
- package/dist/slh-dsa-sha2-128f.min.js +0 -0
- package/dist/slh-dsa-sha2-128s.deno.js +0 -0
- package/dist/slh-dsa-sha2-128s.min.js +0 -0
- package/dist/slh-dsa-sha2-192f.deno.js +0 -0
- package/dist/slh-dsa-sha2-192f.min.js +0 -0
- package/dist/slh-dsa-sha2-192s.deno.js +0 -0
- package/dist/slh-dsa-sha2-192s.min.js +0 -0
- package/dist/slh-dsa-sha2-256f.deno.js +0 -0
- package/dist/slh-dsa-sha2-256f.min.js +0 -0
- package/dist/slh-dsa-sha2-256s.deno.js +0 -0
- package/dist/slh-dsa-sha2-256s.min.js +0 -0
- package/dist/slh-dsa-shake-128f.deno.js +0 -0
- package/dist/slh-dsa-shake-128f.min.js +0 -0
- package/dist/slh-dsa-shake-128s.deno.js +0 -0
- package/dist/slh-dsa-shake-128s.min.js +0 -0
- package/dist/slh-dsa-shake-192f.deno.js +0 -0
- package/dist/slh-dsa-shake-192f.min.js +0 -0
- package/dist/slh-dsa-shake-192s.deno.js +0 -0
- package/dist/slh-dsa-shake-192s.min.js +0 -0
- package/dist/slh-dsa-shake-256f.deno.js +0 -0
- package/dist/slh-dsa-shake-256f.min.js +0 -0
- package/dist/slh-dsa-shake-256s.deno.js +0 -0
- package/dist/slh-dsa-shake-256s.min.js +0 -0
- package/dist/snova-24-5-4-esk.deno.js +0 -0
- package/dist/snova-24-5-4-esk.min.js +0 -0
- package/dist/snova-24-5-4-shake-esk.deno.js +0 -0
- package/dist/snova-24-5-4-shake-esk.min.js +0 -0
- package/dist/snova-24-5-4-shake.deno.js +0 -0
- package/dist/snova-24-5-4-shake.min.js +0 -0
- package/dist/snova-24-5-4.deno.js +0 -0
- package/dist/snova-24-5-4.min.js +0 -0
- package/dist/snova-24-5-5.deno.js +0 -0
- package/dist/snova-24-5-5.min.js +0 -0
- package/dist/snova-25-8-3.deno.js +0 -0
- package/dist/snova-25-8-3.min.js +0 -0
- package/dist/snova-29-6-5.deno.js +0 -0
- package/dist/snova-29-6-5.min.js +0 -0
- package/dist/snova-37-17-2.deno.js +0 -0
- package/dist/snova-37-17-2.min.js +0 -0
- package/dist/snova-37-8-4.deno.js +0 -0
- package/dist/snova-37-8-4.min.js +0 -0
- package/dist/snova-49-11-3.deno.js +0 -0
- package/dist/snova-49-11-3.min.js +0 -0
- package/dist/snova-56-25-2.deno.js +0 -0
- package/dist/snova-56-25-2.min.js +0 -0
- package/dist/snova-60-10-4.deno.js +0 -0
- package/dist/snova-60-10-4.min.js +0 -0
- package/dist/sntrup761.deno.js +0 -0
- package/dist/sntrup761.min.js +0 -0
- package/package.json +108 -0
- package/src/algorithms/kem/classic-mceliece/classic-mceliece-348864.js +336 -0
- package/src/algorithms/kem/classic-mceliece/classic-mceliece-348864f.js +336 -0
- package/src/algorithms/kem/classic-mceliece/classic-mceliece-460896.js +336 -0
- package/src/algorithms/kem/classic-mceliece/classic-mceliece-460896f.js +336 -0
- package/src/algorithms/kem/classic-mceliece/classic-mceliece-6688128.js +336 -0
- package/src/algorithms/kem/classic-mceliece/classic-mceliece-6688128f.js +336 -0
- package/src/algorithms/kem/classic-mceliece/classic-mceliece-6960119.js +336 -0
- package/src/algorithms/kem/classic-mceliece/classic-mceliece-6960119f.js +336 -0
- package/src/algorithms/kem/classic-mceliece/classic-mceliece-8192128.js +336 -0
- package/src/algorithms/kem/classic-mceliece/classic-mceliece-8192128f.js +336 -0
- package/src/algorithms/kem/frodokem/efrodokem-1344-aes.js +366 -0
- package/src/algorithms/kem/frodokem/efrodokem-1344-shake.js +366 -0
- package/src/algorithms/kem/frodokem/efrodokem-640-aes.js +366 -0
- package/src/algorithms/kem/frodokem/efrodokem-640-shake.js +366 -0
- package/src/algorithms/kem/frodokem/efrodokem-976-aes.js +366 -0
- package/src/algorithms/kem/frodokem/efrodokem-976-shake.js +366 -0
- package/src/algorithms/kem/frodokem/frodokem-1344-aes.js +366 -0
- package/src/algorithms/kem/frodokem/frodokem-1344-shake.js +366 -0
- package/src/algorithms/kem/frodokem/frodokem-640-aes.js +366 -0
- package/src/algorithms/kem/frodokem/frodokem-640-shake.js +366 -0
- package/src/algorithms/kem/frodokem/frodokem-976-aes.js +366 -0
- package/src/algorithms/kem/frodokem/frodokem-976-shake.js +366 -0
- package/src/algorithms/kem/hqc/hqc-128.js +366 -0
- package/src/algorithms/kem/hqc/hqc-192.js +366 -0
- package/src/algorithms/kem/hqc/hqc-256.js +366 -0
- package/src/algorithms/kem/kyber/kyber-1024.js +349 -0
- package/src/algorithms/kem/kyber/kyber-512.js +347 -0
- package/src/algorithms/kem/kyber/kyber-768.js +348 -0
- package/src/algorithms/kem/ml-kem/ml-kem-1024.js +345 -0
- package/src/algorithms/kem/ml-kem/ml-kem-512.js +345 -0
- package/src/algorithms/kem/ml-kem/ml-kem-768.js +344 -0
- package/src/algorithms/kem/ntru/ntru-hps-2048-509.js +366 -0
- package/src/algorithms/kem/ntru/ntru-hps-2048-677.js +366 -0
- package/src/algorithms/kem/ntru/ntru-hps-4096-1229.js +366 -0
- package/src/algorithms/kem/ntru/ntru-hps-4096-821.js +366 -0
- package/src/algorithms/kem/ntru/ntru-hrss-1373.js +366 -0
- package/src/algorithms/kem/ntru/ntru-hrss-701.js +366 -0
- package/src/algorithms/kem/ntru/sntrup761.js +367 -0
- package/src/algorithms/sig/cross/cross-rsdp-128-balanced.js +391 -0
- package/src/algorithms/sig/cross/cross-rsdp-128-fast.js +391 -0
- package/src/algorithms/sig/cross/cross-rsdp-128-small.js +391 -0
- package/src/algorithms/sig/cross/cross-rsdp-192-balanced.js +391 -0
- package/src/algorithms/sig/cross/cross-rsdp-192-fast.js +391 -0
- package/src/algorithms/sig/cross/cross-rsdp-192-small.js +391 -0
- package/src/algorithms/sig/cross/cross-rsdp-256-balanced.js +391 -0
- package/src/algorithms/sig/cross/cross-rsdp-256-fast.js +391 -0
- package/src/algorithms/sig/cross/cross-rsdp-256-small.js +391 -0
- package/src/algorithms/sig/cross/cross-rsdpg-128-balanced.js +391 -0
- package/src/algorithms/sig/cross/cross-rsdpg-128-fast.js +391 -0
- package/src/algorithms/sig/cross/cross-rsdpg-128-small.js +391 -0
- package/src/algorithms/sig/cross/cross-rsdpg-192-balanced.js +391 -0
- package/src/algorithms/sig/cross/cross-rsdpg-192-fast.js +391 -0
- package/src/algorithms/sig/cross/cross-rsdpg-192-small.js +391 -0
- package/src/algorithms/sig/cross/cross-rsdpg-256-balanced.js +391 -0
- package/src/algorithms/sig/cross/cross-rsdpg-256-fast.js +391 -0
- package/src/algorithms/sig/cross/cross-rsdpg-256-small.js +391 -0
- package/src/algorithms/sig/falcon/falcon-1024.js +378 -0
- package/src/algorithms/sig/falcon/falcon-512.js +379 -0
- package/src/algorithms/sig/falcon/falcon-padded-1024.js +380 -0
- package/src/algorithms/sig/falcon/falcon-padded-512.js +380 -0
- package/src/algorithms/sig/mayo/mayo-1.js +390 -0
- package/src/algorithms/sig/mayo/mayo-2.js +390 -0
- package/src/algorithms/sig/mayo/mayo-3.js +390 -0
- package/src/algorithms/sig/mayo/mayo-5.js +390 -0
- package/src/algorithms/sig/ml-dsa/ml-dsa-44.js +338 -0
- package/src/algorithms/sig/ml-dsa/ml-dsa-65.js +338 -0
- package/src/algorithms/sig/ml-dsa/ml-dsa-87.js +338 -0
- package/src/algorithms/sig/slh-dsa/slh-dsa-sha2-128f.js +367 -0
- package/src/algorithms/sig/slh-dsa/slh-dsa-sha2-128s.js +367 -0
- package/src/algorithms/sig/slh-dsa/slh-dsa-sha2-192f.js +367 -0
- package/src/algorithms/sig/slh-dsa/slh-dsa-sha2-192s.js +367 -0
- package/src/algorithms/sig/slh-dsa/slh-dsa-sha2-256f.js +367 -0
- package/src/algorithms/sig/slh-dsa/slh-dsa-sha2-256s.js +367 -0
- package/src/algorithms/sig/slh-dsa/slh-dsa-shake-128f.js +367 -0
- package/src/algorithms/sig/slh-dsa/slh-dsa-shake-128s.js +367 -0
- package/src/algorithms/sig/slh-dsa/slh-dsa-shake-192f.js +367 -0
- package/src/algorithms/sig/slh-dsa/slh-dsa-shake-192s.js +367 -0
- package/src/algorithms/sig/slh-dsa/slh-dsa-shake-256f.js +367 -0
- package/src/algorithms/sig/slh-dsa/slh-dsa-shake-256s.js +367 -0
- package/src/algorithms/sig/snova/snova-24-5-4-esk.js +391 -0
- package/src/algorithms/sig/snova/snova-24-5-4-shake-esk.js +391 -0
- package/src/algorithms/sig/snova/snova-24-5-4-shake.js +391 -0
- package/src/algorithms/sig/snova/snova-24-5-4.js +391 -0
- package/src/algorithms/sig/snova/snova-24-5-5.js +391 -0
- package/src/algorithms/sig/snova/snova-25-8-3.js +391 -0
- package/src/algorithms/sig/snova/snova-29-6-5.js +391 -0
- package/src/algorithms/sig/snova/snova-37-17-2.js +391 -0
- package/src/algorithms/sig/snova/snova-37-8-4.js +391 -0
- package/src/algorithms/sig/snova/snova-49-11-3.js +391 -0
- package/src/algorithms/sig/snova/snova-56-25-2.js +391 -0
- package/src/algorithms/sig/snova/snova-60-10-4.js +391 -0
- package/src/algorithms/sig/uov/ov-iii-pkc-skc.js +390 -0
- package/src/algorithms/sig/uov/ov-iii-pkc.js +390 -0
- package/src/algorithms/sig/uov/ov-iii.js +390 -0
- package/src/algorithms/sig/uov/ov-ip-pkc-skc.js +390 -0
- package/src/algorithms/sig/uov/ov-ip-pkc.js +390 -0
- package/src/algorithms/sig/uov/ov-ip.js +390 -0
- package/src/algorithms/sig/uov/ov-is-pkc-skc.js +390 -0
- package/src/algorithms/sig/uov/ov-is-pkc.js +390 -0
- package/src/algorithms/sig/uov/ov-is.js +390 -0
- package/src/algorithms/sig/uov/ov-v-pkc-skc.js +390 -0
- package/src/algorithms/sig/uov/ov-v-pkc.js +390 -0
- package/src/algorithms/sig/uov/ov-v.js +390 -0
- package/src/cli/algorithms.js +254 -0
- package/src/cli/commands/info.js +35 -0
- package/src/cli/commands/kem.js +91 -0
- package/src/cli/commands/list.js +30 -0
- package/src/cli/commands/sig.js +98 -0
- package/src/cli/index.js +86 -0
- package/src/cli/io.js +147 -0
- package/src/cli/parser.js +64 -0
- package/src/core/errors.js +75 -0
- package/src/core/validation.js +28 -0
- package/src/index.js +164 -0
- package/src/kem.js +60 -0
- package/src/sig.js +87 -0
- package/src/types/algorithms.d.ts +1543 -0
- package/src/types/errors.d.ts +60 -0
- 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
|
+
}
|
package/src/cli/index.js
ADDED
|
@@ -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
|
+
}
|