@airterm/protocol 0.2.0 → 0.4.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 (58) hide show
  1. package/README.md +29 -9
  2. package/dist/direct-negotiation.d.ts +40 -0
  3. package/dist/direct-negotiation.d.ts.map +1 -0
  4. package/dist/direct-negotiation.js +169 -0
  5. package/dist/direct-negotiation.js.map +1 -0
  6. package/dist/framing.d.ts +4 -1
  7. package/dist/framing.d.ts.map +1 -1
  8. package/dist/framing.js +3 -0
  9. package/dist/framing.js.map +1 -1
  10. package/dist/index.d.ts +21 -10
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +16 -5
  13. package/dist/index.js.map +1 -1
  14. package/dist/messages.d.ts +3 -1
  15. package/dist/messages.d.ts.map +1 -1
  16. package/dist/messages.js +20 -6
  17. package/dist/messages.js.map +1 -1
  18. package/dist/naming.d.ts +19 -0
  19. package/dist/naming.d.ts.map +1 -0
  20. package/dist/naming.js +85 -0
  21. package/dist/naming.js.map +1 -0
  22. package/dist/outbound-queue.d.ts +17 -0
  23. package/dist/outbound-queue.d.ts.map +1 -0
  24. package/dist/outbound-queue.js +150 -0
  25. package/dist/outbound-queue.js.map +1 -0
  26. package/dist/p2p.d.ts +37 -0
  27. package/dist/p2p.d.ts.map +1 -0
  28. package/dist/p2p.js +91 -0
  29. package/dist/p2p.js.map +1 -0
  30. package/dist/pairing.d.ts +18 -0
  31. package/dist/pairing.d.ts.map +1 -0
  32. package/dist/pairing.js +48 -0
  33. package/dist/pairing.js.map +1 -0
  34. package/dist/peer-transport.d.ts +31 -0
  35. package/dist/peer-transport.d.ts.map +1 -0
  36. package/dist/peer-transport.js +155 -0
  37. package/dist/peer-transport.js.map +1 -0
  38. package/dist/relay-usage.d.ts +13 -0
  39. package/dist/relay-usage.d.ts.map +1 -0
  40. package/dist/relay-usage.js +18 -0
  41. package/dist/relay-usage.js.map +1 -0
  42. package/dist/transport-handoff.d.ts +25 -0
  43. package/dist/transport-handoff.d.ts.map +1 -0
  44. package/dist/transport-handoff.js +207 -0
  45. package/dist/transport-handoff.js.map +1 -0
  46. package/dist/transport.d.ts +39 -0
  47. package/dist/transport.d.ts.map +1 -0
  48. package/dist/transport.js +92 -0
  49. package/dist/transport.js.map +1 -0
  50. package/dist/vault.d.ts +51 -0
  51. package/dist/vault.d.ts.map +1 -0
  52. package/dist/vault.js +215 -0
  53. package/dist/vault.js.map +1 -0
  54. package/dist/webrtc-transport.d.ts +14 -0
  55. package/dist/webrtc-transport.d.ts.map +1 -0
  56. package/dist/webrtc-transport.js +106 -0
  57. package/dist/webrtc-transport.js.map +1 -0
  58. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vault.d.ts","sourceRoot":"","sources":["../src/vault.ts"],"names":[],"mappings":"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"}
package/dist/vault.js ADDED
@@ -0,0 +1,215 @@
1
+ import { decodeBase64Url, encodeBase64Url } from "./capability.js";
2
+ export const VAULT_VERSION = 1;
3
+ export const VAULT_PRF_INPUT = new TextEncoder().encode("airterm/vault/v1/passkey");
4
+ const encoder = new TextEncoder();
5
+ const decoder = new TextDecoder("utf-8", { fatal: true });
6
+ const bytes = (data) => new Uint8Array(data).buffer;
7
+ export const randomVaultBytes = (length = 32) => crypto.getRandomValues(new Uint8Array(length));
8
+ function context(context, purpose) {
9
+ if (!/^[1-9][0-9]{0,18}$/.test(context.accountId) ||
10
+ !Number.isSafeInteger(context.generation) ||
11
+ context.generation < 1)
12
+ throw new Error("Invalid vault identity");
13
+ return encoder.encode(JSON.stringify([
14
+ "airterm-vault",
15
+ 1,
16
+ context.accountId,
17
+ context.generation,
18
+ purpose,
19
+ ]));
20
+ }
21
+ function decode(value, minimum, maximum = minimum) {
22
+ if (typeof value !== "string" ||
23
+ value.length > Math.ceil((maximum * 4) / 3) ||
24
+ !/^[A-Za-z0-9_-]+$/.test(value))
25
+ throw new Error("Invalid vault encoding");
26
+ const result = decodeBase64Url(value);
27
+ if (result.length < minimum ||
28
+ result.length > maximum ||
29
+ encodeBase64Url(result) !== value)
30
+ throw new Error("Invalid vault size");
31
+ return result;
32
+ }
33
+ export async function vaultKdf(secret, salt, identity, purpose) {
34
+ if (secret.length !== 32)
35
+ throw new Error("Invalid key material");
36
+ const key = await crypto.subtle.importKey("raw", bytes(secret), "HKDF", false, ["deriveBits"]);
37
+ return new Uint8Array(await crypto.subtle.deriveBits({
38
+ name: "HKDF",
39
+ hash: "SHA-256",
40
+ salt: bytes(decode(salt, 16)),
41
+ info: bytes(context(identity, purpose)),
42
+ }, key, 256));
43
+ }
44
+ export async function sealVaultValue(data, secret, identity, purpose) {
45
+ if (secret.length !== 32 || data.length > 4096)
46
+ throw new Error("Invalid vault value");
47
+ const nonce = randomVaultBytes(12);
48
+ const key = await crypto.subtle.importKey("raw", bytes(secret), "AES-GCM", false, ["encrypt"]);
49
+ return {
50
+ nonce: encodeBase64Url(nonce),
51
+ ciphertext: encodeBase64Url(new Uint8Array(await crypto.subtle.encrypt({
52
+ name: "AES-GCM",
53
+ iv: bytes(nonce),
54
+ additionalData: bytes(context(identity, purpose)),
55
+ tagLength: 128,
56
+ }, key, bytes(data)))),
57
+ };
58
+ }
59
+ export async function openVaultValue(value, secret, identity, purpose) {
60
+ if (secret.length !== 32)
61
+ throw new Error("Invalid vault key");
62
+ const key = await crypto.subtle.importKey("raw", bytes(secret), "AES-GCM", false, ["decrypt"]);
63
+ return new Uint8Array(await crypto.subtle.decrypt({
64
+ name: "AES-GCM",
65
+ iv: bytes(decode(value.nonce, 12)),
66
+ additionalData: bytes(context(identity, purpose)),
67
+ tagLength: 128,
68
+ }, key, bytes(decode(value.ciphertext, 16, 4112))));
69
+ }
70
+ export async function createRecoveryCode() {
71
+ const secret = randomVaultBytes();
72
+ const checksum = new Uint8Array(await crypto.subtle.digest("SHA-256", bytes(secret))).slice(0, 4);
73
+ return `airterm-recovery-v1.${encodeBase64Url(secret)}.${encodeBase64Url(checksum)}`;
74
+ }
75
+ export async function decodeRecoveryCode(code) {
76
+ const parts = code.split(".");
77
+ if (parts.length !== 3 || parts[0] !== "airterm-recovery-v1")
78
+ throw new Error("Invalid recovery key");
79
+ const secret = decode(parts[1], 32);
80
+ const checksum = new Uint8Array(await crypto.subtle.digest("SHA-256", bytes(secret))).slice(0, 4);
81
+ if (encodeBase64Url(checksum) !== parts[2])
82
+ throw new Error("Invalid recovery key checksum");
83
+ return secret;
84
+ }
85
+ function fields(value, allowed) {
86
+ if (!value || typeof value !== 'object' || Array.isArray(value) || Object.keys(value).some(key => !allowed.includes(key)))
87
+ throw new Error('Unsupported vault fields');
88
+ }
89
+ export function validateVaultEnvelope(value) {
90
+ if (value === null || typeof value !== "object")
91
+ throw new Error("Invalid vault");
92
+ fields(value, ['version', 'accountId', 'generation', 'publicKey', 'privateKey', 'primary', 'recovery']);
93
+ const v = value;
94
+ fields(v.primary, ['mode', 'salt', 'credentialId', 'nonce', 'ciphertext']);
95
+ fields(v.recovery, ['salt', 'nonce', 'ciphertext']);
96
+ fields(v.privateKey, ['nonce', 'ciphertext']);
97
+ if (v.version !== 1)
98
+ throw new Error("Unsupported vault version");
99
+ context(v, "validate");
100
+ decode(v.publicKey, 422, 422);
101
+ if (!v.primary || !["passkey", "passphrase"].includes(v.primary.mode))
102
+ throw new Error("Invalid vault unlock method");
103
+ if (v.primary.mode === "passkey")
104
+ decode(v.primary.credentialId, 1, 1024);
105
+ else if (v.primary.credentialId !== undefined)
106
+ throw new Error("Unexpected passphrase credential");
107
+ for (const wrapper of [v.primary, v.recovery]) {
108
+ decode(wrapper.salt, 16);
109
+ decode(wrapper.nonce, 12);
110
+ decode(wrapper.ciphertext, 48);
111
+ }
112
+ decode(v.privateKey.nonce, 12);
113
+ decode(v.privateKey.ciphertext, 1000, 4112);
114
+ }
115
+ export async function publicKeyFingerprint(publicKey) {
116
+ return encodeBase64Url(new Uint8Array(await crypto.subtle.digest("SHA-256", bytes(decode(publicKey, 422)))));
117
+ }
118
+ async function importPublic(publicKey) {
119
+ const key = await crypto.subtle.importKey("spki", bytes(decode(publicKey, 422)), { name: "RSA-OAEP", hash: "SHA-256" }, false, ["encrypt"]);
120
+ const algorithm = key.algorithm;
121
+ if (algorithm.modulusLength !== 3072 ||
122
+ encodeBase64Url(algorithm.publicExponent) !== "AQAB")
123
+ throw new Error("Unsupported public key");
124
+ return key;
125
+ }
126
+ export async function createVault(identity, primary, wrappingKey, recoveryCode) {
127
+ context(identity, "create");
128
+ const keys = await crypto.subtle.generateKey({
129
+ name: "RSA-OAEP",
130
+ modulusLength: 3072,
131
+ publicExponent: new Uint8Array([1, 0, 1]),
132
+ hash: "SHA-256",
133
+ }, true, ["encrypt", "decrypt"]);
134
+ const vaultKey = randomVaultBytes();
135
+ const rawPrivate = new Uint8Array(await crypto.subtle.exportKey("pkcs8", keys.privateKey));
136
+ const recoverySalt = encodeBase64Url(randomVaultBytes(16));
137
+ const recoveryKey = await vaultKdf(await decodeRecoveryCode(recoveryCode), recoverySalt, identity, "recovery");
138
+ const envelope = {
139
+ version: 1,
140
+ accountId: identity.accountId,
141
+ generation: identity.generation,
142
+ publicKey: encodeBase64Url(new Uint8Array(await crypto.subtle.exportKey("spki", keys.publicKey))),
143
+ privateKey: await sealVaultValue(rawPrivate, vaultKey, identity, "private-key"),
144
+ primary: {
145
+ ...primary,
146
+ ...(await sealVaultValue(vaultKey, wrappingKey, identity, `primary:${primary.mode}:${primary.credentialId ?? ""}`)),
147
+ },
148
+ recovery: {
149
+ salt: recoverySalt,
150
+ ...(await sealVaultValue(vaultKey, recoveryKey, identity, "recovery")),
151
+ },
152
+ };
153
+ const privateKey = await crypto.subtle.importKey('pkcs8', bytes(rawPrivate), { name: 'RSA-OAEP', hash: 'SHA-256' }, false, ['decrypt']);
154
+ rawPrivate.fill(0);
155
+ recoveryKey.fill(0);
156
+ validateVaultEnvelope(envelope);
157
+ return { envelope, vaultKey, privateKey };
158
+ }
159
+ export async function unlockVault(envelope, wrappingKey, recovery = false) {
160
+ validateVaultEnvelope(envelope);
161
+ const primary = envelope.primary;
162
+ const vaultKey = await openVaultValue(recovery ? envelope.recovery : primary, wrappingKey, envelope, recovery
163
+ ? "recovery"
164
+ : `primary:${primary.mode}:${primary.credentialId ?? ""}`);
165
+ const raw = await openVaultValue(envelope.privateKey, vaultKey, envelope, "private-key");
166
+ try {
167
+ const privateKey = await crypto.subtle.importKey("pkcs8", bytes(raw), { name: "RSA-OAEP", hash: "SHA-256" }, false, ["decrypt"]);
168
+ const challenge = randomVaultBytes();
169
+ const encrypted = await crypto.subtle.encrypt({ name: "RSA-OAEP" }, await importPublic(envelope.publicKey), bytes(challenge));
170
+ const opened = new Uint8Array(await crypto.subtle.decrypt({ name: "RSA-OAEP" }, privateKey, encrypted));
171
+ if (encodeBase64Url(challenge) !== encodeBase64Url(opened))
172
+ throw new Error("Vault key mismatch");
173
+ return { vaultKey, privateKey };
174
+ }
175
+ finally {
176
+ raw.fill(0);
177
+ }
178
+ }
179
+ export async function encryptAccountSession(publicKey, identity, sessionId, rootSecret) {
180
+ decode(sessionId, 16);
181
+ decode(rootSecret, 32);
182
+ const payload = encoder.encode(JSON.stringify([
183
+ 1,
184
+ identity.accountId,
185
+ identity.generation,
186
+ sessionId,
187
+ rootSecret,
188
+ ]));
189
+ return {
190
+ version: 1,
191
+ accountId: identity.accountId,
192
+ generation: identity.generation,
193
+ ciphertext: encodeBase64Url(new Uint8Array(await crypto.subtle.encrypt({ name: "RSA-OAEP", label: bytes(context(identity, "session")) }, await importPublic(publicKey), bytes(payload)))),
194
+ };
195
+ }
196
+ export async function decryptAccountSession(privateKey, envelope, identity, sessionId) {
197
+ fields(envelope, ['version', 'accountId', 'generation', 'ciphertext']);
198
+ if (envelope.version !== 1 ||
199
+ envelope.accountId !== identity.accountId ||
200
+ envelope.generation !== identity.generation)
201
+ throw new Error("Session vault mismatch");
202
+ const raw = await crypto.subtle.decrypt({ name: "RSA-OAEP", label: bytes(context(identity, "session")) }, privateKey, bytes(decode(envelope.ciphertext, 384)));
203
+ const payload = JSON.parse(decoder.decode(raw));
204
+ if (!Array.isArray(payload) ||
205
+ payload.length !== 5 ||
206
+ payload[0] !== 1 ||
207
+ payload[1] !== identity.accountId ||
208
+ payload[2] !== identity.generation ||
209
+ payload[3] !== sessionId ||
210
+ typeof payload[4] !== "string")
211
+ throw new Error("Invalid session identity");
212
+ decode(payload[4], 32);
213
+ return payload[4];
214
+ }
215
+ //# sourceMappingURL=vault.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vault.js","sourceRoot":"","sources":["../src/vault.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { BinaryTransport } from './transport.js';
2
+ /** Ordered fragmentation is below encryption; only complete bounded frames escape. */
3
+ export declare class WebRTCTransport implements BinaryTransport {
4
+ #private;
5
+ private readonly channel;
6
+ private readonly receiveFrame;
7
+ private readonly failure;
8
+ constructor(channel: BinaryTransport, receiveFrame: (bytes: Uint8Array) => void, failure: (error: Error) => void);
9
+ get bufferedAmount(): number;
10
+ write(bytes: Uint8Array, done: (error?: Error | null) => void): void;
11
+ receive(fragment: Uint8Array): void;
12
+ close(): void;
13
+ }
14
+ //# sourceMappingURL=webrtc-transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webrtc-transport.d.ts","sourceRoot":"","sources":["../src/webrtc-transport.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAMtD,sFAAsF;AACtF,qBAAa,eAAgB,YAAW,eAAe;;IAO/C,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAFP,OAAO,EAAE,eAAe,EACxB,YAAY,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,EACzC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI;IAEpD,IAAW,cAAc,IAAI,MAAM,CAElC;IACM,KAAK,CACR,KAAK,EAAE,UAAU,EACjB,IAAI,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,KAAK,IAAI,GACrC,IAAI;IAqCA,OAAO,CAAC,QAAQ,EAAE,UAAU,GAAG,IAAI;IAkDnC,KAAK,IAAI,IAAI;CAavB"}
@@ -0,0 +1,106 @@
1
+ import { MAX_CIPHERTEXT_BYTES } from './framing.js';
2
+ const MESSAGE_BYTES = 16 * 1024;
3
+ const HEADER_BYTES = 8;
4
+ const FRAME_BYTES = MAX_CIPHERTEXT_BYTES + 2;
5
+ /** Ordered fragmentation is below encryption; only complete bounded frames escape. */
6
+ export class WebRTCTransport {
7
+ channel;
8
+ receiveFrame;
9
+ failure;
10
+ #assembly;
11
+ #offset = 0;
12
+ #timer;
13
+ #closed = false;
14
+ #writing = false;
15
+ constructor(channel, receiveFrame, failure) {
16
+ this.channel = channel;
17
+ this.receiveFrame = receiveFrame;
18
+ this.failure = failure;
19
+ }
20
+ get bufferedAmount() {
21
+ return this.channel.bufferedAmount;
22
+ }
23
+ write(bytes, done) {
24
+ if (this.#closed ||
25
+ this.#writing ||
26
+ bytes.length < 2 ||
27
+ bytes.length > FRAME_BYTES) {
28
+ done(new Error('Invalid direct transport write.'));
29
+ return;
30
+ }
31
+ this.#writing = true;
32
+ let offset = 0;
33
+ const next = (error) => {
34
+ if (error || this.#closed) {
35
+ this.#writing = false;
36
+ done(error ?? new Error('Direct transport closed.'));
37
+ return;
38
+ }
39
+ if (offset === bytes.length) {
40
+ this.#writing = false;
41
+ done();
42
+ return;
43
+ }
44
+ const end = Math.min(bytes.length, offset + MESSAGE_BYTES - HEADER_BYTES);
45
+ const fragment = new Uint8Array(HEADER_BYTES + end - offset);
46
+ const header = new DataView(fragment.buffer);
47
+ header.setUint32(0, bytes.length);
48
+ header.setUint32(4, offset);
49
+ fragment.set(bytes.subarray(offset, end), HEADER_BYTES);
50
+ offset = end;
51
+ this.channel.write(fragment, next);
52
+ };
53
+ next();
54
+ }
55
+ receive(fragment) {
56
+ if (this.#closed)
57
+ return;
58
+ try {
59
+ if (fragment.length <= HEADER_BYTES ||
60
+ fragment.length > MESSAGE_BYTES)
61
+ throw new Error('Invalid direct fragment size.');
62
+ const view = new DataView(fragment.buffer, fragment.byteOffset, fragment.byteLength);
63
+ const length = view.getUint32(0);
64
+ const offset = view.getUint32(4);
65
+ if (length < 2 || length > FRAME_BYTES || offset !== this.#offset)
66
+ throw new Error('Invalid direct fragment offset.');
67
+ if (this.#assembly === undefined) {
68
+ this.#assembly = new Uint8Array(length);
69
+ this.#timer = setTimeout(() => this.#fail(new Error('Direct frame assembly timed out.')), 10_000);
70
+ }
71
+ if (length !== this.#assembly.length ||
72
+ offset + fragment.length - HEADER_BYTES > length)
73
+ throw new Error('Invalid direct fragment length.');
74
+ this.#assembly.set(fragment.subarray(HEADER_BYTES), offset);
75
+ this.#offset += fragment.length - HEADER_BYTES;
76
+ if (this.#offset === length) {
77
+ const frame = this.#assembly;
78
+ this.#assembly = undefined;
79
+ this.#offset = 0;
80
+ clearTimeout(this.#timer);
81
+ this.#timer = undefined;
82
+ this.receiveFrame(frame);
83
+ }
84
+ }
85
+ catch (error) {
86
+ this.#fail(error instanceof Error
87
+ ? error
88
+ : new Error('Direct transport failed.'));
89
+ }
90
+ }
91
+ close() {
92
+ if (this.#closed)
93
+ return;
94
+ this.#closed = true;
95
+ clearTimeout(this.#timer);
96
+ this.#timer = undefined;
97
+ this.#assembly = undefined;
98
+ this.#offset = 0;
99
+ this.channel.close();
100
+ }
101
+ #fail(error) {
102
+ this.close();
103
+ this.failure(error);
104
+ }
105
+ }
106
+ //# sourceMappingURL=webrtc-transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webrtc-transport.js","sourceRoot":"","sources":["../src/webrtc-transport.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@airterm/protocol",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "Shared browser and Node.js protocol implementation for AirTerm",
5
5
  "keywords": [
6
6
  "terminal",