@sideband/secure-relay 0.0.1 → 0.1.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/dist/LICENSE +695 -0
- package/package.json +1 -2
- package/dist/.tsbuildinfo +0 -1
- package/dist/constants.d.ts +0 -33
- package/dist/constants.d.ts.map +0 -1
- package/dist/constants.js +0 -35
- package/dist/constants.js.map +0 -1
- package/dist/crypto.d.ts +0 -70
- package/dist/crypto.d.ts.map +0 -1
- package/dist/crypto.js +0 -145
- package/dist/crypto.js.map +0 -1
- package/dist/handshake.d.ts +0 -42
- package/dist/handshake.d.ts.map +0 -1
- package/dist/handshake.js +0 -83
- package/dist/handshake.js.map +0 -1
- package/dist/index.d.ts +0 -45
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -11
- package/dist/index.js.map +0 -1
- package/dist/replay.d.ts +0 -32
- package/dist/replay.d.ts.map +0 -1
- package/dist/replay.js +0 -89
- package/dist/replay.js.map +0 -1
- package/dist/session.d.ts +0 -67
- package/dist/session.d.ts.map +0 -1
- package/dist/session.js +0 -123
- package/dist/session.js.map +0 -1
- package/dist/types.d.ts +0 -79
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -39
- package/dist/types.js.map +0 -1
package/dist/handshake.js
DELETED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
// SPDX-FileCopyrightText: 2025-present Sideband
|
|
2
|
-
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
3
|
-
/**
|
|
4
|
-
* E2EE handshake protocol for Sideband Relay Protocol (SBRP).
|
|
5
|
-
*
|
|
6
|
-
* Implements the authenticated key exchange between browser and daemon,
|
|
7
|
-
* with Ed25519 signatures for MITM protection.
|
|
8
|
-
*/
|
|
9
|
-
import { computeSharedSecret, createSignaturePayload, createTranscriptHash, deriveTrafficKeys, generateEphemeralKeyPair, signPayload, verifySignature, zeroize, } from "./crypto.js";
|
|
10
|
-
import { SbrpError, SbrpErrorCode } from "./types.js";
|
|
11
|
-
/**
|
|
12
|
-
* Create a handshake init message (browser side).
|
|
13
|
-
*
|
|
14
|
-
* Generates an ephemeral X25519 keypair for this session.
|
|
15
|
-
*/
|
|
16
|
-
export function createHandshakeInit() {
|
|
17
|
-
const ephemeralKeyPair = generateEphemeralKeyPair();
|
|
18
|
-
return {
|
|
19
|
-
message: {
|
|
20
|
-
type: "handshake.init",
|
|
21
|
-
browserPublicKey: ephemeralKeyPair.publicKey,
|
|
22
|
-
},
|
|
23
|
-
ephemeralKeyPair,
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Process handshake init and create accept message (daemon side).
|
|
28
|
-
*
|
|
29
|
-
* 1. Generate ephemeral X25519 keypair
|
|
30
|
-
* 2. Sign ephemeral public key with identity key (context-bound)
|
|
31
|
-
* 3. Derive traffic keys
|
|
32
|
-
*/
|
|
33
|
-
export function processHandshakeInit(init, daemonId, identityKeyPair) {
|
|
34
|
-
const ephemeralKeyPair = generateEphemeralKeyPair();
|
|
35
|
-
// Sign ephemeral key with context binding
|
|
36
|
-
const signaturePayload = createSignaturePayload(daemonId, init.browserPublicKey, ephemeralKeyPair.publicKey);
|
|
37
|
-
const signature = signPayload(signaturePayload, identityKeyPair.privateKey);
|
|
38
|
-
// Derive traffic keys
|
|
39
|
-
const sharedSecret = computeSharedSecret(ephemeralKeyPair.privateKey, init.browserPublicKey);
|
|
40
|
-
const transcriptHash = createTranscriptHash(daemonId, init.browserPublicKey, ephemeralKeyPair.publicKey, signature);
|
|
41
|
-
const trafficKeys = deriveTrafficKeys(sharedSecret, transcriptHash);
|
|
42
|
-
// Best-effort zeroize shared secret
|
|
43
|
-
zeroize(sharedSecret);
|
|
44
|
-
return {
|
|
45
|
-
message: {
|
|
46
|
-
type: "handshake.accept",
|
|
47
|
-
daemonPublicKey: ephemeralKeyPair.publicKey,
|
|
48
|
-
signature,
|
|
49
|
-
},
|
|
50
|
-
result: {
|
|
51
|
-
trafficKeys,
|
|
52
|
-
ephemeralKeyPair,
|
|
53
|
-
signature,
|
|
54
|
-
},
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Process handshake accept message (client side).
|
|
59
|
-
*
|
|
60
|
-
* 1. Verify signature using PINNED identity key (TOFU)
|
|
61
|
-
* 2. Derive traffic keys using same transcript hash as daemon
|
|
62
|
-
*
|
|
63
|
-
* @throws {SbrpError} with code HandshakeFailed if signature verification fails
|
|
64
|
-
*/
|
|
65
|
-
export function processHandshakeAccept(accept, daemonId, pinnedIdentityPublicKey, ephemeralKeyPair) {
|
|
66
|
-
// Verify daemon signature using PINNED key (not relay-provided!)
|
|
67
|
-
const signaturePayload = createSignaturePayload(daemonId, ephemeralKeyPair.publicKey, accept.daemonPublicKey);
|
|
68
|
-
const valid = verifySignature(signaturePayload, accept.signature, pinnedIdentityPublicKey);
|
|
69
|
-
if (!valid) {
|
|
70
|
-
throw new SbrpError(SbrpErrorCode.HandshakeFailed, "Signature verification failed");
|
|
71
|
-
}
|
|
72
|
-
// Derive traffic keys using same transcript hash as daemon
|
|
73
|
-
const sharedSecret = computeSharedSecret(ephemeralKeyPair.privateKey, accept.daemonPublicKey);
|
|
74
|
-
const transcriptHash = createTranscriptHash(daemonId, ephemeralKeyPair.publicKey, accept.daemonPublicKey, accept.signature);
|
|
75
|
-
const trafficKeys = deriveTrafficKeys(sharedSecret, transcriptHash);
|
|
76
|
-
// Best-effort zeroize shared secret
|
|
77
|
-
zeroize(sharedSecret);
|
|
78
|
-
return {
|
|
79
|
-
trafficKeys,
|
|
80
|
-
ephemeralKeyPair,
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
//# sourceMappingURL=handshake.js.map
|
package/dist/handshake.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"handshake.js","sourceRoot":"","sources":["../src/handshake.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,6CAA6C;AAE7C;;;;;GAKG;AAEH,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,EACpB,iBAAiB,EACjB,wBAAwB,EACxB,WAAW,EACX,eAAe,EACf,OAAO,GACR,MAAM,aAAa,CAAC;AASrB,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAetD;;;;GAIG;AACH,MAAM,UAAU,mBAAmB;IAIjC,MAAM,gBAAgB,GAAG,wBAAwB,EAAE,CAAC;IACpD,OAAO;QACL,OAAO,EAAE;YACP,IAAI,EAAE,gBAAgB;YACtB,gBAAgB,EAAE,gBAAgB,CAAC,SAAS;SAC7C;QACD,gBAAgB;KACjB,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAClC,IAAmB,EACnB,QAAkB,EAClB,eAAgC;IAEhC,MAAM,gBAAgB,GAAG,wBAAwB,EAAE,CAAC;IAEpD,0CAA0C;IAC1C,MAAM,gBAAgB,GAAG,sBAAsB,CAC7C,QAAQ,EACR,IAAI,CAAC,gBAAgB,EACrB,gBAAgB,CAAC,SAAS,CAC3B,CAAC;IACF,MAAM,SAAS,GAAG,WAAW,CAAC,gBAAgB,EAAE,eAAe,CAAC,UAAU,CAAC,CAAC;IAE5E,sBAAsB;IACtB,MAAM,YAAY,GAAG,mBAAmB,CACtC,gBAAgB,CAAC,UAAU,EAC3B,IAAI,CAAC,gBAAgB,CACtB,CAAC;IACF,MAAM,cAAc,GAAG,oBAAoB,CACzC,QAAQ,EACR,IAAI,CAAC,gBAAgB,EACrB,gBAAgB,CAAC,SAAS,EAC1B,SAAS,CACV,CAAC;IACF,MAAM,WAAW,GAAG,iBAAiB,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC;IAEpE,oCAAoC;IACpC,OAAO,CAAC,YAAY,CAAC,CAAC;IAEtB,OAAO;QACL,OAAO,EAAE;YACP,IAAI,EAAE,kBAAkB;YACxB,eAAe,EAAE,gBAAgB,CAAC,SAAS;YAC3C,SAAS;SACV;QACD,MAAM,EAAE;YACN,WAAW;YACX,gBAAgB;YAChB,SAAS;SACV;KACF,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,sBAAsB,CACpC,MAAuB,EACvB,QAAkB,EAClB,uBAAmC,EACnC,gBAAkC;IAElC,iEAAiE;IACjE,MAAM,gBAAgB,GAAG,sBAAsB,CAC7C,QAAQ,EACR,gBAAgB,CAAC,SAAS,EAC1B,MAAM,CAAC,eAAe,CACvB,CAAC;IAEF,MAAM,KAAK,GAAG,eAAe,CAC3B,gBAAgB,EAChB,MAAM,CAAC,SAAS,EAChB,uBAAuB,CACxB,CAAC;IAEF,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,SAAS,CACjB,aAAa,CAAC,eAAe,EAC7B,+BAA+B,CAChC,CAAC;IACJ,CAAC;IAED,2DAA2D;IAC3D,MAAM,YAAY,GAAG,mBAAmB,CACtC,gBAAgB,CAAC,UAAU,EAC3B,MAAM,CAAC,eAAe,CACvB,CAAC;IACF,MAAM,cAAc,GAAG,oBAAoB,CACzC,QAAQ,EACR,gBAAgB,CAAC,SAAS,EAC1B,MAAM,CAAC,eAAe,EACtB,MAAM,CAAC,SAAS,CACjB,CAAC;IACF,MAAM,WAAW,GAAG,iBAAiB,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC;IAEpE,oCAAoC;IACpC,OAAO,CAAC,YAAY,CAAC,CAAC;IAEtB,OAAO;QACL,WAAW;QACX,gBAAgB;KACjB,CAAC;AACJ,CAAC"}
|
package/dist/index.d.ts
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @sideband/secure-relay
|
|
3
|
-
*
|
|
4
|
-
* Sideband Relay Protocol (SBRP) implementation for E2EE communication
|
|
5
|
-
* between daemons and clients via a relay server.
|
|
6
|
-
*
|
|
7
|
-
* Features:
|
|
8
|
-
* - Ed25519 identity signatures for MITM protection
|
|
9
|
-
* - X25519 ephemeral key exchange for forward secrecy
|
|
10
|
-
* - ChaCha20-Poly1305 authenticated encryption
|
|
11
|
-
* - TOFU (Trust On First Use) identity pinning
|
|
12
|
-
* - Bitmap-based replay protection
|
|
13
|
-
*
|
|
14
|
-
* @example
|
|
15
|
-
* ```typescript
|
|
16
|
-
* // Daemon side: generate identity keypair on first run
|
|
17
|
-
* const identity = generateIdentityKeyPair();
|
|
18
|
-
*
|
|
19
|
-
* // Client side: create handshake init
|
|
20
|
-
* const { message: init, ephemeralKeyPair } = createHandshakeInit();
|
|
21
|
-
*
|
|
22
|
-
* // Daemon side: process init and create accept
|
|
23
|
-
* const { message: accept, result } = processHandshakeInit(init, daemonId, identity);
|
|
24
|
-
* const clientSession = createClientSession(clientId, result.trafficKeys);
|
|
25
|
-
*
|
|
26
|
-
* // Client side: process accept (with TOFU-pinned identity)
|
|
27
|
-
* const { trafficKeys } = processHandshakeAccept(accept, daemonId, pinnedKey, ephemeralKeyPair);
|
|
28
|
-
* const daemonConn = createDaemonConnection(trafficKeys);
|
|
29
|
-
*
|
|
30
|
-
* // Encrypt/decrypt messages
|
|
31
|
-
* const encrypted = encryptClientToDaemon(daemonConn, plaintext);
|
|
32
|
-
* const decrypted = decryptClientToDaemon(clientSession, encrypted);
|
|
33
|
-
* ```
|
|
34
|
-
*/
|
|
35
|
-
export type { ClientId, DaemonId, EncryptedMessage, EphemeralKeyPair, HandshakeAccept, HandshakeInit, IdentityKeyPair, PinnedIdentity, TrafficKeys, } from "./types.js";
|
|
36
|
-
export { asClientId, asDaemonId, Direction, SbrpError, SbrpErrorCode } from "./types.js";
|
|
37
|
-
export { AUTH_TAG_LENGTH, DEFAULT_REPLAY_WINDOW_SIZE, DIRECTION_CLIENT_TO_DAEMON, DIRECTION_DAEMON_TO_CLIENT, ED25519_PRIVATE_KEY_LENGTH, ED25519_PUBLIC_KEY_LENGTH, ED25519_SIGNATURE_LENGTH, NONCE_LENGTH, SBRP_HANDSHAKE_CONTEXT, SBRP_SESSION_KEYS_INFO, SBRP_TRANSCRIPT_CONTEXT, SESSION_KEYS_LENGTH, SYMMETRIC_KEY_LENGTH, X25519_PRIVATE_KEY_LENGTH, X25519_PUBLIC_KEY_LENGTH, } from "./constants.js";
|
|
38
|
-
export { computeFingerprint, computeSharedSecret, constructNonce, createSignaturePayload, createTranscriptHash, decrypt, deriveTrafficKeys, encrypt, extractSequence, generateEphemeralKeyPair, generateIdentityKeyPair, randomBytes, signPayload, verifySignature, zeroize, } from "./crypto.js";
|
|
39
|
-
export type { ClientHandshakeResult, DaemonHandshakeResult, } from "./handshake.js";
|
|
40
|
-
export { createHandshakeInit, processHandshakeAccept, processHandshakeInit, } from "./handshake.js";
|
|
41
|
-
export type { ReplayWindow } from "./replay.js";
|
|
42
|
-
export { checkAndUpdateReplay, createReplayWindow, isValidSequence, resetReplayWindow, } from "./replay.js";
|
|
43
|
-
export type { ClientSession, DaemonConnection } from "./session.js";
|
|
44
|
-
export { clearClientSession, clearDaemonConnection, createClientSession, createDaemonConnection, decryptClientToDaemon, decryptDaemonToClient, encryptClientToDaemon, encryptDaemonToClient, } from "./session.js";
|
|
45
|
-
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAGH,YAAY,EACV,QAAQ,EACR,QAAQ,EACR,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,eAAe,EACf,cAAc,EACd,WAAW,GACZ,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAGzF,OAAO,EACL,eAAe,EACf,0BAA0B,EAC1B,0BAA0B,EAC1B,0BAA0B,EAC1B,0BAA0B,EAC1B,yBAAyB,EACzB,wBAAwB,EACxB,YAAY,EACZ,sBAAsB,EACtB,sBAAsB,EACtB,uBAAuB,EACvB,mBAAmB,EACnB,oBAAoB,EACpB,yBAAyB,EACzB,wBAAwB,GACzB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,cAAc,EACd,sBAAsB,EACtB,oBAAoB,EACpB,OAAO,EACP,iBAAiB,EACjB,OAAO,EACP,eAAe,EACf,wBAAwB,EACxB,uBAAuB,EACvB,WAAW,EACX,WAAW,EACX,eAAe,EACf,OAAO,GACR,MAAM,aAAa,CAAC;AAGrB,YAAY,EACV,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,gBAAgB,CAAC;AAGxB,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,eAAe,EACf,iBAAiB,GAClB,MAAM,aAAa,CAAC;AAGrB,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEpE,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EACrB,mBAAmB,EACnB,sBAAsB,EACtB,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,cAAc,CAAC"}
|
package/dist/index.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
// SPDX-FileCopyrightText: 2025-present Sideband
|
|
2
|
-
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
3
|
-
export { asClientId, asDaemonId, Direction, SbrpError, SbrpErrorCode } from "./types.js";
|
|
4
|
-
// Constants
|
|
5
|
-
export { AUTH_TAG_LENGTH, DEFAULT_REPLAY_WINDOW_SIZE, DIRECTION_CLIENT_TO_DAEMON, DIRECTION_DAEMON_TO_CLIENT, ED25519_PRIVATE_KEY_LENGTH, ED25519_PUBLIC_KEY_LENGTH, ED25519_SIGNATURE_LENGTH, NONCE_LENGTH, SBRP_HANDSHAKE_CONTEXT, SBRP_SESSION_KEYS_INFO, SBRP_TRANSCRIPT_CONTEXT, SESSION_KEYS_LENGTH, SYMMETRIC_KEY_LENGTH, X25519_PRIVATE_KEY_LENGTH, X25519_PUBLIC_KEY_LENGTH, } from "./constants.js";
|
|
6
|
-
// Crypto primitives
|
|
7
|
-
export { computeFingerprint, computeSharedSecret, constructNonce, createSignaturePayload, createTranscriptHash, decrypt, deriveTrafficKeys, encrypt, extractSequence, generateEphemeralKeyPair, generateIdentityKeyPair, randomBytes, signPayload, verifySignature, zeroize, } from "./crypto.js";
|
|
8
|
-
export { createHandshakeInit, processHandshakeAccept, processHandshakeInit, } from "./handshake.js";
|
|
9
|
-
export { checkAndUpdateReplay, createReplayWindow, isValidSequence, resetReplayWindow, } from "./replay.js";
|
|
10
|
-
export { clearClientSession, clearDaemonConnection, createClientSession, createDaemonConnection, decryptClientToDaemon, decryptDaemonToClient, encryptClientToDaemon, encryptDaemonToClient, } from "./session.js";
|
|
11
|
-
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,6CAA6C;AAkD7C,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEzF,YAAY;AACZ,OAAO,EACL,eAAe,EACf,0BAA0B,EAC1B,0BAA0B,EAC1B,0BAA0B,EAC1B,0BAA0B,EAC1B,yBAAyB,EACzB,wBAAwB,EACxB,YAAY,EACZ,sBAAsB,EACtB,sBAAsB,EACtB,uBAAuB,EACvB,mBAAmB,EACnB,oBAAoB,EACpB,yBAAyB,EACzB,wBAAwB,GACzB,MAAM,gBAAgB,CAAC;AAExB,oBAAoB;AACpB,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,cAAc,EACd,sBAAsB,EACtB,oBAAoB,EACpB,OAAO,EACP,iBAAiB,EACjB,OAAO,EACP,eAAe,EACf,wBAAwB,EACxB,uBAAuB,EACvB,WAAW,EACX,WAAW,EACX,eAAe,EACf,OAAO,GACR,MAAM,aAAa,CAAC;AAQrB,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,gBAAgB,CAAC;AAKxB,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,eAAe,EACf,iBAAiB,GAClB,MAAM,aAAa,CAAC;AAKrB,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EACrB,mBAAmB,EACnB,sBAAsB,EACtB,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,cAAc,CAAC"}
|
package/dist/replay.d.ts
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
/** Replay window state */
|
|
2
|
-
export interface ReplayWindow {
|
|
3
|
-
/** Highest accepted sequence number */
|
|
4
|
-
maxSeen: bigint;
|
|
5
|
-
/** Bitmap: bit i set = sequence (maxSeen - i) was seen */
|
|
6
|
-
bitmap: bigint;
|
|
7
|
-
/** Window size in bits */
|
|
8
|
-
windowSize: bigint;
|
|
9
|
-
}
|
|
10
|
-
/**
|
|
11
|
-
* Create a new replay window.
|
|
12
|
-
*
|
|
13
|
-
* @param windowSize - Window size in bits (default: 64)
|
|
14
|
-
*/
|
|
15
|
-
export declare function createReplayWindow(windowSize?: bigint): ReplayWindow;
|
|
16
|
-
/**
|
|
17
|
-
* Check if a sequence number is valid (not a replay) and update the window.
|
|
18
|
-
*
|
|
19
|
-
* @returns true if the sequence is valid and accepted, false if it's a replay
|
|
20
|
-
*/
|
|
21
|
-
export declare function checkAndUpdateReplay(seq: bigint, window: ReplayWindow): boolean;
|
|
22
|
-
/**
|
|
23
|
-
* Check if a sequence number would be valid without updating the window.
|
|
24
|
-
*
|
|
25
|
-
* Useful for pre-validation before decryption.
|
|
26
|
-
*/
|
|
27
|
-
export declare function isValidSequence(seq: bigint, window: ReplayWindow): boolean;
|
|
28
|
-
/**
|
|
29
|
-
* Reset the replay window to initial state.
|
|
30
|
-
*/
|
|
31
|
-
export declare function resetReplayWindow(window: ReplayWindow): void;
|
|
32
|
-
//# sourceMappingURL=replay.d.ts.map
|
package/dist/replay.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"replay.d.ts","sourceRoot":"","sources":["../src/replay.ts"],"names":[],"mappings":"AAaA,0BAA0B;AAC1B,MAAM,WAAW,YAAY;IAC3B,uCAAuC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,0DAA0D;IAC1D,MAAM,EAAE,MAAM,CAAC;IACf,0BAA0B;IAC1B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,UAAU,GAAE,MAAmC,GAC9C,YAAY,CAMd;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,YAAY,GACnB,OAAO,CAqCT;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CAgB1E;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAG5D"}
|
package/dist/replay.js
DELETED
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
// SPDX-FileCopyrightText: 2025-present Sideband
|
|
2
|
-
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
3
|
-
/**
|
|
4
|
-
* Bitmap-based replay protection for Sideband Relay Protocol (SBRP).
|
|
5
|
-
*
|
|
6
|
-
* Uses a sliding window to track seen sequence numbers and prevent
|
|
7
|
-
* replay attacks while avoiding memory exhaustion from attacker-controlled
|
|
8
|
-
* sequence numbers.
|
|
9
|
-
*/
|
|
10
|
-
import { DEFAULT_REPLAY_WINDOW_SIZE } from "./constants.js";
|
|
11
|
-
/**
|
|
12
|
-
* Create a new replay window.
|
|
13
|
-
*
|
|
14
|
-
* @param windowSize - Window size in bits (default: 64)
|
|
15
|
-
*/
|
|
16
|
-
export function createReplayWindow(windowSize = DEFAULT_REPLAY_WINDOW_SIZE) {
|
|
17
|
-
return {
|
|
18
|
-
maxSeen: -1n, // No messages seen yet
|
|
19
|
-
bitmap: 0n,
|
|
20
|
-
windowSize,
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Check if a sequence number is valid (not a replay) and update the window.
|
|
25
|
-
*
|
|
26
|
-
* @returns true if the sequence is valid and accepted, false if it's a replay
|
|
27
|
-
*/
|
|
28
|
-
export function checkAndUpdateReplay(seq, window) {
|
|
29
|
-
// First message ever
|
|
30
|
-
if (window.maxSeen === -1n) {
|
|
31
|
-
window.maxSeen = seq;
|
|
32
|
-
window.bitmap = 1n;
|
|
33
|
-
return true;
|
|
34
|
-
}
|
|
35
|
-
if (seq > window.maxSeen) {
|
|
36
|
-
// New high sequence - shift window
|
|
37
|
-
const shift = seq - window.maxSeen;
|
|
38
|
-
if (shift >= window.windowSize) {
|
|
39
|
-
// Sequence is far ahead, reset bitmap
|
|
40
|
-
window.bitmap = 1n;
|
|
41
|
-
}
|
|
42
|
-
else {
|
|
43
|
-
window.bitmap = (window.bitmap << shift) | 1n;
|
|
44
|
-
}
|
|
45
|
-
window.maxSeen = seq;
|
|
46
|
-
return true;
|
|
47
|
-
}
|
|
48
|
-
// Sequence is within or before the window
|
|
49
|
-
const diff = window.maxSeen - seq;
|
|
50
|
-
if (diff >= window.windowSize) {
|
|
51
|
-
// Too old, outside window
|
|
52
|
-
return false;
|
|
53
|
-
}
|
|
54
|
-
const mask = 1n << diff;
|
|
55
|
-
if (window.bitmap & mask) {
|
|
56
|
-
// Already seen (replay)
|
|
57
|
-
return false;
|
|
58
|
-
}
|
|
59
|
-
// Mark as seen
|
|
60
|
-
window.bitmap |= mask;
|
|
61
|
-
return true;
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Check if a sequence number would be valid without updating the window.
|
|
65
|
-
*
|
|
66
|
-
* Useful for pre-validation before decryption.
|
|
67
|
-
*/
|
|
68
|
-
export function isValidSequence(seq, window) {
|
|
69
|
-
if (window.maxSeen === -1n) {
|
|
70
|
-
return true;
|
|
71
|
-
}
|
|
72
|
-
if (seq > window.maxSeen) {
|
|
73
|
-
return true;
|
|
74
|
-
}
|
|
75
|
-
const diff = window.maxSeen - seq;
|
|
76
|
-
if (diff >= window.windowSize) {
|
|
77
|
-
return false;
|
|
78
|
-
}
|
|
79
|
-
const mask = 1n << diff;
|
|
80
|
-
return (window.bitmap & mask) === 0n;
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* Reset the replay window to initial state.
|
|
84
|
-
*/
|
|
85
|
-
export function resetReplayWindow(window) {
|
|
86
|
-
window.maxSeen = -1n;
|
|
87
|
-
window.bitmap = 0n;
|
|
88
|
-
}
|
|
89
|
-
//# sourceMappingURL=replay.js.map
|
package/dist/replay.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"replay.js","sourceRoot":"","sources":["../src/replay.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,6CAA6C;AAE7C;;;;;;GAMG;AAEH,OAAO,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;AAY5D;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAChC,aAAqB,0BAA0B;IAE/C,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,EAAE,uBAAuB;QACrC,MAAM,EAAE,EAAE;QACV,UAAU;KACX,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAClC,GAAW,EACX,MAAoB;IAEpB,qBAAqB;IACrB,IAAI,MAAM,CAAC,OAAO,KAAK,CAAC,EAAE,EAAE,CAAC;QAC3B,MAAM,CAAC,OAAO,GAAG,GAAG,CAAC;QACrB,MAAM,CAAC,MAAM,GAAG,EAAE,CAAC;QACnB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,GAAG,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;QACzB,mCAAmC;QACnC,MAAM,KAAK,GAAG,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC;QACnC,IAAI,KAAK,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;YAC/B,sCAAsC;YACtC,MAAM,CAAC,MAAM,GAAG,EAAE,CAAC;QACrB,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,MAAM,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,KAAK,CAAC,GAAG,EAAE,CAAC;QAChD,CAAC;QACD,MAAM,CAAC,OAAO,GAAG,GAAG,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,0CAA0C;IAC1C,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,GAAG,GAAG,CAAC;IAClC,IAAI,IAAI,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QAC9B,0BAA0B;QAC1B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,IAAI,GAAG,EAAE,IAAI,IAAI,CAAC;IACxB,IAAI,MAAM,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC;QACzB,wBAAwB;QACxB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,eAAe;IACf,MAAM,CAAC,MAAM,IAAI,IAAI,CAAC;IACtB,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,GAAW,EAAE,MAAoB;IAC/D,IAAI,MAAM,CAAC,OAAO,KAAK,CAAC,EAAE,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,GAAG,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,GAAG,GAAG,CAAC;IAClC,IAAI,IAAI,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,IAAI,GAAG,EAAE,IAAI,IAAI,CAAC;IACxB,OAAO,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;AACvC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAoB;IACpD,MAAM,CAAC,OAAO,GAAG,CAAC,EAAE,CAAC;IACrB,MAAM,CAAC,MAAM,GAAG,EAAE,CAAC;AACrB,CAAC"}
|
package/dist/session.d.ts
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { type ReplayWindow } from "./replay.js";
|
|
2
|
-
import type { ClientId, EncryptedMessage, TrafficKeys } from "./types.js";
|
|
3
|
-
/** Crypto state for one direction of communication (traffic key, counters, replay) */
|
|
4
|
-
interface ChannelState {
|
|
5
|
-
trafficKey: Uint8Array;
|
|
6
|
-
sendSeq: bigint;
|
|
7
|
-
recvWindow: ReplayWindow;
|
|
8
|
-
}
|
|
9
|
-
/** Client session (daemon-side state for each connected client) */
|
|
10
|
-
export interface ClientSession {
|
|
11
|
-
clientId: ClientId;
|
|
12
|
-
clientToDaemon: ChannelState;
|
|
13
|
-
daemonToClient: ChannelState;
|
|
14
|
-
}
|
|
15
|
-
/** Daemon connection (client-side state for communicating with daemon) */
|
|
16
|
-
export interface DaemonConnection {
|
|
17
|
-
clientToDaemon: ChannelState;
|
|
18
|
-
daemonToClient: ChannelState;
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Create a client session (daemon side).
|
|
22
|
-
*
|
|
23
|
-
* Used by daemon to manage state for each connected client.
|
|
24
|
-
*/
|
|
25
|
-
export declare function createClientSession(clientId: ClientId, trafficKeys: TrafficKeys): ClientSession;
|
|
26
|
-
/**
|
|
27
|
-
* Create a daemon connection (client side).
|
|
28
|
-
*
|
|
29
|
-
* Used by client to communicate with daemon.
|
|
30
|
-
*/
|
|
31
|
-
export declare function createDaemonConnection(trafficKeys: TrafficKeys): DaemonConnection;
|
|
32
|
-
/**
|
|
33
|
-
* Encrypt a message from client to daemon.
|
|
34
|
-
*/
|
|
35
|
-
export declare function encryptClientToDaemon(conn: DaemonConnection, plaintext: Uint8Array): EncryptedMessage;
|
|
36
|
-
/**
|
|
37
|
-
* Encrypt a message from daemon to client.
|
|
38
|
-
*/
|
|
39
|
-
export declare function encryptDaemonToClient(session: ClientSession, plaintext: Uint8Array): EncryptedMessage;
|
|
40
|
-
/**
|
|
41
|
-
* Decrypt a message received by daemon from client.
|
|
42
|
-
*
|
|
43
|
-
* @throws {SbrpError} with code SequenceError if replay detected
|
|
44
|
-
* @throws {SbrpError} with code DecryptFailed if decryption fails
|
|
45
|
-
*/
|
|
46
|
-
export declare function decryptClientToDaemon(session: ClientSession, message: EncryptedMessage): Uint8Array;
|
|
47
|
-
/**
|
|
48
|
-
* Decrypt a message received by client from daemon.
|
|
49
|
-
*
|
|
50
|
-
* @throws {SbrpError} with code SequenceError if replay detected
|
|
51
|
-
* @throws {SbrpError} with code DecryptFailed if decryption fails
|
|
52
|
-
*/
|
|
53
|
-
export declare function decryptDaemonToClient(conn: DaemonConnection, message: EncryptedMessage): Uint8Array;
|
|
54
|
-
/**
|
|
55
|
-
* Clear all key material from a client session.
|
|
56
|
-
*
|
|
57
|
-
* Best-effort zeroization (JS/GC limitations apply).
|
|
58
|
-
*/
|
|
59
|
-
export declare function clearClientSession(session: ClientSession): void;
|
|
60
|
-
/**
|
|
61
|
-
* Clear all key material from a daemon connection.
|
|
62
|
-
*
|
|
63
|
-
* Best-effort zeroization (JS/GC limitations apply).
|
|
64
|
-
*/
|
|
65
|
-
export declare function clearDaemonConnection(conn: DaemonConnection): void;
|
|
66
|
-
export {};
|
|
67
|
-
//# sourceMappingURL=session.d.ts.map
|
package/dist/session.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAWA,OAAO,EAGL,KAAK,YAAY,EAClB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,QAAQ,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG1E,sFAAsF;AACtF,UAAU,YAAY;IACpB,UAAU,EAAE,UAAU,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,YAAY,CAAC;CAC1B;AAED,mEAAmE;AACnE,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,QAAQ,CAAC;IACnB,cAAc,EAAE,YAAY,CAAC;IAC7B,cAAc,EAAE,YAAY,CAAC;CAC9B;AAED,0EAA0E;AAC1E,MAAM,WAAW,gBAAgB;IAC/B,cAAc,EAAE,YAAY,CAAC;IAC7B,cAAc,EAAE,YAAY,CAAC;CAC9B;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,QAAQ,EAClB,WAAW,EAAE,WAAW,GACvB,aAAa,CAcf;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,WAAW,GACvB,gBAAgB,CAalB;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,gBAAgB,EACtB,SAAS,EAAE,UAAU,GACpB,gBAAgB,CAUlB;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,aAAa,EACtB,SAAS,EAAE,UAAU,GACpB,gBAAgB,CAUlB;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,aAAa,EACtB,OAAO,EAAE,gBAAgB,GACxB,UAAU,CAeZ;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,gBAAgB,EACtB,OAAO,EAAE,gBAAgB,GACxB,UAAU,CAeZ;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAG/D;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAGlE"}
|
package/dist/session.js
DELETED
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
// SPDX-FileCopyrightText: 2025-present Sideband
|
|
2
|
-
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
3
|
-
/**
|
|
4
|
-
* Session management for Sideband Relay Protocol (SBRP).
|
|
5
|
-
*
|
|
6
|
-
* Handles encrypted message sending/receiving with proper key selection,
|
|
7
|
-
* sequence number tracking, and replay protection.
|
|
8
|
-
*/
|
|
9
|
-
import { decrypt, encrypt, extractSequence, zeroize } from "./crypto.js";
|
|
10
|
-
import { checkAndUpdateReplay, createReplayWindow, } from "./replay.js";
|
|
11
|
-
import { Direction, SbrpError, SbrpErrorCode } from "./types.js";
|
|
12
|
-
/**
|
|
13
|
-
* Create a client session (daemon side).
|
|
14
|
-
*
|
|
15
|
-
* Used by daemon to manage state for each connected client.
|
|
16
|
-
*/
|
|
17
|
-
export function createClientSession(clientId, trafficKeys) {
|
|
18
|
-
return {
|
|
19
|
-
clientId,
|
|
20
|
-
clientToDaemon: {
|
|
21
|
-
trafficKey: trafficKeys.clientToDaemon,
|
|
22
|
-
sendSeq: 0n,
|
|
23
|
-
recvWindow: createReplayWindow(),
|
|
24
|
-
},
|
|
25
|
-
daemonToClient: {
|
|
26
|
-
trafficKey: trafficKeys.daemonToClient,
|
|
27
|
-
sendSeq: 0n,
|
|
28
|
-
recvWindow: createReplayWindow(),
|
|
29
|
-
},
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Create a daemon connection (client side).
|
|
34
|
-
*
|
|
35
|
-
* Used by client to communicate with daemon.
|
|
36
|
-
*/
|
|
37
|
-
export function createDaemonConnection(trafficKeys) {
|
|
38
|
-
return {
|
|
39
|
-
clientToDaemon: {
|
|
40
|
-
trafficKey: trafficKeys.clientToDaemon,
|
|
41
|
-
sendSeq: 0n,
|
|
42
|
-
recvWindow: createReplayWindow(),
|
|
43
|
-
},
|
|
44
|
-
daemonToClient: {
|
|
45
|
-
trafficKey: trafficKeys.daemonToClient,
|
|
46
|
-
sendSeq: 0n,
|
|
47
|
-
recvWindow: createReplayWindow(),
|
|
48
|
-
},
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Encrypt a message from client to daemon.
|
|
53
|
-
*/
|
|
54
|
-
export function encryptClientToDaemon(conn, plaintext) {
|
|
55
|
-
const seq = conn.clientToDaemon.sendSeq++;
|
|
56
|
-
const data = encrypt(conn.clientToDaemon.trafficKey, Direction.ClientToDaemon, seq, plaintext);
|
|
57
|
-
return { type: "encrypted", seq, data };
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Encrypt a message from daemon to client.
|
|
61
|
-
*/
|
|
62
|
-
export function encryptDaemonToClient(session, plaintext) {
|
|
63
|
-
const seq = session.daemonToClient.sendSeq++;
|
|
64
|
-
const data = encrypt(session.daemonToClient.trafficKey, Direction.DaemonToClient, seq, plaintext);
|
|
65
|
-
return { type: "encrypted", seq, data };
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Decrypt a message received by daemon from client.
|
|
69
|
-
*
|
|
70
|
-
* @throws {SbrpError} with code SequenceError if replay detected
|
|
71
|
-
* @throws {SbrpError} with code DecryptFailed if decryption fails
|
|
72
|
-
*/
|
|
73
|
-
export function decryptClientToDaemon(session, message) {
|
|
74
|
-
// Check replay protection
|
|
75
|
-
const seq = extractSequence(message.data);
|
|
76
|
-
if (!checkAndUpdateReplay(seq, session.clientToDaemon.recvWindow)) {
|
|
77
|
-
throw new SbrpError(SbrpErrorCode.SequenceError, "Sequence number outside valid window or replay detected");
|
|
78
|
-
}
|
|
79
|
-
try {
|
|
80
|
-
return decrypt(session.clientToDaemon.trafficKey, message.data);
|
|
81
|
-
}
|
|
82
|
-
catch {
|
|
83
|
-
throw new SbrpError(SbrpErrorCode.DecryptFailed, "Message decryption failed");
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Decrypt a message received by client from daemon.
|
|
88
|
-
*
|
|
89
|
-
* @throws {SbrpError} with code SequenceError if replay detected
|
|
90
|
-
* @throws {SbrpError} with code DecryptFailed if decryption fails
|
|
91
|
-
*/
|
|
92
|
-
export function decryptDaemonToClient(conn, message) {
|
|
93
|
-
// Check replay protection
|
|
94
|
-
const seq = extractSequence(message.data);
|
|
95
|
-
if (!checkAndUpdateReplay(seq, conn.daemonToClient.recvWindow)) {
|
|
96
|
-
throw new SbrpError(SbrpErrorCode.SequenceError, "Sequence number outside valid window or replay detected");
|
|
97
|
-
}
|
|
98
|
-
try {
|
|
99
|
-
return decrypt(conn.daemonToClient.trafficKey, message.data);
|
|
100
|
-
}
|
|
101
|
-
catch {
|
|
102
|
-
throw new SbrpError(SbrpErrorCode.DecryptFailed, "Message decryption failed");
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* Clear all key material from a client session.
|
|
107
|
-
*
|
|
108
|
-
* Best-effort zeroization (JS/GC limitations apply).
|
|
109
|
-
*/
|
|
110
|
-
export function clearClientSession(session) {
|
|
111
|
-
zeroize(session.clientToDaemon.trafficKey);
|
|
112
|
-
zeroize(session.daemonToClient.trafficKey);
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* Clear all key material from a daemon connection.
|
|
116
|
-
*
|
|
117
|
-
* Best-effort zeroization (JS/GC limitations apply).
|
|
118
|
-
*/
|
|
119
|
-
export function clearDaemonConnection(conn) {
|
|
120
|
-
zeroize(conn.clientToDaemon.trafficKey);
|
|
121
|
-
zeroize(conn.daemonToClient.trafficKey);
|
|
122
|
-
}
|
|
123
|
-
//# sourceMappingURL=session.js.map
|
package/dist/session.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Type definitions for Sideband Relay Protocol (SBRP).
|
|
3
|
-
*/
|
|
4
|
-
/** Branded type for daemon identifiers */
|
|
5
|
-
export type DaemonId = string & {
|
|
6
|
-
readonly __brand: "DaemonId";
|
|
7
|
-
};
|
|
8
|
-
/** Branded type for client session identifiers (relay-assigned) */
|
|
9
|
-
export type ClientId = string & {
|
|
10
|
-
readonly __brand: "ClientId";
|
|
11
|
-
};
|
|
12
|
-
/** Ed25519 identity keypair for daemon authentication */
|
|
13
|
-
export interface IdentityKeyPair {
|
|
14
|
-
publicKey: Uint8Array;
|
|
15
|
-
privateKey: Uint8Array;
|
|
16
|
-
}
|
|
17
|
-
/** X25519 ephemeral keypair for key exchange */
|
|
18
|
-
export interface EphemeralKeyPair {
|
|
19
|
-
publicKey: Uint8Array;
|
|
20
|
-
privateKey: Uint8Array;
|
|
21
|
-
}
|
|
22
|
-
/** Pinned identity for TOFU verification (browser-side storage) */
|
|
23
|
-
export interface PinnedIdentity {
|
|
24
|
-
daemonId: DaemonId;
|
|
25
|
-
identityPublicKey: Uint8Array;
|
|
26
|
-
firstSeen: Date;
|
|
27
|
-
lastSeen: Date;
|
|
28
|
-
}
|
|
29
|
-
/** Traffic keys derived from handshake (directional symmetric keys) */
|
|
30
|
-
export interface TrafficKeys {
|
|
31
|
-
/** Key for encrypting client→daemon messages */
|
|
32
|
-
clientToDaemon: Uint8Array;
|
|
33
|
-
/** Key for encrypting daemon→client messages */
|
|
34
|
-
daemonToClient: Uint8Array;
|
|
35
|
-
}
|
|
36
|
-
/** Handshake init message (browser → daemon) */
|
|
37
|
-
export interface HandshakeInit {
|
|
38
|
-
type: "handshake.init";
|
|
39
|
-
browserPublicKey: Uint8Array;
|
|
40
|
-
}
|
|
41
|
-
/** Handshake accept message (daemon → browser) */
|
|
42
|
-
export interface HandshakeAccept {
|
|
43
|
-
type: "handshake.accept";
|
|
44
|
-
daemonPublicKey: Uint8Array;
|
|
45
|
-
signature: Uint8Array;
|
|
46
|
-
}
|
|
47
|
-
/** Encrypted message envelope */
|
|
48
|
-
export interface EncryptedMessage {
|
|
49
|
-
type: "encrypted";
|
|
50
|
-
seq: bigint;
|
|
51
|
-
data: Uint8Array;
|
|
52
|
-
}
|
|
53
|
-
/** Direction of message flow (used in nonce construction) */
|
|
54
|
-
export declare const enum Direction {
|
|
55
|
-
ClientToDaemon = 1,
|
|
56
|
-
DaemonToClient = 2
|
|
57
|
-
}
|
|
58
|
-
/** SBRP error codes */
|
|
59
|
-
export declare const enum SbrpErrorCode {
|
|
60
|
-
Unauthorized = "unauthorized",
|
|
61
|
-
DaemonNotFound = "daemon_not_found",
|
|
62
|
-
DaemonOffline = "daemon_offline",
|
|
63
|
-
DaemonNotOwned = "daemon_not_owned",
|
|
64
|
-
IdentityKeyChanged = "identity_key_changed",
|
|
65
|
-
HandshakeFailed = "handshake_failed",
|
|
66
|
-
DecryptFailed = "decrypt_failed",
|
|
67
|
-
SequenceError = "sequence_error",
|
|
68
|
-
RateLimited = "rate_limited"
|
|
69
|
-
}
|
|
70
|
-
/** SBRP-specific error */
|
|
71
|
-
export declare class SbrpError extends Error {
|
|
72
|
-
readonly code: SbrpErrorCode;
|
|
73
|
-
constructor(code: SbrpErrorCode, message: string);
|
|
74
|
-
}
|
|
75
|
-
/** Type guard for DaemonId */
|
|
76
|
-
export declare function asDaemonId(value: string): DaemonId;
|
|
77
|
-
/** Type guard for ClientId */
|
|
78
|
-
export declare function asClientId(value: string): ClientId;
|
|
79
|
-
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAGA;;GAEG;AAEH,0CAA0C;AAC1C,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG;IAAE,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAA;CAAE,CAAC;AAEjE,mEAAmE;AACnE,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG;IAAE,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAA;CAAE,CAAC;AAEjE,yDAAyD;AACzD,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,UAAU,CAAC;IACtB,UAAU,EAAE,UAAU,CAAC;CACxB;AAED,gDAAgD;AAChD,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,UAAU,CAAC;IACtB,UAAU,EAAE,UAAU,CAAC;CACxB;AAED,mEAAmE;AACnE,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,QAAQ,CAAC;IACnB,iBAAiB,EAAE,UAAU,CAAC;IAC9B,SAAS,EAAE,IAAI,CAAC;IAChB,QAAQ,EAAE,IAAI,CAAC;CAChB;AAED,uEAAuE;AACvE,MAAM,WAAW,WAAW;IAC1B,gDAAgD;IAChD,cAAc,EAAE,UAAU,CAAC;IAC3B,gDAAgD;IAChD,cAAc,EAAE,UAAU,CAAC;CAC5B;AAED,gDAAgD;AAChD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,gBAAgB,CAAC;IACvB,gBAAgB,EAAE,UAAU,CAAC;CAC9B;AAED,kDAAkD;AAClD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,kBAAkB,CAAC;IACzB,eAAe,EAAE,UAAU,CAAC;IAC5B,SAAS,EAAE,UAAU,CAAC;CACvB;AAED,iCAAiC;AACjC,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,WAAW,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,UAAU,CAAC;CAClB;AAED,6DAA6D;AAC7D,0BAAkB,SAAS;IACzB,cAAc,IAAI;IAClB,cAAc,IAAI;CACnB;AAED,uBAAuB;AACvB,0BAAkB,aAAa;IAC7B,YAAY,iBAAiB;IAC7B,cAAc,qBAAqB;IACnC,aAAa,mBAAmB;IAChC,cAAc,qBAAqB;IACnC,kBAAkB,yBAAyB;IAC3C,eAAe,qBAAqB;IACpC,aAAa,mBAAmB;IAChC,aAAa,mBAAmB;IAChC,WAAW,iBAAiB;CAC7B;AAED,0BAA0B;AAC1B,qBAAa,SAAU,SAAQ,KAAK;aAEhB,IAAI,EAAE,aAAa;gBAAnB,IAAI,EAAE,aAAa,EACnC,OAAO,EAAE,MAAM;CAKlB;AAED,8BAA8B;AAC9B,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,CAElD;AAED,8BAA8B;AAC9B,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,CAElD"}
|
package/dist/types.js
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
// SPDX-FileCopyrightText: 2025-present Sideband
|
|
2
|
-
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
3
|
-
/** Direction of message flow (used in nonce construction) */
|
|
4
|
-
export var Direction;
|
|
5
|
-
(function (Direction) {
|
|
6
|
-
Direction[Direction["ClientToDaemon"] = 1] = "ClientToDaemon";
|
|
7
|
-
Direction[Direction["DaemonToClient"] = 2] = "DaemonToClient";
|
|
8
|
-
})(Direction || (Direction = {}));
|
|
9
|
-
/** SBRP error codes */
|
|
10
|
-
export var SbrpErrorCode;
|
|
11
|
-
(function (SbrpErrorCode) {
|
|
12
|
-
SbrpErrorCode["Unauthorized"] = "unauthorized";
|
|
13
|
-
SbrpErrorCode["DaemonNotFound"] = "daemon_not_found";
|
|
14
|
-
SbrpErrorCode["DaemonOffline"] = "daemon_offline";
|
|
15
|
-
SbrpErrorCode["DaemonNotOwned"] = "daemon_not_owned";
|
|
16
|
-
SbrpErrorCode["IdentityKeyChanged"] = "identity_key_changed";
|
|
17
|
-
SbrpErrorCode["HandshakeFailed"] = "handshake_failed";
|
|
18
|
-
SbrpErrorCode["DecryptFailed"] = "decrypt_failed";
|
|
19
|
-
SbrpErrorCode["SequenceError"] = "sequence_error";
|
|
20
|
-
SbrpErrorCode["RateLimited"] = "rate_limited";
|
|
21
|
-
})(SbrpErrorCode || (SbrpErrorCode = {}));
|
|
22
|
-
/** SBRP-specific error */
|
|
23
|
-
export class SbrpError extends Error {
|
|
24
|
-
code;
|
|
25
|
-
constructor(code, message) {
|
|
26
|
-
super(message);
|
|
27
|
-
this.code = code;
|
|
28
|
-
this.name = "SbrpError";
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
/** Type guard for DaemonId */
|
|
32
|
-
export function asDaemonId(value) {
|
|
33
|
-
return value;
|
|
34
|
-
}
|
|
35
|
-
/** Type guard for ClientId */
|
|
36
|
-
export function asClientId(value) {
|
|
37
|
-
return value;
|
|
38
|
-
}
|
|
39
|
-
//# sourceMappingURL=types.js.map
|
package/dist/types.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,6CAA6C;AA4D7C,6DAA6D;AAC7D,MAAM,CAAN,IAAkB,SAGjB;AAHD,WAAkB,SAAS;IACzB,6DAAkB,CAAA;IAClB,6DAAkB,CAAA;AACpB,CAAC,EAHiB,SAAS,KAAT,SAAS,QAG1B;AAED,uBAAuB;AACvB,MAAM,CAAN,IAAkB,aAUjB;AAVD,WAAkB,aAAa;IAC7B,8CAA6B,CAAA;IAC7B,oDAAmC,CAAA;IACnC,iDAAgC,CAAA;IAChC,oDAAmC,CAAA;IACnC,4DAA2C,CAAA;IAC3C,qDAAoC,CAAA;IACpC,iDAAgC,CAAA;IAChC,iDAAgC,CAAA;IAChC,6CAA4B,CAAA;AAC9B,CAAC,EAViB,aAAa,KAAb,aAAa,QAU9B;AAED,0BAA0B;AAC1B,MAAM,OAAO,SAAU,SAAQ,KAAK;IAEhB;IADlB,YACkB,IAAmB,EACnC,OAAe;QAEf,KAAK,CAAC,OAAO,CAAC,CAAC;QAHC,SAAI,GAAJ,IAAI,CAAe;QAInC,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;IAC1B,CAAC;CACF;AAED,8BAA8B;AAC9B,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,OAAO,KAAiB,CAAC;AAC3B,CAAC;AAED,8BAA8B;AAC9B,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,OAAO,KAAiB,CAAC;AAC3B,CAAC"}
|