@floegence/flowersec-core 0.27.0 → 2.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/README.md +91 -22
- package/THIRD_PARTY_NOTICES.md +141 -0
- package/dist/browser/connectSession.d.ts +13 -0
- package/dist/browser/connectSession.js +40 -0
- package/dist/browser/index.d.ts +3 -10
- package/dist/browser/index.js +2 -5
- package/dist/browser/runtimeCapability.d.ts +13 -0
- package/dist/browser/runtimeCapability.js +27 -0
- package/dist/browser/sessionRuntime.d.ts +2 -0
- package/dist/browser/sessionRuntime.js +21 -0
- package/dist/browser/webTransportClient.d.ts +8 -0
- package/dist/browser/webTransportClient.js +55 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +126 -0
- package/dist/cliSpendMarker.d.ts +1 -0
- package/dist/cliSpendMarker.js +22 -0
- package/dist/connectionController.d.ts +54 -0
- package/dist/connectionController.js +438 -0
- package/dist/connector/adapters/webSocketCandidate.d.ts +7 -0
- package/dist/connector/adapters/webSocketCandidate.js +116 -0
- package/dist/connector/adapters/webTransportCandidate.d.ts +5 -0
- package/dist/connector/adapters/webTransportCandidate.js +73 -0
- package/dist/connector/admissionCommit.d.ts +31 -0
- package/dist/connector/admissionCommit.js +239 -0
- package/dist/connector/sessionAcceptor.d.ts +16 -0
- package/dist/connector/sessionAcceptor.js +114 -0
- package/dist/connector/sessionConfig.d.ts +3 -0
- package/dist/connector/sessionConfig.js +30 -0
- package/dist/connector/sessionConnector.d.ts +45 -0
- package/dist/connector/sessionConnector.js +603 -0
- package/dist/defaults.d.ts +7 -7
- package/dist/defaults.js +7 -7
- package/dist/facade.d.ts +12 -27
- package/dist/facade.js +6 -24
- package/dist/node/connectSession.d.ts +21 -0
- package/dist/node/connectSession.js +62 -0
- package/dist/node/index.d.ts +3 -11
- package/dist/node/index.js +2 -8
- package/dist/node/runtimeCapability.d.ts +7 -0
- package/dist/node/runtimeCapability.js +10 -0
- package/dist/node/sessionRuntime.d.ts +2 -0
- package/dist/node/sessionRuntime.js +13 -0
- package/dist/node/webTransportClient.d.ts +9 -0
- package/dist/node/webTransportClient.js +56 -0
- package/dist/node/webTransportServer.d.ts +22 -0
- package/dist/node/webTransportServer.js +100 -0
- package/dist/node/wsFactory.d.ts +3 -1
- package/dist/node/wsFactory.js +4 -3
- package/dist/proxy/controllerGuard.d.ts +4 -4
- package/dist/proxy/controllerGuard.js +83 -177
- package/dist/proxy/disableUpstreamServiceWorkerRegister.d.ts +3 -1
- package/dist/proxy/disableUpstreamServiceWorkerRegister.js +19 -17
- package/dist/proxy/index.d.ts +16 -15
- package/dist/proxy/index.js +8 -14
- package/dist/proxy/integration.d.ts +23 -71
- package/dist/proxy/integration.js +37 -340
- package/dist/proxy/registerServiceWorker.d.ts +1 -10
- package/dist/proxy/registerServiceWorker.js +43 -105
- package/dist/proxy/runtime.d.ts +3 -63
- package/dist/proxy/runtime.js +349 -462
- package/dist/proxy/scope.d.ts +6 -0
- package/dist/proxy/scope.js +131 -0
- package/dist/proxy/serviceWorker.d.ts +5 -16
- package/dist/proxy/serviceWorker.js +230 -617
- package/dist/proxy/stream.d.ts +9 -0
- package/dist/proxy/stream.js +40 -0
- package/dist/proxy/types.d.ts +78 -30
- package/dist/proxy/windowBridge.d.ts +61 -0
- package/dist/proxy/windowBridge.js +344 -0
- package/dist/proxy/wsPatch.d.ts +4 -14
- package/dist/proxy/wsPatch.js +173 -268
- package/dist/public/artifact.d.ts +11 -0
- package/dist/public/artifact.js +44 -0
- package/dist/public/artifactLease.d.ts +10 -0
- package/dist/public/artifactLease.js +48 -0
- package/dist/public/connectError.d.ts +6 -0
- package/dist/public/connectError.js +9 -0
- package/dist/public/contract.d.ts +83 -0
- package/dist/public/contract.js +17 -0
- package/dist/public/streamMetadata.d.ts +10 -0
- package/dist/public/streamMetadata.js +40 -0
- package/dist/rpc/caller.d.ts +1 -1
- package/dist/rpc/client.d.ts +1 -4
- package/dist/rpc/client.js +0 -21
- package/dist/rpc/rpcProxy.d.ts +1 -1
- package/dist/rpc/server.d.ts +1 -1
- package/dist/rpc/validate.d.ts +1 -1
- package/dist/rpc/wire.d.ts +15 -0
- package/dist/runtime/errors.d.ts +6 -0
- package/dist/runtime/errors.js +10 -0
- package/dist/transport/webSocketAdapter.d.ts +24 -0
- package/dist/transport/webSocketAdapter.js +234 -0
- package/dist/transport/webTransportAdapter.d.ts +27 -0
- package/dist/transport/webTransportAdapter.js +519 -0
- package/dist/utils/errors.d.ts +2 -20
- package/dist/utils/errors.js +73 -20
- package/dist/v2/admissionError.d.ts +4 -0
- package/dist/v2/admissionError.js +8 -0
- package/dist/v2/artifact.d.ts +128 -0
- package/dist/v2/artifact.js +1126 -0
- package/dist/v2/artifactLease.d.ts +1 -0
- package/dist/v2/artifactLease.js +7 -0
- package/dist/v2/capability.d.ts +29 -0
- package/dist/v2/capability.js +190 -0
- package/dist/v2/carrier.d.ts +79 -0
- package/dist/v2/carrier.js +405 -0
- package/dist/v2/contract.d.ts +37 -0
- package/dist/v2/contract.js +1 -0
- package/dist/v2/handshake.d.ts +80 -0
- package/dist/v2/handshake.js +470 -0
- package/dist/v2/opaqueArtifact.d.ts +1 -0
- package/dist/v2/opaqueArtifact.js +2 -0
- package/dist/v2/protocol.d.ts +99 -0
- package/dist/v2/protocol.js +739 -0
- package/dist/v2/publicSession.d.ts +1 -0
- package/dist/v2/publicSession.js +179 -0
- package/dist/v2/retryDisposition.d.ts +16 -0
- package/dist/v2/retryDisposition.js +30 -0
- package/dist/v2/session.d.ts +277 -0
- package/dist/v2/session.js +1879 -0
- package/dist/v2/streamLifetimeLedger.d.ts +31 -0
- package/dist/v2/streamLifetimeLedger.js +131 -0
- package/dist/v2/streamMetadata.d.ts +1 -0
- package/dist/v2/streamMetadata.js +7 -0
- package/dist/v2/unreliableMessage.d.ts +43 -0
- package/dist/v2/unreliableMessage.js +252 -0
- package/dist/vendor/tr46.d.ts +10 -0
- package/dist/vendor/tr46.js +501 -0
- package/dist/ws-client/binaryTransport.d.ts +0 -3
- package/dist/ws-client/binaryTransport.js +15 -39
- package/dist/yamux/errors.d.ts +0 -4
- package/dist/yamux/errors.js +0 -9
- package/dist/yamux/session.d.ts +0 -5
- package/dist/yamux/session.js +4 -70
- package/dist/yamux/stream.d.ts +1 -0
- package/dist/yamux/stream.js +4 -0
- package/package.json +29 -81
- package/sbom/cyclonedx.json +2764 -0
- package/sbom/spdx.json +1947 -0
- package/YAMUX_ALIGNMENT.md +0 -127
- package/dist/_examples/flowersec/demo/v1.facade.gen.d.ts +0 -12
- package/dist/_examples/flowersec/demo/v1.facade.gen.js +0 -15
- package/dist/_examples/flowersec/demo/v1.gen.d.ts +0 -16
- package/dist/_examples/flowersec/demo/v1.gen.js +0 -86
- package/dist/_examples/flowersec/demo/v1.rpc.gen.d.ts +0 -11
- package/dist/_examples/flowersec/demo/v1.rpc.gen.js +0 -22
- package/dist/browser/connect.d.ts +0 -13
- package/dist/browser/connect.js +0 -31
- package/dist/browser/reconnectConfig.d.ts +0 -15
- package/dist/browser/reconnectConfig.js +0 -20
- package/dist/client-connect/common.d.ts +0 -26
- package/dist/client-connect/common.js +0 -167
- package/dist/client-connect/connectCore.d.ts +0 -61
- package/dist/client-connect/connectCore.js +0 -572
- package/dist/client-connect/contract.d.ts +0 -8
- package/dist/client-connect/contract.js +0 -51
- package/dist/client-connect/termination.d.ts +0 -6
- package/dist/client-connect/termination.js +0 -7
- package/dist/client-connect/transportSecurity.d.ts +0 -27
- package/dist/client-connect/transportSecurity.js +0 -199
- package/dist/client-connect/tunnelAttachCloseReason.d.ts +0 -3
- package/dist/client-connect/tunnelAttachCloseReason.js +0 -23
- package/dist/client.d.ts +0 -23
- package/dist/connect/artifact.d.ts +0 -36
- package/dist/connect/artifact.js +0 -213
- package/dist/connect/resolveArtifact.d.ts +0 -22
- package/dist/connect/resolveArtifact.js +0 -87
- package/dist/controlplane/channelInit.d.ts +0 -27
- package/dist/controlplane/channelInit.js +0 -116
- package/dist/controlplane/http.d.ts +0 -16
- package/dist/controlplane/http.js +0 -59
- package/dist/controlplane/index.d.ts +0 -6
- package/dist/controlplane/index.js +0 -5
- package/dist/controlplane/issuer.d.ts +0 -18
- package/dist/controlplane/issuer.js +0 -113
- package/dist/controlplane/request.d.ts +0 -51
- package/dist/controlplane/request.js +0 -273
- package/dist/controlplane/token.d.ts +0 -33
- package/dist/controlplane/token.js +0 -119
- package/dist/direct-client/connect.d.ts +0 -9
- package/dist/direct-client/connect.js +0 -90
- package/dist/direct-client/index.d.ts +0 -1
- package/dist/direct-client/index.js +0 -1
- package/dist/e2ee/constants.d.ts +0 -9
- package/dist/e2ee/constants.js +0 -18
- package/dist/e2ee/errors.d.ts +0 -5
- package/dist/e2ee/errors.js +0 -8
- package/dist/e2ee/framing.d.ts +0 -12
- package/dist/e2ee/framing.js +0 -57
- package/dist/e2ee/handshake.d.ts +0 -88
- package/dist/e2ee/handshake.js +0 -353
- package/dist/e2ee/index.d.ts +0 -7
- package/dist/e2ee/index.js +0 -7
- package/dist/e2ee/kdf.d.ts +0 -15
- package/dist/e2ee/kdf.js +0 -39
- package/dist/e2ee/record.d.ts +0 -11
- package/dist/e2ee/record.js +0 -80
- package/dist/e2ee/secureChannel.d.ts +0 -93
- package/dist/e2ee/secureChannel.js +0 -342
- package/dist/e2ee/transcript.d.ts +0 -23
- package/dist/e2ee/transcript.js +0 -31
- package/dist/endpoint/index.d.ts +0 -84
- package/dist/endpoint/index.js +0 -557
- package/dist/endpoint/node.d.ts +0 -9
- package/dist/endpoint/node.js +0 -51
- package/dist/gen/flowersec/controlplane/v1.gen.d.ts +0 -36
- package/dist/gen/flowersec/controlplane/v1.gen.js +0 -135
- package/dist/gen/flowersec/direct/v1.gen.d.ts +0 -21
- package/dist/gen/flowersec/direct/v1.gen.js +0 -101
- package/dist/gen/flowersec/e2ee/v1.gen.d.ts +0 -68
- package/dist/gen/flowersec/e2ee/v1.gen.js +0 -194
- package/dist/gen/flowersec/rpc/v1.gen.d.ts +0 -30
- package/dist/gen/flowersec/rpc/v1.gen.js +0 -107
- package/dist/gen/flowersec/tunnel/v1.gen.d.ts +0 -23
- package/dist/gen/flowersec/tunnel/v1.gen.js +0 -104
- package/dist/index.d.ts +0 -22
- package/dist/index.js +0 -22
- package/dist/node/connect.d.ts +0 -10
- package/dist/node/connect.js +0 -29
- package/dist/node/reconnectConfig.d.ts +0 -16
- package/dist/node/reconnectConfig.js +0 -20
- package/dist/observability/index.d.ts +0 -1
- package/dist/observability/index.js +0 -1
- package/dist/observability/observer.d.ts +0 -52
- package/dist/observability/observer.js +0 -314
- package/dist/proxy/appWindow.d.ts +0 -37
- package/dist/proxy/appWindow.js +0 -273
- package/dist/proxy/bootstrap.d.ts +0 -35
- package/dist/proxy/bootstrap.js +0 -119
- package/dist/proxy/constants.d.ts +0 -7
- package/dist/proxy/constants.js +0 -8
- package/dist/proxy/controllerWindow.d.ts +0 -12
- package/dist/proxy/controllerWindow.js +0 -384
- package/dist/proxy/cookieJar.d.ts +0 -7
- package/dist/proxy/cookieJar.js +0 -136
- package/dist/proxy/headerPolicy.d.ts +0 -14
- package/dist/proxy/headerPolicy.js +0 -134
- package/dist/proxy/portStream.d.ts +0 -5
- package/dist/proxy/portStream.js +0 -256
- package/dist/proxy/preset.d.ts +0 -29
- package/dist/proxy/preset.js +0 -111
- package/dist/proxy/runtimeScope.d.ts +0 -57
- package/dist/proxy/runtimeScope.js +0 -218
- package/dist/proxy/server.d.ts +0 -28
- package/dist/proxy/server.js +0 -833
- package/dist/proxy/windowBridgeProtocol.d.ts +0 -65
- package/dist/proxy/windowBridgeProtocol.js +0 -11
- package/dist/reconnect/artifactControlplane.d.ts +0 -16
- package/dist/reconnect/artifactControlplane.js +0 -35
- package/dist/reconnect/index.d.ts +0 -36
- package/dist/reconnect/index.js +0 -388
- package/dist/rpc-proxy/index.d.ts +0 -1
- package/dist/rpc-proxy/index.js +0 -1
- package/dist/rpc-proxy/rpcProxy.d.ts +0 -1
- package/dist/rpc-proxy/rpcProxy.js +0 -1
- package/dist/streamhello/index.d.ts +0 -1
- package/dist/streamhello/index.js +0 -1
- package/dist/streamhello/streamHello.d.ts +0 -3
- package/dist/streamhello/streamHello.js +0 -13
- package/dist/streamio/index.d.ts +0 -32
- package/dist/streamio/index.js +0 -87
- package/dist/tunnel-client/connect.d.ts +0 -9
- package/dist/tunnel-client/connect.js +0 -147
- package/dist/tunnel-client/index.d.ts +0 -1
- package/dist/tunnel-client/index.js +0 -1
- package/dist/ws/index.d.ts +0 -1
- package/dist/ws/index.js +0 -1
- /package/dist/{client.js → rpc/wire.js} +0 -0
|
@@ -1,342 +0,0 @@
|
|
|
1
|
-
import { RECORD_FLAG_APP, RECORD_FLAG_PING, RECORD_FLAG_REKEY } from "./constants.js";
|
|
2
|
-
import { decryptRecord, encryptRecord, maxPlaintextBytes } from "./record.js";
|
|
3
|
-
import { deriveRekeyKey } from "./kdf.js";
|
|
4
|
-
import { SDK_DEFAULTS } from "../defaults.js";
|
|
5
|
-
const maxRecordSeq = (1n << 64n) - 1n;
|
|
6
|
-
class RecordSeqExhaustedError extends Error {
|
|
7
|
-
constructor() {
|
|
8
|
-
super("record seq exhausted");
|
|
9
|
-
this.name = "RecordSeqExhaustedError";
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
// SecureChannel encrypts/decrypts records and buffers application payloads.
|
|
13
|
-
export class SecureChannel {
|
|
14
|
-
// Underlying transport for encrypted record frames.
|
|
15
|
-
transport;
|
|
16
|
-
// Maximum allowed bytes per record frame.
|
|
17
|
-
maxRecordBytes;
|
|
18
|
-
outboundRecordChunkBytes;
|
|
19
|
-
maxInboundBufferedBytes;
|
|
20
|
-
maxOutboundBufferedBytes;
|
|
21
|
-
// Active encryption keys and nonce prefixes for the current epoch.
|
|
22
|
-
sendKey;
|
|
23
|
-
recvKey;
|
|
24
|
-
sendNoncePrefix;
|
|
25
|
-
recvNoncePrefix;
|
|
26
|
-
// Rekey base secret derived from the handshake.
|
|
27
|
-
rekeyBase;
|
|
28
|
-
// Transcript hash binding rekeys to the handshake.
|
|
29
|
-
transcriptHash;
|
|
30
|
-
// Rekey direction identifiers for send/recv.
|
|
31
|
-
sendDir;
|
|
32
|
-
recvDir;
|
|
33
|
-
// Monotonic record sequence numbers per direction.
|
|
34
|
-
sendSeq;
|
|
35
|
-
recvSeq;
|
|
36
|
-
// Send queue and waiters for backpressure.
|
|
37
|
-
sendQueue = [];
|
|
38
|
-
sendQueueHead = 0;
|
|
39
|
-
sendWaiters = [];
|
|
40
|
-
sendWaitersHead = 0;
|
|
41
|
-
sendQueueBytes = 0;
|
|
42
|
-
sendClosed = false;
|
|
43
|
-
sendErr = null;
|
|
44
|
-
// Receive queue and waiters for plaintext delivery.
|
|
45
|
-
recvQueue = [];
|
|
46
|
-
recvQueueHead = 0;
|
|
47
|
-
recvQueueBytes = 0;
|
|
48
|
-
recvWaiters = [];
|
|
49
|
-
readErr = null;
|
|
50
|
-
closed = false;
|
|
51
|
-
constructor(args) {
|
|
52
|
-
this.transport = args.transport;
|
|
53
|
-
this.maxRecordBytes = args.maxRecordBytes;
|
|
54
|
-
const maxPlain = Math.max(1, maxPlaintextBytes(this.maxRecordBytes));
|
|
55
|
-
this.outboundRecordChunkBytes = args.outboundRecordChunkBytes ?? Math.min(SDK_DEFAULTS.e2ee.outboundRecordChunkBytes, maxPlain);
|
|
56
|
-
if (!Number.isSafeInteger(this.outboundRecordChunkBytes) || this.outboundRecordChunkBytes <= 0 || this.outboundRecordChunkBytes > maxPlain) {
|
|
57
|
-
throw new RangeError("outboundRecordChunkBytes must be a positive integer within the record plaintext limit");
|
|
58
|
-
}
|
|
59
|
-
this.maxInboundBufferedBytes = Math.max(0, args.maxBufferedBytes ?? SDK_DEFAULTS.e2ee.maxInboundBufferedBytes);
|
|
60
|
-
const maxOutboundBufferedBytes = args.maxOutboundBufferedBytes ?? SDK_DEFAULTS.e2ee.maxOutboundBufferedBytes;
|
|
61
|
-
if (!Number.isSafeInteger(maxOutboundBufferedBytes) || maxOutboundBufferedBytes < 0) {
|
|
62
|
-
throw new RangeError("maxOutboundBufferedBytes must be a non-negative safe integer");
|
|
63
|
-
}
|
|
64
|
-
this.maxOutboundBufferedBytes = maxOutboundBufferedBytes === 0 ? SDK_DEFAULTS.e2ee.maxOutboundBufferedBytes : maxOutboundBufferedBytes;
|
|
65
|
-
this.sendKey = args.sendKey.slice();
|
|
66
|
-
this.recvKey = args.recvKey.slice();
|
|
67
|
-
this.sendNoncePrefix = args.sendNoncePrefix;
|
|
68
|
-
this.recvNoncePrefix = args.recvNoncePrefix;
|
|
69
|
-
this.rekeyBase = args.rekeyBase.slice();
|
|
70
|
-
this.transcriptHash = args.transcriptHash;
|
|
71
|
-
this.sendDir = args.sendDir;
|
|
72
|
-
this.recvDir = args.recvDir;
|
|
73
|
-
this.sendSeq = args.sendSeq ?? 1n;
|
|
74
|
-
this.recvSeq = args.recvSeq ?? 1n;
|
|
75
|
-
void this.readLoop();
|
|
76
|
-
void this.sendLoop();
|
|
77
|
-
}
|
|
78
|
-
// write splits payloads into record-sized chunks and queues them for send.
|
|
79
|
-
async write(plaintext) {
|
|
80
|
-
if (plaintext.length === 0)
|
|
81
|
-
return;
|
|
82
|
-
await this.enqueueSend("app", plaintext);
|
|
83
|
-
}
|
|
84
|
-
// read resolves with the next plaintext chunk or throws on errors/close.
|
|
85
|
-
async read() {
|
|
86
|
-
while (true) {
|
|
87
|
-
if (this.recvQueueHead < this.recvQueue.length) {
|
|
88
|
-
const b = this.recvQueue[this.recvQueueHead];
|
|
89
|
-
this.recvQueueHead++;
|
|
90
|
-
if (this.recvQueueHead === this.recvQueue.length) {
|
|
91
|
-
this.recvQueue = [];
|
|
92
|
-
this.recvQueueHead = 0;
|
|
93
|
-
}
|
|
94
|
-
else if (this.recvQueueHead > 1024 && this.recvQueueHead * 2 > this.recvQueue.length) {
|
|
95
|
-
this.recvQueue.splice(0, this.recvQueueHead);
|
|
96
|
-
this.recvQueueHead = 0;
|
|
97
|
-
}
|
|
98
|
-
this.recvQueueBytes -= b.length;
|
|
99
|
-
return b;
|
|
100
|
-
}
|
|
101
|
-
if (this.readErr != null)
|
|
102
|
-
throw this.readErr;
|
|
103
|
-
if (this.closed)
|
|
104
|
-
throw new Error("closed");
|
|
105
|
-
await new Promise((resolve) => this.recvWaiters.push(resolve));
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
// close shuts down the transport and rejects any pending senders.
|
|
109
|
-
close() {
|
|
110
|
-
if (this.closed)
|
|
111
|
-
return;
|
|
112
|
-
this.closed = true;
|
|
113
|
-
this.sendClosed = true;
|
|
114
|
-
this.rejectQueuedSenders(this.sendErr ?? new Error("closed"));
|
|
115
|
-
this.wakeSendWaiters();
|
|
116
|
-
const ws = this.recvWaiters;
|
|
117
|
-
this.recvWaiters = [];
|
|
118
|
-
for (const w of ws)
|
|
119
|
-
w();
|
|
120
|
-
try {
|
|
121
|
-
this.transport.close();
|
|
122
|
-
}
|
|
123
|
-
finally {
|
|
124
|
-
this.clearKeyMaterial();
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
// sendPing emits a keepalive record.
|
|
128
|
-
async sendPing() {
|
|
129
|
-
await this.enqueueSend("ping");
|
|
130
|
-
}
|
|
131
|
-
// rekeyNow emits a rekey record and advances the send key.
|
|
132
|
-
async rekeyNow() {
|
|
133
|
-
await this.enqueueSend("rekey");
|
|
134
|
-
}
|
|
135
|
-
enqueueSend(kind, payload) {
|
|
136
|
-
if (this.sendErr != null)
|
|
137
|
-
return Promise.reject(this.sendErr);
|
|
138
|
-
if (this.closed || this.sendClosed)
|
|
139
|
-
return Promise.reject(new Error("closed"));
|
|
140
|
-
const bufferedBytes = payload?.byteLength ?? 0;
|
|
141
|
-
if (this.sendQueueBytes + bufferedBytes > this.maxOutboundBufferedBytes) {
|
|
142
|
-
return Promise.reject(new Error("secure channel outbound buffer exceeded"));
|
|
143
|
-
}
|
|
144
|
-
return new Promise((resolve, reject) => {
|
|
145
|
-
if (this.sendErr != null) {
|
|
146
|
-
reject(this.sendErr);
|
|
147
|
-
return;
|
|
148
|
-
}
|
|
149
|
-
if (this.closed || this.sendClosed) {
|
|
150
|
-
reject(new Error("closed"));
|
|
151
|
-
return;
|
|
152
|
-
}
|
|
153
|
-
if (this.sendQueueBytes + bufferedBytes > this.maxOutboundBufferedBytes) {
|
|
154
|
-
reject(new Error("secure channel outbound buffer exceeded"));
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
const retainedPayload = payload?.slice();
|
|
158
|
-
const req = retainedPayload === undefined
|
|
159
|
-
? { kind, bufferedBytes, resolve, reject }
|
|
160
|
-
: { kind, payload: retainedPayload, bufferedBytes, resolve, reject };
|
|
161
|
-
this.sendQueueBytes += bufferedBytes;
|
|
162
|
-
this.sendQueue.push(req);
|
|
163
|
-
const w = this.shiftSendWaiter();
|
|
164
|
-
if (w != null)
|
|
165
|
-
w();
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
async nextSend() {
|
|
169
|
-
const immediate = this.dequeueSend();
|
|
170
|
-
if (immediate != null)
|
|
171
|
-
return immediate;
|
|
172
|
-
if (this.closed || this.sendClosed)
|
|
173
|
-
return null;
|
|
174
|
-
return await new Promise((resolve) => {
|
|
175
|
-
this.sendWaiters.push(() => resolve(this.dequeueSend()));
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
|
-
dequeueSend() {
|
|
179
|
-
if (this.sendQueueHead >= this.sendQueue.length)
|
|
180
|
-
return null;
|
|
181
|
-
const req = this.sendQueue[this.sendQueueHead];
|
|
182
|
-
this.sendQueueHead++;
|
|
183
|
-
if (this.sendQueueHead === this.sendQueue.length) {
|
|
184
|
-
this.sendQueue = [];
|
|
185
|
-
this.sendQueueHead = 0;
|
|
186
|
-
}
|
|
187
|
-
else if (this.sendQueueHead > 1024 && this.sendQueueHead * 2 > this.sendQueue.length) {
|
|
188
|
-
this.sendQueue.splice(0, this.sendQueueHead);
|
|
189
|
-
this.sendQueueHead = 0;
|
|
190
|
-
}
|
|
191
|
-
return req;
|
|
192
|
-
}
|
|
193
|
-
shiftSendWaiter() {
|
|
194
|
-
if (this.sendWaitersHead >= this.sendWaiters.length)
|
|
195
|
-
return undefined;
|
|
196
|
-
const w = this.sendWaiters[this.sendWaitersHead];
|
|
197
|
-
this.sendWaitersHead++;
|
|
198
|
-
if (this.sendWaitersHead === this.sendWaiters.length) {
|
|
199
|
-
this.sendWaiters = [];
|
|
200
|
-
this.sendWaitersHead = 0;
|
|
201
|
-
}
|
|
202
|
-
else if (this.sendWaitersHead > 1024 && this.sendWaitersHead * 2 > this.sendWaiters.length) {
|
|
203
|
-
this.sendWaiters.splice(0, this.sendWaitersHead);
|
|
204
|
-
this.sendWaitersHead = 0;
|
|
205
|
-
}
|
|
206
|
-
return w;
|
|
207
|
-
}
|
|
208
|
-
wakeSendWaiters() {
|
|
209
|
-
const ws = this.sendWaiters;
|
|
210
|
-
const start = this.sendWaitersHead;
|
|
211
|
-
this.sendWaiters = [];
|
|
212
|
-
this.sendWaitersHead = 0;
|
|
213
|
-
for (let i = start; i < ws.length; i++)
|
|
214
|
-
ws[i]();
|
|
215
|
-
}
|
|
216
|
-
rejectQueuedSenders(err) {
|
|
217
|
-
const queued = this.sendQueue;
|
|
218
|
-
const start = this.sendQueueHead;
|
|
219
|
-
this.sendQueue = [];
|
|
220
|
-
this.sendQueueHead = 0;
|
|
221
|
-
for (let i = start; i < queued.length; i++) {
|
|
222
|
-
const req = queued[i];
|
|
223
|
-
this.sendQueueBytes = Math.max(0, this.sendQueueBytes - req.bufferedBytes);
|
|
224
|
-
req.reject(err);
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
failSend(err) {
|
|
228
|
-
if (this.sendErr != null)
|
|
229
|
-
return;
|
|
230
|
-
this.sendErr = err;
|
|
231
|
-
this.rejectQueuedSenders(err);
|
|
232
|
-
this.wakeSendWaiters();
|
|
233
|
-
}
|
|
234
|
-
reserveSendSeq() {
|
|
235
|
-
if (this.sendSeq >= maxRecordSeq) {
|
|
236
|
-
const err = new RecordSeqExhaustedError();
|
|
237
|
-
this.failSend(err);
|
|
238
|
-
throw err;
|
|
239
|
-
}
|
|
240
|
-
const seq = this.sendSeq;
|
|
241
|
-
this.sendSeq++;
|
|
242
|
-
return seq;
|
|
243
|
-
}
|
|
244
|
-
async sendLoop() {
|
|
245
|
-
while (true) {
|
|
246
|
-
const req = await this.nextSend();
|
|
247
|
-
if (req == null)
|
|
248
|
-
return;
|
|
249
|
-
try {
|
|
250
|
-
if (this.sendErr != null) {
|
|
251
|
-
req.reject(this.sendErr);
|
|
252
|
-
continue;
|
|
253
|
-
}
|
|
254
|
-
if (this.closed || this.sendClosed) {
|
|
255
|
-
req.reject(new Error("closed"));
|
|
256
|
-
continue;
|
|
257
|
-
}
|
|
258
|
-
let frame;
|
|
259
|
-
if (req.kind === "app") {
|
|
260
|
-
const payload = req.payload ?? new Uint8Array();
|
|
261
|
-
for (let offset = 0; offset < payload.length; offset += this.outboundRecordChunkBytes) {
|
|
262
|
-
if (this.closed || this.sendClosed)
|
|
263
|
-
throw new Error("closed");
|
|
264
|
-
const chunk = payload.subarray(offset, Math.min(payload.length, offset + this.outboundRecordChunkBytes));
|
|
265
|
-
const seq = this.reserveSendSeq();
|
|
266
|
-
frame = encryptRecord(this.sendKey, this.sendNoncePrefix, RECORD_FLAG_APP, seq, chunk, this.maxRecordBytes);
|
|
267
|
-
await this.transport.writeBinary(frame);
|
|
268
|
-
}
|
|
269
|
-
req.resolve();
|
|
270
|
-
continue;
|
|
271
|
-
}
|
|
272
|
-
else if (req.kind === "ping") {
|
|
273
|
-
const seq = this.reserveSendSeq();
|
|
274
|
-
frame = encryptRecord(this.sendKey, this.sendNoncePrefix, RECORD_FLAG_PING, seq, new Uint8Array(), this.maxRecordBytes);
|
|
275
|
-
}
|
|
276
|
-
else {
|
|
277
|
-
const seq = this.reserveSendSeq();
|
|
278
|
-
frame = encryptRecord(this.sendKey, this.sendNoncePrefix, RECORD_FLAG_REKEY, seq, new Uint8Array(), this.maxRecordBytes);
|
|
279
|
-
// Update the send key after enqueuing the rekey frame.
|
|
280
|
-
this.sendKey = deriveRekeyKey(this.rekeyBase, this.transcriptHash, seq, this.sendDir);
|
|
281
|
-
}
|
|
282
|
-
await this.transport.writeBinary(frame);
|
|
283
|
-
req.resolve();
|
|
284
|
-
}
|
|
285
|
-
catch (e) {
|
|
286
|
-
req.reject(e);
|
|
287
|
-
this.failSend(e);
|
|
288
|
-
this.close();
|
|
289
|
-
return;
|
|
290
|
-
}
|
|
291
|
-
finally {
|
|
292
|
-
this.sendQueueBytes = Math.max(0, this.sendQueueBytes - req.bufferedBytes);
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
async readLoop() {
|
|
297
|
-
try {
|
|
298
|
-
while (!this.closed) {
|
|
299
|
-
const frame = await this.transport.readBinary();
|
|
300
|
-
if (this.closed)
|
|
301
|
-
return;
|
|
302
|
-
const { flags, seq, plaintext } = decryptRecord(this.recvKey, this.recvNoncePrefix, frame, this.recvSeq, this.maxRecordBytes);
|
|
303
|
-
if (seq >= maxRecordSeq) {
|
|
304
|
-
throw new RecordSeqExhaustedError();
|
|
305
|
-
}
|
|
306
|
-
this.recvSeq = seq + 1n;
|
|
307
|
-
if (flags === RECORD_FLAG_APP) {
|
|
308
|
-
if (this.maxInboundBufferedBytes > 0 && this.recvQueueBytes + plaintext.length > this.maxInboundBufferedBytes) {
|
|
309
|
-
throw new Error("recv buffer exceeded");
|
|
310
|
-
}
|
|
311
|
-
this.recvQueue.push(plaintext);
|
|
312
|
-
this.recvQueueBytes += plaintext.length;
|
|
313
|
-
const ws = this.recvWaiters;
|
|
314
|
-
this.recvWaiters = [];
|
|
315
|
-
for (const w of ws)
|
|
316
|
-
w();
|
|
317
|
-
continue;
|
|
318
|
-
}
|
|
319
|
-
if (flags === RECORD_FLAG_PING)
|
|
320
|
-
continue;
|
|
321
|
-
if (flags === RECORD_FLAG_REKEY) {
|
|
322
|
-
this.recvKey = deriveRekeyKey(this.rekeyBase, this.transcriptHash, seq, this.recvDir);
|
|
323
|
-
continue;
|
|
324
|
-
}
|
|
325
|
-
throw new Error(`unknown record flag ${flags}`);
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
catch (e) {
|
|
329
|
-
this.readErr = e;
|
|
330
|
-
const ws = this.recvWaiters;
|
|
331
|
-
this.recvWaiters = [];
|
|
332
|
-
for (const w of ws)
|
|
333
|
-
w();
|
|
334
|
-
this.close();
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
clearKeyMaterial() {
|
|
338
|
-
this.sendKey.fill(0);
|
|
339
|
-
this.recvKey.fill(0);
|
|
340
|
-
this.rekeyBase.fill(0);
|
|
341
|
-
}
|
|
342
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
export type TranscriptInputs = Readonly<{
|
|
2
|
-
/** Protocol version byte used in the transcript. */
|
|
3
|
-
version: number;
|
|
4
|
-
/** Numeric suite identifier (see e2ee suite). */
|
|
5
|
-
suite: number;
|
|
6
|
-
/** Role byte (client=1, server=2). */
|
|
7
|
-
role: number;
|
|
8
|
-
/** Client feature bitset. */
|
|
9
|
-
clientFeatures: number;
|
|
10
|
-
/** Server feature bitset. */
|
|
11
|
-
serverFeatures: number;
|
|
12
|
-
/** Channel identifier shared by both endpoints. */
|
|
13
|
-
channelId: string;
|
|
14
|
-
/** Client nonce (32 bytes). */
|
|
15
|
-
nonceC: Uint8Array;
|
|
16
|
-
/** Server nonce (32 bytes). */
|
|
17
|
-
nonceS: Uint8Array;
|
|
18
|
-
/** Client ephemeral public key bytes. */
|
|
19
|
-
clientEphPub: Uint8Array;
|
|
20
|
-
/** Server ephemeral public key bytes. */
|
|
21
|
-
serverEphPub: Uint8Array;
|
|
22
|
-
}>;
|
|
23
|
-
export declare function transcriptHash(inputs: TranscriptInputs): Uint8Array;
|
package/dist/e2ee/transcript.js
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { sha256 } from "@noble/hashes/sha256";
|
|
2
|
-
import { concatBytes, u16be, u32be } from "../utils/bin.js";
|
|
3
|
-
const te = new TextEncoder();
|
|
4
|
-
// transcriptHash computes the SHA-256 hash of the handshake transcript.
|
|
5
|
-
export function transcriptHash(inputs) {
|
|
6
|
-
if (inputs.nonceC.length !== 32 || inputs.nonceS.length !== 32)
|
|
7
|
-
throw new Error("nonce must be 32 bytes");
|
|
8
|
-
const channelIdBytes = te.encode(inputs.channelId);
|
|
9
|
-
if (channelIdBytes.length > 0xffff)
|
|
10
|
-
throw new Error("channel_id too long");
|
|
11
|
-
if (inputs.clientEphPub.length > 0xffff || inputs.serverEphPub.length > 0xffff)
|
|
12
|
-
throw new Error("pub too long");
|
|
13
|
-
const prefix = te.encode("flowersec-e2ee-v1");
|
|
14
|
-
const body = concatBytes([
|
|
15
|
-
prefix,
|
|
16
|
-
new Uint8Array([inputs.version & 0xff]),
|
|
17
|
-
u16be(inputs.suite),
|
|
18
|
-
new Uint8Array([inputs.role & 0xff]),
|
|
19
|
-
u32be(inputs.clientFeatures >>> 0),
|
|
20
|
-
u32be(inputs.serverFeatures >>> 0),
|
|
21
|
-
u16be(channelIdBytes.length),
|
|
22
|
-
channelIdBytes,
|
|
23
|
-
inputs.nonceC,
|
|
24
|
-
inputs.nonceS,
|
|
25
|
-
u16be(inputs.clientEphPub.length),
|
|
26
|
-
inputs.clientEphPub,
|
|
27
|
-
u16be(inputs.serverEphPub.length),
|
|
28
|
-
inputs.serverEphPub
|
|
29
|
-
]);
|
|
30
|
-
return sha256(body);
|
|
31
|
-
}
|
package/dist/endpoint/index.d.ts
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import { type TransportSecurityPolicy } from "../client-connect/transportSecurity.js";
|
|
2
|
-
import { serverHandshake, ServerHandshakeCache, type Suite } from "../e2ee/handshake.js";
|
|
3
|
-
import { type YamuxLimits } from "../yamux/session.js";
|
|
4
|
-
import type { YamuxStream } from "../yamux/stream.js";
|
|
5
|
-
import { type RpcRouter, type RpcServerOptions } from "../rpc/server.js";
|
|
6
|
-
import { type WebSocketLike, type WebSocketLimits } from "../ws-client/binaryTransport.js";
|
|
7
|
-
export type { Suite } from "../e2ee/handshake.js";
|
|
8
|
-
export type EndpointPath = "direct" | "tunnel";
|
|
9
|
-
export type DirectHandshakeInit = Readonly<{
|
|
10
|
-
channelId: string;
|
|
11
|
-
version: number;
|
|
12
|
-
suite: Suite;
|
|
13
|
-
clientFeatures: number;
|
|
14
|
-
}>;
|
|
15
|
-
export type DirectHandshakeCredential = Readonly<{
|
|
16
|
-
psk: Uint8Array | string;
|
|
17
|
-
initExpireAtUnixS: number;
|
|
18
|
-
commitAuthenticated?: () => void | Promise<void>;
|
|
19
|
-
}>;
|
|
20
|
-
export type DirectCredentialResolver = (init: DirectHandshakeInit) => DirectHandshakeCredential | Promise<DirectHandshakeCredential>;
|
|
21
|
-
export type EndpointOptions = Readonly<{
|
|
22
|
-
signal?: AbortSignal;
|
|
23
|
-
handshakeTimeoutMs?: number;
|
|
24
|
-
handshakeClockSkewMs?: number;
|
|
25
|
-
serverFeatures?: number;
|
|
26
|
-
maxHandshakePayload?: number;
|
|
27
|
-
maxRecordBytes?: number;
|
|
28
|
-
maxBufferedBytes?: number;
|
|
29
|
-
maxOutboundBufferedBytes?: number;
|
|
30
|
-
outboundRecordChunkBytes?: number;
|
|
31
|
-
webSocketLimits?: Partial<WebSocketLimits>;
|
|
32
|
-
yamuxLimits?: Partial<YamuxLimits>;
|
|
33
|
-
handshakeCache?: ServerHandshakeCache;
|
|
34
|
-
}>;
|
|
35
|
-
export type DirectAcceptOptions = EndpointOptions & Readonly<{
|
|
36
|
-
secureTransport?: boolean;
|
|
37
|
-
transportSecurityPolicy?: TransportSecurityPolicy;
|
|
38
|
-
}>;
|
|
39
|
-
export type TunnelEndpointOptions = EndpointOptions & Readonly<{
|
|
40
|
-
origin: string;
|
|
41
|
-
connectTimeoutMs?: number;
|
|
42
|
-
endpointInstanceId?: string;
|
|
43
|
-
wsFactory: (url: string, origin: string) => WebSocketLike;
|
|
44
|
-
transportSecurityPolicy?: TransportSecurityPolicy;
|
|
45
|
-
}>;
|
|
46
|
-
export type EndpointStream = Readonly<{
|
|
47
|
-
kind: string;
|
|
48
|
-
stream: YamuxStream;
|
|
49
|
-
}>;
|
|
50
|
-
export declare class Session {
|
|
51
|
-
private readonly secure;
|
|
52
|
-
private readonly mux;
|
|
53
|
-
readonly path: EndpointPath;
|
|
54
|
-
readonly endpointInstanceId: string | undefined;
|
|
55
|
-
private readonly streams;
|
|
56
|
-
private readonly waiters;
|
|
57
|
-
private terminalError;
|
|
58
|
-
private constructor();
|
|
59
|
-
static create(path: EndpointPath, secure: Awaited<ReturnType<typeof serverHandshake>>, options?: Readonly<{
|
|
60
|
-
yamuxLimits?: Partial<YamuxLimits>;
|
|
61
|
-
endpointInstanceId?: string;
|
|
62
|
-
}>): Session;
|
|
63
|
-
openStream(kind: string, options?: Readonly<{
|
|
64
|
-
signal?: AbortSignal;
|
|
65
|
-
}>): Promise<YamuxStream>;
|
|
66
|
-
acceptStream(options?: Readonly<{
|
|
67
|
-
signal?: AbortSignal;
|
|
68
|
-
}>): Promise<EndpointStream>;
|
|
69
|
-
serveRPC(router: RpcRouter, options?: RpcServerOptions & Readonly<{
|
|
70
|
-
signal?: AbortSignal;
|
|
71
|
-
}>): Promise<void>;
|
|
72
|
-
probeLiveness(timeoutMs?: 10000): Promise<number>;
|
|
73
|
-
rekey(): Promise<void>;
|
|
74
|
-
close(): void;
|
|
75
|
-
private pushStream;
|
|
76
|
-
private acceptRawStream;
|
|
77
|
-
private fail;
|
|
78
|
-
}
|
|
79
|
-
export declare function acceptDirect(websocket: WebSocketLike, handshake: Readonly<{
|
|
80
|
-
channelId: string;
|
|
81
|
-
suite: Suite;
|
|
82
|
-
}> & DirectHandshakeCredential, options?: DirectAcceptOptions): Promise<Session>;
|
|
83
|
-
export declare function acceptDirectResolved(websocket: WebSocketLike, resolver: DirectCredentialResolver, options?: DirectAcceptOptions): Promise<Session>;
|
|
84
|
-
export declare function connectTunnel(grantInput: unknown, options: TunnelEndpointOptions): Promise<Session>;
|