@sebastienrousseau/crypto-benchmarks 0.0.8 → 0.0.24

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.
@@ -1 +1 @@
1
- {"version":3,"file":"asymmetric.d.ts","sourceRoot":"","sources":["../../src/benchmarks/asymmetric.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAM/C,wBAAsB,uBAAuB,CAC3C,UAAU,SAAK,GACd,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAsFhC"}
1
+ {"version":3,"file":"asymmetric.d.ts","sourceRoot":"","sources":["../../src/benchmarks/asymmetric.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAqG/C,wBAAsB,uBAAuB,CAC3C,UAAU,SAAK,GACd,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAUhC"}
@@ -6,33 +6,35 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.runAsymmetricBenchmarks = runAsymmetricBenchmarks;
7
7
  const node_crypto_1 = __importDefault(require("node:crypto"));
8
8
  const timer_1 = require("../timer");
9
- async function runAsymmetricBenchmarks(iterations = 20) {
10
- const results = [];
11
- const message = Buffer.from("Financial Transaction ISO 20022 Compliance Payload");
9
+ async function benchEd25519(message, iterations) {
12
10
  const edKeys = node_crypto_1.default.generateKeyPairSync("ed25519");
13
11
  let edSig = Buffer.alloc(0);
14
12
  const edSignStats = await (0, timer_1.benchmarkOperation)(() => {
15
13
  edSig = node_crypto_1.default.sign(null, message, edKeys.privateKey);
16
14
  }, { iterations, warmup: 3 });
17
- results.push({
18
- name: "Ed25519 Digital Signing",
19
- category: "asymmetric",
20
- algorithm: "Ed25519",
21
- operation: "sign",
22
- quantumSafe: false,
23
- stats: edSignStats,
24
- });
25
15
  const edVerifyStats = await (0, timer_1.benchmarkOperation)(() => {
26
16
  node_crypto_1.default.verify(null, message, edKeys.publicKey, edSig);
27
17
  }, { iterations, warmup: 3 });
28
- results.push({
29
- name: "Ed25519 Signature Verification",
30
- category: "asymmetric",
31
- algorithm: "Ed25519",
32
- operation: "verify",
33
- quantumSafe: false,
34
- stats: edVerifyStats,
35
- });
18
+ return [
19
+ {
20
+ name: "Ed25519 Digital Signing",
21
+ category: "asymmetric",
22
+ algorithm: "Ed25519",
23
+ operation: "sign",
24
+ quantumSafe: false,
25
+ stats: edSignStats,
26
+ },
27
+ {
28
+ name: "Ed25519 Signature Verification",
29
+ category: "asymmetric",
30
+ algorithm: "Ed25519",
31
+ operation: "verify",
32
+ quantumSafe: false,
33
+ stats: edVerifyStats,
34
+ },
35
+ ];
36
+ }
37
+ async function benchEcdsa(message, iterations) {
36
38
  const ecKeys = node_crypto_1.default.generateKeyPairSync("ec", { namedCurve: "prime256v1" });
37
39
  const ecSignStats = await (0, timer_1.benchmarkOperation)(() => {
38
40
  const sign = node_crypto_1.default.createSign("SHA256");
@@ -40,14 +42,16 @@ async function runAsymmetricBenchmarks(iterations = 20) {
40
42
  sign.end();
41
43
  sign.sign(ecKeys.privateKey);
42
44
  }, { iterations, warmup: 3 });
43
- results.push({
45
+ return {
44
46
  name: "ECDSA (P-256) Digital Signing",
45
47
  category: "asymmetric",
46
48
  algorithm: "ECDSA-P256",
47
49
  operation: "sign",
48
50
  quantumSafe: false,
49
51
  stats: ecSignStats,
50
- });
52
+ };
53
+ }
54
+ async function benchRsa(message, iterations) {
51
55
  const rsaKeys = node_crypto_1.default.generateKeyPairSync("rsa", { modulusLength: 2048 });
52
56
  const rsaSignStats = await (0, timer_1.benchmarkOperation)(() => {
53
57
  const sign = node_crypto_1.default.createSign("SHA256");
@@ -55,14 +59,20 @@ async function runAsymmetricBenchmarks(iterations = 20) {
55
59
  sign.end();
56
60
  sign.sign(rsaKeys.privateKey);
57
61
  }, { iterations: Math.min(iterations, 10), warmup: 2 });
58
- results.push({
62
+ return {
59
63
  name: "RSA-2048 Digital Signing",
60
64
  category: "asymmetric",
61
65
  algorithm: "RSA-2048",
62
66
  operation: "sign",
63
67
  quantumSafe: false,
64
68
  stats: rsaSignStats,
65
- });
66
- return results;
69
+ };
70
+ }
71
+ async function runAsymmetricBenchmarks(iterations = 20) {
72
+ const message = Buffer.from("Financial Transaction ISO 20022 Compliance Payload");
73
+ const edResults = await benchEd25519(message, iterations);
74
+ const ecResult = await benchEcdsa(message, iterations);
75
+ const rsaResult = await benchRsa(message, iterations);
76
+ return [...edResults, ecResult, rsaResult];
67
77
  }
68
78
  //# sourceMappingURL=asymmetric.js.map
@@ -0,0 +1,20 @@
1
+ import { type MultiPqRecipient } from "@sebastienrousseau/crypto-lib";
2
+ import { BenchmarkItemResult } from "../types";
3
+ export interface StreamingOperations {
4
+ payload64k: Uint8Array;
5
+ symmetricKey: Uint8Array;
6
+ symmetricCiphertext64k: Uint8Array;
7
+ x25519Public: string;
8
+ x25519Secret: string;
9
+ mlKemPublic: string;
10
+ mlKemSecret: string;
11
+ pqCiphertext64k: Uint8Array;
12
+ multiRecipients: MultiPqRecipient[];
13
+ aliceId: string;
14
+ aliceX25519Secret: string;
15
+ aliceMlKemSecret: string;
16
+ multiPqCiphertext64k: Uint8Array;
17
+ }
18
+ export declare function createStreamingOperations(): StreamingOperations;
19
+ export declare function runStreamingBenchmarks(iterations?: number): Promise<BenchmarkItemResult[]>;
20
+ //# sourceMappingURL=streaming.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streaming.d.ts","sourceRoot":"","sources":["../../src/benchmarks/streaming.ts"],"names":[],"mappings":"AAGA,OAAO,EASL,KAAK,gBAAgB,EACtB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAI/C,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,UAAU,CAAC;IACvB,YAAY,EAAE,UAAU,CAAC;IACzB,sBAAsB,EAAE,UAAU,CAAC;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,UAAU,CAAC;IAC5B,eAAe,EAAE,gBAAgB,EAAE,CAAC;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,oBAAoB,EAAE,UAAU,CAAC;CAClC;AA8CD,wBAAgB,yBAAyB,IAAI,mBAAmB,CAkC/D;AA2ID,wBAAsB,sBAAsB,CAC1C,UAAU,SAAK,GACd,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAMhC"}
@@ -0,0 +1,180 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createStreamingOperations = createStreamingOperations;
7
+ exports.runStreamingBenchmarks = runStreamingBenchmarks;
8
+ const node_crypto_1 = __importDefault(require("node:crypto"));
9
+ const crypto_lib_1 = require("@sebastienrousseau/crypto-lib");
10
+ const timer_1 = require("../timer");
11
+ function createMultiRecipients() {
12
+ const aliceX = (0, crypto_lib_1.generateX25519KeyPair)();
13
+ const aliceMl = (0, crypto_lib_1.mlKemKeygen)(768);
14
+ const bobX = (0, crypto_lib_1.generateX25519KeyPair)();
15
+ const bobMl = (0, crypto_lib_1.mlKemKeygen)(768);
16
+ const charlieX = (0, crypto_lib_1.generateX25519KeyPair)();
17
+ const charlieMl = (0, crypto_lib_1.mlKemKeygen)(768);
18
+ const recipients = [
19
+ {
20
+ recipientId: "alice@example.com",
21
+ recipientX25519Public: aliceX.publicKey,
22
+ recipientMlKemPublic: aliceMl.publicKey,
23
+ },
24
+ {
25
+ recipientId: "bob@example.com",
26
+ recipientX25519Public: bobX.publicKey,
27
+ recipientMlKemPublic: bobMl.publicKey,
28
+ },
29
+ {
30
+ recipientId: "charlie@example.com",
31
+ recipientX25519Public: charlieX.publicKey,
32
+ recipientMlKemPublic: charlieMl.publicKey,
33
+ },
34
+ ];
35
+ return {
36
+ recipients,
37
+ alice: {
38
+ id: "alice@example.com",
39
+ xSec: aliceX.privateKey,
40
+ mlSec: aliceMl.secretKey,
41
+ },
42
+ };
43
+ }
44
+ function createStreamingOperations() {
45
+ const payload64k = node_crypto_1.default.randomBytes(64 * 1024);
46
+ const symmetricKey = node_crypto_1.default.randomBytes(32);
47
+ const symEnc = (0, crypto_lib_1.streamEncrypt)({ key: symmetricKey, plaintext: payload64k });
48
+ const x25519 = (0, crypto_lib_1.generateX25519KeyPair)();
49
+ const mlkem = (0, crypto_lib_1.mlKemKeygen)(768);
50
+ const pqEnc = (0, crypto_lib_1.streamPqEncrypt)({
51
+ recipientX25519Public: x25519.publicKey,
52
+ recipientMlKemPublic: mlkem.publicKey,
53
+ plaintext: payload64k,
54
+ });
55
+ const { recipients, alice } = createMultiRecipients();
56
+ const multiPqEnc = (0, crypto_lib_1.streamMultiPqEncrypt)({
57
+ recipients,
58
+ plaintext: payload64k,
59
+ });
60
+ return {
61
+ payload64k,
62
+ symmetricKey,
63
+ symmetricCiphertext64k: symEnc.ciphertext,
64
+ x25519Public: x25519.publicKey,
65
+ x25519Secret: x25519.privateKey,
66
+ mlKemPublic: mlkem.publicKey,
67
+ mlKemSecret: mlkem.secretKey,
68
+ pqCiphertext64k: pqEnc.ciphertext,
69
+ multiRecipients: recipients,
70
+ aliceId: alice.id,
71
+ aliceX25519Secret: alice.xSec,
72
+ aliceMlKemSecret: alice.mlSec,
73
+ multiPqCiphertext64k: multiPqEnc.ciphertext,
74
+ };
75
+ }
76
+ async function benchmarkSymmetricStreaming(ops, iterations) {
77
+ const encStats = await (0, timer_1.benchmarkOperation)(() => {
78
+ (0, crypto_lib_1.streamEncrypt)({ key: ops.symmetricKey, plaintext: ops.payload64k });
79
+ }, { iterations, warmup: 5 });
80
+ const decStats = await (0, timer_1.benchmarkOperation)(() => {
81
+ (0, crypto_lib_1.streamDecrypt)({
82
+ key: ops.symmetricKey,
83
+ ciphertext: ops.symmetricCiphertext64k,
84
+ });
85
+ }, { iterations, warmup: 5 });
86
+ return [
87
+ {
88
+ name: "Symmetric Stream AEAD Encrypt (64KB)",
89
+ category: "streaming",
90
+ algorithm: "XChaCha20-Poly1305",
91
+ operation: "encrypt",
92
+ quantumSafe: true,
93
+ stats: encStats,
94
+ },
95
+ {
96
+ name: "Symmetric Stream AEAD Decrypt (64KB)",
97
+ category: "streaming",
98
+ algorithm: "XChaCha20-Poly1305",
99
+ operation: "decrypt",
100
+ quantumSafe: true,
101
+ stats: decStats,
102
+ },
103
+ ];
104
+ }
105
+ async function benchmarkPqStreaming(ops, iterations) {
106
+ const encStats = await (0, timer_1.benchmarkOperation)(() => {
107
+ (0, crypto_lib_1.streamPqEncrypt)({
108
+ recipientX25519Public: ops.x25519Public,
109
+ recipientMlKemPublic: ops.mlKemPublic,
110
+ plaintext: ops.payload64k,
111
+ });
112
+ }, { iterations, warmup: 5 });
113
+ const decStats = await (0, timer_1.benchmarkOperation)(() => {
114
+ (0, crypto_lib_1.streamPqDecrypt)({
115
+ recipientX25519Secret: ops.x25519Secret,
116
+ recipientMlKemSecret: ops.mlKemSecret,
117
+ ciphertext: ops.pqCiphertext64k,
118
+ });
119
+ }, { iterations, warmup: 5 });
120
+ return [
121
+ {
122
+ name: "Post-Quantum Stream AEAD Encrypt (64KB)",
123
+ category: "streaming",
124
+ algorithm: "X25519+ML-KEM-768",
125
+ operation: "encrypt",
126
+ quantumSafe: true,
127
+ stats: encStats,
128
+ },
129
+ {
130
+ name: "Post-Quantum Stream AEAD Decrypt (64KB)",
131
+ category: "streaming",
132
+ algorithm: "X25519+ML-KEM-768",
133
+ operation: "decrypt",
134
+ quantumSafe: true,
135
+ stats: decStats,
136
+ },
137
+ ];
138
+ }
139
+ async function benchmarkMultiPqStreaming(ops, iterations) {
140
+ const encStats = await (0, timer_1.benchmarkOperation)(() => {
141
+ (0, crypto_lib_1.streamMultiPqEncrypt)({
142
+ recipients: ops.multiRecipients,
143
+ plaintext: ops.payload64k,
144
+ });
145
+ }, { iterations, warmup: 5 });
146
+ const decStats = await (0, timer_1.benchmarkOperation)(() => {
147
+ (0, crypto_lib_1.streamMultiPqDecrypt)({
148
+ recipientId: ops.aliceId,
149
+ recipientX25519Secret: ops.aliceX25519Secret,
150
+ recipientMlKemSecret: ops.aliceMlKemSecret,
151
+ ciphertext: ops.multiPqCiphertext64k,
152
+ });
153
+ }, { iterations, warmup: 5 });
154
+ return [
155
+ {
156
+ name: "Multi-Recipient PQ Stream AEAD Encrypt (3 recipients, 64KB)",
157
+ category: "streaming",
158
+ algorithm: "Multi-X25519+ML-KEM-768",
159
+ operation: "encrypt",
160
+ quantumSafe: true,
161
+ stats: encStats,
162
+ },
163
+ {
164
+ name: "Multi-Recipient PQ Stream AEAD Decrypt (3 recipients, 64KB)",
165
+ category: "streaming",
166
+ algorithm: "Multi-X25519+ML-KEM-768",
167
+ operation: "decrypt",
168
+ quantumSafe: true,
169
+ stats: decStats,
170
+ },
171
+ ];
172
+ }
173
+ async function runStreamingBenchmarks(iterations = 30) {
174
+ const ops = createStreamingOperations();
175
+ const symmetric = await benchmarkSymmetricStreaming(ops, iterations);
176
+ const pq = await benchmarkPqStreaming(ops, iterations);
177
+ const multiPq = await benchmarkMultiPqStreaming(ops, iterations);
178
+ return [...symmetric, ...pq, ...multiPq];
179
+ }
180
+ //# sourceMappingURL=streaming.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"symmetric.d.ts","sourceRoot":"","sources":["../../src/benchmarks/symmetric.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAM/C,wBAAsB,sBAAsB,CAC1C,UAAU,SAAK,GACd,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAsEhC"}
1
+ {"version":3,"file":"symmetric.d.ts","sourceRoot":"","sources":["../../src/benchmarks/symmetric.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAwF/C,wBAAsB,sBAAsB,CAC1C,UAAU,SAAK,GACd,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAYhC"}
@@ -6,56 +6,65 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.runSymmetricBenchmarks = runSymmetricBenchmarks;
7
7
  const node_crypto_1 = __importDefault(require("node:crypto"));
8
8
  const timer_1 = require("../timer");
9
- async function runSymmetricBenchmarks(iterations = 50) {
10
- const results = [];
11
- const payload = node_crypto_1.default.randomBytes(1024);
12
- const key32 = node_crypto_1.default.randomBytes(32);
13
- const key16 = node_crypto_1.default.randomBytes(16);
14
- const iv12 = node_crypto_1.default.randomBytes(12);
15
- const iv16 = node_crypto_1.default.randomBytes(16);
16
- const aesGcmEncStats = await (0, timer_1.benchmarkOperation)(() => {
17
- const cipher = node_crypto_1.default.createCipheriv("aes-256-gcm", key32, iv12);
9
+ async function benchAesGcm(payload, key, iv, iterations) {
10
+ const stats = await (0, timer_1.benchmarkOperation)(() => {
11
+ const cipher = node_crypto_1.default.createCipheriv("aes-256-gcm", key, iv);
18
12
  cipher.update(payload);
19
13
  cipher.final();
20
14
  cipher.getAuthTag();
21
15
  }, { iterations, warmup: 5 });
22
- results.push({
16
+ return {
23
17
  name: "AES-256-GCM Encryption (1KB)",
24
18
  category: "symmetric",
25
19
  algorithm: "AES-256-GCM",
26
20
  operation: "encrypt",
27
21
  quantumSafe: true,
28
- stats: aesGcmEncStats,
29
- });
30
- const chachaEncStats = await (0, timer_1.benchmarkOperation)(() => {
31
- const cipher = node_crypto_1.default.createCipheriv("chacha20-poly1305", key32, iv12, {
22
+ stats,
23
+ };
24
+ }
25
+ async function benchChaCha(payload, key, iv, iterations) {
26
+ const stats = await (0, timer_1.benchmarkOperation)(() => {
27
+ const cipher = node_crypto_1.default.createCipheriv("chacha20-poly1305", key, iv, {
32
28
  authTagLength: 16,
33
29
  });
34
30
  cipher.update(payload);
35
31
  cipher.final();
36
32
  cipher.getAuthTag();
37
33
  }, { iterations, warmup: 5 });
38
- results.push({
34
+ return {
39
35
  name: "ChaCha20-Poly1305 Encryption (1KB)",
40
36
  category: "symmetric",
41
37
  algorithm: "ChaCha20-Poly1305",
42
38
  operation: "encrypt",
43
39
  quantumSafe: true,
44
- stats: chachaEncStats,
45
- });
46
- const aesCbcEncStats = await (0, timer_1.benchmarkOperation)(() => {
47
- const cipher = node_crypto_1.default.createCipheriv("aes-128-cbc", key16, iv16);
40
+ stats,
41
+ };
42
+ }
43
+ async function benchAesCbc(payload, key, iv, iterations) {
44
+ const stats = await (0, timer_1.benchmarkOperation)(() => {
45
+ const cipher = node_crypto_1.default.createCipheriv("aes-128-cbc", key, iv);
48
46
  cipher.update(payload);
49
47
  cipher.final();
50
48
  }, { iterations, warmup: 5 });
51
- results.push({
49
+ return {
52
50
  name: "AES-128-CBC Encryption (1KB)",
53
51
  category: "symmetric",
54
52
  algorithm: "AES-128-CBC",
55
53
  operation: "encrypt",
56
54
  quantumSafe: false,
57
- stats: aesCbcEncStats,
58
- });
59
- return results;
55
+ stats,
56
+ };
57
+ }
58
+ async function runSymmetricBenchmarks(iterations = 50) {
59
+ const payload = node_crypto_1.default.randomBytes(1024);
60
+ const key32 = node_crypto_1.default.randomBytes(32);
61
+ const key16 = node_crypto_1.default.randomBytes(16);
62
+ const iv12 = node_crypto_1.default.randomBytes(12);
63
+ const iv16 = node_crypto_1.default.randomBytes(16);
64
+ return [
65
+ await benchAesGcm(payload, key32, iv12, iterations),
66
+ await benchChaCha(payload, key32, iv12, iterations),
67
+ await benchAesCbc(payload, key16, iv16, iterations),
68
+ ];
60
69
  }
61
70
  //# sourceMappingURL=symmetric.js.map
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAOA,wBAAsB,GAAG,CACvB,IAAI,GAAE,MAAM,EAA0B,GACrC,OAAO,CAAC,MAAM,CAAC,CAsDjB"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAwCA,wBAAsB,GAAG,CACvB,IAAI,GAAE,MAAM,EAA0B,GACrC,OAAO,CAAC,MAAM,CAAC,CA8BjB"}
package/dist/cli.js CHANGED
@@ -7,49 +7,46 @@ Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.run = run;
8
8
  const node_process_1 = __importDefault(require("node:process"));
9
9
  const runner_1 = require("./runner");
10
+ const SUITES = [
11
+ "all",
12
+ "symmetric",
13
+ "asymmetric",
14
+ "pqc",
15
+ "hash",
16
+ "streaming",
17
+ ];
18
+ const FORMATS = ["table", "json", "markdown"];
19
+ function optionValue(args, flag) {
20
+ const idx = args.indexOf(flag);
21
+ return idx !== -1 && args[idx + 1] ? args[idx + 1] : undefined;
22
+ }
23
+ function pickChoice(args, flag, allowed, fallback) {
24
+ const value = optionValue(args, flag)?.toLowerCase();
25
+ return allowed.find((a) => a === value) ?? fallback;
26
+ }
27
+ function parseIterations(raw) {
28
+ const parsed = raw === undefined ? NaN : parseInt(raw, 10);
29
+ return !isNaN(parsed) && parsed > 0 ? parsed : 30;
30
+ }
10
31
  async function run(args = node_process_1.default.argv.slice(2)) {
11
32
  if (args.includes("--help") || args.includes("-h")) {
12
33
  node_process_1.default.stdout.write("Usage: crypto-benchmarks [options]\n");
13
34
  node_process_1.default.stdout.write("Options:\n");
14
- node_process_1.default.stdout.write(" --suite <all|symmetric|asymmetric|pqc|hash> Benchmark suite to run (default: all)\n");
35
+ node_process_1.default.stdout.write(" --suite <all|symmetric|asymmetric|pqc|hash|streaming> Benchmark suite to run (default: all)\n");
15
36
  node_process_1.default.stdout.write(" --iterations <N> Number of iterations (default: 30)\n");
16
37
  node_process_1.default.stdout.write(" --format <table|json|markdown> Output format (default: table)\n");
17
38
  return 0;
18
39
  }
19
- let suite = "all";
20
- const suiteIdx = args.indexOf("--suite");
21
- if (suiteIdx !== -1 && args[suiteIdx + 1]) {
22
- const s = args[suiteIdx + 1].toLowerCase();
23
- if (["all", "symmetric", "asymmetric", "pqc", "hash"].includes(s)) {
24
- suite = s;
25
- }
26
- }
27
- let iterations = 30;
28
- const iterIdx = args.indexOf("--iterations");
29
- if (iterIdx !== -1 && args[iterIdx + 1]) {
30
- const parsed = parseInt(args[iterIdx + 1], 10);
31
- if (!isNaN(parsed) && parsed > 0) {
32
- iterations = parsed;
33
- }
34
- }
35
- let format = "table";
36
- const formatIdx = args.indexOf("--format");
37
- if (formatIdx !== -1 && args[formatIdx + 1]) {
38
- const f = args[formatIdx + 1].toLowerCase();
39
- if (["table", "json", "markdown"].includes(f)) {
40
- format = f;
41
- }
42
- }
40
+ const suite = pickChoice(args, "--suite", SUITES, "all");
41
+ const iterations = parseIterations(optionValue(args, "--iterations"));
42
+ const format = pickChoice(args, "--format", FORMATS, "table");
43
43
  const report = await (0, runner_1.runSuite)({ suite, iterations, format });
44
- if (format === "json") {
45
- node_process_1.default.stdout.write(JSON.stringify(report, null, 2) + "\n");
46
- }
47
- else if (format === "markdown") {
48
- node_process_1.default.stdout.write(report.summaryMarkdown + "\n");
49
- }
50
- else {
51
- node_process_1.default.stdout.write(report.summaryTable + "\n");
52
- }
44
+ const output = {
45
+ json: () => JSON.stringify(report, null, 2),
46
+ markdown: () => report.summaryMarkdown,
47
+ table: () => report.summaryTable,
48
+ };
49
+ node_process_1.default.stdout.write(output[format]() + "\n");
53
50
  return 0;
54
51
  }
55
52
  if (require.main === module) {
package/dist/index.d.ts CHANGED
@@ -4,6 +4,7 @@ export * from "./benchmarks/symmetric";
4
4
  export * from "./benchmarks/asymmetric";
5
5
  export * from "./benchmarks/pqc";
6
6
  export * from "./benchmarks/hash";
7
+ export * from "./benchmarks/streaming";
7
8
  export * from "./runner";
8
9
  export * from "./cli";
9
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,UAAU,CAAC;AACzB,cAAc,OAAO,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,wBAAwB,CAAC;AACvC,cAAc,UAAU,CAAC;AACzB,cAAc,OAAO,CAAC"}
package/dist/index.js CHANGED
@@ -20,6 +20,7 @@ __exportStar(require("./benchmarks/symmetric"), exports);
20
20
  __exportStar(require("./benchmarks/asymmetric"), exports);
21
21
  __exportStar(require("./benchmarks/pqc"), exports);
22
22
  __exportStar(require("./benchmarks/hash"), exports);
23
+ __exportStar(require("./benchmarks/streaming"), exports);
23
24
  __exportStar(require("./runner"), exports);
24
25
  __exportStar(require("./cli"), exports);
25
26
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,eAAe,EAAuB,eAAe,EAAE,MAAM,SAAS,CAAC;AAShF,wBAAsB,QAAQ,CAC5B,MAAM,GAAE,eAAoB,GAC3B,OAAO,CAAC,eAAe,CAAC,CAsE1B"}
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,eAAe,EAAuB,eAAe,EAAE,MAAM,SAAS,CAAC;AAmDhF,wBAAsB,QAAQ,CAC5B,MAAM,GAAE,eAAoB,GAC3B,OAAO,CAAC,eAAe,CAAC,CAgC1B"}
package/dist/runner.js CHANGED
@@ -10,30 +10,13 @@ const symmetric_1 = require("./benchmarks/symmetric");
10
10
  const asymmetric_1 = require("./benchmarks/asymmetric");
11
11
  const pqc_1 = require("./benchmarks/pqc");
12
12
  const hash_1 = require("./benchmarks/hash");
13
- async function runSuite(config = {}) {
14
- const suite = config.suite || "all";
15
- const iterations = config.iterations || 30;
16
- const results = [];
17
- if (suite === "all" || suite === "symmetric") {
18
- results.push(...(await (0, symmetric_1.runSymmetricBenchmarks)(iterations)));
19
- }
20
- if (suite === "all" || suite === "asymmetric") {
21
- results.push(...(await (0, asymmetric_1.runAsymmetricBenchmarks)(iterations)));
22
- }
23
- if (suite === "all" || suite === "pqc") {
24
- results.push(...(await (0, pqc_1.runPqcBenchmarks)(iterations)));
25
- }
26
- if (suite === "all" || suite === "hash") {
27
- results.push(...(await (0, hash_1.runHashBenchmarks)(iterations)));
28
- }
29
- const timestamp = new Date().toISOString();
30
- const platform = `${node_os_1.default.platform()} ${node_os_1.default.arch()}`;
31
- const nodeVersion = node_process_1.default.version;
13
+ const streaming_1 = require("./benchmarks/streaming");
14
+ function formatMarkdown(timestamp, platform, nodeVersion, results) {
32
15
  const mdRows = results.map((r) => {
33
16
  const qs = r.quantumSafe ? "✅ Yes" : "❌ No";
34
17
  return `| ${r.name} | ${r.algorithm} | ${r.stats.meanMs.toFixed(3)} | ${r.stats.p95Ms.toFixed(3)} | ${r.stats.opsPerSec.toLocaleString()} | ${qs} |`;
35
18
  });
36
- const summaryMarkdown = [
19
+ return [
37
20
  `# Cryptographic Performance Benchmark Report`,
38
21
  ``,
39
22
  `- **Date:** ${timestamp}`,
@@ -46,6 +29,8 @@ async function runSuite(config = {}) {
46
29
  ...mdRows,
47
30
  ``,
48
31
  ].join("\n");
32
+ }
33
+ function formatTable(results) {
49
34
  const tableHeader = `Name Algorithm Mean(ms) Ops/sec QuantumSafe`;
50
35
  const tableDivider = `--------------------------------------------------------------------------------`;
51
36
  const tableRows = results.map((r) => {
@@ -56,20 +41,35 @@ async function runSuite(config = {}) {
56
41
  const qs = (r.quantumSafe ? "Yes" : "No").padStart(10);
57
42
  return `${name} ${alg} ${mean} ${ops} ${qs}`;
58
43
  });
59
- const summaryTable = [
60
- tableHeader,
61
- tableDivider,
62
- ...tableRows,
63
- tableDivider,
64
- ].join("\n");
44
+ return [tableHeader, tableDivider, ...tableRows, tableDivider].join("\n");
45
+ }
46
+ async function runSuite(config = {}) {
47
+ const suite = config.suite || "all";
48
+ const iterations = config.iterations || 30;
49
+ const results = [];
50
+ const suites = {
51
+ symmetric: symmetric_1.runSymmetricBenchmarks,
52
+ asymmetric: asymmetric_1.runAsymmetricBenchmarks,
53
+ pqc: pqc_1.runPqcBenchmarks,
54
+ hash: hash_1.runHashBenchmarks,
55
+ streaming: streaming_1.runStreamingBenchmarks,
56
+ };
57
+ for (const [name, run] of Object.entries(suites)) {
58
+ if (suite === "all" || suite === name) {
59
+ results.push(...(await run(iterations)));
60
+ }
61
+ }
62
+ const timestamp = new Date().toISOString();
63
+ const platform = `${node_os_1.default.platform()} ${node_os_1.default.arch()}`;
64
+ const nodeVersion = node_process_1.default.version;
65
65
  return {
66
66
  timestamp,
67
67
  platform,
68
68
  nodeVersion,
69
69
  totalBenchmarks: results.length,
70
70
  results,
71
- summaryMarkdown,
72
- summaryTable,
71
+ summaryMarkdown: formatMarkdown(timestamp, platform, nodeVersion, results),
72
+ summaryTable: formatTable(results),
73
73
  };
74
74
  }
75
75
  //# sourceMappingURL=runner.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"timer.d.ts","sourceRoot":"","sources":["../src/timer.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEzC,MAAM,WAAW,YAAY;IAC3B,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B;AAKD,wBAAsB,kBAAkB,CACtC,EAAE,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,EAC9B,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,cAAc,CAAC,CAmEzB"}
1
+ {"version":3,"file":"timer.d.ts","sourceRoot":"","sources":["../src/timer.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEzC,MAAM,WAAW,YAAY;IAC3B,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B;AAaD,wBAAsB,kBAAkB,CACtC,EAAE,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,EAC9B,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,cAAc,CAAC,CA6DzB"}
package/dist/timer.js CHANGED
@@ -5,23 +5,23 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.benchmarkOperation = benchmarkOperation;
7
7
  const node_process_1 = __importDefault(require("node:process"));
8
+ async function runOnce(fn) {
9
+ const res = fn();
10
+ if (res instanceof Promise) {
11
+ await res;
12
+ }
13
+ }
8
14
  async function benchmarkOperation(fn, options = {}) {
9
15
  const iterations = options.iterations && options.iterations > 0 ? options.iterations : 10;
10
16
  const warmup = options.warmup !== undefined && options.warmup >= 0 ? options.warmup : 2;
11
17
  for (let i = 0; i < warmup; i++) {
12
- const res = fn();
13
- if (res instanceof Promise) {
14
- await res;
15
- }
18
+ await runOnce(fn);
16
19
  }
17
20
  const timesMs = [];
18
21
  const startTotal = node_process_1.default.hrtime.bigint();
19
22
  for (let i = 0; i < iterations; i++) {
20
23
  const start = node_process_1.default.hrtime.bigint();
21
- const res = fn();
22
- if (res instanceof Promise) {
23
- await res;
24
- }
24
+ await runOnce(fn);
25
25
  const end = node_process_1.default.hrtime.bigint();
26
26
  const diffMs = Number(end - start) / 1_000_000;
27
27
  timesMs.push(diffMs);
package/dist/types.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export type SuiteName = "all" | "symmetric" | "asymmetric" | "pqc" | "hash";
1
+ export type SuiteName = "all" | "symmetric" | "asymmetric" | "pqc" | "hash" | "streaming";
2
2
  export type OutputFormat = "table" | "json" | "markdown";
3
3
  export interface BenchmarkConfig {
4
4
  suite?: SuiteName | undefined;
@@ -19,7 +19,7 @@ export interface BenchmarkStats {
19
19
  }
20
20
  export interface BenchmarkItemResult {
21
21
  name: string;
22
- category: "symmetric" | "asymmetric" | "pqc" | "hash";
22
+ category: "symmetric" | "asymmetric" | "pqc" | "hash" | "streaming";
23
23
  algorithm: string;
24
24
  operation: string;
25
25
  quantumSafe: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,WAAW,GAAG,YAAY,GAAG,KAAK,GAAG,MAAM,CAAC;AAC5E,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,MAAM,GAAG,UAAU,CAAC;AAEzD,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,MAAM,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;CACnC;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,WAAW,GAAG,YAAY,GAAG,KAAK,GAAG,MAAM,CAAC;IACtD,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;IACrB,KAAK,EAAE,cAAc,CAAC;CACvB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,mBAAmB,EAAE,CAAC;IAC/B,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;CACtB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,SAAS,GACnB,KAAK,GAAG,WAAW,GAAG,YAAY,GAAG,KAAK,GAAG,MAAM,GAAG,WAAW,CAAC;AACpE,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,MAAM,GAAG,UAAU,CAAC;AAEzD,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,MAAM,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;CACnC;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,WAAW,GAAG,YAAY,GAAG,KAAK,GAAG,MAAM,GAAG,WAAW,CAAC;IACpE,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;IACrB,KAAK,EAAE,cAAc,CAAC;CACvB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,mBAAmB,EAAE,CAAC;IAC/B,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;CACtB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sebastienrousseau/crypto-benchmarks",
3
- "version": "0.0.8",
3
+ "version": "0.0.24",
4
4
  "description": "Performance benchmarking and latency profiling harness comparing classical vs post-quantum cryptographic primitives across JavaScript, WebAssembly, and native runtimes.",
5
5
  "author": "Sebastien Rousseau <sebastienrousseau@users.noreply.github.com>",
6
6
  "license": "MIT OR Apache-2.0",
@@ -16,8 +16,17 @@
16
16
  "engines": {
17
17
  "node": ">=22.0.0"
18
18
  },
19
+ "type": "commonjs",
19
20
  "main": "./dist/index.js",
20
21
  "types": "./dist/index.d.ts",
22
+ "exports": {
23
+ ".": {
24
+ "types": "./dist/index.d.ts",
25
+ "require": "./dist/index.js",
26
+ "default": "./dist/index.js"
27
+ },
28
+ "./package.json": "./package.json"
29
+ },
21
30
  "sideEffects": false,
22
31
  "bin": {
23
32
  "crypto-benchmarks": "./dist/cli.js"
@@ -28,17 +37,17 @@
28
37
  "dist/**/*.d.ts.map"
29
38
  ],
30
39
  "dependencies": {
31
- "@sebastienrousseau/crypto-lib": "0.0.8"
40
+ "@sebastienrousseau/crypto-lib": "0.0.24"
32
41
  },
33
42
  "devDependencies": {
34
- "@types/chai": "^4.3.7",
43
+ "@types/chai": "^5.2.3",
35
44
  "@types/chai-as-promised": "^8.0.2",
36
- "@types/mocha": "^10.0.2",
45
+ "@types/mocha": "^10.0.10",
37
46
  "@types/node": "^26.6.3",
38
47
  "c8": "^12.0.0",
39
- "chai": "^4.5.0",
40
- "chai-as-promised": "^7.1.2",
41
- "mocha": "^10.8.2",
48
+ "chai": "^6.3.0",
49
+ "chai-as-promised": "^8.0.2",
50
+ "mocha": "^12.0.3",
42
51
  "rimraf": "^6.1.3",
43
52
  "ts-node": "^10.9.2",
44
53
  "typedoc": "^0.28.20",
@@ -50,8 +59,8 @@
50
59
  "scripts": {
51
60
  "build": "tsc --build tsconfig.json",
52
61
  "clean": "rimraf ./coverage ./dist ./docs",
53
- "lint": "eslint --ext .ts src __tests__",
54
- "lint:fix": "eslint --cache --fix --ext .ts src __tests__",
62
+ "lint": "eslint src __tests__",
63
+ "lint:fix": "eslint --cache --fix src __tests__",
55
64
  "format": "prettier --write src/**/*.ts",
56
65
  "format:check": "prettier --check \"src/**/*.ts\"",
57
66
  "test": "c8 --check-coverage --lines 100 --branches 100 --functions 100 --reporter=lcov --reporter=text mocha --config=.mocharc.cjs",