@sebastienrousseau/crypto-testing 0.0.8
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 +295 -0
- package/dist/fixtures.d.ts +26 -0
- package/dist/fixtures.d.ts.map +1 -0
- package/dist/fixtures.js +43 -0
- package/dist/helpers.d.ts +12 -0
- package/dist/helpers.d.ts.map +1 -0
- package/dist/helpers.js +82 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/keys.d.ts +23 -0
- package/dist/keys.d.ts.map +1 -0
- package/dist/keys.js +26 -0
- package/dist/mock.d.ts +24 -0
- package/dist/mock.d.ts.map +1 -0
- package/dist/mock.js +91 -0
- package/package.json +73 -0
package/LICENSE
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
<!-- SPDX-License-Identifier: Apache-2.0 OR MIT -->
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img src="https://raw.githubusercontent.com/sebastienrousseau/crypto-service/main/assets/crypto-testing-logo.svg" alt="crypto-testing logo" width="360" />
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
<h1 align="center">@sebastienrousseau/crypto-testing</h1>
|
|
8
|
+
|
|
9
|
+
<p align="center">
|
|
10
|
+
Deterministic keys, fast mocks, and test fixtures for crypto-lib — make your CI/CD pipeline fast and reproducible.
|
|
11
|
+
</p>
|
|
12
|
+
|
|
13
|
+
<p align="center">
|
|
14
|
+
<a href="https://github.com/sebastienrousseau/crypto-service/actions"><img src="https://img.shields.io/github/actions/workflow/status/sebastienrousseau/crypto-service/ci.yml?branch=main&style=for-the-badge&logo=github" alt="Build" /></a>
|
|
15
|
+
<a href="https://coveralls.io/github/sebastienrousseau/crypto-service?branch=main"><img src="https://img.shields.io/coveralls/github/sebastienrousseau/crypto-service?branch=main&style=for-the-badge" alt="Coverage" /></a>
|
|
16
|
+
<a href="https://www.npmjs.com/package/@sebastienrousseau/crypto-testing"><img src="https://img.shields.io/npm/v/@sebastienrousseau/crypto-testing.svg?style=for-the-badge&color=f14041&logo=npm" alt="Registry" /></a>
|
|
17
|
+
<a href="https://sebastienrousseau.github.io/crypto-service/"><img src="https://img.shields.io/badge/docs-TypeDoc-blue.svg?style=for-the-badge&labelColor=555555&logo=typescript" alt="Docs" /></a>
|
|
18
|
+
<a href="https://scorecard.dev/viewer/?uri=github.com/sebastienrousseau/crypto-service" title="ossf-scorecard"><img src="https://img.shields.io/badge/OpenSSF-Scorecard-blue?style=for-the-badge&logo=openssf" alt="OpenSSF Scorecard" /></a>
|
|
19
|
+
<a href="https://github.com/sebastienrousseau/crypto-service/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-Apache--2.0%20OR%20MIT-blue.svg?style=for-the-badge" alt="License: Apache-2.0 OR MIT" /></a>
|
|
20
|
+
<a href="https://github.com/sebastienrousseau/crypto-service/blob/main/docs/POLICIES.md"><img src="https://img.shields.io/badge/Node.js-%3E%3D22-93450a.svg?style=for-the-badge&logo=node.js" alt="Node.js 22 or newer" /></a>
|
|
21
|
+
</p>
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Contents
|
|
26
|
+
|
|
27
|
+
**Getting started**
|
|
28
|
+
|
|
29
|
+
- [Install](#install) — installation via pnpm, npm, or yarn
|
|
30
|
+
- [Requirements](#requirements) — runtime floor and environment prerequisites
|
|
31
|
+
- [Quick Start](#quick-start) — minimal working usage sample
|
|
32
|
+
|
|
33
|
+
**The Crypto Service ecosystem**
|
|
34
|
+
|
|
35
|
+
- [The Crypto Service ecosystem](#the-crypto-service-ecosystem) — full 14-package suite overview
|
|
36
|
+
|
|
37
|
+
**Package reference**
|
|
38
|
+
|
|
39
|
+
- [Reference & Usage](#overview) — features, configuration, and capabilities
|
|
40
|
+
- [Examples](#examples) — runnable sample code
|
|
41
|
+
|
|
42
|
+
**Operational**
|
|
43
|
+
|
|
44
|
+
- [Development](#development) — build, lint, format, and test targets
|
|
45
|
+
- [Security](#security) — vulnerability disclosure and cryptographic invariants
|
|
46
|
+
- [Documentation](#documentation) — TypeDoc API docs and ecosystem guides
|
|
47
|
+
- [Stability guarantees](#stability-guarantees) — SemVer axis and release policy
|
|
48
|
+
- [License](#license)
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Install
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
pnpm add @sebastienrousseau/crypto-testing
|
|
56
|
+
# or
|
|
57
|
+
npm install @sebastienrousseau/crypto-testing
|
|
58
|
+
# or
|
|
59
|
+
yarn add @sebastienrousseau/crypto-testing
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
<p align="right"><a href="#contents">Back to Top</a></p>
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Requirements
|
|
67
|
+
|
|
68
|
+
- **Node.js**: `^22.0.0` or `>=24.0.0` (active and maintenance LTS releases)
|
|
69
|
+
- **Package Manager**: `pnpm >=9` (recommended) or `npm >=10`
|
|
70
|
+
- **TypeScript**: `>=5.0` (when compiling with TypeScript)
|
|
71
|
+
|
|
72
|
+
<p align="right"><a href="#contents">Back to Top</a></p>
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Quick Start
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
import {
|
|
80
|
+
TEST_KEYS,
|
|
81
|
+
TEST_VECTORS,
|
|
82
|
+
mockEncrypt,
|
|
83
|
+
mockDecrypt,
|
|
84
|
+
createTestKeyring,
|
|
85
|
+
expectValidHex,
|
|
86
|
+
expectSignVerifyRoundTrip,
|
|
87
|
+
} from "@sebastienrousseau/crypto-testing";
|
|
88
|
+
|
|
89
|
+
// Use deterministic keys instead of generating new ones every run
|
|
90
|
+
const { publicKey, privateKey } = TEST_KEYS.ed25519;
|
|
91
|
+
|
|
92
|
+
// Mock encrypt/decrypt for fast unit tests
|
|
93
|
+
const ct = mockEncrypt(TEST_KEYS.aes256, "secret data");
|
|
94
|
+
const pt = mockDecrypt(TEST_KEYS.aes256, ct);
|
|
95
|
+
|
|
96
|
+
// Validate outputs
|
|
97
|
+
expectValidHex(publicKey, 32);
|
|
98
|
+
|
|
99
|
+
// Full sign/verify round-trip with real crypto-lib
|
|
100
|
+
expectSignVerifyRoundTrip("ed25519");
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
<p align="right"><a href="#contents">Back to Top</a></p>
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## The Crypto Service ecosystem
|
|
108
|
+
|
|
109
|
+
Crypto Service provides a complete cryptography stack across 14 specialized packages:
|
|
110
|
+
|
|
111
|
+
| Package | Role | Description |
|
|
112
|
+
| :---------------------------------------------------------------------------- | :--------------- | :------------------------------------------------------------------------------------------------------------------------------------- |
|
|
113
|
+
| [`@sebastienrousseau/crypto-api`](../crypto-api) | API Schemas | Shared TypeScript types and utilities for the Crypto Service Suite, defining the canonical API surface. |
|
|
114
|
+
| [`@sebastienrousseau/crypto-cli`](../crypto-cli) | Terminal CLI | An interactive command-line interface for cryptographic operations, supporting both legacy OpenPGP and modern post-quantum algorithms. |
|
|
115
|
+
| [`@sebastienrousseau/crypto-edge`](../crypto-edge) | Edge Runtime | Edge-runtime cryptographic operations using the Web Crypto API, optimized for Cloudflare Workers, Vercel Edge, and Deno. |
|
|
116
|
+
| [`@sebastienrousseau/crypto-kms`](../crypto-kms) | Cloud KMS | Unified Key Management Service interface for AWS KMS, GCP Cloud KMS, Azure Key Vault, and HashiCorp Vault. |
|
|
117
|
+
| [`@sebastienrousseau/crypto-lib`](../crypto-lib) | Core Library | A modern cryptographic library for TypeScript, with post-quantum support, zero unsafe dependencies, and 100% test coverage. |
|
|
118
|
+
| [`@sebastienrousseau/crypto-middleware`](../crypto-middleware) | Middleware | Framework-agnostic cryptographic middleware for Express, Fastify, and Koa applications. |
|
|
119
|
+
| [`@sebastienrousseau/crypto-prisma`](../crypto-prisma) | ORM Adapter | Transparent field-level encryption extension for Prisma Client, using XChaCha20-Poly1305. |
|
|
120
|
+
| [`@sebastienrousseau/crypto-react`](../crypto-react) | React Hooks | React hooks and context provider for client-side cryptographic operations with zero boilerplate. |
|
|
121
|
+
| [`@sebastienrousseau/crypto-sdk`](../crypto-sdk) | Client SDK | A zero-dependency, typed HTTP client for the Crypto Service REST API, with full post-quantum support. |
|
|
122
|
+
| [`@sebastienrousseau/crypto-server`](../crypto-server) | HTTP API | A hardened Fastify REST API for cryptographic operations, with rate limiting, OpenAPI schemas, and post-quantum endpoints. |
|
|
123
|
+
| **[`@sebastienrousseau/crypto-testing`](../crypto-testing)** _(this package)_ | **Test Support** | **Deterministic keys, fast mocks, and test fixtures for crypto-lib** |
|
|
124
|
+
| [`@sebastienrousseau/crypto-typeorm`](../crypto-typeorm) | ORM Adapter | TypeORM column-level encryption with a single decorator, powered by crypto-lib. |
|
|
125
|
+
| [`@sebastienrousseau/crypto-vue`](../crypto-vue) | Vue Composables | Vue 3 composables for client-side cryptography |
|
|
126
|
+
| [`@sebastienrousseau/crypto-wasm`](../crypto-wasm) | Acceleration | WebAssembly performance accelerator for crypto-lib |
|
|
127
|
+
|
|
128
|
+
<p align="right"><a href="#contents">Back to Top</a></p>
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Overview
|
|
133
|
+
|
|
134
|
+
crypto-testing is the test utility package for the Crypto Service
|
|
135
|
+
Suite. It provides pre-generated deterministic keys, instant
|
|
136
|
+
XOR-based mock functions for expensive crypto operations, one-call
|
|
137
|
+
fixture generators, and assertion helpers for hex, Base64, key-pair,
|
|
138
|
+
and round-trip validations. Use it to make your CI/CD pipeline fast
|
|
139
|
+
and reproducible without sacrificing coverage.
|
|
140
|
+
|
|
141
|
+
<p align="right"><a href="#contents">Back to Top</a></p>
|
|
142
|
+
|
|
143
|
+
## Features
|
|
144
|
+
|
|
145
|
+
| Category | What you get |
|
|
146
|
+
| :------------- | :---------------------------------------------------------------------------- |
|
|
147
|
+
| **Keys** | Pre-generated Ed25519, X25519, P-256, AES-256, and HMAC key pairs/keys |
|
|
148
|
+
| **Vectors** | Known plaintext with expected SHA-256, SHA3-256, and BLAKE3 digests |
|
|
149
|
+
| **Mocks** | Instant XOR-based fakes for encrypt, decrypt, sign, verify, password hashing |
|
|
150
|
+
| **Fixtures** | One-call generators for keyrings, encrypted messages, signed messages, hashes |
|
|
151
|
+
| **Assertions** | Hex, Base64, key-pair, encrypt/decrypt, and sign/verify round-trip helpers |
|
|
152
|
+
|
|
153
|
+
<p align="right"><a href="#contents">Back to Top</a></p>
|
|
154
|
+
|
|
155
|
+
## Deterministic Keys
|
|
156
|
+
|
|
157
|
+
`TEST_KEYS` provides well-known key pairs that never change between
|
|
158
|
+
runs:
|
|
159
|
+
|
|
160
|
+
| Key | Algorithm | Description |
|
|
161
|
+
| :-------- | :-------- | :------------------------------- |
|
|
162
|
+
| `ed25519` | Ed25519 | 32-byte signing key pair |
|
|
163
|
+
| `x25519` | X25519 | 32-byte key-exchange pair |
|
|
164
|
+
| `p256` | P-256 | ECDSA signing key pair |
|
|
165
|
+
| `aes256` | AES-256 | 32-byte symmetric encryption key |
|
|
166
|
+
| `hmacKey` | HMAC | 32-byte HMAC key |
|
|
167
|
+
|
|
168
|
+
`TEST_VECTORS` includes a known plaintext and its expected hashes.
|
|
169
|
+
|
|
170
|
+
<p align="right"><a href="#contents">Back to Top</a></p>
|
|
171
|
+
|
|
172
|
+
## Mock Functions
|
|
173
|
+
|
|
174
|
+
Replace expensive crypto operations with instant, deterministic
|
|
175
|
+
fakes:
|
|
176
|
+
|
|
177
|
+
| Function | Replaces | Speed |
|
|
178
|
+
| :-------------------- | :----------------------- | :-------- |
|
|
179
|
+
| `mockHashPassword` | Argon2id (100+ ms) | < 0.01 ms |
|
|
180
|
+
| `mockGenerateKeyPair` | Real key generation | < 0.01 ms |
|
|
181
|
+
| `mockEncrypt` | XChaCha20-Poly1305 | < 0.01 ms |
|
|
182
|
+
| `mockDecrypt` | XChaCha20-Poly1305 | < 0.01 ms |
|
|
183
|
+
| `mockSign` | Ed25519/ECDSA signatures | < 0.01 ms |
|
|
184
|
+
| `mockVerify` | Signature verification | < 0.01 ms |
|
|
185
|
+
|
|
186
|
+
All mock functions use XOR internally -- they are **not
|
|
187
|
+
cryptographically secure** but are deterministic and round-trip
|
|
188
|
+
correctly.
|
|
189
|
+
|
|
190
|
+
<p align="right"><a href="#contents">Back to Top</a></p>
|
|
191
|
+
|
|
192
|
+
## Fixtures
|
|
193
|
+
|
|
194
|
+
Fixture generators produce complete test data structures in one
|
|
195
|
+
call:
|
|
196
|
+
|
|
197
|
+
| Function | Returns |
|
|
198
|
+
| :----------------------------- | :-------------------------------------------------------------- |
|
|
199
|
+
| `createTestKeyring()` | Keyring with signing, exchange, ECDSA, symmetric, and HMAC keys |
|
|
200
|
+
| `createTestEncryptedMessage()` | Key + plaintext + mock ciphertext |
|
|
201
|
+
| `createTestSignedMessage()` | Key pair + message + mock signature |
|
|
202
|
+
| `createTestPasswordHash()` | Hash + salt + params + PHC string |
|
|
203
|
+
|
|
204
|
+
<p align="right"><a href="#contents">Back to Top</a></p>
|
|
205
|
+
|
|
206
|
+
## Assertion Helpers
|
|
207
|
+
|
|
208
|
+
One-liner assertions that throw descriptive errors on failure:
|
|
209
|
+
|
|
210
|
+
| Helper | Checks |
|
|
211
|
+
| :------------------------------ | :------------------------------------- |
|
|
212
|
+
| `expectValidHex(value, len?)` | Valid hex string, optional byte length |
|
|
213
|
+
| `expectValidBase64(value)` | Valid Base64 string with round-trip |
|
|
214
|
+
| `expectKeyPair(kp)` | Non-empty hex keys, pub != priv |
|
|
215
|
+
| `expectEncryptDecryptRoundTrip` | Real secretbox encrypt then decrypt |
|
|
216
|
+
| `expectSignVerifyRoundTrip` | Real keygen, sign, and verify |
|
|
217
|
+
|
|
218
|
+
<p align="right"><a href="#contents">Back to Top</a></p>
|
|
219
|
+
|
|
220
|
+
## Examples
|
|
221
|
+
|
|
222
|
+
All examples are self-contained TypeScript files in the `examples/`
|
|
223
|
+
directory. Run any example with:
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
npx ts-node examples/<name>.ts
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
| Category | Example | Purpose |
|
|
230
|
+
| :--------- | :-------------------------------------- | :---------------------------------- |
|
|
231
|
+
| Keys | [keys.ts](examples/keys.ts) | Using deterministic test keys |
|
|
232
|
+
| Mocks | [mocks.ts](examples/mocks.ts) | Mocking crypto operations for speed |
|
|
233
|
+
| Fixtures | [fixtures.ts](examples/fixtures.ts) | Using pre-built test fixtures |
|
|
234
|
+
| Assertions | [assertions.ts](examples/assertions.ts) | Assertion helpers in tests |
|
|
235
|
+
|
|
236
|
+
<p align="right"><a href="#contents">Back to Top</a></p>
|
|
237
|
+
|
|
238
|
+
<p align="right"><a href="#contents">Back to Top</a></p>
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## Development
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
pnpm --filter @sebastienrousseau/crypto-testing run build
|
|
246
|
+
pnpm --filter @sebastienrousseau/crypto-testing run test
|
|
247
|
+
pnpm --filter @sebastienrousseau/crypto-testing run lint
|
|
248
|
+
pnpm --filter @sebastienrousseau/crypto-testing run format
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
All 18 packages in the Crypto Service workspace maintain a **100% coverage floor** across statements, branches, functions, and lines.
|
|
252
|
+
|
|
253
|
+
<p align="right"><a href="#contents">Back to Top</a></p>
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## Security
|
|
258
|
+
|
|
259
|
+
Report vulnerabilities privately via [GitHub Security Advisories](https://github.com/sebastienrousseau/crypto-service/security/advisories) or according to [`SECURITY.md`](../../SECURITY.md). Never report security issues publicly.
|
|
260
|
+
|
|
261
|
+
Cryptographic operations use the `@noble/*` libraries, Node.js `crypto` and OpenPGP.js. `@noble/post-quantum` has not been independently audited and does not guarantee constant-time execution, and no module in this suite is FIPS 140-3 validated. Key zeroization is limited: JavaScript strings and garbage-collected buffers cannot be reliably wiped. See [`SECURITY.md`](../../SECURITY.md).
|
|
262
|
+
|
|
263
|
+
<p align="right"><a href="#contents">Back to Top</a></p>
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## Documentation
|
|
268
|
+
|
|
269
|
+
- [Full Suite Documentation](https://sebastienrousseau.github.io/crypto-service/)
|
|
270
|
+
- [API Reference (TypeDoc)](https://sebastienrousseau.github.io/crypto-service/)
|
|
271
|
+
- [Developer Guide](../../DEVELOPMENT.md)
|
|
272
|
+
- [Security Policy](../../SECURITY.md)
|
|
273
|
+
- [Architecture & Design](../../ARCHITECTURE.md)
|
|
274
|
+
|
|
275
|
+
<p align="right"><a href="#contents">Back to Top</a></p>
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
## Stability guarantees
|
|
280
|
+
|
|
281
|
+
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.
|
|
282
|
+
|
|
283
|
+
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).
|
|
284
|
+
|
|
285
|
+
<p align="right"><a href="#contents">Back to Top</a></p>
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## License
|
|
290
|
+
|
|
291
|
+
Dual-licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0) or [MIT](https://opensource.org/licenses/MIT), at your option.
|
|
292
|
+
|
|
293
|
+
Copyright (c) 2022-2026 Sebastien Rousseau and The Crypto Service Suite contributors.
|
|
294
|
+
|
|
295
|
+
<p align="right"><a href="#contents">Back to Top</a></p>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type MockKeyPair, type MockHashPasswordResult } from "./mock";
|
|
2
|
+
export interface TestKeyring {
|
|
3
|
+
signing: MockKeyPair;
|
|
4
|
+
exchange: MockKeyPair;
|
|
5
|
+
ecdsa: MockKeyPair;
|
|
6
|
+
symmetric: string;
|
|
7
|
+
hmac: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function createTestKeyring(): TestKeyring;
|
|
10
|
+
export interface TestEncryptedMessage {
|
|
11
|
+
key: string;
|
|
12
|
+
plaintext: string;
|
|
13
|
+
ciphertext: string;
|
|
14
|
+
algorithm: "mock-xor";
|
|
15
|
+
}
|
|
16
|
+
export declare function createTestEncryptedMessage(plaintext?: string, key?: string): TestEncryptedMessage;
|
|
17
|
+
export interface TestSignedMessage {
|
|
18
|
+
algorithm: string;
|
|
19
|
+
publicKey: string;
|
|
20
|
+
privateKey: string;
|
|
21
|
+
message: string;
|
|
22
|
+
signature: string;
|
|
23
|
+
}
|
|
24
|
+
export declare function createTestSignedMessage(algorithm?: string, message?: string): TestSignedMessage;
|
|
25
|
+
export declare function createTestPasswordHash(password?: string): MockHashPasswordResult;
|
|
26
|
+
//# sourceMappingURL=fixtures.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fixtures.d.ts","sourceRoot":"","sources":["../src/fixtures.ts"],"names":[],"mappings":"AAYA,OAAO,EAKL,KAAK,WAAW,EAChB,KAAK,sBAAsB,EAC5B,MAAM,QAAQ,CAAC;AAiBhB,MAAM,WAAW,WAAW;IAE1B,OAAO,EAAE,WAAW,CAAC;IAErB,QAAQ,EAAE,WAAW,CAAC;IAEtB,KAAK,EAAE,WAAW,CAAC;IAEnB,SAAS,EAAE,MAAM,CAAC;IAElB,IAAI,EAAE,MAAM,CAAC;CACd;AAcD,wBAAgB,iBAAiB,IAAI,WAAW,CAQ/C;AAiBD,MAAM,WAAW,oBAAoB;IAEnC,GAAG,EAAE,MAAM,CAAC;IAEZ,SAAS,EAAE,MAAM,CAAC;IAElB,UAAU,EAAE,MAAM,CAAC;IAEnB,SAAS,EAAE,UAAU,CAAC;CACvB;AAiBD,wBAAgB,0BAA0B,CACxC,SAAS,CAAC,EAAE,MAAM,EAClB,GAAG,CAAC,EAAE,MAAM,GACX,oBAAoB,CAStB;AAiBD,MAAM,WAAW,iBAAiB;IAEhC,SAAS,EAAE,MAAM,CAAC;IAElB,SAAS,EAAE,MAAM,CAAC;IAElB,UAAU,EAAE,MAAM,CAAC;IAEnB,OAAO,EAAE,MAAM,CAAC;IAEhB,SAAS,EAAE,MAAM,CAAC;CACnB;AAgBD,wBAAgB,uBAAuB,CACrC,SAAS,CAAC,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,MAAM,GACf,iBAAiB,CAWnB;AAmBD,wBAAgB,sBAAsB,CACpC,QAAQ,CAAC,EAAE,MAAM,GAChB,sBAAsB,CAExB"}
|
package/dist/fixtures.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createTestKeyring = createTestKeyring;
|
|
4
|
+
exports.createTestEncryptedMessage = createTestEncryptedMessage;
|
|
5
|
+
exports.createTestSignedMessage = createTestSignedMessage;
|
|
6
|
+
exports.createTestPasswordHash = createTestPasswordHash;
|
|
7
|
+
const keys_1 = require("./keys");
|
|
8
|
+
const mock_1 = require("./mock");
|
|
9
|
+
function createTestKeyring() {
|
|
10
|
+
return {
|
|
11
|
+
signing: (0, mock_1.mockGenerateKeyPair)("ed25519"),
|
|
12
|
+
exchange: (0, mock_1.mockGenerateKeyPair)("x25519"),
|
|
13
|
+
ecdsa: (0, mock_1.mockGenerateKeyPair)("p256"),
|
|
14
|
+
symmetric: keys_1.TEST_KEYS.aes256,
|
|
15
|
+
hmac: keys_1.TEST_KEYS.hmacKey,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function createTestEncryptedMessage(plaintext, key) {
|
|
19
|
+
const pt = plaintext ?? keys_1.TEST_VECTORS.plaintext;
|
|
20
|
+
const k = key ?? keys_1.TEST_KEYS.aes256;
|
|
21
|
+
return {
|
|
22
|
+
key: k,
|
|
23
|
+
plaintext: pt,
|
|
24
|
+
ciphertext: (0, mock_1.mockEncrypt)(k, pt),
|
|
25
|
+
algorithm: "mock-xor",
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function createTestSignedMessage(algorithm, message) {
|
|
29
|
+
const alg = algorithm ?? "ed25519";
|
|
30
|
+
const msg = message ?? keys_1.TEST_VECTORS.plaintext;
|
|
31
|
+
const kp = (0, mock_1.mockGenerateKeyPair)(alg);
|
|
32
|
+
return {
|
|
33
|
+
algorithm: alg,
|
|
34
|
+
publicKey: kp.publicKey,
|
|
35
|
+
privateKey: kp.privateKey,
|
|
36
|
+
message: msg,
|
|
37
|
+
signature: (0, mock_1.mockSign)(kp.privateKey, msg),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function createTestPasswordHash(password) {
|
|
41
|
+
return (0, mock_1.mockHashPassword)(password ?? "test-password-123");
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=fixtures.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type SignAlgorithm } from "@sebastienrousseau/crypto-lib";
|
|
2
|
+
export declare function expectValidHex(value: string, length?: number): void;
|
|
3
|
+
export declare function expectValidBase64(value: string): void;
|
|
4
|
+
export interface MinimalKeyPair {
|
|
5
|
+
publicKey: string;
|
|
6
|
+
privateKey: string;
|
|
7
|
+
algorithm?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function expectKeyPair(kp: MinimalKeyPair): void;
|
|
10
|
+
export declare function expectEncryptDecryptRoundTrip(key: string, plaintext: string): void;
|
|
11
|
+
export declare function expectSignVerifyRoundTrip(algorithm: SignAlgorithm): void;
|
|
12
|
+
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAUA,OAAO,EAAU,KAAK,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAyB3E,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAsBnE;AAsBD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAYrD;AAgBD,MAAM,WAAW,cAAc;IAE7B,SAAS,EAAE,MAAM,CAAC;IAElB,UAAU,EAAE,MAAM,CAAC;IAEnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAmBD,wBAAgB,aAAa,CAAC,EAAE,EAAE,cAAc,GAAG,IAAI,CAStD;AAqBD,wBAAgB,6BAA6B,CAC3C,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,GAChB,IAAI,CASN;AAsBD,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,aAAa,GAAG,IAAI,CAgCxE"}
|
package/dist/helpers.js
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.expectValidHex = expectValidHex;
|
|
4
|
+
exports.expectValidBase64 = expectValidBase64;
|
|
5
|
+
exports.expectKeyPair = expectKeyPair;
|
|
6
|
+
exports.expectEncryptDecryptRoundTrip = expectEncryptDecryptRoundTrip;
|
|
7
|
+
exports.expectSignVerifyRoundTrip = expectSignVerifyRoundTrip;
|
|
8
|
+
const crypto_lib_1 = require("@sebastienrousseau/crypto-lib");
|
|
9
|
+
const HEX_RE = /^[0-9a-fA-F]+$/;
|
|
10
|
+
function expectValidHex(value, length) {
|
|
11
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
12
|
+
throw new Error("Expected a non-empty hex string");
|
|
13
|
+
}
|
|
14
|
+
if (value.length % 2 !== 0) {
|
|
15
|
+
throw new Error(`Hex string has odd length (${value.length}); must be even`);
|
|
16
|
+
}
|
|
17
|
+
if (!HEX_RE.test(value)) {
|
|
18
|
+
throw new Error(`String is not valid hexadecimal: "${value.slice(0, 20)}..."`);
|
|
19
|
+
}
|
|
20
|
+
if (length !== undefined) {
|
|
21
|
+
const byteLen = value.length / 2;
|
|
22
|
+
if (byteLen !== length) {
|
|
23
|
+
throw new Error(`Expected ${length} bytes (${length * 2} hex chars), got ${byteLen} bytes (${value.length} hex chars)`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const BASE64_RE = /^[A-Za-z0-9+/]*={0,2}$/;
|
|
28
|
+
function expectValidBase64(value) {
|
|
29
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
30
|
+
throw new Error("Expected a non-empty Base64 string");
|
|
31
|
+
}
|
|
32
|
+
if (!BASE64_RE.test(value)) {
|
|
33
|
+
throw new Error(`String is not valid Base64: "${value.slice(0, 20)}..."`);
|
|
34
|
+
}
|
|
35
|
+
const buf = Buffer.from(value, "base64");
|
|
36
|
+
if (buf.toString("base64") !== value) {
|
|
37
|
+
throw new Error("Base64 string does not survive round-trip decode/encode");
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function expectKeyPair(kp) {
|
|
41
|
+
if (!kp || typeof kp !== "object") {
|
|
42
|
+
throw new Error("Expected a key pair object");
|
|
43
|
+
}
|
|
44
|
+
expectValidHex(kp.publicKey);
|
|
45
|
+
expectValidHex(kp.privateKey);
|
|
46
|
+
if (kp.publicKey === kp.privateKey) {
|
|
47
|
+
throw new Error("Public key and private key must not be identical");
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function expectEncryptDecryptRoundTrip(key, plaintext) {
|
|
51
|
+
const sealed = crypto_lib_1.crypto.encrypt(key, plaintext);
|
|
52
|
+
const decrypted = crypto_lib_1.crypto.decrypt(key, sealed);
|
|
53
|
+
const result = Buffer.from(decrypted).toString("utf8");
|
|
54
|
+
if (result !== plaintext) {
|
|
55
|
+
throw new Error(`Round-trip failed: expected "${plaintext}", got "${result}"`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function expectSignVerifyRoundTrip(algorithm) {
|
|
59
|
+
const keyAlgorithmMap = {
|
|
60
|
+
ed25519: "ed25519",
|
|
61
|
+
ed448: "ed448",
|
|
62
|
+
"ecdsa-p256": "p256",
|
|
63
|
+
"ecdsa-p384": "p384",
|
|
64
|
+
schnorr: "ed25519",
|
|
65
|
+
"ml-dsa-44": "ml-dsa-44",
|
|
66
|
+
"ml-dsa-65": "ml-dsa-65",
|
|
67
|
+
"ml-dsa-87": "ml-dsa-87",
|
|
68
|
+
};
|
|
69
|
+
const keyAlg = keyAlgorithmMap[algorithm];
|
|
70
|
+
if (!keyAlg) {
|
|
71
|
+
throw new Error(`No key algorithm mapping for sign algorithm "${algorithm}"`);
|
|
72
|
+
}
|
|
73
|
+
const kp = crypto_lib_1.crypto.generateKeyPair(keyAlg);
|
|
74
|
+
const message = "crypto-testing round-trip verification";
|
|
75
|
+
const signature = crypto_lib_1.crypto.sign(algorithm, kp.privateKey, message);
|
|
76
|
+
expectValidHex(signature);
|
|
77
|
+
const valid = crypto_lib_1.crypto.verify(algorithm, kp.publicKey, message, signature);
|
|
78
|
+
if (!valid) {
|
|
79
|
+
throw new Error(`Sign/verify round-trip failed for algorithm "${algorithm}"`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=helpers.js.map
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { TEST_KEYS, TEST_VECTORS } from "./keys";
|
|
2
|
+
export { mockHashPassword, mockGenerateKeyPair, mockEncrypt, mockDecrypt, mockSign, mockVerify, } from "./mock";
|
|
3
|
+
export { createTestKeyring, createTestEncryptedMessage, createTestSignedMessage, createTestPasswordHash, } from "./fixtures";
|
|
4
|
+
export { expectValidHex, expectValidBase64, expectKeyPair, expectEncryptDecryptRoundTrip, expectSignVerifyRoundTrip, } from "./helpers";
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAGjD,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,WAAW,EACX,WAAW,EACX,QAAQ,EACR,UAAU,GACX,MAAM,QAAQ,CAAC;AAGhB,OAAO,EACL,iBAAiB,EACjB,0BAA0B,EAC1B,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,aAAa,EACb,6BAA6B,EAC7B,yBAAyB,GAC1B,MAAM,WAAW,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.expectSignVerifyRoundTrip = exports.expectEncryptDecryptRoundTrip = exports.expectKeyPair = exports.expectValidBase64 = exports.expectValidHex = exports.createTestPasswordHash = exports.createTestSignedMessage = exports.createTestEncryptedMessage = exports.createTestKeyring = exports.mockVerify = exports.mockSign = exports.mockDecrypt = exports.mockEncrypt = exports.mockGenerateKeyPair = exports.mockHashPassword = exports.TEST_VECTORS = exports.TEST_KEYS = void 0;
|
|
4
|
+
var keys_1 = require("./keys");
|
|
5
|
+
Object.defineProperty(exports, "TEST_KEYS", { enumerable: true, get: function () { return keys_1.TEST_KEYS; } });
|
|
6
|
+
Object.defineProperty(exports, "TEST_VECTORS", { enumerable: true, get: function () { return keys_1.TEST_VECTORS; } });
|
|
7
|
+
var mock_1 = require("./mock");
|
|
8
|
+
Object.defineProperty(exports, "mockHashPassword", { enumerable: true, get: function () { return mock_1.mockHashPassword; } });
|
|
9
|
+
Object.defineProperty(exports, "mockGenerateKeyPair", { enumerable: true, get: function () { return mock_1.mockGenerateKeyPair; } });
|
|
10
|
+
Object.defineProperty(exports, "mockEncrypt", { enumerable: true, get: function () { return mock_1.mockEncrypt; } });
|
|
11
|
+
Object.defineProperty(exports, "mockDecrypt", { enumerable: true, get: function () { return mock_1.mockDecrypt; } });
|
|
12
|
+
Object.defineProperty(exports, "mockSign", { enumerable: true, get: function () { return mock_1.mockSign; } });
|
|
13
|
+
Object.defineProperty(exports, "mockVerify", { enumerable: true, get: function () { return mock_1.mockVerify; } });
|
|
14
|
+
var fixtures_1 = require("./fixtures");
|
|
15
|
+
Object.defineProperty(exports, "createTestKeyring", { enumerable: true, get: function () { return fixtures_1.createTestKeyring; } });
|
|
16
|
+
Object.defineProperty(exports, "createTestEncryptedMessage", { enumerable: true, get: function () { return fixtures_1.createTestEncryptedMessage; } });
|
|
17
|
+
Object.defineProperty(exports, "createTestSignedMessage", { enumerable: true, get: function () { return fixtures_1.createTestSignedMessage; } });
|
|
18
|
+
Object.defineProperty(exports, "createTestPasswordHash", { enumerable: true, get: function () { return fixtures_1.createTestPasswordHash; } });
|
|
19
|
+
var helpers_1 = require("./helpers");
|
|
20
|
+
Object.defineProperty(exports, "expectValidHex", { enumerable: true, get: function () { return helpers_1.expectValidHex; } });
|
|
21
|
+
Object.defineProperty(exports, "expectValidBase64", { enumerable: true, get: function () { return helpers_1.expectValidBase64; } });
|
|
22
|
+
Object.defineProperty(exports, "expectKeyPair", { enumerable: true, get: function () { return helpers_1.expectKeyPair; } });
|
|
23
|
+
Object.defineProperty(exports, "expectEncryptDecryptRoundTrip", { enumerable: true, get: function () { return helpers_1.expectEncryptDecryptRoundTrip; } });
|
|
24
|
+
Object.defineProperty(exports, "expectSignVerifyRoundTrip", { enumerable: true, get: function () { return helpers_1.expectSignVerifyRoundTrip; } });
|
|
25
|
+
//# sourceMappingURL=index.js.map
|
package/dist/keys.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export declare const TEST_KEYS: {
|
|
2
|
+
readonly ed25519: {
|
|
3
|
+
readonly publicKey: "d75a980182b10ab7d54bfed3c964073a0ee172f3daa3f4a18446b7e8c38f1dd5";
|
|
4
|
+
readonly privateKey: "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60";
|
|
5
|
+
};
|
|
6
|
+
readonly x25519: {
|
|
7
|
+
readonly publicKey: "8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a";
|
|
8
|
+
readonly privateKey: "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a";
|
|
9
|
+
};
|
|
10
|
+
readonly p256: {
|
|
11
|
+
readonly publicKey: "0437c1b9e44bcb3d97a78b8b5e71f5e3e5a4a0e7d6b8c2f1e0d9c8b7a6f5e4d3c2b1a09f8e7d6c5b4a3029f8e7d6c5b4a3029f8e7d6c5b4a3029f8e7d6c5b4a302";
|
|
12
|
+
readonly privateKey: "c9afa9d845ba75166b5c215767b1d6934e50c3db36e89b127b8a622b120f6721";
|
|
13
|
+
};
|
|
14
|
+
readonly aes256: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
|
|
15
|
+
readonly hmacKey: "cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe";
|
|
16
|
+
};
|
|
17
|
+
export declare const TEST_VECTORS: {
|
|
18
|
+
readonly plaintext: "The quick brown fox jumps over the lazy dog";
|
|
19
|
+
readonly sha256: "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592";
|
|
20
|
+
readonly sha3_256: "a80f839cd4f83f6c3dafc87feae470045e4eb0d366397d5c6ce34ba1739f734d";
|
|
21
|
+
readonly blake3: "8e7e26d7e72a04d2ed173f90a72ec2a3bf3bb38890c9a2f95f3ab0e18a1e1a4a";
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=keys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../src/keys.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;CAgCZ,CAAC;AAaX,eAAO,MAAM,YAAY;;;;;CASf,CAAC"}
|
package/dist/keys.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TEST_VECTORS = exports.TEST_KEYS = void 0;
|
|
4
|
+
exports.TEST_KEYS = {
|
|
5
|
+
ed25519: {
|
|
6
|
+
publicKey: "d75a980182b10ab7d54bfed3c964073a0ee172f3daa3f4a18446b7e8c38f1dd5",
|
|
7
|
+
privateKey: "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60",
|
|
8
|
+
},
|
|
9
|
+
x25519: {
|
|
10
|
+
publicKey: "8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a",
|
|
11
|
+
privateKey: "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a",
|
|
12
|
+
},
|
|
13
|
+
p256: {
|
|
14
|
+
publicKey: "0437c1b9e44bcb3d97a78b8b5e71f5e3e5a4a0e7d6b8c2f1e0d9c8b7a6f5e4d3c2b1a09f8e7d6c5b4a3029f8e7d6c5b4a3029f8e7d6c5b4a3029f8e7d6c5b4a302",
|
|
15
|
+
privateKey: "c9afa9d845ba75166b5c215767b1d6934e50c3db36e89b127b8a622b120f6721",
|
|
16
|
+
},
|
|
17
|
+
aes256: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
|
|
18
|
+
hmacKey: "cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe",
|
|
19
|
+
};
|
|
20
|
+
exports.TEST_VECTORS = {
|
|
21
|
+
plaintext: "The quick brown fox jumps over the lazy dog",
|
|
22
|
+
sha256: "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592",
|
|
23
|
+
sha3_256: "a80f839cd4f83f6c3dafc87feae470045e4eb0d366397d5c6ce34ba1739f734d",
|
|
24
|
+
blake3: "8e7e26d7e72a04d2ed173f90a72ec2a3bf3bb38890c9a2f95f3ab0e18a1e1a4a",
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=keys.js.map
|
package/dist/mock.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface MockHashPasswordResult {
|
|
2
|
+
hash: string;
|
|
3
|
+
salt: string;
|
|
4
|
+
params: {
|
|
5
|
+
t: number;
|
|
6
|
+
m: number;
|
|
7
|
+
p: number;
|
|
8
|
+
};
|
|
9
|
+
algorithm: "mock-argon2id";
|
|
10
|
+
phc: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function mockHashPassword(password: string | Uint8Array): MockHashPasswordResult;
|
|
13
|
+
export interface MockKeyPair {
|
|
14
|
+
publicKey: string;
|
|
15
|
+
privateKey: string;
|
|
16
|
+
algorithm: string;
|
|
17
|
+
kid: string;
|
|
18
|
+
}
|
|
19
|
+
export declare function mockGenerateKeyPair(algorithm?: string): MockKeyPair;
|
|
20
|
+
export declare function mockEncrypt(key: string, plaintext: string | Uint8Array): string;
|
|
21
|
+
export declare function mockDecrypt(key: string, ciphertext: string): Uint8Array;
|
|
22
|
+
export declare function mockSign(privateKey: string, message: string | Uint8Array): string;
|
|
23
|
+
export declare function mockVerify(_publicKey: string, message: string | Uint8Array, signature: string, privateKey: string): boolean;
|
|
24
|
+
//# sourceMappingURL=mock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mock.d.ts","sourceRoot":"","sources":["../src/mock.ts"],"names":[],"mappings":"AAwDA,MAAM,WAAW,sBAAsB;IAErC,IAAI,EAAE,MAAM,CAAC;IAEb,IAAI,EAAE,MAAM,CAAC;IAEb,MAAM,EAAE;QAEN,CAAC,EAAE,MAAM,CAAC;QAEV,CAAC,EAAE,MAAM,CAAC;QAEV,CAAC,EAAE,MAAM,CAAC;KACX,CAAC;IAEF,SAAS,EAAE,eAAe,CAAC;IAE3B,GAAG,EAAE,MAAM,CAAC;CACb;AAkBD,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,GAAG,UAAU,GAC5B,sBAAsB,CAaxB;AAiBD,MAAM,WAAW,WAAW;IAE1B,SAAS,EAAE,MAAM,CAAC;IAElB,UAAU,EAAE,MAAM,CAAC;IAEnB,SAAS,EAAE,MAAM,CAAC;IAElB,GAAG,EAAE,MAAM,CAAC;CACb;AAiBD,wBAAgB,mBAAmB,CACjC,SAAS,GAAE,MAAkB,GAC5B,WAAW,CA+Bb;AAqBD,wBAAgB,WAAW,CACzB,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,GAAG,UAAU,GAC7B,MAAM,CAIR;AAiBD,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,UAAU,CAIvE;AAuBD,wBAAgB,QAAQ,CACtB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,GAAG,UAAU,GAC3B,MAAM,CAIR;AAsBD,wBAAgB,UAAU,CACxB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,GAAG,UAAU,EAC5B,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GACjB,OAAO,CAGT"}
|
package/dist/mock.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mockHashPassword = mockHashPassword;
|
|
4
|
+
exports.mockGenerateKeyPair = mockGenerateKeyPair;
|
|
5
|
+
exports.mockEncrypt = mockEncrypt;
|
|
6
|
+
exports.mockDecrypt = mockDecrypt;
|
|
7
|
+
exports.mockSign = mockSign;
|
|
8
|
+
exports.mockVerify = mockVerify;
|
|
9
|
+
const keys_1 = require("./keys");
|
|
10
|
+
function xorCipher(data, key) {
|
|
11
|
+
const out = new Uint8Array(data.length);
|
|
12
|
+
for (let i = 0; i < data.length; i++) {
|
|
13
|
+
out[i] = data[i] ^ key[i % key.length];
|
|
14
|
+
}
|
|
15
|
+
return out;
|
|
16
|
+
}
|
|
17
|
+
function toBytes(input) {
|
|
18
|
+
return input instanceof Uint8Array ? input : Buffer.from(input, "utf8");
|
|
19
|
+
}
|
|
20
|
+
function toHex(bytes) {
|
|
21
|
+
return Buffer.from(bytes).toString("hex");
|
|
22
|
+
}
|
|
23
|
+
function hexToBytes(hex) {
|
|
24
|
+
return Buffer.from(hex, "hex");
|
|
25
|
+
}
|
|
26
|
+
function mockHashPassword(password) {
|
|
27
|
+
const pw = toBytes(password);
|
|
28
|
+
const salt = hexToBytes("00".repeat(16));
|
|
29
|
+
const fakeHash = xorCipher(pw, salt);
|
|
30
|
+
const hashHex = toHex(fakeHash).padEnd(64, "0");
|
|
31
|
+
const saltHex = "00".repeat(16);
|
|
32
|
+
return {
|
|
33
|
+
hash: hashHex,
|
|
34
|
+
salt: saltHex,
|
|
35
|
+
params: { t: 1, m: 1024, p: 1 },
|
|
36
|
+
algorithm: "mock-argon2id",
|
|
37
|
+
phc: `$mock-argon2id$v=19$m=1024,t=1,p=1$${Buffer.from(salt).toString("base64")}$${Buffer.from(hexToBytes(hashHex)).toString("base64")}`,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function mockGenerateKeyPair(algorithm = "ed25519") {
|
|
41
|
+
switch (algorithm) {
|
|
42
|
+
case "ed25519":
|
|
43
|
+
return {
|
|
44
|
+
publicKey: keys_1.TEST_KEYS.ed25519.publicKey,
|
|
45
|
+
privateKey: keys_1.TEST_KEYS.ed25519.privateKey,
|
|
46
|
+
algorithm,
|
|
47
|
+
kid: "mock-ed25519-kid",
|
|
48
|
+
};
|
|
49
|
+
case "x25519":
|
|
50
|
+
return {
|
|
51
|
+
publicKey: keys_1.TEST_KEYS.x25519.publicKey,
|
|
52
|
+
privateKey: keys_1.TEST_KEYS.x25519.privateKey,
|
|
53
|
+
algorithm,
|
|
54
|
+
kid: "mock-x25519-kid",
|
|
55
|
+
};
|
|
56
|
+
case "p256":
|
|
57
|
+
return {
|
|
58
|
+
publicKey: keys_1.TEST_KEYS.p256.publicKey,
|
|
59
|
+
privateKey: keys_1.TEST_KEYS.p256.privateKey,
|
|
60
|
+
algorithm,
|
|
61
|
+
kid: "mock-p256-kid",
|
|
62
|
+
};
|
|
63
|
+
default:
|
|
64
|
+
return {
|
|
65
|
+
publicKey: "aa".repeat(32),
|
|
66
|
+
privateKey: "bb".repeat(32),
|
|
67
|
+
algorithm,
|
|
68
|
+
kid: `mock-${algorithm}-kid`,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function mockEncrypt(key, plaintext) {
|
|
73
|
+
const keyBytes = hexToBytes(key);
|
|
74
|
+
const ptBytes = toBytes(plaintext);
|
|
75
|
+
return toHex(xorCipher(ptBytes, keyBytes));
|
|
76
|
+
}
|
|
77
|
+
function mockDecrypt(key, ciphertext) {
|
|
78
|
+
const keyBytes = hexToBytes(key);
|
|
79
|
+
const ctBytes = hexToBytes(ciphertext);
|
|
80
|
+
return xorCipher(ctBytes, keyBytes);
|
|
81
|
+
}
|
|
82
|
+
function mockSign(privateKey, message) {
|
|
83
|
+
const keyBytes = hexToBytes(privateKey);
|
|
84
|
+
const msgBytes = toBytes(message);
|
|
85
|
+
return toHex(xorCipher(msgBytes, keyBytes));
|
|
86
|
+
}
|
|
87
|
+
function mockVerify(_publicKey, message, signature, privateKey) {
|
|
88
|
+
const expected = mockSign(privateKey, message);
|
|
89
|
+
return expected === signature;
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=mock.js.map
|
package/package.json
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sebastienrousseau/crypto-testing",
|
|
3
|
+
"version": "0.0.8",
|
|
4
|
+
"description": "Deterministic keys, fast mocks, and test fixtures for crypto-lib — make your CI/CD pipeline fast and reproducible.",
|
|
5
|
+
"author": "Sebastien Rousseau <sebastienrousseau@users.noreply.github.com>",
|
|
6
|
+
"license": "MIT OR Apache-2.0",
|
|
7
|
+
"homepage": "https://github.com/sebastienrousseau/crypto-service/tree/main/packages/crypto-testing",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/sebastienrousseau/crypto-service.git",
|
|
11
|
+
"directory": "packages/crypto-testing"
|
|
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
|
+
"exports": {
|
|
23
|
+
".": {
|
|
24
|
+
"types": "./dist/index.d.ts",
|
|
25
|
+
"require": "./dist/index.js",
|
|
26
|
+
"import": "./dist/index.js"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"dist/**/*.js",
|
|
31
|
+
"dist/**/*.d.ts",
|
|
32
|
+
"dist/**/*.d.ts.map"
|
|
33
|
+
],
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@sebastienrousseau/crypto-lib": "0.0.8"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@sebastienrousseau/mocha-config": "^0.0.5",
|
|
39
|
+
"@types/chai": "^4.3.7",
|
|
40
|
+
"@types/chai-as-promised": "^8.0.2",
|
|
41
|
+
"@types/mocha": "^10.0.2",
|
|
42
|
+
"@types/node": "^26.6.3",
|
|
43
|
+
"c8": "^12.0.0",
|
|
44
|
+
"chai": "^4.5.0",
|
|
45
|
+
"chai-as-promised": "^7.1.2",
|
|
46
|
+
"mocha": "^10.8.2",
|
|
47
|
+
"rimraf": "^6.1.3",
|
|
48
|
+
"ts-node": "^10.9.2",
|
|
49
|
+
"typedoc": "^0.28.20",
|
|
50
|
+
"typescript": "~5.9.3"
|
|
51
|
+
},
|
|
52
|
+
"keywords": [
|
|
53
|
+
"crypto-testing",
|
|
54
|
+
"test-fixtures",
|
|
55
|
+
"deterministic-keys",
|
|
56
|
+
"mock-crypto",
|
|
57
|
+
"crypto-lib"
|
|
58
|
+
],
|
|
59
|
+
"publishConfig": {
|
|
60
|
+
"access": "public"
|
|
61
|
+
},
|
|
62
|
+
"private": false,
|
|
63
|
+
"scripts": {
|
|
64
|
+
"build": "tsc --build tsconfig.json",
|
|
65
|
+
"clean": "rimraf ./coverage ./dist ./docs",
|
|
66
|
+
"test": "c8 --check-coverage --lines 100 --branches 100 --functions 100 --reporter=lcov --reporter=text mocha --config=.mocharc.cjs",
|
|
67
|
+
"docs": "typedoc",
|
|
68
|
+
"lint": "eslint --ext .ts src __tests__",
|
|
69
|
+
"lint:fix": "eslint --cache --fix --ext .ts src __tests__",
|
|
70
|
+
"format": "prettier --write src/**/*.ts",
|
|
71
|
+
"format:check": "prettier --check \"src/**/*.ts\""
|
|
72
|
+
}
|
|
73
|
+
}
|