@haven-chat-org/core 1.0.0

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 (81) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +71 -0
  3. package/dist/crypto/backup.d.ts +87 -0
  4. package/dist/crypto/backup.js +62 -0
  5. package/dist/crypto/backup.js.map +1 -0
  6. package/dist/crypto/double-ratchet.d.ts +104 -0
  7. package/dist/crypto/double-ratchet.js +274 -0
  8. package/dist/crypto/double-ratchet.js.map +1 -0
  9. package/dist/crypto/file.d.ts +14 -0
  10. package/dist/crypto/file.js +20 -0
  11. package/dist/crypto/file.js.map +1 -0
  12. package/dist/crypto/index.d.ts +9 -0
  13. package/dist/crypto/index.js +10 -0
  14. package/dist/crypto/index.js.map +1 -0
  15. package/dist/crypto/keys.d.ts +61 -0
  16. package/dist/crypto/keys.js +79 -0
  17. package/dist/crypto/keys.js.map +1 -0
  18. package/dist/crypto/passphrase.d.ts +10 -0
  19. package/dist/crypto/passphrase.js +142 -0
  20. package/dist/crypto/passphrase.js.map +1 -0
  21. package/dist/crypto/profile.d.ts +31 -0
  22. package/dist/crypto/profile.js +73 -0
  23. package/dist/crypto/profile.js.map +1 -0
  24. package/dist/crypto/sender-keys.d.ts +76 -0
  25. package/dist/crypto/sender-keys.js +170 -0
  26. package/dist/crypto/sender-keys.js.map +1 -0
  27. package/dist/crypto/sender-keys.test.d.ts +1 -0
  28. package/dist/crypto/sender-keys.test.js +272 -0
  29. package/dist/crypto/sender-keys.test.js.map +1 -0
  30. package/dist/crypto/utils.d.ts +41 -0
  31. package/dist/crypto/utils.js +102 -0
  32. package/dist/crypto/utils.js.map +1 -0
  33. package/dist/crypto/x3dh.d.ts +45 -0
  34. package/dist/crypto/x3dh.js +106 -0
  35. package/dist/crypto/x3dh.js.map +1 -0
  36. package/dist/export/__tests__/archive.test.d.ts +1 -0
  37. package/dist/export/__tests__/archive.test.js +276 -0
  38. package/dist/export/__tests__/archive.test.js.map +1 -0
  39. package/dist/export/archive.d.ts +38 -0
  40. package/dist/export/archive.js +107 -0
  41. package/dist/export/archive.js.map +1 -0
  42. package/dist/export/index.d.ts +4 -0
  43. package/dist/export/index.js +4 -0
  44. package/dist/export/index.js.map +1 -0
  45. package/dist/export/reader.d.ts +27 -0
  46. package/dist/export/reader.js +101 -0
  47. package/dist/export/reader.js.map +1 -0
  48. package/dist/export/signing.d.ts +15 -0
  49. package/dist/export/signing.js +44 -0
  50. package/dist/export/signing.js.map +1 -0
  51. package/dist/export/types.d.ts +128 -0
  52. package/dist/export/types.js +3 -0
  53. package/dist/export/types.js.map +1 -0
  54. package/dist/index.d.ts +5 -0
  55. package/dist/index.js +6 -0
  56. package/dist/index.js.map +1 -0
  57. package/dist/net/api.d.ts +200 -0
  58. package/dist/net/api.js +715 -0
  59. package/dist/net/api.js.map +1 -0
  60. package/dist/net/api.test.d.ts +1 -0
  61. package/dist/net/api.test.js +884 -0
  62. package/dist/net/api.test.js.map +1 -0
  63. package/dist/net/index.d.ts +2 -0
  64. package/dist/net/index.js +3 -0
  65. package/dist/net/index.js.map +1 -0
  66. package/dist/net/ws.d.ts +71 -0
  67. package/dist/net/ws.js +257 -0
  68. package/dist/net/ws.js.map +1 -0
  69. package/dist/store/index.d.ts +2 -0
  70. package/dist/store/index.js +2 -0
  71. package/dist/store/index.js.map +1 -0
  72. package/dist/store/memory.d.ts +24 -0
  73. package/dist/store/memory.js +50 -0
  74. package/dist/store/memory.js.map +1 -0
  75. package/dist/store/types.d.ts +23 -0
  76. package/dist/store/types.js +2 -0
  77. package/dist/store/types.js.map +1 -0
  78. package/dist/types.d.ts +850 -0
  79. package/dist/types.js +35 -0
  80. package/dist/types.js.map +1 -0
  81. package/package.json +41 -0
@@ -0,0 +1,10 @@
1
+ export { initSodium, getSodium, toBase64, fromBase64, randomBytes } from "./utils.js";
2
+ export { encryptFile, decryptFile } from "./file.js";
3
+ export { generateIdentityKeyPair, generateDHKeyPair, generateSignedPreKey, generateOneTimePreKeys, prepareRegistrationKeys, verifySignature, } from "./keys.js";
4
+ export { x3dhInitiate, x3dhRespond } from "./x3dh.js";
5
+ export { DoubleRatchetSession, serializeMessage, deserializeMessage, } from "./double-ratchet.js";
6
+ export { GROUP_MSG_TYPE, generateSenderKey, createSkdmPayload, parseSkdmPayload, encryptSkdm, decryptSkdm, senderKeyEncrypt, senderKeyDecrypt, } from "./sender-keys.js";
7
+ export { generateProfileKey, encryptProfile, decryptProfile, encryptProfileKeyFor, decryptProfileKey, encryptProfileToBase64, decryptProfileFromBase64, } from "./profile.js";
8
+ export { encryptBackup, decryptBackup, deriveBackupKey, generateRecoveryKey, } from "./backup.js";
9
+ export { generatePassphrase } from "./passphrase.js";
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/crypto/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACtF,OAAO,EAAE,WAAW,EAAE,WAAW,EAAsB,MAAM,WAAW,CAAC;AACzE,OAAO,EAIL,uBAAuB,EACvB,iBAAiB,EACjB,oBAAoB,EACpB,sBAAsB,EACtB,uBAAuB,EACvB,eAAe,GAChB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAmB,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACvE,OAAO,EACL,oBAAoB,EAIpB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAIL,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,cAAc,EACd,oBAAoB,EACpB,iBAAiB,EACjB,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,aAAa,EACb,aAAa,EACb,eAAe,EACf,mBAAmB,GAIpB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,61 @@
1
+ /** Ed25519 identity keypair — used for signing and converted to X25519 for DH. */
2
+ export interface IdentityKeyPair {
3
+ publicKey: Uint8Array;
4
+ privateKey: Uint8Array;
5
+ }
6
+ /** X25519 keypair for Diffie-Hellman (prekeys, ephemeral keys). */
7
+ export interface DHKeyPair {
8
+ publicKey: Uint8Array;
9
+ privateKey: Uint8Array;
10
+ }
11
+ /** Signed prekey with Ed25519 signature from identity key. */
12
+ export interface SignedPreKey {
13
+ keyPair: DHKeyPair;
14
+ signature: Uint8Array;
15
+ }
16
+ /**
17
+ * Generate a new Ed25519 identity keypair.
18
+ * The identity key is used for:
19
+ * - Signing the signed prekey (Ed25519)
20
+ * - X3DH DH operations (converted to X25519)
21
+ */
22
+ export declare function generateIdentityKeyPair(): IdentityKeyPair;
23
+ /**
24
+ * Generate a new X25519 DH keypair (for prekeys and ephemeral keys).
25
+ */
26
+ export declare function generateDHKeyPair(): DHKeyPair;
27
+ /**
28
+ * Generate a signed prekey: a DH keypair signed with the identity key.
29
+ */
30
+ export declare function generateSignedPreKey(identityKeyPair: IdentityKeyPair): SignedPreKey;
31
+ /**
32
+ * Generate a batch of one-time prekeys (X25519 DH keypairs).
33
+ * Returns the keypairs — public keys get uploaded, private keys stored locally.
34
+ */
35
+ export declare function generateOneTimePreKeys(count: number): DHKeyPair[];
36
+ /**
37
+ * Convert an Ed25519 public key to an X25519 public key for DH.
38
+ */
39
+ export declare function ed25519PkToX25519(edPk: Uint8Array): Uint8Array;
40
+ /**
41
+ * Convert an Ed25519 secret key to an X25519 secret key for DH.
42
+ */
43
+ export declare function ed25519SkToX25519(edSk: Uint8Array): Uint8Array;
44
+ /**
45
+ * Perform X25519 Diffie-Hellman: shared_secret = DH(ourPrivate, theirPublic).
46
+ */
47
+ export declare function dh(ourPrivateKey: Uint8Array, theirPublicKey: Uint8Array): Uint8Array;
48
+ /**
49
+ * Verify an Ed25519 signature.
50
+ */
51
+ export declare function verifySignature(signature: Uint8Array, message: Uint8Array, publicKey: Uint8Array): boolean;
52
+ /**
53
+ * Prepare the local key material for registration.
54
+ * Returns base64-encoded values ready for the register API.
55
+ */
56
+ export declare function prepareRegistrationKeys(identityKeyPair: IdentityKeyPair, signedPreKey: SignedPreKey, oneTimePreKeys: DHKeyPair[]): {
57
+ identity_key: string;
58
+ signed_prekey: string;
59
+ signed_prekey_signature: string;
60
+ one_time_prekeys: string[];
61
+ };
@@ -0,0 +1,79 @@
1
+ import { getSodium, toBase64 } from "./utils.js";
2
+ // ─── Key Generation ────────────────────────────────────
3
+ /**
4
+ * Generate a new Ed25519 identity keypair.
5
+ * The identity key is used for:
6
+ * - Signing the signed prekey (Ed25519)
7
+ * - X3DH DH operations (converted to X25519)
8
+ */
9
+ export function generateIdentityKeyPair() {
10
+ const kp = getSodium().crypto_sign_keypair();
11
+ return { publicKey: kp.publicKey, privateKey: kp.privateKey };
12
+ }
13
+ /**
14
+ * Generate a new X25519 DH keypair (for prekeys and ephemeral keys).
15
+ */
16
+ export function generateDHKeyPair() {
17
+ const kp = getSodium().crypto_box_keypair();
18
+ return { publicKey: kp.publicKey, privateKey: kp.privateKey };
19
+ }
20
+ /**
21
+ * Generate a signed prekey: a DH keypair signed with the identity key.
22
+ */
23
+ export function generateSignedPreKey(identityKeyPair) {
24
+ const keyPair = generateDHKeyPair();
25
+ const signature = getSodium().crypto_sign_detached(keyPair.publicKey, identityKeyPair.privateKey);
26
+ return { keyPair, signature };
27
+ }
28
+ /**
29
+ * Generate a batch of one-time prekeys (X25519 DH keypairs).
30
+ * Returns the keypairs — public keys get uploaded, private keys stored locally.
31
+ */
32
+ export function generateOneTimePreKeys(count) {
33
+ return Array.from({ length: count }, () => generateDHKeyPair());
34
+ }
35
+ // ─── Key Conversion ────────────────────────────────────
36
+ /**
37
+ * Convert an Ed25519 public key to an X25519 public key for DH.
38
+ */
39
+ export function ed25519PkToX25519(edPk) {
40
+ return getSodium().crypto_sign_ed25519_pk_to_curve25519(edPk);
41
+ }
42
+ /**
43
+ * Convert an Ed25519 secret key to an X25519 secret key for DH.
44
+ */
45
+ export function ed25519SkToX25519(edSk) {
46
+ return getSodium().crypto_sign_ed25519_sk_to_curve25519(edSk);
47
+ }
48
+ // ─── DH & Signatures ──────────────────────────────────
49
+ /**
50
+ * Perform X25519 Diffie-Hellman: shared_secret = DH(ourPrivate, theirPublic).
51
+ */
52
+ export function dh(ourPrivateKey, theirPublicKey) {
53
+ return getSodium().crypto_scalarmult(ourPrivateKey, theirPublicKey);
54
+ }
55
+ /**
56
+ * Verify an Ed25519 signature.
57
+ */
58
+ export function verifySignature(signature, message, publicKey) {
59
+ try {
60
+ return getSodium().crypto_sign_verify_detached(signature, message, publicKey);
61
+ }
62
+ catch {
63
+ return false;
64
+ }
65
+ }
66
+ // ─── Serialization Helpers ─────────────────────────────
67
+ /**
68
+ * Prepare the local key material for registration.
69
+ * Returns base64-encoded values ready for the register API.
70
+ */
71
+ export function prepareRegistrationKeys(identityKeyPair, signedPreKey, oneTimePreKeys) {
72
+ return {
73
+ identity_key: toBase64(identityKeyPair.publicKey),
74
+ signed_prekey: toBase64(signedPreKey.keyPair.publicKey),
75
+ signed_prekey_signature: toBase64(signedPreKey.signature),
76
+ one_time_prekeys: oneTimePreKeys.map((kp) => toBase64(kp.publicKey)),
77
+ };
78
+ }
79
+ //# sourceMappingURL=keys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keys.js","sourceRoot":"","sources":["../../src/crypto/keys.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAsBjD,0DAA0D;AAE1D;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB;IACrC,MAAM,EAAE,GAAG,SAAS,EAAE,CAAC,mBAAmB,EAAE,CAAC;IAC7C,OAAO,EAAE,SAAS,EAAE,EAAE,CAAC,SAAS,EAAE,UAAU,EAAE,EAAE,CAAC,UAAU,EAAE,CAAC;AAChE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB;IAC/B,MAAM,EAAE,GAAG,SAAS,EAAE,CAAC,kBAAkB,EAAE,CAAC;IAC5C,OAAO,EAAE,SAAS,EAAE,EAAE,CAAC,SAAS,EAAE,UAAU,EAAE,EAAE,CAAC,UAAU,EAAE,CAAC;AAChE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,eAAgC;IACnE,MAAM,OAAO,GAAG,iBAAiB,EAAE,CAAC;IACpC,MAAM,SAAS,GAAG,SAAS,EAAE,CAAC,oBAAoB,CAAC,OAAO,CAAC,SAAS,EAAE,eAAe,CAAC,UAAU,CAAC,CAAC;IAClG,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;AAChC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,KAAa;IAClD,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAC;AAClE,CAAC;AAED,0DAA0D;AAE1D;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAgB;IAChD,OAAO,SAAS,EAAE,CAAC,oCAAoC,CAAC,IAAI,CAAC,CAAC;AAChE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAgB;IAChD,OAAO,SAAS,EAAE,CAAC,oCAAoC,CAAC,IAAI,CAAC,CAAC;AAChE,CAAC;AAED,yDAAyD;AAEzD;;GAEG;AACH,MAAM,UAAU,EAAE,CAAC,aAAyB,EAAE,cAA0B;IACtE,OAAO,SAAS,EAAE,CAAC,iBAAiB,CAAC,aAAa,EAAE,cAAc,CAAC,CAAC;AACtE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAC7B,SAAqB,EACrB,OAAmB,EACnB,SAAqB;IAErB,IAAI,CAAC;QACH,OAAO,SAAS,EAAE,CAAC,2BAA2B,CAAC,SAAS,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;IAChF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,0DAA0D;AAE1D;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CACrC,eAAgC,EAChC,YAA0B,EAC1B,cAA2B;IAE3B,OAAO;QACL,YAAY,EAAE,QAAQ,CAAC,eAAe,CAAC,SAAS,CAAC;QACjD,aAAa,EAAE,QAAQ,CAAC,YAAY,CAAC,OAAO,CAAC,SAAS,CAAC;QACvD,uBAAuB,EAAE,QAAQ,CAAC,YAAY,CAAC,SAAS,CAAC;QACzD,gBAAgB,EAAE,cAAc,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC;KACrE,CAAC;AACJ,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Passphrase generator using a curated wordlist and crypto.getRandomValues().
3
+ * Generates memorable passphrases like "correct-horse-battery-staple".
4
+ */
5
+ /**
6
+ * Generate a random passphrase using cryptographic randomness.
7
+ * @param wordCount Number of words (default 6, ~60 bits of entropy)
8
+ * @returns Hyphen-separated passphrase, e.g. "correct-horse-battery-staple-anchor-brave"
9
+ */
10
+ export declare function generatePassphrase(wordCount?: number): string;
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Passphrase generator using a curated wordlist and crypto.getRandomValues().
3
+ * Generates memorable passphrases like "correct-horse-battery-staple".
4
+ */
5
+ // 1024-word curated list (10 bits of entropy per word)
6
+ // 6 words → ~60 bits, 8 words → ~80 bits
7
+ const WORDS = [
8
+ "abandon", "able", "about", "above", "absorb", "abstract", "absurd", "abuse",
9
+ "access", "acid", "across", "act", "action", "actual", "adapt", "add",
10
+ "addict", "address", "adjust", "admit", "adult", "advance", "advice", "afford",
11
+ "again", "age", "agent", "agree", "ahead", "aim", "air", "alarm",
12
+ "album", "alert", "alien", "all", "alley", "allow", "almost", "alone",
13
+ "alpha", "already", "also", "alter", "always", "amazing", "among", "amount",
14
+ "amuse", "anchor", "ancient", "angel", "anger", "angle", "animal", "ankle",
15
+ "announce", "annual", "another", "answer", "antenna", "antique", "anxiety", "any",
16
+ "apart", "apology", "appear", "apple", "approve", "april", "arch", "arctic",
17
+ "area", "arena", "armor", "army", "arrange", "arrest", "arrive", "arrow",
18
+ "art", "artist", "asthma", "atom", "attack", "attend", "attract", "auction",
19
+ "audit", "august", "aunt", "auto", "autumn", "average", "avocado", "avoid",
20
+ "awake", "aware", "axis", "baby", "bachelor", "bacon", "badge", "bag",
21
+ "balance", "balcony", "ball", "bamboo", "banana", "banner", "bar", "barely",
22
+ "barrel", "base", "basic", "basket", "battle", "beach", "bean", "beauty",
23
+ "become", "beef", "before", "begin", "behave", "behind", "believe", "bench",
24
+ "benefit", "best", "betray", "better", "between", "beyond", "bicycle", "bird",
25
+ "birth", "bitter", "blade", "blame", "blanket", "blast", "blaze", "bleak",
26
+ "bless", "blind", "blood", "blossom", "blue", "blur", "blush", "board",
27
+ "boat", "body", "bomb", "bone", "bonus", "book", "boost", "border",
28
+ "boring", "borrow", "boss", "bottom", "bounce", "bowl", "brave", "bread",
29
+ "breeze", "brick", "bridge", "brief", "bright", "bring", "brisk", "broken",
30
+ "bronze", "brother", "brown", "brush", "bubble", "buddy", "budget", "buffalo",
31
+ "build", "bulb", "bulk", "bullet", "bundle", "burger", "burst", "bus",
32
+ "butter", "buyer", "cabin", "cable", "cactus", "cage", "cake", "call",
33
+ "calm", "camera", "camp", "canal", "cancel", "candy", "canoe", "canvas",
34
+ "canyon", "capable", "capital", "captain", "carbon", "card", "cargo", "carpet",
35
+ "carry", "case", "cash", "castle", "casual", "catalog", "catch", "category",
36
+ "cattle", "caught", "cause", "caution", "cave", "ceiling", "celery", "cement",
37
+ "census", "century", "cereal", "certain", "chair", "chalk", "champion", "change",
38
+ "chaos", "chapter", "charge", "chase", "cheap", "check", "cheese", "cherry",
39
+ "chest", "chicken", "chief", "child", "chimney", "choice", "chunk", "cinema",
40
+ "circle", "citizen", "city", "civil", "claim", "clap", "clarify", "claw",
41
+ "clean", "clerk", "clever", "cliff", "climb", "clinic", "clip", "clock",
42
+ "close", "cloth", "cloud", "clown", "club", "cluster", "clutch", "coach",
43
+ "coast", "coconut", "code", "coffee", "coil", "coin", "collect", "color",
44
+ "column", "combine", "come", "comfort", "comic", "common", "company", "concert",
45
+ "conduct", "confirm", "connect", "consider", "control", "convince", "cook", "cool",
46
+ "copper", "copy", "coral", "core", "corn", "correct", "cost", "cotton",
47
+ "couch", "country", "couple", "course", "cousin", "cover", "craft", "crane",
48
+ "crash", "crater", "crawl", "crazy", "cream", "credit", "crew", "cricket",
49
+ "crime", "crisp", "cross", "crouch", "crowd", "crucial", "cruel", "cruise",
50
+ "crumble", "crush", "crystal", "cube", "culture", "cup", "cupboard", "curious",
51
+ "current", "curtain", "curve", "cushion", "custom", "cute", "cycle", "dad",
52
+ "damage", "dance", "danger", "daring", "dash", "daughter", "dawn", "day",
53
+ "deal", "debate", "debris", "decade", "december", "decide", "decline", "decorate",
54
+ "decrease", "deer", "defense", "define", "defy", "degree", "delay", "deliver",
55
+ "demand", "denial", "dentist", "deny", "depart", "depend", "deposit", "depth",
56
+ "deputy", "derive", "describe", "desert", "design", "desk", "despair", "destroy",
57
+ "detail", "detect", "develop", "device", "devote", "diamond", "diary", "diesel",
58
+ "differ", "digital", "dignity", "dilemma", "dinner", "dinosaur", "direct", "dirt",
59
+ "disagree", "discover", "disease", "dish", "dismiss", "disorder", "display", "distance",
60
+ "divert", "divide", "divorce", "dizzy", "doctor", "document", "dog", "dolphin",
61
+ "domain", "donate", "donkey", "donor", "door", "dose", "double", "dove",
62
+ "draft", "dragon", "drama", "drastic", "draw", "dream", "dress", "drift",
63
+ "drill", "drink", "drip", "drive", "drop", "drum", "dry", "duck",
64
+ "dumb", "dune", "during", "dust", "dutch", "duty", "dwarf", "dynamic",
65
+ "eager", "eagle", "early", "earn", "earth", "east", "easy", "echo",
66
+ "ecology", "economy", "edge", "edit", "educate", "effort", "eight", "either",
67
+ "elbow", "elder", "electric", "elegant", "element", "elephant", "elevator", "elite",
68
+ "else", "embark", "embody", "embrace", "emerge", "emotion", "employ", "empower",
69
+ "empty", "enable", "enact", "end", "endless", "endorse", "enemy", "energy",
70
+ "enforce", "engage", "engine", "enhance", "enjoy", "enlist", "enough", "enrich",
71
+ "enroll", "ensure", "enter", "entire", "entry", "envelope", "episode", "equal",
72
+ "equip", "era", "erase", "erode", "erosion", "error", "erupt", "escape",
73
+ "essay", "essence", "estate", "eternal", "ethics", "evidence", "evil", "evolve",
74
+ "exact", "example", "excess", "exchange", "excite", "exclude", "excuse", "execute",
75
+ "exercise", "exhaust", "exhibit", "exist", "exit", "exotic", "expand", "expect",
76
+ "expire", "explain", "expose", "express", "extend", "extra", "eye", "fabric",
77
+ "face", "faculty", "fade", "faint", "faith", "fall", "false", "family",
78
+ "famous", "fan", "fancy", "fantasy", "farm", "fashion", "fatal", "father",
79
+ "fatigue", "fault", "favorite", "feature", "february", "federal", "feel", "female",
80
+ "fence", "festival", "fetch", "fever", "few", "fiber", "fiction", "field",
81
+ "figure", "file", "film", "filter", "final", "find", "finger", "finish",
82
+ "fire", "firm", "fiscal", "fish", "fit", "fitness", "fix", "flag",
83
+ "flame", "flash", "flat", "flavor", "flee", "flight", "flip", "float",
84
+ "flock", "floor", "flower", "fluid", "flush", "fly", "foam", "focus",
85
+ "fog", "foil", "fold", "follow", "food", "foot", "force", "forest",
86
+ "forget", "fork", "fortune", "forum", "forward", "fossil", "foster", "found",
87
+ "fox", "fragile", "frame", "frequent", "fresh", "friend", "fringe", "frog",
88
+ "front", "frost", "frown", "frozen", "fruit", "fuel", "fun", "funny",
89
+ "furnace", "fury", "future", "gadget", "galaxy", "gallery", "game", "gap",
90
+ "garage", "garbage", "garden", "garlic", "garment", "gas", "gasp", "gate",
91
+ "gather", "gauge", "gaze", "general", "genius", "genre", "gentle", "genuine",
92
+ "gesture", "ghost", "giant", "gift", "giggle", "ginger", "giraffe", "glad",
93
+ "glance", "glare", "glass", "glide", "glimpse", "globe", "gloom", "glory",
94
+ "glove", "glow", "glue", "goat", "goddess", "gold", "good", "goose",
95
+ "gorilla", "gospel", "gossip", "govern", "gown", "grab", "grace", "grain",
96
+ "grant", "grape", "grass", "gravity", "great", "green", "grid", "grief",
97
+ "grit", "grocery", "group", "grow", "grunt", "guard", "guess", "guide",
98
+ "guilt", "guitar", "gun", "gym", "habit", "half", "hammer", "hamster",
99
+ "hand", "happy", "harbor", "hard", "harsh", "harvest", "hat", "have",
100
+ "hawk", "hazard", "head", "health", "heart", "heavy", "hedgehog", "height",
101
+ "hello", "help", "hen", "hero", "hidden", "high", "hill", "hint",
102
+ "hip", "hire", "history", "hobby", "hockey", "hold", "hole", "holiday",
103
+ "hollow", "home", "honey", "hood", "hope", "horn", "horror", "horse",
104
+ "hospital", "host", "hotel", "hour", "hover", "hub", "huge", "human",
105
+ "humble", "humor", "hundred", "hungry", "hunt", "hurdle", "hurry", "hurt",
106
+ "hybrid", "ice", "icon", "idea", "identify", "idle", "ignore", "image",
107
+ "immune", "impact", "impose", "improve", "impulse", "inch", "include", "income",
108
+ "increase", "index", "indicate", "indoor", "industry", "infant", "inflict", "inform",
109
+ "initial", "inner", "innocent", "input", "inquiry", "insane", "insect", "inside",
110
+ "inspire", "install", "intact", "interest", "into", "invest", "invite", "iron",
111
+ "island", "isolate", "issue", "item", "ivory", "jacket", "jaguar", "jazz",
112
+ "jealous", "jeans", "jelly", "jewel", "job", "join", "joke", "journey",
113
+ "joy", "judge", "juice", "jump", "jungle", "junior", "junk", "just",
114
+ "kangaroo", "keen", "keep", "kettle", "key", "kick", "kid", "kidney",
115
+ "kind", "kingdom", "kiss", "kit", "kitchen", "kite", "kitten", "kiwi",
116
+ "knee", "knife", "knock", "know", "label", "labor", "ladder", "lady",
117
+ "lake", "lamp", "language", "laptop", "large", "later", "latin", "laugh",
118
+ "laundry", "lava", "law", "lawn", "lawsuit", "layer", "lazy", "leader",
119
+ "leaf", "learn", "leave", "lecture", "left", "legal", "legend", "leisure",
120
+ "lemon", "length", "lens", "leopard", "lesson", "letter", "level", "liberty",
121
+ "library", "license", "life", "lift", "light", "like", "limb", "limit",
122
+ "link", "lion", "liquid", "list", "little", "live", "lizard", "load",
123
+ "loan", "lobster", "local", "lock", "logic", "lonely", "long", "loop",
124
+ "lottery", "loud", "lounge", "love", "loyal", "lucky", "lumber", "lunar",
125
+ "lunch", "luxury", "lyrics", "machine", "mad", "magic", "magnet", "maid",
126
+ "mail", "main", "major", "make", "mammal", "manage", "mandate", "mango",
127
+ ];
128
+ /**
129
+ * Generate a random passphrase using cryptographic randomness.
130
+ * @param wordCount Number of words (default 6, ~60 bits of entropy)
131
+ * @returns Hyphen-separated passphrase, e.g. "correct-horse-battery-staple-anchor-brave"
132
+ */
133
+ export function generatePassphrase(wordCount = 6) {
134
+ const indices = new Uint32Array(wordCount);
135
+ crypto.getRandomValues(indices);
136
+ const words = [];
137
+ for (let i = 0; i < wordCount; i++) {
138
+ words.push(WORDS[indices[i] % WORDS.length]);
139
+ }
140
+ return words.join("-").toUpperCase();
141
+ }
142
+ //# sourceMappingURL=passphrase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"passphrase.js","sourceRoot":"","sources":["../../src/crypto/passphrase.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Profile encryption: selective encryption of about_me, custom_status, custom_status_emoji.
3
+ *
4
+ * Model:
5
+ * - User generates a 32-byte profile key on registration (stored client-side)
6
+ * - Profile fields are JSON-serialized, then encrypted with XChaCha20-Poly1305 using the profile key
7
+ * - The encrypted blob is stored on the server as `encrypted_profile`
8
+ * - Profile key is distributed to contacts via crypto_box_seal (using recipient's identity public key)
9
+ * - Recipients decrypt the profile key, then use it to decrypt the profile blob
10
+ */
11
+ import type { ProfileFields } from "../types.js";
12
+ /** Generate a random 32-byte profile key. */
13
+ export declare function generateProfileKey(): Uint8Array;
14
+ /** Encrypt profile fields into a single blob using the profile key. */
15
+ export declare function encryptProfile(profileKey: Uint8Array, fields: ProfileFields): Uint8Array;
16
+ /** Decrypt a profile blob using the profile key. Returns the plaintext fields. */
17
+ export declare function decryptProfile(profileKey: Uint8Array, encrypted: Uint8Array): ProfileFields;
18
+ /**
19
+ * Encrypt a profile key for a recipient using their identity public key.
20
+ * Uses crypto_box_seal (anonymous, authenticated encryption).
21
+ */
22
+ export declare function encryptProfileKeyFor(profileKey: Uint8Array, recipientIdentityPublicKey: Uint8Array): Uint8Array;
23
+ /**
24
+ * Decrypt a profile key that was encrypted to our identity key.
25
+ * Requires both the public and secret parts of our identity key pair.
26
+ */
27
+ export declare function decryptProfileKey(encryptedKey: Uint8Array, identityPublicKey: Uint8Array, identitySecretKey: Uint8Array): Uint8Array;
28
+ /** Convenience: encrypt profile fields and return as base64. */
29
+ export declare function encryptProfileToBase64(profileKey: Uint8Array, fields: ProfileFields): string;
30
+ /** Convenience: decrypt a base64 profile blob. */
31
+ export declare function decryptProfileFromBase64(profileKey: Uint8Array, encryptedBase64: string): ProfileFields;
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Profile encryption: selective encryption of about_me, custom_status, custom_status_emoji.
3
+ *
4
+ * Model:
5
+ * - User generates a 32-byte profile key on registration (stored client-side)
6
+ * - Profile fields are JSON-serialized, then encrypted with XChaCha20-Poly1305 using the profile key
7
+ * - The encrypted blob is stored on the server as `encrypted_profile`
8
+ * - Profile key is distributed to contacts via crypto_box_seal (using recipient's identity public key)
9
+ * - Recipients decrypt the profile key, then use it to decrypt the profile blob
10
+ */
11
+ import { getSodium, toBase64, fromBase64, randomBytes } from "./utils.js";
12
+ /** Generate a random 32-byte profile key. */
13
+ export function generateProfileKey() {
14
+ return randomBytes(32);
15
+ }
16
+ /** Encrypt profile fields into a single blob using the profile key. */
17
+ export function encryptProfile(profileKey, fields) {
18
+ const s = getSodium();
19
+ const plaintext = new TextEncoder().encode(JSON.stringify(fields));
20
+ const nonce = s.randombytes_buf(s.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
21
+ const ciphertext = s.crypto_aead_xchacha20poly1305_ietf_encrypt(plaintext, null, // additional data
22
+ null, // nsec (unused)
23
+ nonce, profileKey);
24
+ // Format: [nonce || ciphertext]
25
+ const result = new Uint8Array(nonce.length + ciphertext.length);
26
+ result.set(nonce, 0);
27
+ result.set(ciphertext, nonce.length);
28
+ return result;
29
+ }
30
+ /** Decrypt a profile blob using the profile key. Returns the plaintext fields. */
31
+ export function decryptProfile(profileKey, encrypted) {
32
+ const s = getSodium();
33
+ const nonceLen = s.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES;
34
+ if (encrypted.length < nonceLen) {
35
+ throw new Error("Encrypted profile too short");
36
+ }
37
+ const nonce = encrypted.slice(0, nonceLen);
38
+ const ciphertext = encrypted.slice(nonceLen);
39
+ const plaintext = s.crypto_aead_xchacha20poly1305_ietf_decrypt(null, // nsec (unused)
40
+ ciphertext, null, // additional data
41
+ nonce, profileKey);
42
+ return JSON.parse(new TextDecoder().decode(plaintext));
43
+ }
44
+ /**
45
+ * Encrypt a profile key for a recipient using their identity public key.
46
+ * Uses crypto_box_seal (anonymous, authenticated encryption).
47
+ */
48
+ export function encryptProfileKeyFor(profileKey, recipientIdentityPublicKey) {
49
+ const s = getSodium();
50
+ // Convert identity key (Ed25519) to X25519 for crypto_box
51
+ const x25519Pub = s.crypto_sign_ed25519_pk_to_curve25519(recipientIdentityPublicKey);
52
+ return s.crypto_box_seal(profileKey, x25519Pub);
53
+ }
54
+ /**
55
+ * Decrypt a profile key that was encrypted to our identity key.
56
+ * Requires both the public and secret parts of our identity key pair.
57
+ */
58
+ export function decryptProfileKey(encryptedKey, identityPublicKey, identitySecretKey) {
59
+ const s = getSodium();
60
+ // Convert Ed25519 keys to X25519
61
+ const x25519Pub = s.crypto_sign_ed25519_pk_to_curve25519(identityPublicKey);
62
+ const x25519Sec = s.crypto_sign_ed25519_sk_to_curve25519(identitySecretKey);
63
+ return s.crypto_box_seal_open(encryptedKey, x25519Pub, x25519Sec);
64
+ }
65
+ /** Convenience: encrypt profile fields and return as base64. */
66
+ export function encryptProfileToBase64(profileKey, fields) {
67
+ return toBase64(encryptProfile(profileKey, fields));
68
+ }
69
+ /** Convenience: decrypt a base64 profile blob. */
70
+ export function decryptProfileFromBase64(profileKey, encryptedBase64) {
71
+ return decryptProfile(profileKey, fromBase64(encryptedBase64));
72
+ }
73
+ //# sourceMappingURL=profile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile.js","sourceRoot":"","sources":["../../src/crypto/profile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Signal-style Sender Keys protocol for group E2EE.
3
+ *
4
+ * Each member generates a sender key per channel. Messages are encrypted O(1)
5
+ * using a symmetric chain ratchet. Distribution uses crypto_box_seal to each
6
+ * recipient's X25519 identity key.
7
+ *
8
+ * Wire format (type 0x03):
9
+ * [0x03][distributionId:16][chainIndex:4 LE][nonce:24][ciphertext+tag]
10
+ * Overhead: 45 bytes + ciphertext
11
+ *
12
+ * References:
13
+ * - https://signal.org/docs/specifications/group-v2/
14
+ */
15
+ import { type IdentityKeyPair } from "./keys.js";
16
+ export declare const GROUP_MSG_TYPE = 3;
17
+ /** The sender's own key state for one channel. */
18
+ export interface SenderKeyState {
19
+ distributionId: Uint8Array;
20
+ chainKey: Uint8Array;
21
+ chainIndex: number;
22
+ }
23
+ /** A received sender key from another member. */
24
+ export interface ReceivedSenderKey {
25
+ distributionId: Uint8Array;
26
+ chainKey: Uint8Array;
27
+ chainIndex: number;
28
+ }
29
+ /** SKDM payload fields (before encryption). */
30
+ export interface SenderKeyDistributionPayload {
31
+ distributionId: Uint8Array;
32
+ chainKey: Uint8Array;
33
+ chainIndex: number;
34
+ }
35
+ /**
36
+ * Generate a fresh sender key for a channel.
37
+ * Called when first joining a channel or after a re-key event.
38
+ */
39
+ export declare function generateSenderKey(): SenderKeyState;
40
+ /**
41
+ * Serialize an SKDM payload for distribution.
42
+ * Format: [distributionId:16][chainIndex:4 LE][chainKey:32] = 52 bytes
43
+ */
44
+ export declare function createSkdmPayload(state: SenderKeyState): Uint8Array;
45
+ /**
46
+ * Parse an SKDM payload back into structured data.
47
+ */
48
+ export declare function parseSkdmPayload(buf: Uint8Array): SenderKeyDistributionPayload;
49
+ /**
50
+ * Encrypt an SKDM for a single recipient using crypto_box_seal.
51
+ * The recipient's Ed25519 identity key is converted to X25519 for sealing.
52
+ */
53
+ export declare function encryptSkdm(skdmPayload: Uint8Array, recipientIdentityKeyEd25519: Uint8Array): Uint8Array;
54
+ /**
55
+ * Decrypt an SKDM received for us.
56
+ */
57
+ export declare function decryptSkdm(encrypted: Uint8Array, ourIdentityKeyPair: IdentityKeyPair): Uint8Array;
58
+ /**
59
+ * Encrypt a message using the sender's key for a channel.
60
+ * Ratchets the chain forward. Returns the full wire-format bytes.
61
+ *
62
+ * Wire format:
63
+ * [0x03][distributionId:16][chainIndex:4 LE][nonce:24][ciphertext+tag]
64
+ *
65
+ * @param senderKey The sender's key state (mutated: chain ratchets forward)
66
+ * @param plaintext The message plaintext bytes
67
+ */
68
+ export declare function senderKeyEncrypt(senderKey: SenderKeyState, plaintext: Uint8Array): Uint8Array;
69
+ /**
70
+ * Decrypt a group message using a received sender key.
71
+ * Ratchets the received key forward to match the message's chain index.
72
+ *
73
+ * @param wireBytes Full wire-format bytes (including type byte 0x03)
74
+ * @param receivedKey The sender's key (mutated: ratchets forward)
75
+ */
76
+ export declare function senderKeyDecrypt(wireBytes: Uint8Array, receivedKey: ReceivedSenderKey): Uint8Array;