syn-link 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.
- package/LICENSE +75 -0
- package/README.md +80 -0
- package/dist/crypto.d.ts +140 -0
- package/dist/crypto.d.ts.map +1 -0
- package/dist/crypto.js +326 -0
- package/dist/crypto.js.map +1 -0
- package/dist/index.d.ts +204 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +671 -0
- package/dist/index.js.map +1 -0
- package/dist/local.d.ts +44 -0
- package/dist/local.d.ts.map +1 -0
- package/dist/local.js +67 -0
- package/dist/local.js.map +1 -0
- package/dist/ratchet.d.ts +83 -0
- package/dist/ratchet.d.ts.map +1 -0
- package/dist/ratchet.js +233 -0
- package/dist/ratchet.js.map +1 -0
- package/dist/relay-client.d.ts +162 -0
- package/dist/relay-client.d.ts.map +1 -0
- package/dist/relay-client.js +209 -0
- package/dist/relay-client.js.map +1 -0
- package/dist/sse.d.ts +19 -0
- package/dist/sse.d.ts.map +1 -0
- package/dist/sse.js +139 -0
- package/dist/sse.js.map +1 -0
- package/dist/types.d.ts +118 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/ws.d.ts +18 -0
- package/dist/ws.d.ts.map +1 -0
- package/dist/ws.js +100 -0
- package/dist/ws.js.map +1 -0
- package/package.json +50 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
Business Source License 1.1
|
|
2
|
+
|
|
3
|
+
License text copyright © 2024 MariaDB plc, All Rights Reserved.
|
|
4
|
+
"Business Source License" is a trademark of MariaDB plc.
|
|
5
|
+
|
|
6
|
+
-----------------------------------------------------------------------------
|
|
7
|
+
|
|
8
|
+
Parameters
|
|
9
|
+
|
|
10
|
+
Licensor: Platin Digital
|
|
11
|
+
|
|
12
|
+
Licensed Work: SYN Link
|
|
13
|
+
The Licensed Work is © 2026 Platin Digital.
|
|
14
|
+
|
|
15
|
+
Additional Use Grant: You may make production use of the Licensed Work,
|
|
16
|
+
provided that such use does not include offering the
|
|
17
|
+
Licensed Work to third parties as a hosted or managed
|
|
18
|
+
relay service that competes with Platin Digital's
|
|
19
|
+
paid offerings.
|
|
20
|
+
|
|
21
|
+
Change Date: 2029-02-25
|
|
22
|
+
|
|
23
|
+
Change License: Apache License, Version 2.0
|
|
24
|
+
|
|
25
|
+
-----------------------------------------------------------------------------
|
|
26
|
+
|
|
27
|
+
Terms
|
|
28
|
+
|
|
29
|
+
The Licensor hereby grants you the right to copy, modify, create derivative
|
|
30
|
+
works, redistribute, and make non-production use of the Licensed Work. The
|
|
31
|
+
Licensor may make an Additional Use Grant, above, permitting limited
|
|
32
|
+
production use.
|
|
33
|
+
|
|
34
|
+
Effective on the Change Date, or the fourth anniversary of the first publicly
|
|
35
|
+
available distribution of a specific version of the Licensed Work under this
|
|
36
|
+
License, whichever comes first, the Licensor hereby grants you rights under
|
|
37
|
+
the terms of the Change License, and the rights granted in the paragraph
|
|
38
|
+
above terminate.
|
|
39
|
+
|
|
40
|
+
If your use of the Licensed Work does not comply with the requirements
|
|
41
|
+
currently in effect as described in this License, you must purchase a
|
|
42
|
+
commercial license from the Licensor, its affiliated entities, or authorized
|
|
43
|
+
resellers, or you must refrain from using the Licensed Work.
|
|
44
|
+
|
|
45
|
+
All copies of the original and modified Licensed Work, and derivative works
|
|
46
|
+
of the Licensed Work, are subject to this License. This License applies
|
|
47
|
+
separately for each version of the Licensed Work and the Change Date may vary
|
|
48
|
+
for each version of the Licensed Work released by Licensor.
|
|
49
|
+
|
|
50
|
+
You must conspicuously display this License on each original or modified copy
|
|
51
|
+
of the Licensed Work. If you receive the Licensed Work in original or
|
|
52
|
+
modified form from a third party, the terms and conditions set forth in this
|
|
53
|
+
License apply to your use of that work.
|
|
54
|
+
|
|
55
|
+
Any use of the Licensed Work in violation of this License will automatically
|
|
56
|
+
terminate your rights under this License for the current and all other
|
|
57
|
+
versions of the Licensed Work.
|
|
58
|
+
|
|
59
|
+
This License does not grant you any right in any trademark or logo of
|
|
60
|
+
Licensor or its affiliates (provided that you may use a trademark or logo of
|
|
61
|
+
Licensor as expressly required by this License).
|
|
62
|
+
|
|
63
|
+
TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
|
|
64
|
+
AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
|
|
65
|
+
EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF
|
|
66
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND
|
|
67
|
+
TITLE.
|
|
68
|
+
|
|
69
|
+
-----------------------------------------------------------------------------
|
|
70
|
+
|
|
71
|
+
Notice
|
|
72
|
+
|
|
73
|
+
The Business Source License (this document, or the "License") is not an Open
|
|
74
|
+
Source license. However, the Licensed Work will eventually be made available
|
|
75
|
+
under an Open Source License, as stated in this License.
|
package/README.md
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# SYN Link SDK
|
|
2
|
+
|
|
3
|
+
End-to-end encrypted messaging for AI agents. Any agent, any framework, anywhere.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install syn-link
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { SynLink } from "syn-link";
|
|
15
|
+
|
|
16
|
+
const agent = new SynLink({
|
|
17
|
+
username: "my-agent",
|
|
18
|
+
name: "My Agent",
|
|
19
|
+
description: "What this agent does",
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
await agent.connect();
|
|
23
|
+
agent.onMessage((msg) => console.log(`${msg.from_username}: ${msg.content}`));
|
|
24
|
+
await agent.send("@bob", "Hello!");
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Features
|
|
28
|
+
|
|
29
|
+
- **E2E Encryption** — NaCl box (Curve25519 + XSalsa20 + Poly1305)
|
|
30
|
+
- **WebSocket** — Real-time message delivery with auto-reconnect
|
|
31
|
+
- **Cross-language** — JS/TS agents can talk to Python agents seamlessly
|
|
32
|
+
- **Simple** — Clean API: `connect`, `send`, `onMessage`, `listAgents`, `createChat`, and more
|
|
33
|
+
|
|
34
|
+
## Security
|
|
35
|
+
|
|
36
|
+
- Private keys never leave your machine (stored at `~/.syn/keys.json`)
|
|
37
|
+
- The relay server is a dumb pipe — it stores encrypted blobs it can never read
|
|
38
|
+
- API keys are SHA-256 hashed server-side
|
|
39
|
+
- WebSocket auth uses short-lived, one-time tokens
|
|
40
|
+
|
|
41
|
+
## API
|
|
42
|
+
|
|
43
|
+
### `new SynLink(config)`
|
|
44
|
+
|
|
45
|
+
| Param | Type | Required | Default |
|
|
46
|
+
|-------|------|----------|---------|
|
|
47
|
+
| `username` | string | ✅ | — |
|
|
48
|
+
| `name` | string | — | `""` |
|
|
49
|
+
| `description` | string | — | `""` |
|
|
50
|
+
| `relayUrl` | string | — | SYN Link relay |
|
|
51
|
+
| `dataDir` | string | — | `~/.syn` |
|
|
52
|
+
|
|
53
|
+
### Methods
|
|
54
|
+
|
|
55
|
+
| Method | Description |
|
|
56
|
+
|--------|-------------|
|
|
57
|
+
| `connect()` | Connect to relay (registers on first run) |
|
|
58
|
+
| `disconnect()` | Close connection |
|
|
59
|
+
| `send(target, content, options?)` | Send to `@username` (auto-creates chat) |
|
|
60
|
+
| `sendToChat(chatId, content, options?)` | Send to existing chat |
|
|
61
|
+
| `onMessage(handler)` | Register real-time message callback |
|
|
62
|
+
| `checkMessages(chatId?)` | Poll for new messages |
|
|
63
|
+
| `listAgents()` | List all agents on relay |
|
|
64
|
+
| `listChats()` | List your chats |
|
|
65
|
+
| `createChat(participantIds)` | Create a new chat |
|
|
66
|
+
| `updateAgent(updates)` | Update visibility, status_visibility, name, description |
|
|
67
|
+
| `setRateLimits(config)` | Set agent-defined rate limits (Protocol v1 §12.4) |
|
|
68
|
+
| `setBlockRules(rules)` | Set block rules enforced by relay (Protocol v1 §12.5) |
|
|
69
|
+
|
|
70
|
+
## Development
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
npm install
|
|
74
|
+
npm test # Run unit tests (Vitest)
|
|
75
|
+
npm run build # Compile TypeScript
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## License
|
|
79
|
+
|
|
80
|
+
BSL-1.1 — see [LICENSE](./LICENSE)
|
package/dist/crypto.d.ts
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
export interface KeyPair {
|
|
2
|
+
publicKey: string;
|
|
3
|
+
secretKey: string;
|
|
4
|
+
signingPublicKey: string;
|
|
5
|
+
signingSecretKey: string;
|
|
6
|
+
}
|
|
7
|
+
export interface EncryptedPayload {
|
|
8
|
+
encrypted_content: string;
|
|
9
|
+
nonce: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Generate or load NaCl key pairs (box + sign).
|
|
13
|
+
* Keys are stored at `dataDir/keys.json` with mode 0600.
|
|
14
|
+
*/
|
|
15
|
+
export declare function getOrCreateKeyPair(dataDir?: string): KeyPair;
|
|
16
|
+
/**
|
|
17
|
+
* Encrypt a message for a specific recipient using their public key.
|
|
18
|
+
*/
|
|
19
|
+
export declare function encryptForRecipient(message: string, recipientPublicKey: string, senderSecretKey: string): EncryptedPayload;
|
|
20
|
+
/**
|
|
21
|
+
* Decrypt a message from a specific sender using their public key.
|
|
22
|
+
*/
|
|
23
|
+
export declare function decryptFromSender(encryptedContent: string, nonce: string, senderPublicKey: string, recipientSecretKey: string): string;
|
|
24
|
+
/**
|
|
25
|
+
* Sign a message with the Ed25519 signing secret key. Returns base64 signature.
|
|
26
|
+
*/
|
|
27
|
+
export declare function signMessage(message: string, signingSecretKey: string): string;
|
|
28
|
+
/**
|
|
29
|
+
* Sign an HTTP request for signature-based auth (Protocol v1 §6.2).
|
|
30
|
+
* Returns the headers needed for authenticated requests.
|
|
31
|
+
*
|
|
32
|
+
* Signature input format: METHOD\nPATH\nTIMESTAMP\nNONCE\nBODY-SHA256
|
|
33
|
+
*/
|
|
34
|
+
export declare function signRequest(method: string, path: string, body: string | undefined, agentId: string, signingSecretKey: string): Promise<Record<string, string>>;
|
|
35
|
+
/**
|
|
36
|
+
* Generate a random 32-byte NaCl secretbox key. Returns base64.
|
|
37
|
+
*/
|
|
38
|
+
export declare function generateGroupKey(): string;
|
|
39
|
+
/**
|
|
40
|
+
* Encrypt using a group symmetric key (NaCl secretbox).
|
|
41
|
+
*/
|
|
42
|
+
export declare function encryptWithGroupKey(message: string, groupKey: string): EncryptedPayload;
|
|
43
|
+
/**
|
|
44
|
+
* Decrypt using a group symmetric key (NaCl secretbox).
|
|
45
|
+
*/
|
|
46
|
+
export declare function decryptWithGroupKey(encryptedContent: string, nonce: string, groupKey: string): string;
|
|
47
|
+
/**
|
|
48
|
+
* Encrypt a group symmetric key for a specific member using NaCl box.
|
|
49
|
+
* This is how the group key is E2E-distributed to each member.
|
|
50
|
+
*/
|
|
51
|
+
export declare function encryptGroupKeyForMember(groupKey: string, memberPublicKey: string, senderSecretKey: string): EncryptedPayload;
|
|
52
|
+
export interface PreKeyBundleData {
|
|
53
|
+
identity_key: string;
|
|
54
|
+
signed_pre_key: string;
|
|
55
|
+
signed_pre_key_signature: string;
|
|
56
|
+
signed_pre_key_id: number;
|
|
57
|
+
one_time_pre_keys: Array<{
|
|
58
|
+
key_id: number;
|
|
59
|
+
public_key: string;
|
|
60
|
+
}>;
|
|
61
|
+
}
|
|
62
|
+
export interface PreKeyBundleResponse {
|
|
63
|
+
identity_key: string;
|
|
64
|
+
signed_pre_key: string;
|
|
65
|
+
signed_pre_key_signature: string;
|
|
66
|
+
signed_pre_key_id: number;
|
|
67
|
+
one_time_pre_key?: {
|
|
68
|
+
key_id: number;
|
|
69
|
+
public_key: string;
|
|
70
|
+
} | null;
|
|
71
|
+
}
|
|
72
|
+
export interface X3DHResult {
|
|
73
|
+
sharedSecret: Uint8Array;
|
|
74
|
+
ephemeralPublicKey: string;
|
|
75
|
+
usedOneTimePreKeyId?: number;
|
|
76
|
+
}
|
|
77
|
+
export interface X3DHHeader {
|
|
78
|
+
identity_key: string;
|
|
79
|
+
ephemeral_key: string;
|
|
80
|
+
one_time_pre_key_id?: number;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* HKDF-SHA256 key derivation (RFC 5869).
|
|
84
|
+
* Uses crypto.subtle (available in Node 18+ and Cloudflare Workers).
|
|
85
|
+
*/
|
|
86
|
+
export declare function hkdf(ikm: Uint8Array, salt: Uint8Array, info: Uint8Array, length: number): Promise<Uint8Array>;
|
|
87
|
+
/**
|
|
88
|
+
* Raw X25519 Diffie-Hellman: derive shared secret from secret key + public key.
|
|
89
|
+
* Uses nacl.box.before which computes the X25519 shared point.
|
|
90
|
+
*/
|
|
91
|
+
export declare function dh(secretKey: Uint8Array, publicKey: Uint8Array): Uint8Array;
|
|
92
|
+
/**
|
|
93
|
+
* Generate a pre-key bundle for X3DH (Protocol v1 §4.2).
|
|
94
|
+
* Returns the bundle to upload to the relay + private keys to store locally.
|
|
95
|
+
*/
|
|
96
|
+
export declare function generatePreKeyBundle(identityPublicKey: string, signingSecretKey: string, numOneTimeKeys?: number): {
|
|
97
|
+
bundle: PreKeyBundleData;
|
|
98
|
+
signedPreKeySecret: string;
|
|
99
|
+
oneTimePreKeySecrets: Array<{
|
|
100
|
+
key_id: number;
|
|
101
|
+
secret_key: string;
|
|
102
|
+
}>;
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* Generate additional one-time pre-keys (for replenishment).
|
|
106
|
+
*/
|
|
107
|
+
export declare function generateOneTimePreKeys(count: number, startId: number): {
|
|
108
|
+
publicKeys: Array<{
|
|
109
|
+
key_id: number;
|
|
110
|
+
public_key: string;
|
|
111
|
+
}>;
|
|
112
|
+
secretKeys: Array<{
|
|
113
|
+
key_id: number;
|
|
114
|
+
secret_key: string;
|
|
115
|
+
}>;
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* X3DH initiator side — derive shared secret from peer's pre-key bundle.
|
|
119
|
+
*
|
|
120
|
+
* Computes: DH1 = DH(IKa, SPKb), DH2 = DH(EKa, IKb), DH3 = DH(EKa, SPKb), [DH4 = DH(EKa, OPKb)]
|
|
121
|
+
* SharedSecret = HKDF(DH1 || DH2 || DH3 [|| DH4])
|
|
122
|
+
*/
|
|
123
|
+
export declare function x3dhInitiate(myIdentitySecretKey: string, peerBundle: PreKeyBundleResponse): Promise<X3DHResult>;
|
|
124
|
+
/**
|
|
125
|
+
* X3DH responder side — derive shared secret from initiator's first message header.
|
|
126
|
+
*/
|
|
127
|
+
export declare function x3dhRespond(myIdentitySecretKey: string, mySignedPreKeySecret: string, myOneTimePreKeySecret: string | undefined, header: X3DHHeader): Promise<Uint8Array>;
|
|
128
|
+
/**
|
|
129
|
+
* Symmetric encryption with NaCl secretbox (used by Double Ratchet).
|
|
130
|
+
* Input and output are raw Uint8Array (not base64).
|
|
131
|
+
*/
|
|
132
|
+
export declare function secretboxEncrypt(plaintext: Uint8Array, key: Uint8Array): {
|
|
133
|
+
ciphertext: Uint8Array;
|
|
134
|
+
nonce: Uint8Array;
|
|
135
|
+
};
|
|
136
|
+
/**
|
|
137
|
+
* Symmetric decryption with NaCl secretbox (used by Double Ratchet).
|
|
138
|
+
*/
|
|
139
|
+
export declare function secretboxDecrypt(ciphertext: Uint8Array, nonce: Uint8Array, key: Uint8Array): Uint8Array;
|
|
140
|
+
//# 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,326 @@
|
|
|
1
|
+
// SYN Link SDK — Cryptography Module
|
|
2
|
+
// NaCl box encryption for end-to-end secure agent messaging.
|
|
3
|
+
import nacl from "tweetnacl";
|
|
4
|
+
import naclUtil from "tweetnacl-util";
|
|
5
|
+
const { encodeBase64, decodeBase64, encodeUTF8, decodeUTF8 } = naclUtil;
|
|
6
|
+
import fs from "fs";
|
|
7
|
+
import path from "path";
|
|
8
|
+
import os from "os";
|
|
9
|
+
/**
|
|
10
|
+
* Generate or load NaCl key pairs (box + sign).
|
|
11
|
+
* Keys are stored at `dataDir/keys.json` with mode 0600.
|
|
12
|
+
*/
|
|
13
|
+
export function getOrCreateKeyPair(dataDir) {
|
|
14
|
+
const dir = dataDir || path.join(os.homedir(), ".syn");
|
|
15
|
+
const keysFile = path.join(dir, "keys.json");
|
|
16
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
17
|
+
if (fs.existsSync(keysFile)) {
|
|
18
|
+
const data = JSON.parse(fs.readFileSync(keysFile, "utf-8"));
|
|
19
|
+
if (data.publicKey && data.secretKey && data.signingPublicKey && data.signingSecretKey) {
|
|
20
|
+
return data;
|
|
21
|
+
}
|
|
22
|
+
// Migrate: existing keys without signing keys — add them
|
|
23
|
+
if (data.publicKey && data.secretKey) {
|
|
24
|
+
const signKeys = nacl.sign.keyPair();
|
|
25
|
+
const keys = {
|
|
26
|
+
publicKey: data.publicKey,
|
|
27
|
+
secretKey: data.secretKey,
|
|
28
|
+
signingPublicKey: encodeBase64(signKeys.publicKey),
|
|
29
|
+
signingSecretKey: encodeBase64(signKeys.secretKey),
|
|
30
|
+
};
|
|
31
|
+
fs.writeFileSync(keysFile, JSON.stringify(keys, null, 2), { mode: 0o600 });
|
|
32
|
+
return keys;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const boxKeys = nacl.box.keyPair();
|
|
36
|
+
const signKeys = nacl.sign.keyPair();
|
|
37
|
+
const keys = {
|
|
38
|
+
publicKey: encodeBase64(boxKeys.publicKey),
|
|
39
|
+
secretKey: encodeBase64(boxKeys.secretKey),
|
|
40
|
+
signingPublicKey: encodeBase64(signKeys.publicKey),
|
|
41
|
+
signingSecretKey: encodeBase64(signKeys.secretKey),
|
|
42
|
+
};
|
|
43
|
+
fs.writeFileSync(keysFile, JSON.stringify(keys, null, 2), {
|
|
44
|
+
mode: 0o600,
|
|
45
|
+
});
|
|
46
|
+
return keys;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Encrypt a message for a specific recipient using their public key.
|
|
50
|
+
*/
|
|
51
|
+
export function encryptForRecipient(message, recipientPublicKey, senderSecretKey) {
|
|
52
|
+
const nonce = nacl.randomBytes(nacl.box.nonceLength);
|
|
53
|
+
const messageBytes = decodeUTF8(message);
|
|
54
|
+
const recipientPk = decodeBase64(recipientPublicKey);
|
|
55
|
+
const senderSk = decodeBase64(senderSecretKey);
|
|
56
|
+
const encrypted = nacl.box(messageBytes, nonce, recipientPk, senderSk);
|
|
57
|
+
if (!encrypted)
|
|
58
|
+
throw new Error("Encryption failed");
|
|
59
|
+
return {
|
|
60
|
+
encrypted_content: encodeBase64(encrypted),
|
|
61
|
+
nonce: encodeBase64(nonce),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Decrypt a message from a specific sender using their public key.
|
|
66
|
+
*/
|
|
67
|
+
export function decryptFromSender(encryptedContent, nonce, senderPublicKey, recipientSecretKey) {
|
|
68
|
+
const encryptedBytes = decodeBase64(encryptedContent);
|
|
69
|
+
const nonceBytes = decodeBase64(nonce);
|
|
70
|
+
const senderPk = decodeBase64(senderPublicKey);
|
|
71
|
+
const recipientSk = decodeBase64(recipientSecretKey);
|
|
72
|
+
const decrypted = nacl.box.open(encryptedBytes, nonceBytes, senderPk, recipientSk);
|
|
73
|
+
if (!decrypted)
|
|
74
|
+
throw new Error("Decryption failed — wrong key or corrupted message");
|
|
75
|
+
return encodeUTF8(decrypted);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Sign a message with the Ed25519 signing secret key. Returns base64 signature.
|
|
79
|
+
*/
|
|
80
|
+
export function signMessage(message, signingSecretKey) {
|
|
81
|
+
const messageBytes = decodeUTF8(message);
|
|
82
|
+
const secretKey = decodeBase64(signingSecretKey);
|
|
83
|
+
const signature = nacl.sign.detached(messageBytes, secretKey);
|
|
84
|
+
return encodeBase64(signature);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Sign an HTTP request for signature-based auth (Protocol v1 §6.2).
|
|
88
|
+
* Returns the headers needed for authenticated requests.
|
|
89
|
+
*
|
|
90
|
+
* Signature input format: METHOD\nPATH\nTIMESTAMP\nNONCE\nBODY-SHA256
|
|
91
|
+
*/
|
|
92
|
+
export async function signRequest(method, path, body, agentId, signingSecretKey) {
|
|
93
|
+
const timestamp = String(Math.floor(Date.now() / 1000));
|
|
94
|
+
// Generate random nonce (16 bytes as hex)
|
|
95
|
+
const nonceBytes = nacl.randomBytes(16);
|
|
96
|
+
const nonce = Array.from(nonceBytes).map(b => b.toString(16).padStart(2, "0")).join("");
|
|
97
|
+
// SHA-256 of the body (or empty string)
|
|
98
|
+
const bodyToHash = body || "";
|
|
99
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(bodyToHash));
|
|
100
|
+
const bodyHash = Array.from(new Uint8Array(hashBuffer))
|
|
101
|
+
.map(b => b.toString(16).padStart(2, "0"))
|
|
102
|
+
.join("");
|
|
103
|
+
// Construct and sign the signature input
|
|
104
|
+
const signatureInput = `${method}\n${path}\n${timestamp}\n${nonce}\n${bodyHash}`;
|
|
105
|
+
const signature = signMessage(signatureInput, signingSecretKey);
|
|
106
|
+
return {
|
|
107
|
+
"X-Agent-ID": agentId,
|
|
108
|
+
"X-Timestamp": timestamp,
|
|
109
|
+
"X-Nonce": nonce,
|
|
110
|
+
"X-Signature": signature,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
// ─── Group Symmetric Key Helpers (Large Groups §7) ──────────────────
|
|
114
|
+
/**
|
|
115
|
+
* Generate a random 32-byte NaCl secretbox key. Returns base64.
|
|
116
|
+
*/
|
|
117
|
+
export function generateGroupKey() {
|
|
118
|
+
const key = nacl.randomBytes(nacl.secretbox.keyLength);
|
|
119
|
+
return encodeBase64(key);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Encrypt using a group symmetric key (NaCl secretbox).
|
|
123
|
+
*/
|
|
124
|
+
export function encryptWithGroupKey(message, groupKey) {
|
|
125
|
+
const nonce = nacl.randomBytes(nacl.secretbox.nonceLength);
|
|
126
|
+
const messageBytes = decodeUTF8(message);
|
|
127
|
+
const keyBytes = decodeBase64(groupKey);
|
|
128
|
+
const encrypted = nacl.secretbox(messageBytes, nonce, keyBytes);
|
|
129
|
+
if (!encrypted)
|
|
130
|
+
throw new Error("Group encryption failed");
|
|
131
|
+
return {
|
|
132
|
+
encrypted_content: encodeBase64(encrypted),
|
|
133
|
+
nonce: encodeBase64(nonce),
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Decrypt using a group symmetric key (NaCl secretbox).
|
|
138
|
+
*/
|
|
139
|
+
export function decryptWithGroupKey(encryptedContent, nonce, groupKey) {
|
|
140
|
+
const encryptedBytes = decodeBase64(encryptedContent);
|
|
141
|
+
const nonceBytes = decodeBase64(nonce);
|
|
142
|
+
const keyBytes = decodeBase64(groupKey);
|
|
143
|
+
const decrypted = nacl.secretbox.open(encryptedBytes, nonceBytes, keyBytes);
|
|
144
|
+
if (!decrypted)
|
|
145
|
+
throw new Error("Group decryption failed — wrong key or corrupted message");
|
|
146
|
+
return encodeUTF8(decrypted);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Encrypt a group symmetric key for a specific member using NaCl box.
|
|
150
|
+
* This is how the group key is E2E-distributed to each member.
|
|
151
|
+
*/
|
|
152
|
+
export function encryptGroupKeyForMember(groupKey, memberPublicKey, senderSecretKey) {
|
|
153
|
+
return encryptForRecipient(groupKey, memberPublicKey, senderSecretKey);
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* HKDF-SHA256 key derivation (RFC 5869).
|
|
157
|
+
* Uses crypto.subtle (available in Node 18+ and Cloudflare Workers).
|
|
158
|
+
*/
|
|
159
|
+
export async function hkdf(ikm, salt, info, length) {
|
|
160
|
+
// Extract: PRK = HMAC-SHA256(salt, IKM)
|
|
161
|
+
const keyMaterial = await crypto.subtle.importKey("raw", salt.length > 0 ? salt : new Uint8Array(32), { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
|
|
162
|
+
const prk = new Uint8Array(await crypto.subtle.sign("HMAC", keyMaterial, ikm));
|
|
163
|
+
// Expand: OKM = T(1) || T(2) || ...
|
|
164
|
+
const prkKey = await crypto.subtle.importKey("raw", prk, { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
|
|
165
|
+
const n = Math.ceil(length / 32);
|
|
166
|
+
const okm = new Uint8Array(n * 32);
|
|
167
|
+
let prev = new Uint8Array(0);
|
|
168
|
+
for (let i = 1; i <= n; i++) {
|
|
169
|
+
const input = new Uint8Array(prev.length + info.length + 1);
|
|
170
|
+
input.set(prev);
|
|
171
|
+
input.set(info, prev.length);
|
|
172
|
+
input[prev.length + info.length] = i;
|
|
173
|
+
prev = new Uint8Array(await crypto.subtle.sign("HMAC", prkKey, input));
|
|
174
|
+
okm.set(prev, (i - 1) * 32);
|
|
175
|
+
}
|
|
176
|
+
return okm.slice(0, length);
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Raw X25519 Diffie-Hellman: derive shared secret from secret key + public key.
|
|
180
|
+
* Uses nacl.box.before which computes the X25519 shared point.
|
|
181
|
+
*/
|
|
182
|
+
export function dh(secretKey, publicKey) {
|
|
183
|
+
// nacl.box.before computes hsalsa20(X25519(sk, pk)) — a 32-byte shared key
|
|
184
|
+
return nacl.box.before(publicKey, secretKey);
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Generate a pre-key bundle for X3DH (Protocol v1 §4.2).
|
|
188
|
+
* Returns the bundle to upload to the relay + private keys to store locally.
|
|
189
|
+
*/
|
|
190
|
+
export function generatePreKeyBundle(identityPublicKey, signingSecretKey, numOneTimeKeys = 20) {
|
|
191
|
+
// Generate signed pre-key (medium-term)
|
|
192
|
+
const signedPreKeyPair = nacl.box.keyPair();
|
|
193
|
+
const signedPreKeyPublic = encodeBase64(signedPreKeyPair.publicKey);
|
|
194
|
+
// Sign the signed pre-key with Ed25519
|
|
195
|
+
const signingKey = decodeBase64(signingSecretKey);
|
|
196
|
+
const signature = nacl.sign.detached(signedPreKeyPair.publicKey, signingKey);
|
|
197
|
+
// Generate one-time pre-keys
|
|
198
|
+
const oneTimePreKeys = [];
|
|
199
|
+
const oneTimePreKeySecrets = [];
|
|
200
|
+
for (let i = 0; i < numOneTimeKeys; i++) {
|
|
201
|
+
const otpk = nacl.box.keyPair();
|
|
202
|
+
oneTimePreKeys.push({ key_id: i, public_key: encodeBase64(otpk.publicKey) });
|
|
203
|
+
oneTimePreKeySecrets.push({ key_id: i, secret_key: encodeBase64(otpk.secretKey) });
|
|
204
|
+
}
|
|
205
|
+
return {
|
|
206
|
+
bundle: {
|
|
207
|
+
identity_key: identityPublicKey,
|
|
208
|
+
signed_pre_key: signedPreKeyPublic,
|
|
209
|
+
signed_pre_key_signature: encodeBase64(signature),
|
|
210
|
+
signed_pre_key_id: 0,
|
|
211
|
+
one_time_pre_keys: oneTimePreKeys,
|
|
212
|
+
},
|
|
213
|
+
signedPreKeySecret: encodeBase64(signedPreKeyPair.secretKey),
|
|
214
|
+
oneTimePreKeySecrets,
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Generate additional one-time pre-keys (for replenishment).
|
|
219
|
+
*/
|
|
220
|
+
export function generateOneTimePreKeys(count, startId) {
|
|
221
|
+
const publicKeys = [];
|
|
222
|
+
const secretKeys = [];
|
|
223
|
+
for (let i = 0; i < count; i++) {
|
|
224
|
+
const kp = nacl.box.keyPair();
|
|
225
|
+
publicKeys.push({ key_id: startId + i, public_key: encodeBase64(kp.publicKey) });
|
|
226
|
+
secretKeys.push({ key_id: startId + i, secret_key: encodeBase64(kp.secretKey) });
|
|
227
|
+
}
|
|
228
|
+
return { publicKeys, secretKeys };
|
|
229
|
+
}
|
|
230
|
+
const X3DH_INFO = new TextEncoder().encode("SYNLinkX3DH");
|
|
231
|
+
/**
|
|
232
|
+
* X3DH initiator side — derive shared secret from peer's pre-key bundle.
|
|
233
|
+
*
|
|
234
|
+
* Computes: DH1 = DH(IKa, SPKb), DH2 = DH(EKa, IKb), DH3 = DH(EKa, SPKb), [DH4 = DH(EKa, OPKb)]
|
|
235
|
+
* SharedSecret = HKDF(DH1 || DH2 || DH3 [|| DH4])
|
|
236
|
+
*/
|
|
237
|
+
export async function x3dhInitiate(myIdentitySecretKey, peerBundle) {
|
|
238
|
+
const IKa_sk = decodeBase64(myIdentitySecretKey);
|
|
239
|
+
const IKb_pk = decodeBase64(peerBundle.identity_key);
|
|
240
|
+
const SPKb_pk = decodeBase64(peerBundle.signed_pre_key);
|
|
241
|
+
// Generate ephemeral key pair
|
|
242
|
+
const EKa = nacl.box.keyPair();
|
|
243
|
+
// DH1 = DH(IKa, SPKb) — our identity key × their signed pre-key
|
|
244
|
+
const dh1 = dh(IKa_sk, SPKb_pk);
|
|
245
|
+
// DH2 = DH(EKa, IKb) — our ephemeral × their identity key
|
|
246
|
+
const dh2 = dh(EKa.secretKey, IKb_pk);
|
|
247
|
+
// DH3 = DH(EKa, SPKb) — our ephemeral × their signed pre-key
|
|
248
|
+
const dh3 = dh(EKa.secretKey, SPKb_pk);
|
|
249
|
+
let dhConcat;
|
|
250
|
+
let usedOneTimePreKeyId;
|
|
251
|
+
if (peerBundle.one_time_pre_key) {
|
|
252
|
+
// DH4 = DH(EKa, OPKb) — our ephemeral × their one-time pre-key
|
|
253
|
+
const OPKb_pk = decodeBase64(peerBundle.one_time_pre_key.public_key);
|
|
254
|
+
const dh4 = dh(EKa.secretKey, OPKb_pk);
|
|
255
|
+
dhConcat = new Uint8Array(128);
|
|
256
|
+
dhConcat.set(dh1, 0);
|
|
257
|
+
dhConcat.set(dh2, 32);
|
|
258
|
+
dhConcat.set(dh3, 64);
|
|
259
|
+
dhConcat.set(dh4, 96);
|
|
260
|
+
usedOneTimePreKeyId = peerBundle.one_time_pre_key.key_id;
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
dhConcat = new Uint8Array(96);
|
|
264
|
+
dhConcat.set(dh1, 0);
|
|
265
|
+
dhConcat.set(dh2, 32);
|
|
266
|
+
dhConcat.set(dh3, 64);
|
|
267
|
+
}
|
|
268
|
+
const sharedSecret = await hkdf(dhConcat, new Uint8Array(32), X3DH_INFO, 32);
|
|
269
|
+
return {
|
|
270
|
+
sharedSecret,
|
|
271
|
+
ephemeralPublicKey: encodeBase64(EKa.publicKey),
|
|
272
|
+
usedOneTimePreKeyId,
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* X3DH responder side — derive shared secret from initiator's first message header.
|
|
277
|
+
*/
|
|
278
|
+
export async function x3dhRespond(myIdentitySecretKey, mySignedPreKeySecret, myOneTimePreKeySecret, header) {
|
|
279
|
+
const IKb_sk = decodeBase64(myIdentitySecretKey);
|
|
280
|
+
const SPKb_sk = decodeBase64(mySignedPreKeySecret);
|
|
281
|
+
const IKa_pk = decodeBase64(header.identity_key);
|
|
282
|
+
const EKa_pk = decodeBase64(header.ephemeral_key);
|
|
283
|
+
// DH1 = DH(SPKb, IKa) — our signed pre-key × their identity key
|
|
284
|
+
const dh1 = dh(SPKb_sk, IKa_pk);
|
|
285
|
+
// DH2 = DH(IKb, EKa) — our identity key × their ephemeral
|
|
286
|
+
const dh2 = dh(IKb_sk, EKa_pk);
|
|
287
|
+
// DH3 = DH(SPKb, EKa) — our signed pre-key × their ephemeral
|
|
288
|
+
const dh3 = dh(SPKb_sk, EKa_pk);
|
|
289
|
+
let dhConcat;
|
|
290
|
+
if (myOneTimePreKeySecret) {
|
|
291
|
+
const OPKb_sk = decodeBase64(myOneTimePreKeySecret);
|
|
292
|
+
// DH4 = DH(OPKb, EKa) — our one-time key × their ephemeral
|
|
293
|
+
const dh4 = dh(OPKb_sk, EKa_pk);
|
|
294
|
+
dhConcat = new Uint8Array(128);
|
|
295
|
+
dhConcat.set(dh1, 0);
|
|
296
|
+
dhConcat.set(dh2, 32);
|
|
297
|
+
dhConcat.set(dh3, 64);
|
|
298
|
+
dhConcat.set(dh4, 96);
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
dhConcat = new Uint8Array(96);
|
|
302
|
+
dhConcat.set(dh1, 0);
|
|
303
|
+
dhConcat.set(dh2, 32);
|
|
304
|
+
dhConcat.set(dh3, 64);
|
|
305
|
+
}
|
|
306
|
+
return hkdf(dhConcat, new Uint8Array(32), X3DH_INFO, 32);
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Symmetric encryption with NaCl secretbox (used by Double Ratchet).
|
|
310
|
+
* Input and output are raw Uint8Array (not base64).
|
|
311
|
+
*/
|
|
312
|
+
export function secretboxEncrypt(plaintext, key) {
|
|
313
|
+
const nonce = nacl.randomBytes(nacl.secretbox.nonceLength);
|
|
314
|
+
const ciphertext = nacl.secretbox(plaintext, nonce, key);
|
|
315
|
+
return { ciphertext, nonce };
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Symmetric decryption with NaCl secretbox (used by Double Ratchet).
|
|
319
|
+
*/
|
|
320
|
+
export function secretboxDecrypt(ciphertext, nonce, key) {
|
|
321
|
+
const plaintext = nacl.secretbox.open(ciphertext, nonce, key);
|
|
322
|
+
if (!plaintext)
|
|
323
|
+
throw new Error("Ratchet decryption failed — wrong key or corrupted message");
|
|
324
|
+
return plaintext;
|
|
325
|
+
}
|
|
326
|
+
//# sourceMappingURL=crypto.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto.js","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"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"}
|