@cello-protocol/crypto 0.0.2
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/dist/checkpoint.d.ts +52 -0
- package/dist/checkpoint.d.ts.map +1 -0
- package/dist/checkpoint.js +70 -0
- package/dist/checkpoint.js.map +1 -0
- package/dist/ed25519.d.ts +25 -0
- package/dist/ed25519.d.ts.map +1 -0
- package/dist/ed25519.js +120 -0
- package/dist/ed25519.js.map +1 -0
- package/dist/frost/frost-threshold-signer.d.ts +178 -0
- package/dist/frost/frost-threshold-signer.d.ts.map +1 -0
- package/dist/frost/frost-threshold-signer.js +478 -0
- package/dist/frost/frost-threshold-signer.js.map +1 -0
- package/dist/frost/index.d.ts +23 -0
- package/dist/frost/index.d.ts.map +1 -0
- package/dist/frost/index.js +22 -0
- package/dist/frost/index.js.map +1 -0
- package/dist/frost/stubs.d.ts +82 -0
- package/dist/frost/stubs.d.ts.map +1 -0
- package/dist/frost/stubs.js +157 -0
- package/dist/frost/stubs.js.map +1 -0
- package/dist/frost/types.d.ts +173 -0
- package/dist/frost/types.d.ts.map +1 -0
- package/dist/frost/types.js +21 -0
- package/dist/frost/types.js.map +1 -0
- package/dist/hashing.d.ts +17 -0
- package/dist/hashing.d.ts.map +1 -0
- package/dist/hashing.js +50 -0
- package/dist/hashing.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/merkle.d.ts +162 -0
- package/dist/merkle.d.ts.map +1 -0
- package/dist/merkle.js +240 -0
- package/dist/merkle.js.map +1 -0
- package/dist/ml-dsa.d.ts +100 -0
- package/dist/ml-dsa.d.ts.map +1 -0
- package/dist/ml-dsa.js +257 -0
- package/dist/ml-dsa.js.map +1 -0
- package/dist/relay-registration.d.ts +62 -0
- package/dist/relay-registration.d.ts.map +1 -0
- package/dist/relay-registration.js +87 -0
- package/dist/relay-registration.js.map +1 -0
- package/dist/types.d.ts +11 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +49 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FEDERATION-002 — Canonical checkpoint TBS (to-be-signed) serialization.
|
|
3
|
+
*
|
|
4
|
+
* buildCheckpointTbs produces the canonical byte representation for the checkpoint hash:
|
|
5
|
+
* SHA-256(mmr_peaks_serialized || identity_merkle_root || checkpoint_id)
|
|
6
|
+
*
|
|
7
|
+
* where mmr_peaks_serialized is a canonical JSON array of hex-encoded peak hashes
|
|
8
|
+
* ordered by MMR position ascending — e.g. '["aabb...","ccdd..."]' with no
|
|
9
|
+
* whitespace and no object keys, UTF-8 encoded.
|
|
10
|
+
*
|
|
11
|
+
* This function MUST live in @cello-protocol/crypto so both:
|
|
12
|
+
* - the coordinator (which computes the hash to broadcast)
|
|
13
|
+
* - the non-coordinator (which independently recomputes to verify)
|
|
14
|
+
* import the same serialization. AC-010-canonical-tbs: no inline serialization
|
|
15
|
+
* of mmr_peaks exists in packages/directory.
|
|
16
|
+
*
|
|
17
|
+
* References: FIPS 180-4 (SHA-256), RFC 8032 (Ed25519).
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Produce the canonical TBS bytes for a checkpoint hash.
|
|
21
|
+
*
|
|
22
|
+
* Pseudocode:
|
|
23
|
+
* 1. Serialize mmr_peaks as a compact JSON array: JSON.stringify(mmrPeaks)
|
|
24
|
+
* mmrPeaks must be an array of hex strings ordered by MMR position ascending.
|
|
25
|
+
* JSON.stringify produces no whitespace: '["aabb...","ccdd..."]' — FIPS 180-4.
|
|
26
|
+
* 2. Encode mmr_peaks_serialized as UTF-8 bytes.
|
|
27
|
+
* 3. Encode identity_merkle_root as UTF-8 bytes.
|
|
28
|
+
* 4. Encode checkpoint_id as UTF-8 bytes.
|
|
29
|
+
* 5. Concatenate: mmr_peaks_serialized_bytes || identity_merkle_root_bytes || checkpoint_id_bytes
|
|
30
|
+
* 6. Compute SHA-256(concatenation) — FIPS 180-4.
|
|
31
|
+
* 7. Return the 32-byte digest as a Uint8Array.
|
|
32
|
+
*
|
|
33
|
+
* @param mmrPeaks - Hex-encoded peak hashes ordered by MMR position ascending.
|
|
34
|
+
* Example: ["aabb...", "ccdd..."] for a 3-leaf MMR with 2 peaks.
|
|
35
|
+
* @param identityMerkleRoot - Hex-encoded identity Merkle root (32 bytes as hex).
|
|
36
|
+
* @param checkpointId - UUID string for this checkpoint (as issued by the coordinator).
|
|
37
|
+
* @returns 32-byte SHA-256 digest — FIPS 180-4.
|
|
38
|
+
*/
|
|
39
|
+
export declare function buildCheckpointTbs(mmrPeaks: readonly string[], identityMerkleRoot: string, checkpointId: string): Uint8Array;
|
|
40
|
+
/**
|
|
41
|
+
* Compute the hex-encoded checkpoint hash from canonical TBS.
|
|
42
|
+
*
|
|
43
|
+
* Convenience wrapper around buildCheckpointTbs that returns a hex string
|
|
44
|
+
* (matching the `checkpoint_hash` column type in directory_checkpoints).
|
|
45
|
+
*
|
|
46
|
+
* @param mmrPeaks - Hex-encoded peak hashes ordered by MMR position ascending.
|
|
47
|
+
* @param identityMerkleRoot - Hex-encoded identity Merkle root.
|
|
48
|
+
* @param checkpointId - UUID string for this checkpoint.
|
|
49
|
+
* @returns 64-character lowercase hex string (32-byte SHA-256 digest).
|
|
50
|
+
*/
|
|
51
|
+
export declare function computeCheckpointHash(mmrPeaks: readonly string[], identityMerkleRoot: string, checkpointId: string): string;
|
|
52
|
+
//# sourceMappingURL=checkpoint.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkpoint.d.ts","sourceRoot":"","sources":["../src/checkpoint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,kBAAkB,EAAE,MAAM,EAC1B,YAAY,EAAE,MAAM,GACnB,UAAU,CAkBZ;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,kBAAkB,EAAE,MAAM,EAC1B,YAAY,EAAE,MAAM,GACnB,MAAM,CAER"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FEDERATION-002 — Canonical checkpoint TBS (to-be-signed) serialization.
|
|
3
|
+
*
|
|
4
|
+
* buildCheckpointTbs produces the canonical byte representation for the checkpoint hash:
|
|
5
|
+
* SHA-256(mmr_peaks_serialized || identity_merkle_root || checkpoint_id)
|
|
6
|
+
*
|
|
7
|
+
* where mmr_peaks_serialized is a canonical JSON array of hex-encoded peak hashes
|
|
8
|
+
* ordered by MMR position ascending — e.g. '["aabb...","ccdd..."]' with no
|
|
9
|
+
* whitespace and no object keys, UTF-8 encoded.
|
|
10
|
+
*
|
|
11
|
+
* This function MUST live in @cello-protocol/crypto so both:
|
|
12
|
+
* - the coordinator (which computes the hash to broadcast)
|
|
13
|
+
* - the non-coordinator (which independently recomputes to verify)
|
|
14
|
+
* import the same serialization. AC-010-canonical-tbs: no inline serialization
|
|
15
|
+
* of mmr_peaks exists in packages/directory.
|
|
16
|
+
*
|
|
17
|
+
* References: FIPS 180-4 (SHA-256), RFC 8032 (Ed25519).
|
|
18
|
+
*/
|
|
19
|
+
import { createHash } from "node:crypto";
|
|
20
|
+
/**
|
|
21
|
+
* Produce the canonical TBS bytes for a checkpoint hash.
|
|
22
|
+
*
|
|
23
|
+
* Pseudocode:
|
|
24
|
+
* 1. Serialize mmr_peaks as a compact JSON array: JSON.stringify(mmrPeaks)
|
|
25
|
+
* mmrPeaks must be an array of hex strings ordered by MMR position ascending.
|
|
26
|
+
* JSON.stringify produces no whitespace: '["aabb...","ccdd..."]' — FIPS 180-4.
|
|
27
|
+
* 2. Encode mmr_peaks_serialized as UTF-8 bytes.
|
|
28
|
+
* 3. Encode identity_merkle_root as UTF-8 bytes.
|
|
29
|
+
* 4. Encode checkpoint_id as UTF-8 bytes.
|
|
30
|
+
* 5. Concatenate: mmr_peaks_serialized_bytes || identity_merkle_root_bytes || checkpoint_id_bytes
|
|
31
|
+
* 6. Compute SHA-256(concatenation) — FIPS 180-4.
|
|
32
|
+
* 7. Return the 32-byte digest as a Uint8Array.
|
|
33
|
+
*
|
|
34
|
+
* @param mmrPeaks - Hex-encoded peak hashes ordered by MMR position ascending.
|
|
35
|
+
* Example: ["aabb...", "ccdd..."] for a 3-leaf MMR with 2 peaks.
|
|
36
|
+
* @param identityMerkleRoot - Hex-encoded identity Merkle root (32 bytes as hex).
|
|
37
|
+
* @param checkpointId - UUID string for this checkpoint (as issued by the coordinator).
|
|
38
|
+
* @returns 32-byte SHA-256 digest — FIPS 180-4.
|
|
39
|
+
*/
|
|
40
|
+
export function buildCheckpointTbs(mmrPeaks, identityMerkleRoot, checkpointId) {
|
|
41
|
+
// Step 1+2: canonical JSON serialization of the peak array — no whitespace (FIPS 180-4 §6.2)
|
|
42
|
+
const mmrPeaksSerialized = JSON.stringify(mmrPeaks);
|
|
43
|
+
// Steps 3-5: UTF-8 encode and concatenate components
|
|
44
|
+
const encoder = new TextEncoder();
|
|
45
|
+
const peakBytes = encoder.encode(mmrPeaksSerialized);
|
|
46
|
+
const identityBytes = encoder.encode(identityMerkleRoot);
|
|
47
|
+
const checkpointBytes = encoder.encode(checkpointId);
|
|
48
|
+
// Step 6: SHA-256(mmr_peaks_serialized || identity_merkle_root || checkpoint_id)
|
|
49
|
+
const combined = Buffer.concat([
|
|
50
|
+
Buffer.from(peakBytes),
|
|
51
|
+
Buffer.from(identityBytes),
|
|
52
|
+
Buffer.from(checkpointBytes),
|
|
53
|
+
]);
|
|
54
|
+
return new Uint8Array(createHash("sha256").update(combined).digest());
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Compute the hex-encoded checkpoint hash from canonical TBS.
|
|
58
|
+
*
|
|
59
|
+
* Convenience wrapper around buildCheckpointTbs that returns a hex string
|
|
60
|
+
* (matching the `checkpoint_hash` column type in directory_checkpoints).
|
|
61
|
+
*
|
|
62
|
+
* @param mmrPeaks - Hex-encoded peak hashes ordered by MMR position ascending.
|
|
63
|
+
* @param identityMerkleRoot - Hex-encoded identity Merkle root.
|
|
64
|
+
* @param checkpointId - UUID string for this checkpoint.
|
|
65
|
+
* @returns 64-character lowercase hex string (32-byte SHA-256 digest).
|
|
66
|
+
*/
|
|
67
|
+
export function computeCheckpointHash(mmrPeaks, identityMerkleRoot, checkpointId) {
|
|
68
|
+
return Buffer.from(buildCheckpointTbs(mmrPeaks, identityMerkleRoot, checkpointId)).toString("hex");
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=checkpoint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkpoint.js","sourceRoot":"","sources":["../src/checkpoint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,kBAAkB,CAChC,QAA2B,EAC3B,kBAA0B,EAC1B,YAAoB;IAEpB,6FAA6F;IAC7F,MAAM,kBAAkB,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAEpD,qDAAqD;IACrD,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAClC,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;IACrD,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;IACzD,MAAM,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IAErD,iFAAiF;IACjF,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC;QAC7B,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;QACtB,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC;QAC1B,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC;KAC7B,CAAC,CAAC;IAEH,OAAO,IAAI,UAAU,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;AACxE,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,qBAAqB,CACnC,QAA2B,EAC3B,kBAA0B,EAC1B,YAAoB;IAEpB,OAAO,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,QAAQ,EAAE,kBAAkB,EAAE,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACrG,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { KeyProvider, PublicKey, Signature } from "./types.js";
|
|
2
|
+
declare const INSPECT: unique symbol;
|
|
3
|
+
export declare class InMemoryKeyProvider implements KeyProvider {
|
|
4
|
+
#private;
|
|
5
|
+
constructor(seed: Uint8Array);
|
|
6
|
+
getPublicKey(): Promise<PublicKey>;
|
|
7
|
+
sign(data: Uint8Array): Promise<Signature>;
|
|
8
|
+
toJSON(): Record<string, string>;
|
|
9
|
+
toString(): string;
|
|
10
|
+
[INSPECT](): string;
|
|
11
|
+
}
|
|
12
|
+
export declare class FileKeyProvider implements KeyProvider {
|
|
13
|
+
#private;
|
|
14
|
+
private constructor();
|
|
15
|
+
static load(path: string): Promise<FileKeyProvider>;
|
|
16
|
+
getPublicKey(): Promise<PublicKey>;
|
|
17
|
+
sign(data: Uint8Array): Promise<Signature>;
|
|
18
|
+
toJSON(): Record<string, unknown>;
|
|
19
|
+
toString(): string;
|
|
20
|
+
[INSPECT](): string;
|
|
21
|
+
}
|
|
22
|
+
export declare function generateKeypair(): InMemoryKeyProvider;
|
|
23
|
+
export declare function verify(publicKey: PublicKey, data: Uint8Array, signature: Signature): boolean;
|
|
24
|
+
export {};
|
|
25
|
+
//# sourceMappingURL=ed25519.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ed25519.d.ts","sourceRoot":"","sources":["../src/ed25519.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEpE,QAAA,MAAM,OAAO,eAA2C,CAAC;AAOzD,qBAAa,mBAAoB,YAAW,WAAW;;gBAIzC,IAAI,EAAE,UAAU;IAMtB,YAAY,IAAI,OAAO,CAAC,SAAS,CAAC;IAIlC,IAAI,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC;IAIhD,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAIhC,QAAQ,IAAI,MAAM;IAIlB,CAAC,OAAO,CAAC,IAAI,MAAM;CAGpB;AAED,qBAAa,eAAgB,YAAW,WAAW;;IAGjD,OAAO;WAIM,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAuDnD,YAAY,IAAI,OAAO,CAAC,SAAS,CAAC;IAIlC,IAAI,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC;IAIhD,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAIjC,QAAQ,IAAI,MAAM;IAIlB,CAAC,OAAO,CAAC,IAAI,MAAM;CAGpB;AAED,wBAAgB,eAAe,IAAI,mBAAmB,CAErD;AAED,wBAAgB,MAAM,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,GAAG,OAAO,CAM5F"}
|
package/dist/ed25519.js
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { ed25519 } from "@noble/curves/ed25519.js";
|
|
2
|
+
import { randomBytes } from "@noble/hashes/utils.js";
|
|
3
|
+
import { readFile, rename, mkdir, open as fsOpen } from "node:fs/promises";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
const INSPECT = Symbol.for("nodejs.util.inspect.custom");
|
|
6
|
+
const KEY_FILE_MAGIC = new Uint8Array([0xce, 0x11, 0x0e, 0x01]); // "CELLO\x01"
|
|
7
|
+
const KEY_FILE_VERSION = 1;
|
|
8
|
+
const SEED_BYTES = 32;
|
|
9
|
+
// Magic(4) + version(1) + seed(32) = 37 bytes
|
|
10
|
+
const KEY_FILE_SIZE = KEY_FILE_MAGIC.length + 1 + SEED_BYTES;
|
|
11
|
+
export class InMemoryKeyProvider {
|
|
12
|
+
#seed;
|
|
13
|
+
#publicKey;
|
|
14
|
+
constructor(seed) {
|
|
15
|
+
if (seed.length !== SEED_BYTES)
|
|
16
|
+
throw new Error("seed must be 32 bytes");
|
|
17
|
+
this.#seed = seed;
|
|
18
|
+
this.#publicKey = ed25519.getPublicKey(seed);
|
|
19
|
+
}
|
|
20
|
+
async getPublicKey() {
|
|
21
|
+
return this.#publicKey;
|
|
22
|
+
}
|
|
23
|
+
async sign(data) {
|
|
24
|
+
return ed25519.sign(data, this.#seed);
|
|
25
|
+
}
|
|
26
|
+
toJSON() {
|
|
27
|
+
return { type: "InMemoryKeyProvider", publicKey: Buffer.from(this.#publicKey).toString("hex") };
|
|
28
|
+
}
|
|
29
|
+
toString() {
|
|
30
|
+
return `InMemoryKeyProvider(pubkey=${Buffer.from(this.#publicKey).toString("hex")})`;
|
|
31
|
+
}
|
|
32
|
+
[INSPECT]() {
|
|
33
|
+
return this.toString();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export class FileKeyProvider {
|
|
37
|
+
#inner;
|
|
38
|
+
constructor(inner) {
|
|
39
|
+
this.#inner = inner;
|
|
40
|
+
}
|
|
41
|
+
static async load(path) {
|
|
42
|
+
// Attempt to read without existsSync to avoid TOCTOU: if the file disappears
|
|
43
|
+
// between a check and a read, readFile throws ENOENT — treated as "not found".
|
|
44
|
+
let raw = null;
|
|
45
|
+
try {
|
|
46
|
+
raw = await readFile(path);
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
const code = err.code;
|
|
50
|
+
if (code !== "ENOENT") {
|
|
51
|
+
throw { reason: "key_file_corrupt", message: `cannot read key file: ${err.message}` };
|
|
52
|
+
}
|
|
53
|
+
// ENOENT → fall through to generation
|
|
54
|
+
}
|
|
55
|
+
if (raw !== null) {
|
|
56
|
+
if (raw.length !== KEY_FILE_SIZE) {
|
|
57
|
+
throw { reason: "key_file_corrupt", message: `key file has wrong length: expected ${KEY_FILE_SIZE}, got ${raw.length}` };
|
|
58
|
+
}
|
|
59
|
+
for (let i = 0; i < KEY_FILE_MAGIC.length; i++) {
|
|
60
|
+
if (raw[i] !== KEY_FILE_MAGIC[i]) {
|
|
61
|
+
throw { reason: "key_file_corrupt", message: "key file has invalid magic bytes" };
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (raw[KEY_FILE_MAGIC.length] !== KEY_FILE_VERSION) {
|
|
65
|
+
throw { reason: "key_file_corrupt", message: `key file has unsupported version: ${raw[KEY_FILE_MAGIC.length]}` };
|
|
66
|
+
}
|
|
67
|
+
const seed = raw.slice(KEY_FILE_MAGIC.length + 1, KEY_FILE_MAGIC.length + 1 + SEED_BYTES);
|
|
68
|
+
return new FileKeyProvider(new InMemoryKeyProvider(seed));
|
|
69
|
+
}
|
|
70
|
+
// Generate and atomically write a new key file.
|
|
71
|
+
// Tmp file lives in the same directory as the target so rename() is same-filesystem.
|
|
72
|
+
const seed = randomBytes(SEED_BYTES);
|
|
73
|
+
const buf = Buffer.alloc(KEY_FILE_SIZE);
|
|
74
|
+
KEY_FILE_MAGIC.forEach((b, i) => { buf[i] = b; });
|
|
75
|
+
buf[KEY_FILE_MAGIC.length] = KEY_FILE_VERSION;
|
|
76
|
+
seed.forEach((b, i) => { buf[KEY_FILE_MAGIC.length + 1 + i] = b; });
|
|
77
|
+
const dir = dirname(path);
|
|
78
|
+
await mkdir(dir, { recursive: true });
|
|
79
|
+
const tmp = join(dir, `.cello-key-tmp-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
80
|
+
// Write to tmp fd with O_CREAT|O_EXCL, fchmod before close, then rename — so the file
|
|
81
|
+
// arrives at its final path with 0o600 already set (no post-rename chmod race window).
|
|
82
|
+
const fd = await fsOpen(tmp, "wx", 0o600);
|
|
83
|
+
try {
|
|
84
|
+
await fd.write(buf);
|
|
85
|
+
await fd.chmod(0o600);
|
|
86
|
+
}
|
|
87
|
+
finally {
|
|
88
|
+
await fd.close();
|
|
89
|
+
}
|
|
90
|
+
await rename(tmp, path);
|
|
91
|
+
return new FileKeyProvider(new InMemoryKeyProvider(seed));
|
|
92
|
+
}
|
|
93
|
+
async getPublicKey() {
|
|
94
|
+
return this.#inner.getPublicKey();
|
|
95
|
+
}
|
|
96
|
+
async sign(data) {
|
|
97
|
+
return this.#inner.sign(data);
|
|
98
|
+
}
|
|
99
|
+
toJSON() {
|
|
100
|
+
return { type: "FileKeyProvider", publicKey: this.#inner.toJSON().publicKey };
|
|
101
|
+
}
|
|
102
|
+
toString() {
|
|
103
|
+
return `FileKeyProvider(pubkey=${this.#inner.toJSON().publicKey})`;
|
|
104
|
+
}
|
|
105
|
+
[INSPECT]() {
|
|
106
|
+
return this.toString();
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
export function generateKeypair() {
|
|
110
|
+
return new InMemoryKeyProvider(randomBytes(SEED_BYTES));
|
|
111
|
+
}
|
|
112
|
+
export function verify(publicKey, data, signature) {
|
|
113
|
+
try {
|
|
114
|
+
return ed25519.verify(signature, data, publicKey);
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=ed25519.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ed25519.js","sourceRoot":"","sources":["../src/ed25519.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FrostThresholdSigner — FROST threshold signing over Ed25519 (RFC 9591)
|
|
3
|
+
*
|
|
4
|
+
* CELLO-CRYPTO-003
|
|
5
|
+
*
|
|
6
|
+
* Crypto reference: FROST / RFC 9591, Ed25519 / RFC 8032
|
|
7
|
+
* Implementation: @noble/curves/ed25519 — ed25519_FROST
|
|
8
|
+
*
|
|
9
|
+
* ─── Phase P: Pseudocode ─────────────────────────────────────────────────────
|
|
10
|
+
*
|
|
11
|
+
* bootstrapKeyShares(agentPubkey, config):
|
|
12
|
+
* // TEST-ONLY shortcut — NOT real multi-round DKG (that's M3)
|
|
13
|
+
* // Guard: only callable in NODE_ENV=test
|
|
14
|
+
* assert NODE_ENV === 'test'
|
|
15
|
+
* identifiers = [derive(stub.id) for stub in stubs]
|
|
16
|
+
* dealerShares = trustedDealer({ min: threshold, max: participants }, identifiers)
|
|
17
|
+
* // Distribute each stub its share (persists in stub.#key)
|
|
18
|
+
* for each stub, share in dealerShares.secretShares:
|
|
19
|
+
* stub.receiveShare(share, dealerShares.public)
|
|
20
|
+
* // primary_pubkey = commitments[0] from the shared public package
|
|
21
|
+
* primary_pubkey = dealerShares.public.commitments[0]
|
|
22
|
+
* // Persist client's local key share (stored in module-level map keyed by agentPubkey)
|
|
23
|
+
* storeLocalShare(agentPubkey, { share: agentShare, pub: dealerShares.public })
|
|
24
|
+
* return { primaryPubkey: primary_pubkey }
|
|
25
|
+
* // NOTE: signing share NEVER returned or logged
|
|
26
|
+
*
|
|
27
|
+
* FrostThresholdSigner.participateInCeremony(ceremonyId, tbs, context):
|
|
28
|
+
* // Coordinator flow — RFC 9591 Section 5
|
|
29
|
+
* frame(tbs, context) → msg = encode(context + '\0' + tbs) // domain separation
|
|
30
|
+
* localShare = loadLocalShare(agentPubkey)
|
|
31
|
+
* if localShare is null: throw "not bootstrapped"
|
|
32
|
+
* availableStubs = stubs (or directoryNodes via stream in production)
|
|
33
|
+
*
|
|
34
|
+
* // Attempt loop — up to maxRetries
|
|
35
|
+
* for attempt in 1..maxRetries (honoring ceremonyTimeout):
|
|
36
|
+
* reachableStubs = stubs where not excluded
|
|
37
|
+
* if |reachableStubs| < threshold: return DIRECTORY_BELOW_THRESHOLD
|
|
38
|
+
* selectedStubs = reachableStubs[0..threshold-1]
|
|
39
|
+
*
|
|
40
|
+
* // Round 1 — collect commitments (coordinator generates local nonce too)
|
|
41
|
+
* localNonce = commit(localShare.secret)
|
|
42
|
+
* commitments = [localNonce.commitments]
|
|
43
|
+
* for each stub in selectedStubs:
|
|
44
|
+
* c = stub.generateCommitment()
|
|
45
|
+
* commitments.push(c.commitment)
|
|
46
|
+
* commitmentList = sort(commitments, by identifier)
|
|
47
|
+
*
|
|
48
|
+
* // Round 2 — collect partial signatures (with per-node timeout)
|
|
49
|
+
* validShares = {}
|
|
50
|
+
* excludedInThisRound = []
|
|
51
|
+
* for each (stub, stubCommitment) in selectedStubs (with roundTimeout):
|
|
52
|
+
* partialSig = await stub.signRound(pub, commitmentList, msg) // timeout → null
|
|
53
|
+
* if partialSig is null: excludedInThisRound.push(stub); continue
|
|
54
|
+
* if !verifyShare(pub, commitmentList, msg, stub.id, partialSig):
|
|
55
|
+
* excludedInThisRound.push(stub); continue // invalid partial — same as timeout
|
|
56
|
+
* validShares[stub.id] = partialSig
|
|
57
|
+
*
|
|
58
|
+
* // Also compute coordinator's own partial sig
|
|
59
|
+
* coordinatorPartialSig = signShare(localShare.secret, pub, localNonce.nonces, commitmentList, msg)
|
|
60
|
+
* validShares[coordinatorId] = coordinatorPartialSig
|
|
61
|
+
*
|
|
62
|
+
* if |validShares| >= threshold:
|
|
63
|
+
* signature = aggregate(pub, commitmentList, msg, validShares)
|
|
64
|
+
* return { ok: true, signature }
|
|
65
|
+
* else:
|
|
66
|
+
* // Not enough valid shares — retry with different participants
|
|
67
|
+
* continue
|
|
68
|
+
*
|
|
69
|
+
* return { ok: false, error: { reason: 'CEREMONY_EXHAUSTED' } }
|
|
70
|
+
*
|
|
71
|
+
* primary_pubkey derivation:
|
|
72
|
+
* // In trustedDealer mode: commitments[0] is the group public key
|
|
73
|
+
* // This is the constant term of the dealer's Shamir polynomial commitment
|
|
74
|
+
* // It is deterministic given the dealer's secret polynomial
|
|
75
|
+
* // All participants' public shares verify against the same commitments[0]
|
|
76
|
+
* primary_pubkey = dealerShares.public.commitments[0]
|
|
77
|
+
*
|
|
78
|
+
* Round timeout / node replacement:
|
|
79
|
+
* // Each stub.signRound wraps in Promise.race([real, timeoutPromise])
|
|
80
|
+
* // If timeout wins → stub treated as excluded (same path as invalid sig)
|
|
81
|
+
* // On retry, excluded stubs are filtered from available pool
|
|
82
|
+
* // If available < threshold → DIRECTORY_BELOW_THRESHOLD (not retried)
|
|
83
|
+
*
|
|
84
|
+
* ─── End Pseudocode ──────────────────────────────────────────────────────────
|
|
85
|
+
*/
|
|
86
|
+
import type { FrostPublic, FrostSecret } from "@noble/curves/abstract/frost.js";
|
|
87
|
+
import type { IThresholdSigner, ThresholdSignature, FrostThresholdSignerConfig, BootstrapResult, FrostContext } from "./types.js";
|
|
88
|
+
import { CONTEXT_SESSION_ESTABLISHMENT, CONTEXT_SEAL } from "./types.js";
|
|
89
|
+
/**
|
|
90
|
+
* Clear all local key shares stored in the module-level map.
|
|
91
|
+
*
|
|
92
|
+
* TEST-ONLY: guards against accumulation of key material across test cases.
|
|
93
|
+
* Call in afterEach/afterAll to evict shares seeded by bootstrapKeyShares.
|
|
94
|
+
*
|
|
95
|
+
* Throws if called outside NODE_ENV=test so it can never be misused in
|
|
96
|
+
* production (where it would collapse multi-party FROST to zero-share state).
|
|
97
|
+
*/
|
|
98
|
+
export declare function clearTestShares(): void;
|
|
99
|
+
/**
|
|
100
|
+
* Store the client's local DKG key share after a real DKG ceremony completes.
|
|
101
|
+
*
|
|
102
|
+
* Production path: called after runNetworkDkg completes successfully.
|
|
103
|
+
* No NODE_ENV guard — this is the production key storage path (unlike bootstrapKeyShares).
|
|
104
|
+
*
|
|
105
|
+
* SECURITY: validates the secret against the public before storing.
|
|
106
|
+
* The FrostSecret is stored in the module-level map keyed by agentPubkeyHex.
|
|
107
|
+
*/
|
|
108
|
+
export declare function storeDkgResult(agentPubkeyHex: string, secret: FrostSecret, pub: FrostPublic): void;
|
|
109
|
+
/**
|
|
110
|
+
* Test-harness shortcut for key share bootstrap.
|
|
111
|
+
*
|
|
112
|
+
* GUARD: Only callable in NODE_ENV=test. This is NOT a real multi-round DKG
|
|
113
|
+
* (that comes in M3). It uses trustedDealer to pre-populate shares for testing.
|
|
114
|
+
*
|
|
115
|
+
* Behavior:
|
|
116
|
+
* 1. Generate FROST shares via trustedDealer for all n stub nodes
|
|
117
|
+
* 2. Distribute each stub its signing share
|
|
118
|
+
* 3. One of the identifiers is the "client" (coordinator) — its share is stored locally
|
|
119
|
+
* 4. primary_pubkey = commitments[0] from the shared public package
|
|
120
|
+
* 5. Return { primaryPubkey } — no key material beyond the group public key
|
|
121
|
+
*/
|
|
122
|
+
export declare function bootstrapKeyShares(agentPubkey: Uint8Array, config: FrostThresholdSignerConfig): Promise<BootstrapResult>;
|
|
123
|
+
export declare class FrostThresholdSigner implements IThresholdSigner {
|
|
124
|
+
#private;
|
|
125
|
+
constructor(config: FrostThresholdSignerConfig, agentPubkey: Uint8Array);
|
|
126
|
+
/**
|
|
127
|
+
* Get the group public key (primary_pubkey) for this signer.
|
|
128
|
+
* Returns the key from the stored local share (populated by bootstrapKeyShares).
|
|
129
|
+
*/
|
|
130
|
+
getPrimaryPubkey(): Uint8Array;
|
|
131
|
+
/**
|
|
132
|
+
* Verify a threshold signature against a public key and TBS with context.
|
|
133
|
+
* Used by callers (and tests) to verify signatures produced by participateInCeremony.
|
|
134
|
+
*/
|
|
135
|
+
verifySignature(signature: Uint8Array, tbs: Uint8Array, context: string, publicKey: Uint8Array): boolean;
|
|
136
|
+
/**
|
|
137
|
+
* Participate in a FROST threshold signing ceremony as coordinator.
|
|
138
|
+
*
|
|
139
|
+
* RFC 9591 Section 5 coordinator flow with in-process stubs.
|
|
140
|
+
* Full round coordination, timeout handling, and participant exclusion.
|
|
141
|
+
*/
|
|
142
|
+
participateInCeremony(ceremonyId: string, tbs: Uint8Array, context: FrostContext, onProgress?: import("./types.js").CeremonyProgressCallback): Promise<ThresholdSignature>;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Verify a FROST threshold signature without a signer instance.
|
|
146
|
+
*
|
|
147
|
+
* Used by the client when it is the counterparty (participant B) and has no
|
|
148
|
+
* IThresholdSigner injected. Verifies the domain-separated FROST signature
|
|
149
|
+
* against the provided public key.
|
|
150
|
+
*
|
|
151
|
+
* @param signature - 64-byte threshold signature from the SessionAssignment
|
|
152
|
+
* @param tbs - to-be-signed bytes (from buildSessionEstablishmentTbs)
|
|
153
|
+
* @param context - domain context string (e.g. CONTEXT_SESSION_ESTABLISHMENT)
|
|
154
|
+
* @param publicKey - 32-byte Ed25519 group public key to verify against
|
|
155
|
+
* @returns true if signature verifies; false otherwise (never throws)
|
|
156
|
+
*/
|
|
157
|
+
export declare function verifyFrostSignature(signature: Uint8Array, tbs: Uint8Array, context: string, publicKey: Uint8Array): boolean;
|
|
158
|
+
/**
|
|
159
|
+
* MockThresholdSigner: confirms the IThresholdSigner swap point is real.
|
|
160
|
+
*
|
|
161
|
+
* Implements IThresholdSigner without any FROST crypto. Used by AC-010 to
|
|
162
|
+
* verify that callers work correctly against the interface without knowing
|
|
163
|
+
* the concrete implementation.
|
|
164
|
+
*
|
|
165
|
+
* Returns a deterministic 64-byte signature (not cryptographically valid,
|
|
166
|
+
* but structurally correct for interface tests).
|
|
167
|
+
*/
|
|
168
|
+
export declare class MockThresholdSigner implements IThresholdSigner {
|
|
169
|
+
participateInCeremony(_ceremonyId: string, tbs: Uint8Array, _context: FrostContext, _onProgress?: import("./types.js").CeremonyProgressCallback): Promise<ThresholdSignature>;
|
|
170
|
+
/**
|
|
171
|
+
* Return a deterministic 32-byte mock primary pubkey.
|
|
172
|
+
* Not a real Ed25519 point — only for interface shape testing.
|
|
173
|
+
*/
|
|
174
|
+
getPrimaryPubkey(): Uint8Array;
|
|
175
|
+
verifySignature(_signature: Uint8Array, _tbs: Uint8Array, _context: FrostContext, _publicKey: Uint8Array): boolean;
|
|
176
|
+
}
|
|
177
|
+
export { CONTEXT_SESSION_ESTABLISHMENT, CONTEXT_SEAL };
|
|
178
|
+
//# sourceMappingURL=frost-threshold-signer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frost-threshold-signer.d.ts","sourceRoot":"","sources":["../../src/frost/frost-threshold-signer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoFG;AAGH,OAAO,KAAK,EACV,WAAW,EACX,WAAW,EACZ,MAAM,iCAAiC,CAAC;AACzC,OAAO,KAAK,EACV,gBAAgB,EAChB,kBAAkB,EAClB,0BAA0B,EAE1B,eAAe,EACf,YAAY,EACb,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,6BAA6B,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAgBzE;;;;;;;;GAQG;AACH,wBAAgB,eAAe,IAAI,IAAI,CAKtC;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,WAAW,EACnB,GAAG,EAAE,WAAW,GACf,IAAI,CAGN;AA+BD;;;;;;;;;;;;GAYG;AACH,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,UAAU,EACvB,MAAM,EAAE,0BAA0B,GACjC,OAAO,CAAC,eAAe,CAAC,CAwD1B;AAID,qBAAa,oBAAqB,YAAW,gBAAgB;;gBAa/C,MAAM,EAAE,0BAA0B,EAAE,WAAW,EAAE,UAAU;IAgBvE;;;OAGG;IACH,gBAAgB,IAAI,UAAU;IAU9B;;;OAGG;IACH,eAAe,CACb,SAAS,EAAE,UAAU,EACrB,GAAG,EAAE,UAAU,EACf,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,UAAU,GACpB,OAAO;IASV;;;;;OAKG;IACG,qBAAqB,CACzB,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,UAAU,EACf,OAAO,EAAE,YAAY,EACrB,UAAU,CAAC,EAAE,OAAO,YAAY,EAAE,wBAAwB,GACzD,OAAO,CAAC,kBAAkB,CAAC;CA2M/B;AAID;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,UAAU,EACrB,GAAG,EAAE,UAAU,EACf,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,UAAU,GACpB,OAAO,CAOT;AAID;;;;;;;;;GASG;AACH,qBAAa,mBAAoB,YAAW,gBAAgB;IACpD,qBAAqB,CACzB,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,UAAU,EACf,QAAQ,EAAE,YAAY,EACtB,WAAW,CAAC,EAAE,OAAO,YAAY,EAAE,wBAAwB,GAC1D,OAAO,CAAC,kBAAkB,CAAC;IAW9B;;;OAGG;IACH,gBAAgB,IAAI,UAAU;IAO9B,eAAe,CACb,UAAU,EAAE,UAAU,EACtB,IAAI,EAAE,UAAU,EAChB,QAAQ,EAAE,YAAY,EACtB,UAAU,EAAE,UAAU,GACrB,OAAO;CAIX;AAGD,OAAO,EAAE,6BAA6B,EAAE,YAAY,EAAE,CAAC"}
|