@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.
Files changed (49) hide show
  1. package/dist/checkpoint.d.ts +52 -0
  2. package/dist/checkpoint.d.ts.map +1 -0
  3. package/dist/checkpoint.js +70 -0
  4. package/dist/checkpoint.js.map +1 -0
  5. package/dist/ed25519.d.ts +25 -0
  6. package/dist/ed25519.d.ts.map +1 -0
  7. package/dist/ed25519.js +120 -0
  8. package/dist/ed25519.js.map +1 -0
  9. package/dist/frost/frost-threshold-signer.d.ts +178 -0
  10. package/dist/frost/frost-threshold-signer.d.ts.map +1 -0
  11. package/dist/frost/frost-threshold-signer.js +478 -0
  12. package/dist/frost/frost-threshold-signer.js.map +1 -0
  13. package/dist/frost/index.d.ts +23 -0
  14. package/dist/frost/index.d.ts.map +1 -0
  15. package/dist/frost/index.js +22 -0
  16. package/dist/frost/index.js.map +1 -0
  17. package/dist/frost/stubs.d.ts +82 -0
  18. package/dist/frost/stubs.d.ts.map +1 -0
  19. package/dist/frost/stubs.js +157 -0
  20. package/dist/frost/stubs.js.map +1 -0
  21. package/dist/frost/types.d.ts +173 -0
  22. package/dist/frost/types.d.ts.map +1 -0
  23. package/dist/frost/types.js +21 -0
  24. package/dist/frost/types.js.map +1 -0
  25. package/dist/hashing.d.ts +17 -0
  26. package/dist/hashing.d.ts.map +1 -0
  27. package/dist/hashing.js +50 -0
  28. package/dist/hashing.js.map +1 -0
  29. package/dist/index.d.ts +14 -0
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/index.js +14 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/merkle.d.ts +162 -0
  34. package/dist/merkle.d.ts.map +1 -0
  35. package/dist/merkle.js +240 -0
  36. package/dist/merkle.js.map +1 -0
  37. package/dist/ml-dsa.d.ts +100 -0
  38. package/dist/ml-dsa.d.ts.map +1 -0
  39. package/dist/ml-dsa.js +257 -0
  40. package/dist/ml-dsa.js.map +1 -0
  41. package/dist/relay-registration.d.ts +62 -0
  42. package/dist/relay-registration.d.ts.map +1 -0
  43. package/dist/relay-registration.js +87 -0
  44. package/dist/relay-registration.js.map +1 -0
  45. package/dist/types.d.ts +11 -0
  46. package/dist/types.d.ts.map +1 -0
  47. package/dist/types.js +2 -0
  48. package/dist/types.js.map +1 -0
  49. package/package.json +49 -0
@@ -0,0 +1,62 @@
1
+ /**
2
+ * FEDERATION-003 — Relay registration TBS (to-be-signed) serialization and signature verification.
3
+ *
4
+ * buildRelayRegistrationTbs produces the canonical byte representation for a relay
5
+ * registration self-signature:
6
+ *
7
+ * TBS = SHA-256(relay_id_bytes || public_key_hex_bytes || timestamp_BE8)
8
+ *
9
+ * where:
10
+ * relay_id_bytes: UTF-8 encoding of the relay_id string
11
+ * public_key_hex_bytes: UTF-8 encoding of the public_key_hex string
12
+ * timestamp_BE8: Unix millisecond timestamp as 8-byte big-endian uint64
13
+ *
14
+ * SI-003: This TBS must be used by both the relay (which signs) and the directory
15
+ * (which verifies). Keeping it in @cello-protocol/crypto ensures neither side can diverge.
16
+ *
17
+ * verifyRelayRegistrationSignature verifies that the signature was produced by the
18
+ * private key corresponding to publicKeyHex, preventing an attacker from registering
19
+ * a relay_id for a key they do not control.
20
+ *
21
+ * References: RFC 8032 (Ed25519), FIPS 180-4 (SHA-256).
22
+ */
23
+ /**
24
+ * Build the canonical TBS bytes for a relay registration self-signature.
25
+ *
26
+ * Pseudocode (SPARC Phase P):
27
+ * 1. UTF-8 encode relay_id as relayIdBytes
28
+ * 2. UTF-8 encode public_key_hex as pubKeyHexBytes
29
+ * 3. Encode timestamp as 8-byte big-endian uint64 (BigInt, safe for Unix ms)
30
+ * 4. Concatenate: relayIdBytes || pubKeyHexBytes || timestamp_BE8
31
+ * 5. SHA-256(concatenation) — FIPS 180-4
32
+ * 6. Return 32-byte digest as Uint8Array
33
+ *
34
+ * @param relayId - The relay identifier (hex encoding of the relay's Ed25519 public key)
35
+ * @param publicKeyHex - 64-char hex string of the relay's Ed25519 public key
36
+ * @param timestamp - Unix millisecond timestamp at registration time
37
+ * @returns 32-byte SHA-256 digest — FIPS 180-4
38
+ */
39
+ export declare function buildRelayRegistrationTbs(relayId: string, publicKeyHex: string, timestamp: number): Uint8Array;
40
+ /**
41
+ * Verify a relay registration self-signature.
42
+ *
43
+ * SI-003: The relay signs the registration TBS with its Ed25519 private key.
44
+ * The directory verifies against the public_key_hex submitted in the request.
45
+ * Only a caller that controls the private key corresponding to public_key_hex
46
+ * can produce a valid signature.
47
+ *
48
+ * Pseudocode:
49
+ * 1. Decode publicKeyHex as 32 bytes
50
+ * 2. Compute tbs = buildRelayRegistrationTbs(relayId, publicKeyHex, timestamp)
51
+ * 3. Return ed25519.verify(signature, tbs, publicKeyBytes)
52
+ * — RFC 8032 §5.1.7 verify algorithm
53
+ *
54
+ * @param publicKeyHex - 64-char hex string of the relay's submitted Ed25519 public key
55
+ * @param relayId - The relay identifier submitted in the registration request
56
+ * @param publicKeyHexInTbs - The public_key_hex value used in the TBS (must match publicKeyHex)
57
+ * @param timestamp - The Unix millisecond timestamp from the registration request
58
+ * @param signature - 64-byte Ed25519 signature from the relay
59
+ * @returns true if signature is valid, false otherwise
60
+ */
61
+ export declare function verifyRelayRegistrationSignature(publicKeyHex: string, relayId: string, publicKeyHexInTbs: string, timestamp: number, signature: Uint8Array): Promise<boolean>;
62
+ //# sourceMappingURL=relay-registration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relay-registration.d.ts","sourceRoot":"","sources":["../src/relay-registration.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAKH;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,GAChB,UAAU,CAeZ;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,gCAAgC,CACpD,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,MAAM,EACf,iBAAiB,EAAE,MAAM,EACzB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,UAAU,GACpB,OAAO,CAAC,OAAO,CAAC,CAWlB"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * FEDERATION-003 — Relay registration TBS (to-be-signed) serialization and signature verification.
3
+ *
4
+ * buildRelayRegistrationTbs produces the canonical byte representation for a relay
5
+ * registration self-signature:
6
+ *
7
+ * TBS = SHA-256(relay_id_bytes || public_key_hex_bytes || timestamp_BE8)
8
+ *
9
+ * where:
10
+ * relay_id_bytes: UTF-8 encoding of the relay_id string
11
+ * public_key_hex_bytes: UTF-8 encoding of the public_key_hex string
12
+ * timestamp_BE8: Unix millisecond timestamp as 8-byte big-endian uint64
13
+ *
14
+ * SI-003: This TBS must be used by both the relay (which signs) and the directory
15
+ * (which verifies). Keeping it in @cello-protocol/crypto ensures neither side can diverge.
16
+ *
17
+ * verifyRelayRegistrationSignature verifies that the signature was produced by the
18
+ * private key corresponding to publicKeyHex, preventing an attacker from registering
19
+ * a relay_id for a key they do not control.
20
+ *
21
+ * References: RFC 8032 (Ed25519), FIPS 180-4 (SHA-256).
22
+ */
23
+ import { createHash } from "node:crypto";
24
+ import { ed25519 } from "@noble/curves/ed25519.js";
25
+ /**
26
+ * Build the canonical TBS bytes for a relay registration self-signature.
27
+ *
28
+ * Pseudocode (SPARC Phase P):
29
+ * 1. UTF-8 encode relay_id as relayIdBytes
30
+ * 2. UTF-8 encode public_key_hex as pubKeyHexBytes
31
+ * 3. Encode timestamp as 8-byte big-endian uint64 (BigInt, safe for Unix ms)
32
+ * 4. Concatenate: relayIdBytes || pubKeyHexBytes || timestamp_BE8
33
+ * 5. SHA-256(concatenation) — FIPS 180-4
34
+ * 6. Return 32-byte digest as Uint8Array
35
+ *
36
+ * @param relayId - The relay identifier (hex encoding of the relay's Ed25519 public key)
37
+ * @param publicKeyHex - 64-char hex string of the relay's Ed25519 public key
38
+ * @param timestamp - Unix millisecond timestamp at registration time
39
+ * @returns 32-byte SHA-256 digest — FIPS 180-4
40
+ */
41
+ export function buildRelayRegistrationTbs(relayId, publicKeyHex, timestamp) {
42
+ const encoder = new TextEncoder();
43
+ const relayIdBytes = encoder.encode(relayId);
44
+ const pubKeyHexBytes = encoder.encode(publicKeyHex);
45
+ const tsBuf = Buffer.allocUnsafe(8);
46
+ tsBuf.writeBigUInt64BE(BigInt(timestamp), 0);
47
+ const preimage = Buffer.concat([
48
+ Buffer.from(relayIdBytes),
49
+ Buffer.from(pubKeyHexBytes),
50
+ tsBuf,
51
+ ]);
52
+ return new Uint8Array(createHash("sha256").update(preimage).digest());
53
+ }
54
+ /**
55
+ * Verify a relay registration self-signature.
56
+ *
57
+ * SI-003: The relay signs the registration TBS with its Ed25519 private key.
58
+ * The directory verifies against the public_key_hex submitted in the request.
59
+ * Only a caller that controls the private key corresponding to public_key_hex
60
+ * can produce a valid signature.
61
+ *
62
+ * Pseudocode:
63
+ * 1. Decode publicKeyHex as 32 bytes
64
+ * 2. Compute tbs = buildRelayRegistrationTbs(relayId, publicKeyHex, timestamp)
65
+ * 3. Return ed25519.verify(signature, tbs, publicKeyBytes)
66
+ * — RFC 8032 §5.1.7 verify algorithm
67
+ *
68
+ * @param publicKeyHex - 64-char hex string of the relay's submitted Ed25519 public key
69
+ * @param relayId - The relay identifier submitted in the registration request
70
+ * @param publicKeyHexInTbs - The public_key_hex value used in the TBS (must match publicKeyHex)
71
+ * @param timestamp - The Unix millisecond timestamp from the registration request
72
+ * @param signature - 64-byte Ed25519 signature from the relay
73
+ * @returns true if signature is valid, false otherwise
74
+ */
75
+ export async function verifyRelayRegistrationSignature(publicKeyHex, relayId, publicKeyHexInTbs, timestamp, signature) {
76
+ try {
77
+ const publicKeyBytes = Buffer.from(publicKeyHex, "hex");
78
+ if (publicKeyBytes.length !== 32)
79
+ return false;
80
+ const tbs = buildRelayRegistrationTbs(relayId, publicKeyHexInTbs, timestamp);
81
+ return ed25519.verify(signature, tbs, publicKeyBytes);
82
+ }
83
+ catch {
84
+ return false;
85
+ }
86
+ }
87
+ //# sourceMappingURL=relay-registration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relay-registration.js","sourceRoot":"","sources":["../src/relay-registration.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAEnD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,yBAAyB,CACvC,OAAe,EACf,YAAoB,EACpB,SAAiB;IAEjB,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAClC,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC7C,MAAM,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IAEpD,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IACpC,KAAK,CAAC,gBAAgB,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC;IAE7C,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC;QAC7B,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC;QACzB,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC;QAC3B,KAAK;KACN,CAAC,CAAC;IAEH,OAAO,IAAI,UAAU,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;AACxE,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,KAAK,UAAU,gCAAgC,CACpD,YAAoB,EACpB,OAAe,EACf,iBAAyB,EACzB,SAAiB,EACjB,SAAqB;IAErB,IAAI,CAAC;QACH,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;QACxD,IAAI,cAAc,CAAC,MAAM,KAAK,EAAE;YAAE,OAAO,KAAK,CAAC;QAE/C,MAAM,GAAG,GAAG,yBAAyB,CAAC,OAAO,EAAE,iBAAiB,EAAE,SAAS,CAAC,CAAC;QAE7E,OAAO,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,GAAG,EAAE,cAAc,CAAC,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -0,0 +1,11 @@
1
+ export type PublicKey = Uint8Array;
2
+ export type Signature = Uint8Array;
3
+ export interface KeyProvider {
4
+ getPublicKey(): Promise<PublicKey>;
5
+ sign(data: Uint8Array): Promise<Signature>;
6
+ }
7
+ export interface KeyFileCorruptError {
8
+ reason: "key_file_corrupt";
9
+ message: string;
10
+ }
11
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC;AACnC,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC;AAEnC,MAAM,WAAW,WAAW;IAC1B,YAAY,IAAI,OAAO,CAAC,SAAS,CAAC,CAAC;IACnC,IAAI,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;CAC5C;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,kBAAkB,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;CACjB"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@cello-protocol/crypto",
3
+ "version": "0.0.2",
4
+ "private": false,
5
+ "type": "module",
6
+ "engines": {
7
+ "node": ">=24"
8
+ },
9
+ "publishConfig": {
10
+ "access": "public"
11
+ },
12
+ "main": "./dist/index.js",
13
+ "types": "./dist/index.d.ts",
14
+ "exports": {
15
+ ".": {
16
+ "import": "./dist/index.js",
17
+ "types": "./dist/index.d.ts"
18
+ },
19
+ "./frost/frost-threshold-signer.js": {
20
+ "import": "./dist/frost/frost-threshold-signer.js",
21
+ "types": "./dist/frost/frost-threshold-signer.d.ts"
22
+ },
23
+ "./frost/stubs.js": {
24
+ "import": "./dist/frost/stubs.js",
25
+ "types": "./dist/frost/stubs.d.ts"
26
+ },
27
+ "./frost/types.js": {
28
+ "import": "./dist/frost/types.js",
29
+ "types": "./dist/frost/types.d.ts"
30
+ }
31
+ },
32
+ "files": [
33
+ "dist/",
34
+ "package.json"
35
+ ],
36
+ "dependencies": {
37
+ "@noble/curves": "2.2.0",
38
+ "@noble/hashes": "2.2.0",
39
+ "@oqs/liboqs-js": "^0.15.1"
40
+ },
41
+ "devDependencies": {
42
+ "@claude-flow/testing": "3.0.0-alpha.6",
43
+ "@types/node": "^25.6.2"
44
+ },
45
+ "scripts": {
46
+ "typecheck": "tsc --build",
47
+ "test": "vitest run"
48
+ }
49
+ }