@sebastienrousseau/crypto-benchmarks 0.0.7
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 +8 -0
- package/README.md +90 -0
- package/dist/benchmarks/asymmetric.d.ts +3 -0
- package/dist/benchmarks/asymmetric.d.ts.map +1 -0
- package/dist/benchmarks/asymmetric.js +68 -0
- package/dist/benchmarks/hash.d.ts +3 -0
- package/dist/benchmarks/hash.d.ts.map +1 -0
- package/dist/benchmarks/hash.js +47 -0
- package/dist/benchmarks/pqc.d.ts +10 -0
- package/dist/benchmarks/pqc.d.ts.map +1 -0
- package/dist/benchmarks/pqc.js +65 -0
- package/dist/benchmarks/symmetric.d.ts +3 -0
- package/dist/benchmarks/symmetric.d.ts.map +1 -0
- package/dist/benchmarks/symmetric.js +61 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +58 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/runner.d.ts +3 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +75 -0
- package/dist/timer.d.ts +7 -0
- package/dist/timer.d.ts.map +1 -0
- package/dist/timer.js +57 -0
- package/dist/types.d.ts +37 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/package.json +60 -0
package/LICENSE
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
<!-- SPDX-License-Identifier: Apache-2.0 OR MIT -->
|
|
2
|
+
|
|
3
|
+
# `@sebastienrousseau/crypto-benchmarks`
|
|
4
|
+
|
|
5
|
+
> Performance benchmarking and latency profiling harness comparing classical vs post-quantum cryptographic primitives across JavaScript, WebAssembly, and native runtimes.
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/@sebastienrousseau/crypto-benchmarks)
|
|
8
|
+
[](https://opensource.org/licenses/MIT)
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Overview
|
|
13
|
+
|
|
14
|
+
`@sebastienrousseau/crypto-benchmarks` provides high-precision latency, throughput (MB/s), and operations-per-second (ops/sec) profiling across classical algorithms (RSA, ECDSA, AES, SHA-2) and post-quantum standards (NIST FIPS 203 ML-KEM, FIPS 204 ML-DSA, FIPS 205 SLH-DSA).
|
|
15
|
+
|
|
16
|
+
## Features
|
|
17
|
+
|
|
18
|
+
- **High-Precision Timing Harness**: Sub-microsecond timing using `process.hrtime.bigint()` with statistical distribution metrics (mean, median, p95, p99, standard deviation, ops/sec).
|
|
19
|
+
- **Comparative Profiling**:
|
|
20
|
+
- Symmetric Encryption: `AES-256-GCM` vs `ChaCha20-Poly1305` vs `AES-128-CBC`.
|
|
21
|
+
- Asymmetric Signatures: `ML-DSA-65` vs `Ed25519` vs `ECDSA-P256` vs `RSA-2048`.
|
|
22
|
+
- Key Encapsulation: `ML-KEM-768` vs `ECDH` vs `RSA-3072`.
|
|
23
|
+
- Cryptographic Hashing: `SHA-256` vs `SHA-512` vs `SHA3-256` vs `BLAKE2b`.
|
|
24
|
+
- **Multiple Output Formats**: Human-readable tables, JSON reports, and Markdown summaries suitable for CI performance tracking.
|
|
25
|
+
|
|
26
|
+
## CLI Usage
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
# Run all benchmark suites
|
|
30
|
+
crypto-benchmarks --suite all
|
|
31
|
+
|
|
32
|
+
# Run specific suite with custom iterations
|
|
33
|
+
crypto-benchmarks --suite pqc --iterations 100 --format markdown
|
|
34
|
+
|
|
35
|
+
# Output JSON report for automated monitoring
|
|
36
|
+
crypto-benchmarks --suite symmetric --format json > report.json
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Programmatic API
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
import {
|
|
43
|
+
runSuite,
|
|
44
|
+
benchmarkSymmetric,
|
|
45
|
+
benchmarkPqc,
|
|
46
|
+
} from "@sebastienrousseau/crypto-benchmarks";
|
|
47
|
+
|
|
48
|
+
// Run comprehensive benchmark
|
|
49
|
+
const report = await runSuite({ suite: "all", iterations: 50 });
|
|
50
|
+
console.log(report.summaryMarkdown);
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Development
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
pnpm --filter @sebastienrousseau/crypto-benchmarks run build
|
|
59
|
+
pnpm --filter @sebastienrousseau/crypto-benchmarks run test
|
|
60
|
+
pnpm --filter @sebastienrousseau/crypto-benchmarks run lint
|
|
61
|
+
pnpm --filter @sebastienrousseau/crypto-benchmarks run format
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
All 18 packages in the Crypto Service workspace maintain a **100% coverage floor** across statements, branches, functions, and lines.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Documentation
|
|
69
|
+
|
|
70
|
+
- [Full Suite Documentation](https://docs.crypto-service.co/)
|
|
71
|
+
- [API Reference (TypeDoc)](https://docs.crypto-service.co/packages/crypto-benchmarks/)
|
|
72
|
+
- [Developer Guide](../../DEVELOPMENT.md)
|
|
73
|
+
- [Security Policy](../../SECURITY.md)
|
|
74
|
+
- [Architecture & Design](../../ARCHITECTURE.md)
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Stability guarantees
|
|
79
|
+
|
|
80
|
+
Versions advance strictly one step at a time on the `0.0.x` line (`v0.0.1` → `v0.0.2` → `v0.0.3` ... → `v0.0.999` → `v0.1.0`). Work for every release iteration begins on a dedicated `feat/v<version>` branch.
|
|
81
|
+
|
|
82
|
+
All 18 packages in the workspace move in lockstep. Public API signatures, cipher output formats, and serialization schemas are strictly versioned. Breaking changes to serialized formats or algorithm defaults are considered major breaking changes. Minimum toolchain upgrades (e.g. Node.js LTS floor) are governed by [POLICIES.md](../../docs/POLICIES.md).
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## License
|
|
87
|
+
|
|
88
|
+
Dual-licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0) or [MIT](https://opensource.org/licenses/MIT), at your option.
|
|
89
|
+
|
|
90
|
+
Copyright (c) 2022-2026 Sebastien Rousseau and The Crypto Service Suite contributors.
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
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.runAsymmetricBenchmarks = runAsymmetricBenchmarks;
|
|
7
|
+
const node_crypto_1 = __importDefault(require("node:crypto"));
|
|
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");
|
|
12
|
+
const edKeys = node_crypto_1.default.generateKeyPairSync("ed25519");
|
|
13
|
+
let edSig = Buffer.alloc(0);
|
|
14
|
+
const edSignStats = await (0, timer_1.benchmarkOperation)(() => {
|
|
15
|
+
edSig = node_crypto_1.default.sign(null, message, edKeys.privateKey);
|
|
16
|
+
}, { 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
|
+
const edVerifyStats = await (0, timer_1.benchmarkOperation)(() => {
|
|
26
|
+
node_crypto_1.default.verify(null, message, edKeys.publicKey, edSig);
|
|
27
|
+
}, { 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
|
+
});
|
|
36
|
+
const ecKeys = node_crypto_1.default.generateKeyPairSync("ec", { namedCurve: "prime256v1" });
|
|
37
|
+
const ecSignStats = await (0, timer_1.benchmarkOperation)(() => {
|
|
38
|
+
const sign = node_crypto_1.default.createSign("SHA256");
|
|
39
|
+
sign.update(message);
|
|
40
|
+
sign.end();
|
|
41
|
+
sign.sign(ecKeys.privateKey);
|
|
42
|
+
}, { iterations, warmup: 3 });
|
|
43
|
+
results.push({
|
|
44
|
+
name: "ECDSA (P-256) Digital Signing",
|
|
45
|
+
category: "asymmetric",
|
|
46
|
+
algorithm: "ECDSA-P256",
|
|
47
|
+
operation: "sign",
|
|
48
|
+
quantumSafe: false,
|
|
49
|
+
stats: ecSignStats,
|
|
50
|
+
});
|
|
51
|
+
const rsaKeys = node_crypto_1.default.generateKeyPairSync("rsa", { modulusLength: 2048 });
|
|
52
|
+
const rsaSignStats = await (0, timer_1.benchmarkOperation)(() => {
|
|
53
|
+
const sign = node_crypto_1.default.createSign("SHA256");
|
|
54
|
+
sign.update(message);
|
|
55
|
+
sign.end();
|
|
56
|
+
sign.sign(rsaKeys.privateKey);
|
|
57
|
+
}, { iterations: Math.min(iterations, 10), warmup: 2 });
|
|
58
|
+
results.push({
|
|
59
|
+
name: "RSA-2048 Digital Signing",
|
|
60
|
+
category: "asymmetric",
|
|
61
|
+
algorithm: "RSA-2048",
|
|
62
|
+
operation: "sign",
|
|
63
|
+
quantumSafe: false,
|
|
64
|
+
stats: rsaSignStats,
|
|
65
|
+
});
|
|
66
|
+
return results;
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=asymmetric.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../src/benchmarks/hash.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAM/C,wBAAsB,iBAAiB,CACrC,UAAU,SAAK,GACd,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAwDhC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
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.runHashBenchmarks = runHashBenchmarks;
|
|
7
|
+
const node_crypto_1 = __importDefault(require("node:crypto"));
|
|
8
|
+
const timer_1 = require("../timer");
|
|
9
|
+
async function runHashBenchmarks(iterations = 50) {
|
|
10
|
+
const results = [];
|
|
11
|
+
const payload = node_crypto_1.default.randomBytes(4096);
|
|
12
|
+
const sha256Stats = await (0, timer_1.benchmarkOperation)(() => {
|
|
13
|
+
node_crypto_1.default.createHash("sha256").update(payload).digest();
|
|
14
|
+
}, { iterations, warmup: 5 });
|
|
15
|
+
results.push({
|
|
16
|
+
name: "SHA-256 Throughput (4KB)",
|
|
17
|
+
category: "hash",
|
|
18
|
+
algorithm: "SHA-256",
|
|
19
|
+
operation: "hash",
|
|
20
|
+
quantumSafe: true,
|
|
21
|
+
stats: sha256Stats,
|
|
22
|
+
});
|
|
23
|
+
const sha512Stats = await (0, timer_1.benchmarkOperation)(() => {
|
|
24
|
+
node_crypto_1.default.createHash("sha512").update(payload).digest();
|
|
25
|
+
}, { iterations, warmup: 5 });
|
|
26
|
+
results.push({
|
|
27
|
+
name: "SHA-512 Throughput (4KB)",
|
|
28
|
+
category: "hash",
|
|
29
|
+
algorithm: "SHA-512",
|
|
30
|
+
operation: "hash",
|
|
31
|
+
quantumSafe: true,
|
|
32
|
+
stats: sha512Stats,
|
|
33
|
+
});
|
|
34
|
+
const sha3Stats = await (0, timer_1.benchmarkOperation)(() => {
|
|
35
|
+
node_crypto_1.default.createHash("sha3-256").update(payload).digest();
|
|
36
|
+
}, { iterations, warmup: 5 });
|
|
37
|
+
results.push({
|
|
38
|
+
name: "SHA3-256 (Keccak) Throughput (4KB)",
|
|
39
|
+
category: "hash",
|
|
40
|
+
algorithm: "SHA3-256",
|
|
41
|
+
operation: "hash",
|
|
42
|
+
quantumSafe: true,
|
|
43
|
+
stats: sha3Stats,
|
|
44
|
+
});
|
|
45
|
+
return results;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=hash.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { MlKemEncapResult, MlDsaVerifyResult } from "@sebastienrousseau/crypto-lib";
|
|
2
|
+
import { BenchmarkItemResult } from "../types";
|
|
3
|
+
export interface PqcOperations {
|
|
4
|
+
mlKem768Encapsulate: () => MlKemEncapResult;
|
|
5
|
+
mlKem768SecretKey: string;
|
|
6
|
+
mlDsa65Verify: () => MlDsaVerifyResult;
|
|
7
|
+
}
|
|
8
|
+
export declare function createPqcOperations(): PqcOperations;
|
|
9
|
+
export declare function runPqcBenchmarks(iterations?: number): Promise<BenchmarkItemResult[]>;
|
|
10
|
+
//# sourceMappingURL=pqc.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pqc.d.ts","sourceRoot":"","sources":["../../src/benchmarks/pqc.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EACV,gBAAgB,EAChB,iBAAiB,EAClB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAI/C,MAAM,WAAW,aAAa;IAE5B,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;IAE5C,iBAAiB,EAAE,MAAM,CAAC;IAE1B,aAAa,EAAE,MAAM,iBAAiB,CAAC;CACxC;AAOD,wBAAgB,mBAAmB,IAAI,aAAa,CAWnD;AAOD,wBAAsB,gBAAgB,CACpC,UAAU,SAAK,GACd,OAAO,CAAC,mBAAmB,EAAE,CAAC,CA+DhC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
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.createPqcOperations = createPqcOperations;
|
|
7
|
+
exports.runPqcBenchmarks = runPqcBenchmarks;
|
|
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 createPqcOperations() {
|
|
12
|
+
const kem = (0, crypto_lib_1.mlKemKeygen)(768);
|
|
13
|
+
const dsa = (0, crypto_lib_1.mlDsaKeygen)(65);
|
|
14
|
+
const message = node_crypto_1.default.randomBytes(32);
|
|
15
|
+
const { signature } = (0, crypto_lib_1.mlDsaSign)(65, dsa.secretKey, message);
|
|
16
|
+
return {
|
|
17
|
+
mlKem768Encapsulate: () => (0, crypto_lib_1.mlKemEncap)(768, kem.publicKey),
|
|
18
|
+
mlKem768SecretKey: kem.secretKey,
|
|
19
|
+
mlDsa65Verify: () => (0, crypto_lib_1.mlDsaVerify)(65, dsa.publicKey, message, signature),
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
async function runPqcBenchmarks(iterations = 30) {
|
|
23
|
+
const results = [];
|
|
24
|
+
const ecdh1 = node_crypto_1.default.createECDH("prime256v1");
|
|
25
|
+
const ecdh2 = node_crypto_1.default.createECDH("prime256v1");
|
|
26
|
+
ecdh1.generateKeys();
|
|
27
|
+
ecdh2.generateKeys();
|
|
28
|
+
const pub2 = ecdh2.getPublicKey();
|
|
29
|
+
const ecdhStats = await (0, timer_1.benchmarkOperation)(() => {
|
|
30
|
+
ecdh1.computeSecret(pub2);
|
|
31
|
+
}, { iterations, warmup: 5 });
|
|
32
|
+
results.push({
|
|
33
|
+
name: "Classical ECDH Key Agreement (P-256)",
|
|
34
|
+
category: "pqc",
|
|
35
|
+
algorithm: "ECDH-P256",
|
|
36
|
+
operation: "key-exchange",
|
|
37
|
+
quantumSafe: false,
|
|
38
|
+
stats: ecdhStats,
|
|
39
|
+
});
|
|
40
|
+
const ops = createPqcOperations();
|
|
41
|
+
const kemStats = await (0, timer_1.benchmarkOperation)(() => {
|
|
42
|
+
ops.mlKem768Encapsulate();
|
|
43
|
+
}, { iterations, warmup: 5 });
|
|
44
|
+
results.push({
|
|
45
|
+
name: "Post-Quantum ML-KEM-768 Key Encapsulation",
|
|
46
|
+
category: "pqc",
|
|
47
|
+
algorithm: "ML-KEM-768",
|
|
48
|
+
operation: "encapsulate",
|
|
49
|
+
quantumSafe: true,
|
|
50
|
+
stats: kemStats,
|
|
51
|
+
});
|
|
52
|
+
const dsaStats = await (0, timer_1.benchmarkOperation)(() => {
|
|
53
|
+
ops.mlDsa65Verify();
|
|
54
|
+
}, { iterations, warmup: 5 });
|
|
55
|
+
results.push({
|
|
56
|
+
name: "Post-Quantum ML-DSA-65 Verification",
|
|
57
|
+
category: "pqc",
|
|
58
|
+
algorithm: "ML-DSA-65",
|
|
59
|
+
operation: "verify",
|
|
60
|
+
quantumSafe: true,
|
|
61
|
+
stats: dsaStats,
|
|
62
|
+
});
|
|
63
|
+
return results;
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=pqc.js.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
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.runSymmetricBenchmarks = runSymmetricBenchmarks;
|
|
7
|
+
const node_crypto_1 = __importDefault(require("node:crypto"));
|
|
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);
|
|
18
|
+
cipher.update(payload);
|
|
19
|
+
cipher.final();
|
|
20
|
+
cipher.getAuthTag();
|
|
21
|
+
}, { iterations, warmup: 5 });
|
|
22
|
+
results.push({
|
|
23
|
+
name: "AES-256-GCM Encryption (1KB)",
|
|
24
|
+
category: "symmetric",
|
|
25
|
+
algorithm: "AES-256-GCM",
|
|
26
|
+
operation: "encrypt",
|
|
27
|
+
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, {
|
|
32
|
+
authTagLength: 16,
|
|
33
|
+
});
|
|
34
|
+
cipher.update(payload);
|
|
35
|
+
cipher.final();
|
|
36
|
+
cipher.getAuthTag();
|
|
37
|
+
}, { iterations, warmup: 5 });
|
|
38
|
+
results.push({
|
|
39
|
+
name: "ChaCha20-Poly1305 Encryption (1KB)",
|
|
40
|
+
category: "symmetric",
|
|
41
|
+
algorithm: "ChaCha20-Poly1305",
|
|
42
|
+
operation: "encrypt",
|
|
43
|
+
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);
|
|
48
|
+
cipher.update(payload);
|
|
49
|
+
cipher.final();
|
|
50
|
+
}, { iterations, warmup: 5 });
|
|
51
|
+
results.push({
|
|
52
|
+
name: "AES-128-CBC Encryption (1KB)",
|
|
53
|
+
category: "symmetric",
|
|
54
|
+
algorithm: "AES-128-CBC",
|
|
55
|
+
operation: "encrypt",
|
|
56
|
+
quantumSafe: false,
|
|
57
|
+
stats: aesCbcEncStats,
|
|
58
|
+
});
|
|
59
|
+
return results;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=symmetric.js.map
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +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"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.run = run;
|
|
8
|
+
const node_process_1 = __importDefault(require("node:process"));
|
|
9
|
+
const runner_1 = require("./runner");
|
|
10
|
+
async function run(args = node_process_1.default.argv.slice(2)) {
|
|
11
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
12
|
+
node_process_1.default.stdout.write("Usage: crypto-benchmarks [options]\n");
|
|
13
|
+
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");
|
|
15
|
+
node_process_1.default.stdout.write(" --iterations <N> Number of iterations (default: 30)\n");
|
|
16
|
+
node_process_1.default.stdout.write(" --format <table|json|markdown> Output format (default: table)\n");
|
|
17
|
+
return 0;
|
|
18
|
+
}
|
|
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
|
+
}
|
|
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
|
+
}
|
|
53
|
+
return 0;
|
|
54
|
+
}
|
|
55
|
+
if (require.main === module) {
|
|
56
|
+
run().then((code) => node_process_1.default.exit(code));
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from "./types";
|
|
2
|
+
export * from "./timer";
|
|
3
|
+
export * from "./benchmarks/symmetric";
|
|
4
|
+
export * from "./benchmarks/asymmetric";
|
|
5
|
+
export * from "./benchmarks/pqc";
|
|
6
|
+
export * from "./benchmarks/hash";
|
|
7
|
+
export * from "./runner";
|
|
8
|
+
export * from "./cli";
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./types"), exports);
|
|
18
|
+
__exportStar(require("./timer"), exports);
|
|
19
|
+
__exportStar(require("./benchmarks/symmetric"), exports);
|
|
20
|
+
__exportStar(require("./benchmarks/asymmetric"), exports);
|
|
21
|
+
__exportStar(require("./benchmarks/pqc"), exports);
|
|
22
|
+
__exportStar(require("./benchmarks/hash"), exports);
|
|
23
|
+
__exportStar(require("./runner"), exports);
|
|
24
|
+
__exportStar(require("./cli"), exports);
|
|
25
|
+
//# sourceMappingURL=index.js.map
|
package/dist/runner.d.ts
ADDED
|
@@ -0,0 +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"}
|
package/dist/runner.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
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.runSuite = runSuite;
|
|
7
|
+
const node_process_1 = __importDefault(require("node:process"));
|
|
8
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
9
|
+
const symmetric_1 = require("./benchmarks/symmetric");
|
|
10
|
+
const asymmetric_1 = require("./benchmarks/asymmetric");
|
|
11
|
+
const pqc_1 = require("./benchmarks/pqc");
|
|
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;
|
|
32
|
+
const mdRows = results.map((r) => {
|
|
33
|
+
const qs = r.quantumSafe ? "✅ Yes" : "❌ No";
|
|
34
|
+
return `| ${r.name} | ${r.algorithm} | ${r.stats.meanMs.toFixed(3)} | ${r.stats.p95Ms.toFixed(3)} | ${r.stats.opsPerSec.toLocaleString()} | ${qs} |`;
|
|
35
|
+
});
|
|
36
|
+
const summaryMarkdown = [
|
|
37
|
+
`# Cryptographic Performance Benchmark Report`,
|
|
38
|
+
``,
|
|
39
|
+
`- **Date:** ${timestamp}`,
|
|
40
|
+
`- **Platform:** ${platform}`,
|
|
41
|
+
`- **Node.js:** ${nodeVersion}`,
|
|
42
|
+
`- **Total Benchmarks:** ${results.length}`,
|
|
43
|
+
``,
|
|
44
|
+
`| Benchmark | Algorithm | Mean (ms) | p95 (ms) | Ops/sec | Quantum Safe |`,
|
|
45
|
+
`| :--- | :--- | :--- | :--- | :--- | :--- |`,
|
|
46
|
+
...mdRows,
|
|
47
|
+
``,
|
|
48
|
+
].join("\n");
|
|
49
|
+
const tableHeader = `Name Algorithm Mean(ms) Ops/sec QuantumSafe`;
|
|
50
|
+
const tableDivider = `--------------------------------------------------------------------------------`;
|
|
51
|
+
const tableRows = results.map((r) => {
|
|
52
|
+
const name = r.name.padEnd(32).slice(0, 32);
|
|
53
|
+
const alg = r.algorithm.padEnd(14).slice(0, 14);
|
|
54
|
+
const mean = r.stats.meanMs.toFixed(3).padStart(8);
|
|
55
|
+
const ops = r.stats.opsPerSec.toLocaleString().padStart(10);
|
|
56
|
+
const qs = (r.quantumSafe ? "Yes" : "No").padStart(10);
|
|
57
|
+
return `${name} ${alg} ${mean} ${ops} ${qs}`;
|
|
58
|
+
});
|
|
59
|
+
const summaryTable = [
|
|
60
|
+
tableHeader,
|
|
61
|
+
tableDivider,
|
|
62
|
+
...tableRows,
|
|
63
|
+
tableDivider,
|
|
64
|
+
].join("\n");
|
|
65
|
+
return {
|
|
66
|
+
timestamp,
|
|
67
|
+
platform,
|
|
68
|
+
nodeVersion,
|
|
69
|
+
totalBenchmarks: results.length,
|
|
70
|
+
results,
|
|
71
|
+
summaryMarkdown,
|
|
72
|
+
summaryTable,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=runner.js.map
|
package/dist/timer.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { BenchmarkStats } from "./types";
|
|
2
|
+
export interface TimerOptions {
|
|
3
|
+
iterations?: number | undefined;
|
|
4
|
+
warmup?: number | undefined;
|
|
5
|
+
}
|
|
6
|
+
export declare function benchmarkOperation(fn: () => void | Promise<void>, options?: TimerOptions): Promise<BenchmarkStats>;
|
|
7
|
+
//# sourceMappingURL=timer.d.ts.map
|
|
@@ -0,0 +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"}
|
package/dist/timer.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
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.benchmarkOperation = benchmarkOperation;
|
|
7
|
+
const node_process_1 = __importDefault(require("node:process"));
|
|
8
|
+
async function benchmarkOperation(fn, options = {}) {
|
|
9
|
+
const iterations = options.iterations && options.iterations > 0 ? options.iterations : 10;
|
|
10
|
+
const warmup = options.warmup !== undefined && options.warmup >= 0 ? options.warmup : 2;
|
|
11
|
+
for (let i = 0; i < warmup; i++) {
|
|
12
|
+
const res = fn();
|
|
13
|
+
if (res instanceof Promise) {
|
|
14
|
+
await res;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
const timesMs = [];
|
|
18
|
+
const startTotal = node_process_1.default.hrtime.bigint();
|
|
19
|
+
for (let i = 0; i < iterations; i++) {
|
|
20
|
+
const start = node_process_1.default.hrtime.bigint();
|
|
21
|
+
const res = fn();
|
|
22
|
+
if (res instanceof Promise) {
|
|
23
|
+
await res;
|
|
24
|
+
}
|
|
25
|
+
const end = node_process_1.default.hrtime.bigint();
|
|
26
|
+
const diffMs = Number(end - start) / 1_000_000;
|
|
27
|
+
timesMs.push(diffMs);
|
|
28
|
+
}
|
|
29
|
+
const endTotal = node_process_1.default.hrtime.bigint();
|
|
30
|
+
const totalDurationMs = Number(endTotal - startTotal) / 1_000_000;
|
|
31
|
+
timesMs.sort((a, b) => a - b);
|
|
32
|
+
const minMs = timesMs[0];
|
|
33
|
+
const maxMs = timesMs[timesMs.length - 1];
|
|
34
|
+
const sumMs = timesMs.reduce((acc, val) => acc + val, 0);
|
|
35
|
+
const meanMs = sumMs / iterations;
|
|
36
|
+
const mid = Math.floor(timesMs.length / 2);
|
|
37
|
+
const medianMs = timesMs.length % 2 !== 0
|
|
38
|
+
? timesMs[mid]
|
|
39
|
+
: (timesMs[mid - 1] + timesMs[mid]) / 2;
|
|
40
|
+
const p95Idx = Math.min(timesMs.length - 1, Math.floor(timesMs.length * 0.95));
|
|
41
|
+
const p99Idx = Math.min(timesMs.length - 1, Math.floor(timesMs.length * 0.99));
|
|
42
|
+
const p95Ms = timesMs[p95Idx];
|
|
43
|
+
const p99Ms = timesMs[p99Idx];
|
|
44
|
+
const opsPerSec = (iterations / totalDurationMs) * 1000;
|
|
45
|
+
return {
|
|
46
|
+
meanMs: Number(meanMs.toFixed(4)),
|
|
47
|
+
medianMs: Number(medianMs.toFixed(4)),
|
|
48
|
+
minMs: Number(minMs.toFixed(4)),
|
|
49
|
+
maxMs: Number(maxMs.toFixed(4)),
|
|
50
|
+
p95Ms: Number(p95Ms.toFixed(4)),
|
|
51
|
+
p99Ms: Number(p99Ms.toFixed(4)),
|
|
52
|
+
opsPerSec: Math.round(opsPerSec),
|
|
53
|
+
totalDurationMs: Number(totalDurationMs.toFixed(4)),
|
|
54
|
+
iterations,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=timer.js.map
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export type SuiteName = "all" | "symmetric" | "asymmetric" | "pqc" | "hash";
|
|
2
|
+
export type OutputFormat = "table" | "json" | "markdown";
|
|
3
|
+
export interface BenchmarkConfig {
|
|
4
|
+
suite?: SuiteName | undefined;
|
|
5
|
+
iterations?: number | undefined;
|
|
6
|
+
warmup?: number | undefined;
|
|
7
|
+
format?: OutputFormat | undefined;
|
|
8
|
+
}
|
|
9
|
+
export interface BenchmarkStats {
|
|
10
|
+
meanMs: number;
|
|
11
|
+
medianMs: number;
|
|
12
|
+
minMs: number;
|
|
13
|
+
maxMs: number;
|
|
14
|
+
p95Ms: number;
|
|
15
|
+
p99Ms: number;
|
|
16
|
+
opsPerSec: number;
|
|
17
|
+
totalDurationMs: number;
|
|
18
|
+
iterations: number;
|
|
19
|
+
}
|
|
20
|
+
export interface BenchmarkItemResult {
|
|
21
|
+
name: string;
|
|
22
|
+
category: "symmetric" | "asymmetric" | "pqc" | "hash";
|
|
23
|
+
algorithm: string;
|
|
24
|
+
operation: string;
|
|
25
|
+
quantumSafe: boolean;
|
|
26
|
+
stats: BenchmarkStats;
|
|
27
|
+
}
|
|
28
|
+
export interface BenchmarkReport {
|
|
29
|
+
timestamp: string;
|
|
30
|
+
platform: string;
|
|
31
|
+
nodeVersion: string;
|
|
32
|
+
totalBenchmarks: number;
|
|
33
|
+
results: BenchmarkItemResult[];
|
|
34
|
+
summaryMarkdown: string;
|
|
35
|
+
summaryTable: string;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +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"}
|
package/dist/types.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sebastienrousseau/crypto-benchmarks",
|
|
3
|
+
"version": "0.0.7",
|
|
4
|
+
"description": "Performance benchmarking and latency profiling harness comparing classical vs post-quantum cryptographic primitives across JavaScript, WebAssembly, and native runtimes.",
|
|
5
|
+
"author": "Sebastien Rousseau <sebastienrousseau@users.noreply.github.com>",
|
|
6
|
+
"license": "MIT OR Apache-2.0",
|
|
7
|
+
"homepage": "https://crypto-service.co",
|
|
8
|
+
"repository": {
|
|
9
|
+
"directory": "packages/crypto-benchmarks",
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git@github.com:sebastienrousseau/crypto-service.git"
|
|
12
|
+
},
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/sebastienrousseau/crypto-service/issues"
|
|
15
|
+
},
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": ">=22.0.0"
|
|
18
|
+
},
|
|
19
|
+
"main": "./dist/index.js",
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"sideEffects": false,
|
|
22
|
+
"bin": {
|
|
23
|
+
"crypto-benchmarks": "./dist/cli.js"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"dist/**/*.js",
|
|
27
|
+
"dist/**/*.d.ts",
|
|
28
|
+
"dist/**/*.d.ts.map"
|
|
29
|
+
],
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@sebastienrousseau/crypto-lib": "0.0.7"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@types/chai": "^4.3.7",
|
|
35
|
+
"@types/chai-as-promised": "^8.0.2",
|
|
36
|
+
"@types/mocha": "^10.0.2",
|
|
37
|
+
"@types/node": "^26.4.1",
|
|
38
|
+
"c8": "^12.0.0",
|
|
39
|
+
"chai": "^4.5.0",
|
|
40
|
+
"chai-as-promised": "^7.1.2",
|
|
41
|
+
"mocha": "^10.8.2",
|
|
42
|
+
"rimraf": "^6.1.3",
|
|
43
|
+
"ts-node": "^10.9.2",
|
|
44
|
+
"typedoc": "^0.28.20",
|
|
45
|
+
"typescript": "~5.9.3"
|
|
46
|
+
},
|
|
47
|
+
"publishConfig": {
|
|
48
|
+
"access": "public"
|
|
49
|
+
},
|
|
50
|
+
"scripts": {
|
|
51
|
+
"build": "tsc --build tsconfig.json",
|
|
52
|
+
"clean": "rimraf ./coverage ./dist ./docs",
|
|
53
|
+
"lint": "eslint --ext .ts src __tests__",
|
|
54
|
+
"lint:fix": "eslint --cache --fix --ext .ts src __tests__",
|
|
55
|
+
"format": "prettier --write src/**/*.ts",
|
|
56
|
+
"format:check": "prettier --check \"src/**/*.ts\"",
|
|
57
|
+
"test": "c8 --check-coverage --lines 100 --branches 100 --functions 100 --reporter=lcov --reporter=text mocha --config=.mocharc.cjs",
|
|
58
|
+
"docs": "typedoc"
|
|
59
|
+
}
|
|
60
|
+
}
|