@plane31/blind-relay 0.0.0-stage → 0.1.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 (169) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +26 -2
  3. package/dist/adapters/index.d.ts +18 -0
  4. package/dist/adapters/index.d.ts.map +1 -0
  5. package/dist/adapters/index.js +22 -0
  6. package/dist/adapters/index.js.map +1 -0
  7. package/dist/audience.d.ts +77 -0
  8. package/dist/audience.d.ts.map +1 -0
  9. package/dist/audience.js +76 -0
  10. package/dist/audience.js.map +1 -0
  11. package/dist/bytes.d.ts +54 -0
  12. package/dist/bytes.d.ts.map +1 -0
  13. package/dist/bytes.js +200 -0
  14. package/dist/bytes.js.map +1 -0
  15. package/dist/circle.d.ts +59 -0
  16. package/dist/circle.d.ts.map +1 -0
  17. package/dist/circle.js +105 -0
  18. package/dist/circle.js.map +1 -0
  19. package/dist/client.d.ts +234 -0
  20. package/dist/client.d.ts.map +1 -0
  21. package/dist/client.js +1365 -0
  22. package/dist/client.js.map +1 -0
  23. package/dist/codec.d.ts +189 -0
  24. package/dist/codec.d.ts.map +1 -0
  25. package/dist/codec.js +512 -0
  26. package/dist/codec.js.map +1 -0
  27. package/dist/crypto/backend.d.ts +39 -0
  28. package/dist/crypto/backend.d.ts.map +1 -0
  29. package/dist/crypto/backend.js +8 -0
  30. package/dist/crypto/backend.js.map +1 -0
  31. package/dist/crypto/noble.d.ts +3 -0
  32. package/dist/crypto/noble.d.ts.map +1 -0
  33. package/dist/crypto/noble.js +107 -0
  34. package/dist/crypto/noble.js.map +1 -0
  35. package/dist/crypto/sodium.d.ts +9 -0
  36. package/dist/crypto/sodium.d.ts.map +1 -0
  37. package/dist/crypto/sodium.js +51 -0
  38. package/dist/crypto/sodium.js.map +1 -0
  39. package/dist/crypto.d.ts +66 -0
  40. package/dist/crypto.d.ts.map +1 -0
  41. package/dist/crypto.js +225 -0
  42. package/dist/crypto.js.map +1 -0
  43. package/dist/epoch.d.ts +93 -0
  44. package/dist/epoch.d.ts.map +1 -0
  45. package/dist/epoch.js +121 -0
  46. package/dist/epoch.js.map +1 -0
  47. package/dist/errors.d.ts +17 -0
  48. package/dist/errors.d.ts.map +1 -0
  49. package/dist/errors.js +30 -0
  50. package/dist/errors.js.map +1 -0
  51. package/dist/historyIndex.d.ts +15 -0
  52. package/dist/historyIndex.d.ts.map +1 -0
  53. package/dist/historyIndex.js +57 -0
  54. package/dist/historyIndex.js.map +1 -0
  55. package/dist/identity.d.ts +62 -0
  56. package/dist/identity.d.ts.map +1 -0
  57. package/dist/identity.js +99 -0
  58. package/dist/identity.js.map +1 -0
  59. package/dist/inbox.d.ts +153 -0
  60. package/dist/inbox.d.ts.map +1 -0
  61. package/dist/inbox.js +472 -0
  62. package/dist/inbox.js.map +1 -0
  63. package/dist/index.d.ts +19 -0
  64. package/dist/index.d.ts.map +1 -0
  65. package/dist/index.js +22 -0
  66. package/dist/index.js.map +1 -0
  67. package/dist/outbox.d.ts +96 -0
  68. package/dist/outbox.d.ts.map +1 -0
  69. package/dist/outbox.js +339 -0
  70. package/dist/outbox.js.map +1 -0
  71. package/dist/policy.d.ts +33 -0
  72. package/dist/policy.d.ts.map +1 -0
  73. package/dist/policy.js +71 -0
  74. package/dist/policy.js.map +1 -0
  75. package/dist/record.d.ts +49 -0
  76. package/dist/record.d.ts.map +1 -0
  77. package/dist/record.js +46 -0
  78. package/dist/record.js.map +1 -0
  79. package/dist/reset.d.ts +74 -0
  80. package/dist/reset.d.ts.map +1 -0
  81. package/dist/reset.js +127 -0
  82. package/dist/reset.js.map +1 -0
  83. package/dist/rows.d.ts +16 -0
  84. package/dist/rows.d.ts.map +1 -0
  85. package/dist/rows.js +103 -0
  86. package/dist/rows.js.map +1 -0
  87. package/dist/slots.d.ts +22 -0
  88. package/dist/slots.d.ts.map +1 -0
  89. package/dist/slots.js +38 -0
  90. package/dist/slots.js.map +1 -0
  91. package/dist/store.d.ts +357 -0
  92. package/dist/store.d.ts.map +1 -0
  93. package/dist/store.js +192 -0
  94. package/dist/store.js.map +1 -0
  95. package/dist/testing/clock.d.ts +14 -0
  96. package/dist/testing/clock.d.ts.map +1 -0
  97. package/dist/testing/clock.js +27 -0
  98. package/dist/testing/clock.js.map +1 -0
  99. package/dist/testing/fakeHost.d.ts +118 -0
  100. package/dist/testing/fakeHost.d.ts.map +1 -0
  101. package/dist/testing/fakeHost.js +462 -0
  102. package/dist/testing/fakeHost.js.map +1 -0
  103. package/dist/testing/faults.d.ts +97 -0
  104. package/dist/testing/faults.d.ts.map +1 -0
  105. package/dist/testing/faults.js +264 -0
  106. package/dist/testing/faults.js.map +1 -0
  107. package/dist/testing/fixtures.d.ts +15 -0
  108. package/dist/testing/fixtures.d.ts.map +1 -0
  109. package/dist/testing/fixtures.js +22 -0
  110. package/dist/testing/fixtures.js.map +1 -0
  111. package/dist/testing/index.d.ts +7 -0
  112. package/dist/testing/index.d.ts.map +1 -0
  113. package/dist/testing/index.js +7 -0
  114. package/dist/testing/index.js.map +1 -0
  115. package/dist/testing/providers.d.ts +16 -0
  116. package/dist/testing/providers.d.ts.map +1 -0
  117. package/dist/testing/providers.js +36 -0
  118. package/dist/testing/providers.js.map +1 -0
  119. package/dist/testing/sweep.d.ts +46 -0
  120. package/dist/testing/sweep.d.ts.map +1 -0
  121. package/dist/testing/sweep.js +366 -0
  122. package/dist/testing/sweep.js.map +1 -0
  123. package/dist/transactions.d.ts +75 -0
  124. package/dist/transactions.d.ts.map +1 -0
  125. package/dist/transactions.js +212 -0
  126. package/dist/transactions.js.map +1 -0
  127. package/dist/transport.d.ts +125 -0
  128. package/dist/transport.d.ts.map +1 -0
  129. package/dist/transport.js +6 -0
  130. package/dist/transport.js.map +1 -0
  131. package/dist/vault.d.ts +59 -0
  132. package/dist/vault.d.ts.map +1 -0
  133. package/dist/vault.js +69 -0
  134. package/dist/vault.js.map +1 -0
  135. package/package.json +67 -3
  136. package/src/adapters/index.ts +102 -0
  137. package/src/audience.ts +123 -0
  138. package/src/bytes.ts +209 -0
  139. package/src/circle.ts +127 -0
  140. package/src/client.ts +1442 -0
  141. package/src/codec.ts +642 -0
  142. package/src/crypto/backend.ts +48 -0
  143. package/src/crypto/noble.ts +104 -0
  144. package/src/crypto/node-module.d.ts +11 -0
  145. package/src/crypto/sodium.ts +53 -0
  146. package/src/crypto.ts +266 -0
  147. package/src/epoch.ts +201 -0
  148. package/src/errors.ts +78 -0
  149. package/src/historyIndex.ts +61 -0
  150. package/src/identity.ts +158 -0
  151. package/src/inbox.ts +560 -0
  152. package/src/index.ts +59 -0
  153. package/src/outbox.ts +385 -0
  154. package/src/policy.ts +88 -0
  155. package/src/record.ts +106 -0
  156. package/src/reset.ts +176 -0
  157. package/src/rows.ts +116 -0
  158. package/src/slots.ts +55 -0
  159. package/src/store.ts +557 -0
  160. package/src/testing/clock.ts +29 -0
  161. package/src/testing/fakeHost.ts +482 -0
  162. package/src/testing/faults.ts +321 -0
  163. package/src/testing/fixtures.ts +35 -0
  164. package/src/testing/index.ts +6 -0
  165. package/src/testing/providers.ts +39 -0
  166. package/src/testing/sweep.ts +407 -0
  167. package/src/transactions.ts +231 -0
  168. package/src/transport.ts +106 -0
  169. package/src/vault.ts +126 -0
@@ -0,0 +1,107 @@
1
+ /** The portable backend over the noble libraries (audited pure JavaScript). */
2
+ import { xchacha20poly1305 } from "@noble/ciphers/chacha";
3
+ import { hsalsa, xsalsa20poly1305 } from "@noble/ciphers/salsa";
4
+ import { ed25519, x25519 } from "@noble/curves/ed25519";
5
+ import { blake2b } from "@noble/hashes/blake2b";
6
+ import { sha512 } from "@noble/hashes/sha512";
7
+ import { randomBytes } from "@noble/hashes/utils";
8
+ // "expand 32-byte k" as little-endian u32 words: the Salsa constant.
9
+ const SIGMA = new Uint32Array([0x61707865, 0x3320646e, 0x79622d32, 0x6b206574]);
10
+ function u32(bytes) {
11
+ const out = new Uint32Array(bytes.length / 4);
12
+ const dv = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
13
+ for (let i = 0; i < out.length; i++)
14
+ out[i] = dv.getUint32(i * 4, true);
15
+ return out;
16
+ }
17
+ function fromU32(words) {
18
+ const out = new Uint8Array(words.length * 4);
19
+ const dv = new DataView(out.buffer);
20
+ for (let i = 0; i < words.length; i++)
21
+ dv.setUint32(i * 4, words[i] ?? 0, true);
22
+ return out;
23
+ }
24
+ /** `crypto_box_beforenm`: HSalsa20 of the X25519 shared secret with a zero nonce. */
25
+ function beforeNm(publicKey, secretKey) {
26
+ const shared = x25519.getSharedSecret(secretKey, publicKey);
27
+ const out = new Uint32Array(8);
28
+ hsalsa(SIGMA, u32(shared), u32(new Uint8Array(16)), out);
29
+ return fromU32(out);
30
+ }
31
+ function isCanonicalY(bytes) {
32
+ // y < 2^255 - 19, read little-endian with the sign bit cleared.
33
+ const y = Uint8Array.from(bytes);
34
+ y[31] = (y[31] ?? 0) & 0x7f;
35
+ const P = Uint8Array.from([
36
+ 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f
37
+ ]);
38
+ for (let i = 31; i >= 0; i--) {
39
+ const a = y[i] ?? 0;
40
+ const b = P[i] ?? 0;
41
+ if (a < b)
42
+ return true;
43
+ if (a > b)
44
+ return false;
45
+ }
46
+ return false;
47
+ }
48
+ export const nobleBackend = {
49
+ name: "noble",
50
+ blake2b: (data, outLen, key) => blake2b(data, key ? { dkLen: outLen, key } : { dkLen: outLen }),
51
+ randomBytes: (length) => randomBytes(length),
52
+ signKeypairFromSeed(seed) {
53
+ const publicKey = ed25519.getPublicKey(seed);
54
+ const secretKey = new Uint8Array(64);
55
+ secretKey.set(seed, 0);
56
+ secretKey.set(publicKey, 32);
57
+ return { publicKey, secretKey };
58
+ },
59
+ signDetached: (message, secretKey) => ed25519.sign(message, secretKey.subarray(0, 32)),
60
+ verifyDetached(signature, message, publicKey) {
61
+ try {
62
+ return ed25519.verify(signature, message, publicKey, { zip215: false });
63
+ }
64
+ catch {
65
+ return false;
66
+ }
67
+ },
68
+ isValidSignPoint(publicKey) {
69
+ if (publicKey.length !== 32 || !isCanonicalY(publicKey))
70
+ return false;
71
+ try {
72
+ const p = ed25519.ExtendedPoint.fromHex(publicKey);
73
+ p.assertValidity();
74
+ return !p.equals(ed25519.ExtendedPoint.ZERO) && !p.isSmallOrder() && p.isTorsionFree();
75
+ }
76
+ catch {
77
+ return false;
78
+ }
79
+ },
80
+ boxKeypairFromSeed(seed) {
81
+ const secretKey = sha512(seed).slice(0, 32);
82
+ return { publicKey: x25519.getPublicKey(secretKey), secretKey };
83
+ },
84
+ boxKeypair() {
85
+ const secretKey = randomBytes(32);
86
+ return { publicKey: x25519.getPublicKey(secretKey), secretKey };
87
+ },
88
+ scalarMult(secretKey, publicKey) {
89
+ const shared = x25519.getSharedSecret(secretKey, publicKey); // throws on an all-zero result
90
+ let acc = 0;
91
+ for (const b of shared)
92
+ acc |= b;
93
+ if (acc === 0)
94
+ throw new Error("low-order point");
95
+ return shared;
96
+ },
97
+ boxEasy(message, nonce, publicKey, secretKey) {
98
+ return xsalsa20poly1305(beforeNm(publicKey, secretKey), nonce).encrypt(message); // mac || ciphertext
99
+ },
100
+ boxOpenEasy(box, nonce, publicKey, secretKey) {
101
+ return xsalsa20poly1305(beforeNm(publicKey, secretKey), nonce).decrypt(box);
102
+ },
103
+ aeadEncrypt: (plaintext, aad, nonce, key) => xchacha20poly1305(key, nonce, aad).encrypt(plaintext),
104
+ aeadDecrypt: (ciphertextAndTag, aad, nonce, key) => xchacha20poly1305(key, nonce, aad).decrypt(ciphertextAndTag),
105
+ memzero: (bytes) => bytes.fill(0)
106
+ };
107
+ //# sourceMappingURL=noble.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"noble.js","sourceRoot":"","sources":["../../src/crypto/noble.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { CryptoBackend } from "./backend.js";
2
+ /**
3
+ * Node only. The wrapper is loaded through its `require` condition, the CommonJS build, which is
4
+ * self-contained; its ESM build has shipped broken (0.7.16 imports a sibling file the package does
5
+ * not contain), and a consumer's plain `import` would hit that. The release smoke test loads this
6
+ * entry from the packed tarball in a clean Node to keep it so.
7
+ */
8
+ export declare function loadSodiumBackend(): Promise<CryptoBackend>;
9
+ //# sourceMappingURL=sodium.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sodium.d.ts","sourceRoot":"","sources":["../../src/crypto/sodium.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAc,aAAa,EAAe,MAAM,cAAc,CAAC;AAI3E;;;;;GAKG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,aAAa,CAAC,CAqChE"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * The libsodium backend (wasm). Loaded only when asked for, so the default bundle never carries
3
+ * the wasm; use it on Node, where it is faster than the portable backend, and to cross-check it.
4
+ */
5
+ import { createRequire } from "node:module";
6
+ /**
7
+ * Node only. The wrapper is loaded through its `require` condition, the CommonJS build, which is
8
+ * self-contained; its ESM build has shipped broken (0.7.16 imports a sibling file the package does
9
+ * not contain), and a consumer's plain `import` would hit that. The release smoke test loads this
10
+ * entry from the packed tarball in a clean Node to keep it so.
11
+ */
12
+ export async function loadSodiumBackend() {
13
+ const require = createRequire(import.meta.url);
14
+ const mod = require("libsodium-wrappers-sumo");
15
+ const sodium = mod.default ?? mod;
16
+ await sodium.ready;
17
+ return {
18
+ name: "sodium",
19
+ blake2b: (data, outLen, key) => sodium.crypto_generichash(outLen, data, key ?? null),
20
+ randomBytes: (length) => sodium.randombytes_buf(length),
21
+ signKeypairFromSeed(seed) {
22
+ const kp = sodium.crypto_sign_seed_keypair(seed);
23
+ return { publicKey: kp.publicKey, secretKey: kp.privateKey };
24
+ },
25
+ signDetached: (message, secretKey) => sodium.crypto_sign_detached(message, secretKey),
26
+ verifyDetached(signature, message, publicKey) {
27
+ try {
28
+ return sodium.crypto_sign_verify_detached(signature, message, publicKey);
29
+ }
30
+ catch {
31
+ return false;
32
+ }
33
+ },
34
+ isValidSignPoint: (publicKey) => publicKey.length === 32 && sodium.crypto_core_ed25519_is_valid_point(publicKey),
35
+ boxKeypairFromSeed(seed) {
36
+ const kp = sodium.crypto_box_seed_keypair(seed);
37
+ return { publicKey: kp.publicKey, secretKey: kp.privateKey };
38
+ },
39
+ boxKeypair() {
40
+ const kp = sodium.crypto_box_keypair();
41
+ return { publicKey: kp.publicKey, secretKey: kp.privateKey };
42
+ },
43
+ scalarMult: (secretKey, publicKey) => sodium.crypto_scalarmult(secretKey, publicKey),
44
+ boxEasy: (message, nonce, publicKey, secretKey) => sodium.crypto_box_easy(message, nonce, publicKey, secretKey),
45
+ boxOpenEasy: (box, nonce, publicKey, secretKey) => sodium.crypto_box_open_easy(box, nonce, publicKey, secretKey),
46
+ aeadEncrypt: (plaintext, aad, nonce, key) => sodium.crypto_aead_xchacha20poly1305_ietf_encrypt(plaintext, aad, null, nonce, key),
47
+ aeadDecrypt: (ciphertextAndTag, aad, nonce, key) => sodium.crypto_aead_xchacha20poly1305_ietf_decrypt(null, ciphertextAndTag, aad, nonce, key),
48
+ memzero: (bytes) => sodium.memzero(bytes)
49
+ };
50
+ }
51
+ //# sourceMappingURL=sodium.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sodium.js","sourceRoot":"","sources":["../../src/crypto/sodium.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ import { setCryptoBackend, type BoxKeypair, type CryptoBackend, type SignKeypair as SigningKeypair } from "./crypto/backend.js";
2
+ export type { CryptoBackend, BoxKeypair, SigningKeypair };
3
+ export { setCryptoBackend };
4
+ /** Kept from the protocol's earlier name on purpose: changing it changes every vector. */
5
+ export declare const LABEL_PREFIX = "SealedStream/5/";
6
+ export declare const WIRE_VERSION = 5;
7
+ export declare const HASH_BYTES = 32;
8
+ export declare const KEY_BYTES = 32;
9
+ export declare const SEED_BYTES = 32;
10
+ export declare const NONCE_BYTES = 24;
11
+ export declare const TAG_BYTES = 16;
12
+ export declare const SIGNATURE_BYTES = 64;
13
+ export declare const PUBLIC_KEY_BYTES = 32;
14
+ export declare const SEALED_BOX_BYTES = 80;
15
+ export declare const DEVICE_ID_BYTES = 16;
16
+ /** Recovery code prefix, also kept from the earlier name. */
17
+ export declare const RECOVERY_CODE_PREFIX = "KV1R-";
18
+ export type Label = "identity" | "stream" | "record-id" | "doc-hash" | "device-sign" | "device-box" | "account-sig" | "snapshot-sig" | "epoch-sig" | "record-sig" | "reset-sig" | "reset-keys-sig" | "epoch-key" | "wrap" | "record-aad" | "vault-aad";
19
+ /** Select a backend if none is set (the portable one) and resolve. Idempotent. */
20
+ export declare function ready(): Promise<void>;
21
+ export declare function backendName(): CryptoBackend["name"];
22
+ /** `C(label)` = ASCII("SealedStream/5/" + label) || 0x00. */
23
+ export declare function C(label: Label): Uint8Array;
24
+ /** `H(x)`: BLAKE2b, 32-byte output, unkeyed. */
25
+ export declare function H(data: Uint8Array): Uint8Array;
26
+ /** `D(seed, label)`: BLAKE2b keyed with the seed over `C(label)`, 32-byte output. */
27
+ export declare function D(seed: Uint8Array, label: Label): Uint8Array;
28
+ export declare function bodyHash(body: Uint8Array): Uint8Array;
29
+ export declare function identityId(accountName: string, accountPublicKey: Uint8Array): Uint8Array;
30
+ export declare function streamId(identity: Uint8Array, deviceId: Uint8Array): Uint8Array;
31
+ export declare function recordId(stream: Uint8Array, epoch: number, counter: number): Uint8Array;
32
+ export declare function wrapHash(wrap: Uint8Array): Uint8Array;
33
+ export declare function keyCommitment(stream: Uint8Array, epoch: number, epochKey: Uint8Array): Uint8Array;
34
+ /** `AK` from `accountSeed`. The only thing the account seed ever derives. */
35
+ export declare function accountKeypair(accountSeed: Uint8Array): SigningKeypair;
36
+ /** `DSK` = Ed25519 from `D(deviceSeed, "device-sign")`. */
37
+ export declare function deviceSigningKeypair(deviceSeed: Uint8Array): SigningKeypair;
38
+ /** `DEK` = `crypto_box_seed_keypair(D(deviceSeed, "device-box"))`. The seed is never used as a scalar. */
39
+ export declare function deviceBoxKeypair(deviceSeed: Uint8Array): BoxKeypair;
40
+ export declare function signingKeypairFromSeed(seed: Uint8Array): SigningKeypair;
41
+ /** An Ed25519 public key must be a canonical point on the main subgroup and not the identity. */
42
+ export declare function assertValidSigningKey(publicKey: Uint8Array, stage?: string): void;
43
+ export declare function assertValidBoxKey(publicKey: Uint8Array, stage?: string): void;
44
+ /** Detached Ed25519 over `C(label) || body`. Not Ed25519ph, no intermediate hash. */
45
+ export declare function sign(secretKey: Uint8Array, label: Label, body: Uint8Array): Uint8Array;
46
+ /**
47
+ * Verify a detached signature. Throws `INVALID_KEY` for an invalid or small-order key and
48
+ * `BAD_SIGNATURE` for anything else that does not verify, including a non-canonical scalar.
49
+ */
50
+ export declare function verify(publicKey: Uint8Array, label: Label, body: Uint8Array, signature: Uint8Array, stage?: string): void;
51
+ /** XChaCha20-Poly1305: returns ciphertext with the 16-byte tag appended. */
52
+ export declare function aeadSeal(key: Uint8Array, nonce: Uint8Array, aad: Uint8Array, plaintext: Uint8Array): Uint8Array;
53
+ export declare function aeadOpen(key: Uint8Array, nonce: Uint8Array, aad: Uint8Array, ciphertextAndTag: Uint8Array, stage?: string): Uint8Array;
54
+ /** The sealed-box nonce: BLAKE2b-24 over the ephemeral and recipient public keys, as libsodium defines it. */
55
+ export declare function sealedBoxNonce(ephemeralPublicKey: Uint8Array, recipientPublicKey: Uint8Array): Uint8Array;
56
+ /** `crypto_box_seal` with a given ephemeral keypair (tests reproduce fixture wraps with it). */
57
+ export declare function sealBoxWith(epochKey: Uint8Array, recipientPublicKey: Uint8Array, ephemeral: BoxKeypair): Uint8Array;
58
+ /** `crypto_box_seal` of a 32-byte epoch key: exactly 80 bytes. */
59
+ export declare function sealBox(epochKey: Uint8Array, recipientPublicKey: Uint8Array): Uint8Array;
60
+ export declare function openSealedBox(box: Uint8Array, recipient: BoxKeypair, stage?: string): Uint8Array;
61
+ /** `crypto_box_seed_keypair`, exposed for tests that rebuild fixture wraps from their ephemeral seeds. */
62
+ export declare function boxKeypairFromSeed(seed: Uint8Array): BoxKeypair;
63
+ export declare function randomBytes(length: number): Uint8Array;
64
+ /** Best-effort zeroisation. JavaScript gives no guarantee; the protocol says so. */
65
+ export declare function zero(bytes: Uint8Array): void;
66
+ //# sourceMappingURL=crypto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"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"}
package/dist/crypto.js ADDED
@@ -0,0 +1,225 @@
1
+ /**
2
+ * The one cipher suite of Kavach v1 (protocol section 3) over a primitive backend.
3
+ *
4
+ * Everything here is a thin, checked wrapper: no algorithm choice, no fallback, no key
5
+ * derivation other than the three the protocol names. Call `ready()` once before anything else;
6
+ * it selects the portable backend unless `setCryptoBackend` chose another first.
7
+ */
8
+ import { concat, isAllZero, u32, encodeName } from "./bytes.js";
9
+ import { KavachError } from "./errors.js";
10
+ import { currentBackend, setCryptoBackend } from "./crypto/backend.js";
11
+ import { nobleBackend } from "./crypto/noble.js";
12
+ export { setCryptoBackend };
13
+ /** Kept from the protocol's earlier name on purpose: changing it changes every vector. */
14
+ export const LABEL_PREFIX = "SealedStream/5/";
15
+ export const WIRE_VERSION = 5;
16
+ export const HASH_BYTES = 32;
17
+ export const KEY_BYTES = 32;
18
+ export const SEED_BYTES = 32;
19
+ export const NONCE_BYTES = 24;
20
+ export const TAG_BYTES = 16;
21
+ export const SIGNATURE_BYTES = 64;
22
+ export const PUBLIC_KEY_BYTES = 32;
23
+ export const SEALED_BOX_BYTES = 80;
24
+ export const DEVICE_ID_BYTES = 16;
25
+ /** Recovery code prefix, also kept from the earlier name. */
26
+ export const RECOVERY_CODE_PREFIX = "KV1R-";
27
+ /** Select a backend if none is set (the portable one) and resolve. Idempotent. */
28
+ export async function ready() {
29
+ if (!currentBackend()) {
30
+ // The portable backend draws randomness from the Web Crypto global; Hermes has none until the
31
+ // app installs one (the Expo helper does, from expo-crypto). Say so, rather than fail later.
32
+ const g = globalThis;
33
+ if (typeof g.crypto?.getRandomValues !== "function")
34
+ throw new KavachError("INVALID_KEY", "ready", "no crypto.getRandomValues: install a secure random source before opening Kavach");
35
+ setCryptoBackend(nobleBackend);
36
+ }
37
+ }
38
+ /** The portable backend needs no loading, so it is selected on first use when nothing else was. */
39
+ function be() {
40
+ const b = currentBackend();
41
+ if (b)
42
+ return b;
43
+ setCryptoBackend(nobleBackend);
44
+ return nobleBackend;
45
+ }
46
+ export function backendName() {
47
+ return be().name;
48
+ }
49
+ function ascii(text) {
50
+ const out = new Uint8Array(text.length);
51
+ for (let i = 0; i < text.length; i++) {
52
+ const c = text.charCodeAt(i);
53
+ if (c > 0x7f)
54
+ throw new RangeError("label is not ASCII");
55
+ out[i] = c;
56
+ }
57
+ return out;
58
+ }
59
+ /** `C(label)` = ASCII("SealedStream/5/" + label) || 0x00. */
60
+ export function C(label) {
61
+ return concat(ascii(LABEL_PREFIX + label), Uint8Array.of(0));
62
+ }
63
+ /** `H(x)`: BLAKE2b, 32-byte output, unkeyed. */
64
+ export function H(data) {
65
+ return be().blake2b(data, HASH_BYTES);
66
+ }
67
+ /** `D(seed, label)`: BLAKE2b keyed with the seed over `C(label)`, 32-byte output. */
68
+ export function D(seed, label) {
69
+ if (seed.length !== SEED_BYTES)
70
+ throw new KavachError("INVALID_KEY", "derive", "seed must be 32 bytes");
71
+ return be().blake2b(C(label), HASH_BYTES, seed);
72
+ }
73
+ export function bodyHash(body) {
74
+ return H(concat(C("doc-hash"), body));
75
+ }
76
+ export function identityId(accountName, accountPublicKey) {
77
+ return H(concat(C("identity"), encodeName(accountName), accountPublicKey));
78
+ }
79
+ export function streamId(identity, deviceId) {
80
+ return H(concat(C("stream"), identity, deviceId));
81
+ }
82
+ export function recordId(stream, epoch, counter) {
83
+ return H(concat(C("record-id"), stream, u32(epoch), u32(counter)));
84
+ }
85
+ export function wrapHash(wrap) {
86
+ return H(concat(C("wrap"), wrap));
87
+ }
88
+ export function keyCommitment(stream, epoch, epochKey) {
89
+ return H(concat(C("epoch-key"), stream, u32(epoch), epochKey));
90
+ }
91
+ // Keys ---------------------------------------------------------------------------------------
92
+ /** `AK` from `accountSeed`. The only thing the account seed ever derives. */
93
+ export function accountKeypair(accountSeed) {
94
+ return signingKeypairFromSeed(accountSeed);
95
+ }
96
+ /** `DSK` = Ed25519 from `D(deviceSeed, "device-sign")`. */
97
+ export function deviceSigningKeypair(deviceSeed) {
98
+ return signingKeypairFromSeed(D(deviceSeed, "device-sign"));
99
+ }
100
+ /** `DEK` = `crypto_box_seed_keypair(D(deviceSeed, "device-box"))`. The seed is never used as a scalar. */
101
+ export function deviceBoxKeypair(deviceSeed) {
102
+ return be().boxKeypairFromSeed(D(deviceSeed, "device-box"));
103
+ }
104
+ export function signingKeypairFromSeed(seed) {
105
+ if (seed.length !== SEED_BYTES)
106
+ throw new KavachError("INVALID_KEY", "keypair", "seed must be 32 bytes");
107
+ return be().signKeypairFromSeed(seed);
108
+ }
109
+ /** An Ed25519 public key must be a canonical point on the main subgroup and not the identity. */
110
+ export function assertValidSigningKey(publicKey, stage = "verify") {
111
+ if (publicKey.length !== PUBLIC_KEY_BYTES || !be().isValidSignPoint(publicKey)) {
112
+ throw new KavachError("INVALID_KEY", stage, "invalid Ed25519 public key");
113
+ }
114
+ }
115
+ /**
116
+ * An X25519 public key must not yield an all-zero shared secret. A fixed non-secret scalar
117
+ * probes it; libsodium refuses the low-order result.
118
+ */
119
+ const PROBE_SCALAR = new Uint8Array(32).fill(0x42);
120
+ export function assertValidBoxKey(publicKey, stage = "verify") {
121
+ if (publicKey.length !== PUBLIC_KEY_BYTES || isAllZero(publicKey)) {
122
+ throw new KavachError("INVALID_KEY", stage, "invalid X25519 public key");
123
+ }
124
+ try {
125
+ const shared = be().scalarMult(PROBE_SCALAR, publicKey);
126
+ if (isAllZero(shared))
127
+ throw new Error("zero");
128
+ }
129
+ catch {
130
+ throw new KavachError("INVALID_KEY", stage, "low-order X25519 public key");
131
+ }
132
+ }
133
+ // Signatures ----------------------------------------------------------------------------------
134
+ /** Detached Ed25519 over `C(label) || body`. Not Ed25519ph, no intermediate hash. */
135
+ export function sign(secretKey, label, body) {
136
+ return be().signDetached(concat(C(label), body), secretKey);
137
+ }
138
+ // The Ed25519 group order L, little-endian, for the canonical-scalar check.
139
+ const L = Uint8Array.from([
140
+ 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00,
141
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10
142
+ ]);
143
+ function isCanonicalScalar(s) {
144
+ // s < L, comparing little-endian from the most significant byte.
145
+ for (let i = 31; i >= 0; i--) {
146
+ const a = s[i] ?? 0;
147
+ const b = L[i] ?? 0;
148
+ if (a < b)
149
+ return true;
150
+ if (a > b)
151
+ return false;
152
+ }
153
+ return false;
154
+ }
155
+ /**
156
+ * Verify a detached signature. Throws `INVALID_KEY` for an invalid or small-order key and
157
+ * `BAD_SIGNATURE` for anything else that does not verify, including a non-canonical scalar.
158
+ */
159
+ export function verify(publicKey, label, body, signature, stage = "verify") {
160
+ assertValidSigningKey(publicKey, stage);
161
+ if (signature.length !== SIGNATURE_BYTES || !isCanonicalScalar(signature.subarray(32))) {
162
+ throw new KavachError("BAD_SIGNATURE", stage);
163
+ }
164
+ if (!be().verifyDetached(signature, concat(C(label), body), publicKey))
165
+ throw new KavachError("BAD_SIGNATURE", stage);
166
+ }
167
+ // AEAD ---------------------------------------------------------------------------------------
168
+ /** XChaCha20-Poly1305: returns ciphertext with the 16-byte tag appended. */
169
+ export function aeadSeal(key, nonce, aad, plaintext) {
170
+ if (key.length !== KEY_BYTES || nonce.length !== NONCE_BYTES)
171
+ throw new KavachError("INVALID_KEY", "aead");
172
+ return be().aeadEncrypt(plaintext, aad, nonce, key);
173
+ }
174
+ export function aeadOpen(key, nonce, aad, ciphertextAndTag, stage = "decrypt") {
175
+ if (key.length !== KEY_BYTES || nonce.length !== NONCE_BYTES)
176
+ throw new KavachError("INVALID_KEY", stage);
177
+ try {
178
+ return be().aeadDecrypt(ciphertextAndTag, aad, nonce, key);
179
+ }
180
+ catch {
181
+ throw new KavachError("DECRYPT_FAILED", stage);
182
+ }
183
+ }
184
+ // Sealed boxes -------------------------------------------------------------------------------
185
+ /** The sealed-box nonce: BLAKE2b-24 over the ephemeral and recipient public keys, as libsodium defines it. */
186
+ export function sealedBoxNonce(ephemeralPublicKey, recipientPublicKey) {
187
+ return be().blake2b(concat(ephemeralPublicKey, recipientPublicKey), NONCE_BYTES);
188
+ }
189
+ /** `crypto_box_seal` with a given ephemeral keypair (tests reproduce fixture wraps with it). */
190
+ export function sealBoxWith(epochKey, recipientPublicKey, ephemeral) {
191
+ const nonce = sealedBoxNonce(ephemeral.publicKey, recipientPublicKey);
192
+ return concat(ephemeral.publicKey, be().boxEasy(epochKey, nonce, recipientPublicKey, ephemeral.secretKey));
193
+ }
194
+ /** `crypto_box_seal` of a 32-byte epoch key: exactly 80 bytes. */
195
+ export function sealBox(epochKey, recipientPublicKey) {
196
+ if (epochKey.length !== KEY_BYTES)
197
+ throw new KavachError("INVALID_KEY", "seal");
198
+ assertValidBoxKey(recipientPublicKey, "seal");
199
+ return sealBoxWith(epochKey, recipientPublicKey, be().boxKeypair());
200
+ }
201
+ export function openSealedBox(box, recipient, stage = "open-wrap") {
202
+ if (box.length !== SEALED_BOX_BYTES)
203
+ throw new KavachError("MALFORMED", stage, "wrap must be 80 bytes");
204
+ try {
205
+ const ephemeralPublic = box.subarray(0, PUBLIC_KEY_BYTES);
206
+ const nonce = sealedBoxNonce(ephemeralPublic, recipient.publicKey);
207
+ return be().boxOpenEasy(box.subarray(PUBLIC_KEY_BYTES), nonce, ephemeralPublic, recipient.secretKey);
208
+ }
209
+ catch {
210
+ throw new KavachError("DECRYPT_FAILED", stage);
211
+ }
212
+ }
213
+ /** `crypto_box_seed_keypair`, exposed for tests that rebuild fixture wraps from their ephemeral seeds. */
214
+ export function boxKeypairFromSeed(seed) {
215
+ return be().boxKeypairFromSeed(seed);
216
+ }
217
+ // Randomness and hygiene ----------------------------------------------------------------------
218
+ export function randomBytes(length) {
219
+ return be().randomBytes(length);
220
+ }
221
+ /** Best-effort zeroisation. JavaScript gives no guarantee; the protocol says so. */
222
+ export function zero(bytes) {
223
+ be().memzero(bytes);
224
+ }
225
+ //# sourceMappingURL=crypto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,93 @@
1
+ import type { ResolvedAudience } from "./audience.js";
2
+ import { type EpochManifest, type Parsed } from "./codec.js";
3
+ import { type BoxKeypair } from "./crypto.js";
4
+ export declare const MAX_COUNTER = 4294967295;
5
+ export declare const MAX_EPOCH = 4294967295;
6
+ export interface AuthorKeys {
7
+ readonly identityId: Uint8Array;
8
+ readonly certificateHash: Uint8Array;
9
+ readonly streamId: Uint8Array;
10
+ readonly signingSecretKey: Uint8Array;
11
+ }
12
+ /** Everything T4 persists before any network call. */
13
+ export interface PreparedEpoch {
14
+ readonly epoch: number;
15
+ readonly manifest: Uint8Array;
16
+ readonly manifestHash: Uint8Array;
17
+ /** Wrap per recipient identity id (hex), the author's own included. */
18
+ readonly wraps: ReadonlyMap<string, Uint8Array>;
19
+ readonly epochKey: Uint8Array;
20
+ readonly capturedRevision: bigint;
21
+ readonly audienceKey: string;
22
+ readonly createdAt: bigint;
23
+ }
24
+ /** Prepare an epoch: fresh random key, one sealed box per row, one signature. */
25
+ export declare function prepareEpoch(input: {
26
+ readonly author: AuthorKeys;
27
+ readonly epoch: number;
28
+ readonly createdAt: bigint;
29
+ readonly audience: ResolvedAudience;
30
+ readonly desiredRevision: bigint;
31
+ readonly epochKey?: Uint8Array;
32
+ }): PreparedEpoch;
33
+ export type PublishOutcome = {
34
+ readonly status: "COMMITTED";
35
+ } | {
36
+ readonly status: "ALREADY_COMMITTED";
37
+ } | {
38
+ readonly status: "CONFLICT";
39
+ readonly currentEpoch: number;
40
+ readonly currentManifest: Uint8Array | undefined;
41
+ } | {
42
+ readonly status: "RETRYABLE";
43
+ } | {
44
+ readonly status: "UNAUTHORIZED";
45
+ } | {
46
+ readonly status: "PERMANENT_FAILURE";
47
+ };
48
+ export type PublishResolution = "COMMITTED" | "RETRY";
49
+ /**
50
+ * Resolve a publish outcome for a prepared epoch. Identical bytes at the slot mean committed; a
51
+ * different valid body at the same epoch is `EQUIVOCATION`; a higher committed epoch than the one
52
+ * prepared means local state was lost and the device must replace its stream.
53
+ */
54
+ export declare function resolvePublish(prepared: PreparedEpoch, outcome: PublishOutcome): PublishResolution;
55
+ export type PromotionOutcome = "PROMOTED" | "OBSOLETE";
56
+ /** After commit: promote only if the captured revision and the exact audience still match. */
57
+ export declare function promote(prepared: PreparedEpoch, currentDesiredRevision: bigint, currentAudienceKey: string): PromotionOutcome;
58
+ export type RotationReason = "counterExhausted" | "hygiene" | "clockReversal";
59
+ export interface ActiveEpochView {
60
+ readonly createdAt: bigint;
61
+ readonly nextCounter: number;
62
+ readonly lastSentAt: bigint | undefined;
63
+ }
64
+ export declare function rotationReason(active: ActiveEpochView, now: bigint, hygieneRotationMs: bigint): RotationReason | undefined;
65
+ export interface AuthorCertificateView {
66
+ readonly certificateHash: Uint8Array;
67
+ readonly signingKey: Uint8Array;
68
+ readonly streamId: Uint8Array;
69
+ readonly current: boolean;
70
+ }
71
+ export interface AuthorView {
72
+ readonly identityId: Uint8Array;
73
+ /** The author's current certificate and any archived ones the reader still holds, by hash (hex). */
74
+ readonly certificates: ReadonlyMap<string, AuthorCertificateView>;
75
+ }
76
+ export interface SelfView {
77
+ readonly identityId: Uint8Array;
78
+ readonly certificateHash: Uint8Array;
79
+ readonly box: BoxKeypair;
80
+ }
81
+ export interface OpenedEpoch {
82
+ readonly manifest: Parsed<EpochManifest>;
83
+ readonly epochKey: Uint8Array;
84
+ /** The manifest belongs to a device of the author that is no longer current: history only. */
85
+ readonly superseded: boolean;
86
+ }
87
+ /**
88
+ * Every check of section 8 before a key is stored: manifest signature under the certificate it
89
+ * names, that certificate's identity and stream, the author's own row, the reader's own row at
90
+ * its current certificate, the wrap hash, the sealed box and the key commitment.
91
+ */
92
+ export declare function openEpoch(manifestWire: Uint8Array, author: AuthorView, self: SelfView, wrap: Uint8Array): OpenedEpoch;
93
+ //# sourceMappingURL=epoch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"epoch.d.ts","sourceRoot":"","sources":["../src/epoch.ts"],"names":[],"mappings":"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"}