lemon-tls 0.9.0 → 0.11.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 +168 -41
- package/index.cjs +9 -7
- package/index.d.ts +626 -30
- package/package.json +45 -7
- package/src/ca_store.js +31 -0
- package/src/compat.js +76 -116
- package/src/crypto.js +21 -114
- package/src/dtls_session.js +1284 -390
- package/src/dtls_socket.js +318 -96
- package/src/node_options.js +154 -17
- package/src/record.js +355 -191
- package/src/secure_context.js +97 -39
- package/src/session/ecdh.js +140 -122
- package/src/session/ech.js +92 -32
- package/src/session/hpke.js +12 -44
- package/src/session/message.js +29 -9
- package/src/session/signing.js +80 -22
- package/src/session/ticket.js +5 -3
- package/src/session/x509.js +385 -0
- package/src/tls_session.js +2221 -902
- package/src/tls_socket.js +451 -452
- package/src/wire.js +271 -158
- package/types/crypto.d.ts +40 -0
- package/types/record.d.ts +40 -0
- package/types/session.d.ts +3 -0
- package/types/wire.d.ts +62 -0
package/index.d.ts
CHANGED
|
@@ -7,9 +7,81 @@ import type { X509Certificate } from 'node:crypto';
|
|
|
7
7
|
|
|
8
8
|
// ======================== Types ========================
|
|
9
9
|
|
|
10
|
+
/** A key or certificate: PEM or DER bytes, or a file path. */
|
|
11
|
+
export type PemInput = Buffer | Uint8Array | string;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* createSecureContext()'s options. `key` and `cert` as arrays — node:tls's
|
|
15
|
+
* form — for several certificates of different kinds (an ML-DSA one for
|
|
16
|
+
* clients that ask for post-quantum authentication, an ECDSA or RSA one for
|
|
17
|
+
* the rest): each key is paired with the chain whose leaf carries its public
|
|
18
|
+
* key, the first being the default.
|
|
19
|
+
*/
|
|
20
|
+
export interface SecureContextOptions {
|
|
21
|
+
key?: PemInput | Array<PemInput | { pem: PemInput; passphrase?: string }>;
|
|
22
|
+
cert?: PemInput | PemInput[];
|
|
23
|
+
ca?: PemInput | PemInput[];
|
|
24
|
+
passphrase?: string;
|
|
25
|
+
pfx?: PemInput;
|
|
26
|
+
/** A stapled OCSP response (DER) for the leaf. */
|
|
27
|
+
ocsp?: PemInput;
|
|
28
|
+
ticketKeys?: Buffer | Uint8Array;
|
|
29
|
+
[option: string]: any;
|
|
30
|
+
}
|
|
31
|
+
|
|
10
32
|
export interface SecureContext {
|
|
11
33
|
certificateChain: Array<{ cert: Buffer }>;
|
|
12
34
|
privateKey: any;
|
|
35
|
+
ca?: any[];
|
|
36
|
+
/** The other key/certificate pairs (key/cert arrays). */
|
|
37
|
+
alternates?: Array<{ certificateChain: Array<{ cert: Buffer }>; privateKey: any }>;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* An external PSK (RFC 8446 §2.2): a key both sides hold from elsewhere.
|
|
42
|
+
* TLS 1.3 and DTLS 1.3, psk_dhe_ke (a fresh ECDHE secret is mixed in). The
|
|
43
|
+
* peer that proves it is authenticated by it — no certificate is needed or
|
|
44
|
+
* sent; if the server does not take it, the handshake goes on with its
|
|
45
|
+
* certificate, checked as usual.
|
|
46
|
+
*/
|
|
47
|
+
export interface ExternalPsk {
|
|
48
|
+
/** Its identity: a string (UTF-8) or bytes, 1 to 65535 long. */
|
|
49
|
+
identity: string | Uint8Array;
|
|
50
|
+
psk: Uint8Array;
|
|
51
|
+
/** The hash it is used with (RFC 8446 §4.2.11). Default 'sha256'. */
|
|
52
|
+
hash?: 'sha256' | 'sha384';
|
|
53
|
+
}
|
|
54
|
+
/** A server's answer for an identity: the key (SHA-256), the key and its hash, or none. */
|
|
55
|
+
export type ExternalPskAnswer = Uint8Array | { psk: Uint8Array; hash?: 'sha256' | 'sha384' } | null | undefined;
|
|
56
|
+
|
|
57
|
+
/** The record size limits in force (RFC 8449), in plaintext bytes: what we may send, what we take. */
|
|
58
|
+
export interface RecordSizeLimit {
|
|
59
|
+
send: number;
|
|
60
|
+
receive: number;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** An Encrypted Client Hello key (RFC 9849), from generateEchKey(). */
|
|
64
|
+
export interface EchKey {
|
|
65
|
+
config: Uint8Array;
|
|
66
|
+
privateKey: Uint8Array;
|
|
67
|
+
configList: Uint8Array;
|
|
68
|
+
/** The value of `ech=` in the domain's HTTPS record. */
|
|
69
|
+
configListBase64: string;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** A server's `ech` option. `retry: false`: still accepted, no longer offered to clients. */
|
|
73
|
+
export interface EchServerOption {
|
|
74
|
+
keys: Array<{ config: Uint8Array | Buffer | string; privateKey: Uint8Array | Buffer | string; retry?: boolean }>;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** A saved session ('session' event's Buffer) described without its secrets: sessionInfo(). */
|
|
78
|
+
export interface SessionInfo {
|
|
79
|
+
version: 'TLSv1.3' | 'TLSv1.2' | null;
|
|
80
|
+
servername: string | null;
|
|
81
|
+
alpn: string | null;
|
|
82
|
+
created: number | null;
|
|
83
|
+
expiresAt: number | null;
|
|
84
|
+
earlyData: boolean;
|
|
13
85
|
}
|
|
14
86
|
|
|
15
87
|
export interface CipherInfo {
|
|
@@ -19,6 +91,7 @@ export interface CipherInfo {
|
|
|
19
91
|
}
|
|
20
92
|
|
|
21
93
|
export interface PeerCertificate {
|
|
94
|
+
/** RDN fields as node:tls has them: { C, ST, L, O, OU, CN }. */
|
|
22
95
|
subject: any;
|
|
23
96
|
issuer: any;
|
|
24
97
|
subjectaltname?: string;
|
|
@@ -107,12 +180,19 @@ export interface CertificateCallbackInfo {
|
|
|
107
180
|
export interface TLSSocketOptions {
|
|
108
181
|
isServer?: boolean;
|
|
109
182
|
servername?: string;
|
|
110
|
-
SNICallback?: (servername: string, cb: (err: Error | null, ctx
|
|
183
|
+
SNICallback?: (servername: string, cb: (err: Error | null, ctx?: SecureContext | null) => void) => void;
|
|
184
|
+
/** Server, node:tls's: pick the protocol from what the client offers (exclusive with ALPNProtocols on a Server). */
|
|
185
|
+
ALPNCallback?: (info: { servername: string | null; protocols: string[] }) => string | undefined;
|
|
111
186
|
minVersion?: 'TLSv1.2' | 'TLSv1.3';
|
|
112
187
|
maxVersion?: 'TLSv1.2' | 'TLSv1.3';
|
|
113
188
|
ALPNProtocols?: string[];
|
|
114
189
|
rejectUnauthorized?: boolean;
|
|
115
|
-
|
|
190
|
+
/** Client: the identity check (node:tls's); undefined for a match, an Error otherwise. */
|
|
191
|
+
checkServerIdentity?: (hostname: string, cert: PeerCertificate) => Error | undefined;
|
|
192
|
+
ca?: PemInput | PemInput[];
|
|
193
|
+
/** A context from createSecureContext(), in place of key/cert/ca. */
|
|
194
|
+
secureContext?: SecureContext;
|
|
195
|
+
passphrase?: string;
|
|
116
196
|
ticketKeys?: Buffer;
|
|
117
197
|
/**
|
|
118
198
|
* Server: what to carry inside each session ticket issued. Called once per
|
|
@@ -128,8 +208,76 @@ export interface TLSSocketOptions {
|
|
|
128
208
|
*/
|
|
129
209
|
session?: Buffer | Uint8Array;
|
|
130
210
|
requestCert?: boolean;
|
|
131
|
-
cert?:
|
|
132
|
-
key?:
|
|
211
|
+
cert?: PemInput;
|
|
212
|
+
key?: PemInput;
|
|
213
|
+
|
|
214
|
+
// node:tls's option strings — taken as Node takes them. lemon-tls's code
|
|
215
|
+
// lists (allowedCipherSuites, groups, signatureAlgorithms) win when given.
|
|
216
|
+
/** 'TLS_AES_128_GCM_SHA256:ECDHE-RSA-AES128-GCM-SHA256…' */
|
|
217
|
+
ciphers?: string;
|
|
218
|
+
/** 'X25519:P-256', or 'auto'. */
|
|
219
|
+
ecdhCurve?: string;
|
|
220
|
+
/** 'ecdsa_secp256r1_sha256:rsa_pss_rsae_sha256…' */
|
|
221
|
+
sigalgs?: string;
|
|
222
|
+
/** Server: the cipher suite by the server's order (default: the client's). */
|
|
223
|
+
honorCipherOrder?: boolean;
|
|
224
|
+
|
|
225
|
+
// ---- Encrypted Client Hello (RFC 9849) ----
|
|
226
|
+
/** Server: { keys }. Client: the server's ECHConfigList (bytes, or base64 — `ech=` of its HTTPS record). */
|
|
227
|
+
ech?: EchServerOption | Uint8Array | Buffer | string;
|
|
228
|
+
/** Client: GREASE ECH, without a config. */
|
|
229
|
+
echGrease?: boolean;
|
|
230
|
+
|
|
231
|
+
// ---- OCSP stapling ----
|
|
232
|
+
/** Server: asked when a client requests status; callback(null, response DER) or (null, null). */
|
|
233
|
+
ocspRequest?: (certificate: Buffer, issuer: Buffer | null, callback: (err: Error | null, response: Buffer | Uint8Array | null) => void) => void;
|
|
234
|
+
/** Client: ask the server for a stapled response ('OCSPResponse'). */
|
|
235
|
+
requestOCSP?: boolean;
|
|
236
|
+
|
|
237
|
+
/** RFC 8879: ['brotli', 'zlib', 'zstd'] in order, true (all this build has) or false (none). */
|
|
238
|
+
certificateCompression?: Array<'brotli' | 'zlib' | 'zstd'> | boolean;
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* RFC 8449: the largest record we take — 64 to 16385 (TLS 1.3 counts the
|
|
242
|
+
* content-type byte). A client sends it; a server answers a client's with
|
|
243
|
+
* this or the protocol's maximum. false: never sent or answered. Records
|
|
244
|
+
* we send are cut to the peer's limit.
|
|
245
|
+
*/
|
|
246
|
+
recordSizeLimit?: number | false;
|
|
247
|
+
|
|
248
|
+
// ---- External PSK (TLS 1.3) ----
|
|
249
|
+
/**
|
|
250
|
+
* node:tls's. Client: (hint) → { psk, identity } or null — asked once,
|
|
251
|
+
* hint is null (TLS 1.3 has no identity hint). Server: (socket, identity)
|
|
252
|
+
* → the key or { psk, hash }, or null for an identity it does not know
|
|
253
|
+
* (then session tickets are tried, then a full handshake).
|
|
254
|
+
*/
|
|
255
|
+
pskCallback?: ((hint: null) => (ExternalPsk | null)) | ((socket: TLSSocket, identity: string) => ExternalPskAnswer);
|
|
256
|
+
/** Client: the external PSK, without a callback. */
|
|
257
|
+
psk?: ExternalPsk;
|
|
258
|
+
|
|
259
|
+
// ---- 0-RTT (RFC 8446 §4.2.10) ----
|
|
260
|
+
/** Server: issue tickets that allow it, and take it. Client: with `session`, what is written before 'secureConnect' goes early. */
|
|
261
|
+
earlyData?: boolean;
|
|
262
|
+
/** Server: ms the client's ticket age may differ from ours. */
|
|
263
|
+
earlyDataMaxAge?: number;
|
|
264
|
+
/** Server: the anti-replay store — cb(null, true) when `id` is new (keep it `ttl` ms). */
|
|
265
|
+
earlyDataReplay?: (id: string, ttl: number, cb: (err: Error | null, fresh: boolean) => void) => void;
|
|
266
|
+
/** Server: bytes of early data a ticket allows (16 KB). */
|
|
267
|
+
maxEarlyData?: number;
|
|
268
|
+
|
|
269
|
+
// ---- ClientHello shaping (client) ----
|
|
270
|
+
grease?: boolean;
|
|
271
|
+
permuteExtensions?: boolean;
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Trust the bundled CAs when no `ca` is given (default: true) — a client
|
|
275
|
+
* for the server's chain, a server (requestCert) for the client's. false
|
|
276
|
+
* with no `ca`: no peer is authorized.
|
|
277
|
+
*/
|
|
278
|
+
useDefaultCA?: boolean;
|
|
279
|
+
allowHalfOpen?: boolean;
|
|
280
|
+
highWaterMark?: number;
|
|
133
281
|
|
|
134
282
|
// TCP options, as in node:net. connect() passes them (and the rest of
|
|
135
283
|
// net.connect's: localAddress, localPort, family, lookup, timeout) to
|
|
@@ -150,10 +298,12 @@ export interface TLSSocketOptions {
|
|
|
150
298
|
noTickets?: boolean;
|
|
151
299
|
sessionTickets?: boolean;
|
|
152
300
|
ticketLifetime?: number;
|
|
301
|
+
/** Signature schemes, in preference order. No SHA-1 (0x0201, 0x0203: RFC 9155) — a list naming one throws. */
|
|
153
302
|
signatureAlgorithms?: number[];
|
|
154
303
|
groups?: number[];
|
|
155
304
|
prioritizeChaCha?: boolean;
|
|
156
305
|
maxRecordSize?: number;
|
|
306
|
+
/** Code points to narrow the suites to; a list with none this library carries throws ("no cipher match"). */
|
|
157
307
|
allowedCipherSuites?: number[];
|
|
158
308
|
pins?: string[];
|
|
159
309
|
handshakeTimeout?: number;
|
|
@@ -162,6 +312,27 @@ export interface TLSSocketOptions {
|
|
|
162
312
|
customExtensions?: Array<{ type: number; data: Uint8Array }>;
|
|
163
313
|
}
|
|
164
314
|
|
|
315
|
+
/** connect()'s: the socket's options, where, and node:net's. */
|
|
316
|
+
export interface ConnectOptions extends TLSSocketOptions {
|
|
317
|
+
port?: number;
|
|
318
|
+
host?: string;
|
|
319
|
+
/** STARTTLS: an existing socket to run TLS on (no net.connect). */
|
|
320
|
+
socket?: Duplex;
|
|
321
|
+
lookup?: (...args: any[]) => void;
|
|
322
|
+
[option: string]: any;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/** createServer()'s: the server side of TLSSocketOptions, and node:tls's server ones. */
|
|
326
|
+
export interface ServerOptions extends Omit<TLSSocketOptions, 'key' | 'cert'> {
|
|
327
|
+
key?: SecureContextOptions['key'];
|
|
328
|
+
cert?: SecureContextOptions['cert'];
|
|
329
|
+
/** Seconds a session stays good — tickets and TLS 1.2 Session IDs (Node's default, 300). */
|
|
330
|
+
sessionTimeout?: number;
|
|
331
|
+
/** Sessions under one context do not resume under another. */
|
|
332
|
+
sessionIdContext?: string | Buffer;
|
|
333
|
+
pauseOnConnect?: boolean;
|
|
334
|
+
}
|
|
335
|
+
|
|
165
336
|
// ======================== TLSSocket ========================
|
|
166
337
|
|
|
167
338
|
export class TLSSocket extends Duplex {
|
|
@@ -170,7 +341,8 @@ export class TLSSocket extends Duplex {
|
|
|
170
341
|
// ------- Node.js tls.TLSSocket compatible API -------
|
|
171
342
|
getProtocol(): string | null;
|
|
172
343
|
getCipher(): CipherInfo | null;
|
|
173
|
-
|
|
344
|
+
/** `detailed` is accepted for node:tls's signature; the leaf is described either way. */
|
|
345
|
+
getPeerCertificate(detailed?: boolean): PeerCertificate | null;
|
|
174
346
|
/** Returns our LOCAL cert (what we presented). Empty object if none. */
|
|
175
347
|
getCertificate(): PeerCertificate | {};
|
|
176
348
|
/** Returns the peer cert as a native crypto.X509Certificate object (Node 15.9+). */
|
|
@@ -180,10 +352,16 @@ export class TLSSocket extends Duplex {
|
|
|
180
352
|
isSessionReused(): boolean;
|
|
181
353
|
getFinished(): Buffer | null;
|
|
182
354
|
getPeerFinished(): Buffer | null;
|
|
183
|
-
|
|
184
|
-
|
|
355
|
+
/** null before the handshake completes (Node throws). */
|
|
356
|
+
exportKeyingMaterial(length: number, label: string, context?: Buffer | Uint8Array): Buffer | null;
|
|
357
|
+
/** null on a server socket, as in Node. */
|
|
358
|
+
getEphemeralKeyInfo(): EphemeralKeyInfo | {} | null;
|
|
359
|
+
/** On sockets from connect() and createServer() (compat layer). */
|
|
185
360
|
disableRenegotiation(): void;
|
|
361
|
+
/** On sockets from connect() and createServer() (compat layer). */
|
|
186
362
|
setServername(name: string): void;
|
|
363
|
+
/** The transport's bound address, as node:tls's. */
|
|
364
|
+
address(): { port?: number; family?: string; address?: string };
|
|
187
365
|
/** Returns the opaque serialized session Buffer, or undefined. */
|
|
188
366
|
getSession(): Buffer | undefined;
|
|
189
367
|
/** Returns the TLS 1.2 session ticket as a Buffer, or undefined (incl. for TLS 1.3). */
|
|
@@ -225,6 +403,22 @@ export class TLSSocket extends Duplex {
|
|
|
225
403
|
/** Returns the underlying TLSSession for low-level access. */
|
|
226
404
|
session: TLSSession;
|
|
227
405
|
readonly handshakeDuration: number | null;
|
|
406
|
+
/** 0-RTT. Server: what is read now came early (it may be a replay). Client: it is sending early. */
|
|
407
|
+
readonly isEarlyData: boolean;
|
|
408
|
+
readonly earlyDataBytes: number;
|
|
409
|
+
readonly earlyDataStatus: 'offered' | 'accepted' | 'rejected' | null;
|
|
410
|
+
/** Encrypted Client Hello: what happened to it on this connection. */
|
|
411
|
+
readonly echStatus: string | null;
|
|
412
|
+
readonly echAccepted: boolean;
|
|
413
|
+
/** Server, ECH split mode: ECH accepted by the client-facing server in front of this one; echStatus is 'accepted' either way. */
|
|
414
|
+
readonly echBackend: boolean;
|
|
415
|
+
/** External PSK: the identity this connection was authenticated with (or resumed from one that was), or null. */
|
|
416
|
+
getPskIdentity(): Buffer | null;
|
|
417
|
+
/** Server: the certificate to present, from inside ALPNCallback (a context or { key, cert }). */
|
|
418
|
+
setKeyCert(context: SecureContext | SecureContextOptions): void;
|
|
419
|
+
/** The peer's hello extensions: [{ type, name, data, value }]. */
|
|
420
|
+
getRemoteExtensions(): Array<{ type: number; name: string | null; data: Uint8Array; value: any }>;
|
|
421
|
+
getRemoteExtension(type: number): { type: number; name: string | null; data: Uint8Array; value: any } | null;
|
|
228
422
|
/** JA4 of the ClientHello — the published format, what fingerprint
|
|
229
423
|
* databases match. Changes when a client resumes (pre_shared_key). */
|
|
230
424
|
getJA4(opts?: FingerprintOptions): FingerprintResult | null;
|
|
@@ -256,6 +450,13 @@ export class TLSSocket extends Duplex {
|
|
|
256
450
|
on(event: 'certificateRequest', listener: (msg: any) => void): this;
|
|
257
451
|
on(event: 'newSession', listener: (id: Buffer, data: Buffer, cb: () => void) => void): this;
|
|
258
452
|
on(event: 'resumeSession', listener: (id: Buffer, cb: (err: Error | null, data: Buffer | null) => void) => void): this;
|
|
453
|
+
/** Client: the server's stapled OCSP response (requestOCSP). */
|
|
454
|
+
on(event: 'OCSPResponse', listener: (response: Buffer) => void): this;
|
|
455
|
+
/** 0-RTT decided: whether the server took it. */
|
|
456
|
+
on(event: 'earlyData', listener: (accepted: boolean) => void): this;
|
|
457
|
+
on(event: 'alert', listener: (alert: { level: number; description: number }) => void): this;
|
|
458
|
+
on(event: 'secure', listener: () => void): this;
|
|
459
|
+
on(event: 'psk', listener: (identity: any, callback: (result: { psk: Buffer; cipher: number } | null) => void) => void): this;
|
|
259
460
|
on(event: 'error', listener: (err: Error) => void): this;
|
|
260
461
|
on(event: 'close', listener: () => void): this;
|
|
261
462
|
on(event: string, listener: (...args: any[]) => void): this;
|
|
@@ -274,8 +475,19 @@ export class Server extends EventEmitter {
|
|
|
274
475
|
close(callback?: (err?: Error) => void): this;
|
|
275
476
|
address(): { port: number; family: string; address: string } | string | null;
|
|
276
477
|
|
|
277
|
-
|
|
278
|
-
|
|
478
|
+
getConnections(callback: (err: Error | null, count: number) => void): void;
|
|
479
|
+
/** Node's documented injection of a Duplex into the server ('connection'), as a method. */
|
|
480
|
+
injectConnection(stream: Duplex): this;
|
|
481
|
+
ref(): this;
|
|
482
|
+
unref(): this;
|
|
483
|
+
|
|
484
|
+
/** Replace the server's key/cert at runtime (Let's Encrypt renewals, etc.). Throws on a bad one; the old stays. */
|
|
485
|
+
setSecureContext(options: SecureContextOptions | { secureContext: SecureContext }): void;
|
|
486
|
+
/** A certificate for an SNI name or wildcard ('*.example.com': one label). The latest wins; an exact name beats a wildcard. */
|
|
487
|
+
addContext(hostname: string, context: SecureContext | SecureContextOptions): this;
|
|
488
|
+
/** Encrypted Client Hello keys, rotated without a restart. */
|
|
489
|
+
getEchKeys(): EchServerOption | null;
|
|
490
|
+
setEchKeys(ech: EchServerOption | null): void;
|
|
279
491
|
/** Returns the 48-byte TLS session ticket encryption keys. */
|
|
280
492
|
getTicketKeys(): Buffer;
|
|
281
493
|
/** Sets the 48-byte TLS session ticket encryption keys (for clustered deployments). */
|
|
@@ -287,6 +499,11 @@ export class Server extends EventEmitter {
|
|
|
287
499
|
on(event: 'secureConnection', listener: (socket: TLSSocket) => void): this;
|
|
288
500
|
on(event: 'tlsClientError', listener: (err: Error, socket: TLSSocket | null) => void): this;
|
|
289
501
|
on(event: 'keylog', listener: (line: Buffer, socket: TLSSocket) => void): this;
|
|
502
|
+
/** Before the TLS handshake: the raw socket. */
|
|
503
|
+
on(event: 'connection', listener: (socket: Duplex) => void): this;
|
|
504
|
+
on(event: 'OCSPRequest', listener: (certificate: Buffer, issuer: Buffer | null, callback: (err: Error | null, response: Buffer | Uint8Array | null) => void) => void): this;
|
|
505
|
+
on(event: 'listening', listener: () => void): this;
|
|
506
|
+
on(event: 'drop', listener: (data: any) => void): this;
|
|
290
507
|
on(event: 'newSession', listener: (id: Buffer, data: Buffer, cb: () => void) => void): this;
|
|
291
508
|
on(event: 'resumeSession', listener: (id: Buffer, cb: (err: Error | null, data: Buffer | null) => void) => void): this;
|
|
292
509
|
on(event: 'error', listener: (err: Error) => void): this;
|
|
@@ -305,7 +522,14 @@ export interface TLSSessionOptions {
|
|
|
305
522
|
/** See TLSSocketOptions.ticketData. */
|
|
306
523
|
ticketData?: (resumed: any) => any;
|
|
307
524
|
session?: Buffer | Uint8Array | SessionTicketData;
|
|
308
|
-
|
|
525
|
+
/** Client: an external PSK (or, older, a resumption PSK already decoded). */
|
|
526
|
+
psk?: ExternalPsk | any;
|
|
527
|
+
/** Server: the external PSK for an identity — tried before 'psk' and the session tickets. */
|
|
528
|
+
pskCallback?: (identity: Uint8Array) => ExternalPskAnswer;
|
|
529
|
+
/** See TLSSocketOptions.recordSizeLimit. */
|
|
530
|
+
recordSizeLimit?: number | false;
|
|
531
|
+
/** DTLS: the CID to ask for (DTLSSession turns DTLSCommonOptions.connectionId into it). */
|
|
532
|
+
connectionId?: Uint8Array;
|
|
309
533
|
rejectUnauthorized?: boolean;
|
|
310
534
|
ca?: Buffer | string;
|
|
311
535
|
noTickets?: boolean;
|
|
@@ -352,9 +576,21 @@ export class TLSSession extends EventEmitter {
|
|
|
352
576
|
getVersion(): number | null;
|
|
353
577
|
getCipher(): number | null;
|
|
354
578
|
getALPN(): string | null;
|
|
579
|
+
/** Encrypted Client Hello: null, 'grease' (client), 'accepted', 'rejected'. */
|
|
580
|
+
getEchStatus(): 'grease' | 'accepted' | 'rejected' | null;
|
|
581
|
+
/** Server, ECH split mode: accepted by the client-facing server in front of this one (BoringSSL's SSL_ech_accepted is false here). */
|
|
582
|
+
isEchBackend(): boolean;
|
|
355
583
|
getPeerCertificate(): Array<{ cert: Buffer }> | null;
|
|
356
584
|
/** Our own certificate chain — the one this connection presents. */
|
|
357
585
|
getCertificate(): Array<{ cert: Buffer }> | null;
|
|
586
|
+
/** External PSK: the identity this connection was authenticated with, or null. */
|
|
587
|
+
getPskIdentity(): Uint8Array | null;
|
|
588
|
+
/** RFC 8449: the limits once both sides sent record_size_limit, else null. */
|
|
589
|
+
getRecordSizeLimit(): RecordSizeLimit | null;
|
|
590
|
+
/** The largest handshake message taken: 128 KB, or maxHandshakeSize when smaller. */
|
|
591
|
+
handshakeMessageLimit(): number;
|
|
592
|
+
/** The most content a record we send may carry: the peer's record_size_limit, or 2^14. */
|
|
593
|
+
recordSendLimit(): number;
|
|
358
594
|
getTrafficSecrets(): TrafficSecrets;
|
|
359
595
|
getHandshakeSecrets(): HandshakeSecrets;
|
|
360
596
|
exportKeyingMaterial(length: number, label: string, context: Uint8Array): Uint8Array;
|
|
@@ -375,7 +611,10 @@ export class TLSSession extends EventEmitter {
|
|
|
375
611
|
on(event: 'secureConnect', listener: () => void): this;
|
|
376
612
|
/** Emits the raw internal session blob (Buffer/Uint8Array — encoded session state). */
|
|
377
613
|
on(event: 'session', listener: (data: Buffer) => void): this;
|
|
378
|
-
|
|
614
|
+
/** Server: a PSK identity offered; answer with a resumption PSK, or not at all (the session's own tickets are tried). External PSKs: pskCallback. */
|
|
615
|
+
on(event: 'psk', listener: (info: { identity: Uint8Array; obfuscatedAge: number }, callback: (result: { psk: Uint8Array; cipher: number } | null) => void) => void): this;
|
|
616
|
+
/** DTLS: the Connection IDs were agreed (the record layer's cue). */
|
|
617
|
+
on(event: 'connectionId', listener: (ids: ConnectionIds) => void): this;
|
|
379
618
|
on(event: 'keyUpdate', listener: (info: { direction: 'send' | 'receive'; secret: Uint8Array }) => void): this;
|
|
380
619
|
on(event: 'keylog', listener: (line: Buffer) => void): this;
|
|
381
620
|
on(event: 'clienthello', listener: (raw: Buffer, parsed: any) => void): this;
|
|
@@ -389,16 +628,41 @@ export class TLSSession extends EventEmitter {
|
|
|
389
628
|
|
|
390
629
|
// ======================== Module Functions ========================
|
|
391
630
|
|
|
392
|
-
export function createSecureContext(options:
|
|
631
|
+
export function createSecureContext(options: SecureContextOptions): SecureContext;
|
|
393
632
|
|
|
394
|
-
export function connect(port: number, host: string, options?:
|
|
633
|
+
export function connect(port: number, host: string, options?: ConnectOptions, callback?: () => void): TLSSocket;
|
|
395
634
|
export function connect(port: number, host: string, callback?: () => void): TLSSocket;
|
|
396
|
-
export function connect(options:
|
|
635
|
+
export function connect(options: ConnectOptions, callback?: () => void): TLSSocket;
|
|
636
|
+
|
|
637
|
+
export function createServer(options: ServerOptions, connectionListener?: (socket: TLSSocket) => void): Server;
|
|
638
|
+
export function createServer(connectionListener?: (socket: TLSSocket) => void): Server;
|
|
639
|
+
|
|
640
|
+
// ---- node:tls's option strings → code lists (null when unset). They throw
|
|
641
|
+
// on a name they do not know, as Node's createServer does.
|
|
642
|
+
export function parseCiphers(ciphers: string | null | undefined): number[] | null;
|
|
643
|
+
export function parseEcdhCurve(ecdhCurve: string | null | undefined): number[] | null;
|
|
644
|
+
export function parseSigalgs(sigalgs: string | null | undefined): number[] | null;
|
|
645
|
+
export function parseTlsVersion(version: string | null | undefined, optionName?: string): number | null;
|
|
646
|
+
export function parseCertificateCompression(value: Array<'brotli' | 'zlib' | 'zstd'> | boolean | null | undefined): number[] | null;
|
|
397
647
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
648
|
+
/** A server's certificate chain compressed now, in the background (RFC 8879), so the first handshake does not wait for it. */
|
|
649
|
+
export function precompressCertificate(secureContext: SecureContext, algorithms?: Array<'brotli' | 'zlib' | 'zstd'> | boolean, callback?: () => void): void;
|
|
650
|
+
export function precompressCertificate(secureContext: SecureContext, callback?: () => void): void;
|
|
651
|
+
|
|
652
|
+
/** The key-exchange groups a server offers by default, in order (code points). */
|
|
653
|
+
export const DEFAULT_SERVER_GROUPS: readonly number[];
|
|
654
|
+
/** The signature schemes offered by default, in order (code points). */
|
|
655
|
+
export const DEFAULT_SIGNATURE_SCHEMES: readonly number[];
|
|
656
|
+
|
|
657
|
+
/** A saved session described without its secrets; null if it is not one. */
|
|
658
|
+
export function sessionInfo(session: Buffer | Uint8Array): SessionInfo | null;
|
|
659
|
+
/** A certificate (DER) as getPeerCertificate() describes it. */
|
|
660
|
+
export function certificateObject(der: Buffer | Uint8Array): PeerCertificate | { raw: Buffer | Uint8Array } | null;
|
|
661
|
+
|
|
662
|
+
/** A new ECH key for a server. publicName: the name the outer hello carries (the server holds a certificate for it). */
|
|
663
|
+
export function generateEchKey(options: { publicName: string; configId?: number; maxNameLength?: number; kem?: string | number }): EchKey;
|
|
664
|
+
/** Throws, saying what is wrong, if a server's `ech` option would not work. */
|
|
665
|
+
export function checkEchKeys(ech: EchServerOption | null | undefined): void;
|
|
402
666
|
|
|
403
667
|
export function getCiphers(): string[];
|
|
404
668
|
|
|
@@ -416,13 +680,26 @@ export function getCACertificates(type?: 'default' | 'bundled' | 'extra' | 'syst
|
|
|
416
680
|
export function setDefaultCACertificates(certs: string[]): void;
|
|
417
681
|
|
|
418
682
|
/**
|
|
419
|
-
* Validates that the peer certificate matches the hostname
|
|
420
|
-
*
|
|
421
|
-
*
|
|
422
|
-
*
|
|
683
|
+
* Validates that the peer certificate matches the hostname — the check the
|
|
684
|
+
* handshake itself makes (RFC 9525): the subjectAltName alone (DNS names,
|
|
685
|
+
* whole-label wildcards; IP addresses for an IP), no fallback to the CN.
|
|
686
|
+
* Needs cert.raw, as getPeerCertificate() gives it. Returns undefined on a
|
|
687
|
+
* match, or an Error with code ERR_TLS_CERT_ALTNAME_INVALID, reason, host
|
|
688
|
+
* and cert (Node's shape). The checkServerIdentity option replaces it.
|
|
423
689
|
*/
|
|
424
690
|
export function checkServerIdentity(hostname: string, cert: PeerCertificate): Error | undefined;
|
|
425
691
|
|
|
692
|
+
/**
|
|
693
|
+
* The errors a connection fails with when an alert ends it: ours —
|
|
694
|
+
* code 'ERR_SSL_<ALERT NAME>' (e.g. ERR_SSL_HANDSHAKE_FAILURE) — or the
|
|
695
|
+
* peer's — 'ERR_TLS_ALERT_RECEIVED'; `alert` is the alert's code (RFC 8446
|
|
696
|
+
* §6), the same in TLS and DTLS.
|
|
697
|
+
*/
|
|
698
|
+
export interface TLSAlertError extends Error {
|
|
699
|
+
code: string;
|
|
700
|
+
alert: number;
|
|
701
|
+
}
|
|
702
|
+
|
|
426
703
|
export const DEFAULT_MIN_VERSION: string;
|
|
427
704
|
export const DEFAULT_MAX_VERSION: string;
|
|
428
705
|
/** Node-compat: default colon-separated cipher string. */
|
|
@@ -448,6 +725,16 @@ export declare const crypto: {
|
|
|
448
725
|
/** RFC 8446 §7.5 exporter; labelPrefix defaults to TLS 1.3's ('tls13 '). */
|
|
449
726
|
tls13_exporter: (hash: string, exporterMasterSecret: Uint8Array, label: string,
|
|
450
727
|
context: Uint8Array | null, length: number, labelPrefix?: string) => Uint8Array;
|
|
728
|
+
/** HPKE (RFC 9180) — what ECH encrypts with. */
|
|
729
|
+
hpke: {
|
|
730
|
+
suite: (...args: any[]) => any;
|
|
731
|
+
setupSender: (...args: any[]) => any;
|
|
732
|
+
setupRecipient: (...args: any[]) => any;
|
|
733
|
+
seal: (...args: any[]) => any;
|
|
734
|
+
open: (...args: any[]) => any;
|
|
735
|
+
generateKeyPair: (...args: any[]) => any;
|
|
736
|
+
deriveKeyPair: (...args: any[]) => any;
|
|
737
|
+
};
|
|
451
738
|
};
|
|
452
739
|
|
|
453
740
|
export declare const wire: any;
|
|
@@ -460,17 +747,314 @@ export declare const record: {
|
|
|
460
747
|
};
|
|
461
748
|
|
|
462
749
|
// ======================== DTLS ========================
|
|
463
|
-
// DTLS bindings are exported from the package but typed loosely here —
|
|
464
|
-
// use the JS source directly for exact signatures.
|
|
465
750
|
|
|
466
|
-
|
|
467
|
-
|
|
751
|
+
/**
|
|
752
|
+
* DTLS Connection IDs (RFC 9146; RFC 9147 §9). local: the CID the peer puts
|
|
753
|
+
* in the records we receive (the one we asked for); peer: the one we put in
|
|
754
|
+
* ours. Empty: the side asked for none.
|
|
755
|
+
*/
|
|
756
|
+
export interface ConnectionIds {
|
|
757
|
+
local: Uint8Array;
|
|
758
|
+
peer: Uint8Array;
|
|
468
759
|
}
|
|
469
|
-
|
|
470
|
-
|
|
760
|
+
|
|
761
|
+
/** DTLS options shared by DTLSSession, DTLSSocket, connectDTLS and createDTLSServer. */
|
|
762
|
+
export interface DTLSCommonOptions {
|
|
763
|
+
/** As createSecureContext: arrays for several certificates, the one the peer can verify chosen per handshake. */
|
|
764
|
+
cert?: SecureContextOptions['cert'];
|
|
765
|
+
key?: SecureContextOptions['key'];
|
|
766
|
+
ca?: PemInput | PemInput[];
|
|
767
|
+
minVersion?: 'DTLSv1.2' | 'DTLSv1.3';
|
|
768
|
+
maxVersion?: 'DTLSv1.2' | 'DTLSv1.3';
|
|
769
|
+
rejectUnauthorized?: boolean;
|
|
770
|
+
checkServerIdentity?: (hostname: string, cert: PeerCertificate) => Error | undefined;
|
|
771
|
+
/** Server: ask the client for a certificate (WebRTC: always). */
|
|
772
|
+
requestCert?: boolean;
|
|
773
|
+
servername?: string;
|
|
774
|
+
/** Also spelled ALPNProtocols, as in TLS. */
|
|
775
|
+
alpnProtocols?: string[];
|
|
776
|
+
/** Key-exchange groups, code points (e.g. [29, 23]). Default: a client X25519, P-256, P-384; a server those, X448 and P-521. */
|
|
777
|
+
groups?: number[];
|
|
778
|
+
/** See TLSSocketOptions.recordSizeLimit. A send larger than the peer's limit is refused (RangeError, code ERR_DTLS_RECORD_TOO_LARGE). */
|
|
779
|
+
recordSizeLimit?: number | false;
|
|
780
|
+
/**
|
|
781
|
+
* Connection ID (RFC 9146, RFC 9147 §9): the records survive the peer's
|
|
782
|
+
* address changing (a NAT rebinding). Each side asks for the CID it wants
|
|
783
|
+
* in what it receives. true — a client asks for an empty one (it needs
|
|
784
|
+
* none: the server does not move), a server for 8 random bytes; or the
|
|
785
|
+
* CID itself (up to 255 bytes; not on createDTLSServer, which gives each
|
|
786
|
+
* connection its own). Off by default.
|
|
787
|
+
*/
|
|
788
|
+
connectionId?: boolean | Uint8Array;
|
|
789
|
+
/** Client, DTLS 1.3: an external PSK (see ExternalPsk). */
|
|
790
|
+
psk?: ExternalPsk;
|
|
791
|
+
/**
|
|
792
|
+
* External PSK, DTLS 1.3. DTLSSession (as TLSSession): server,
|
|
793
|
+
* (identity bytes) → the key. DTLSSocket / createDTLSServer / connectDTLS
|
|
794
|
+
* take node:tls's form, as TLSSocket does: see TLSSocketOptions.pskCallback.
|
|
795
|
+
*/
|
|
796
|
+
pskCallback?: ((identity: Uint8Array) => ExternalPskAnswer) | ((hint: null) => (ExternalPsk | null)) | ((socket: DTLSSocket, identity: string) => ExternalPskAnswer);
|
|
797
|
+
/** DTLS-SRTP protection profiles to offer / accept (RFC 5764), code points. */
|
|
798
|
+
srtpProfiles?: number[];
|
|
799
|
+
/**
|
|
800
|
+
* The path MTU: the largest datagram written (every record is one
|
|
801
|
+
* datagram). Integer in [128, 65507]; default 1200. RangeError otherwise.
|
|
802
|
+
*/
|
|
803
|
+
mtu?: number;
|
|
804
|
+
/**
|
|
805
|
+
* Milliseconds each flight's retransmission timer starts at, doubling on
|
|
806
|
+
* every timeout, to 60 s. Given, it is a fixed schedule: no measured round
|
|
807
|
+
* trip changes it. Not given, the timer starts at 1000 ms until a round
|
|
808
|
+
* trip has been measured, then follows it (RFC 6298: SRTT + 4·RTTVAR, at
|
|
809
|
+
* least 100 ms; Karn's rule). A flight is given up after six retransmissions AND 60 s since it
|
|
810
|
+
* began, so a short timer does not give up early on a lossy path.
|
|
811
|
+
* Integer in [10, 60000]; default 1000 (RFC 9147 §5.8.2). RangeError
|
|
812
|
+
* otherwise.
|
|
813
|
+
*/
|
|
814
|
+
initialRetransmitTimeout?: number;
|
|
815
|
+
/**
|
|
816
|
+
* Client: a 'session' Buffer from an earlier connection, to resume —
|
|
817
|
+
* a DTLS 1.3 PSK ticket, or a DTLS 1.2 RFC 5077 ticket / session id.
|
|
818
|
+
* A DTLS 1.2 ticket offered with DTLS 1.3 as well goes with no session_id
|
|
819
|
+
* (RFC 9147 §5.3 leaves such a ClientHello none to carry it); whether the
|
|
820
|
+
* server took it, the message after its ServerHello says (RFC 5077 §3.4).
|
|
821
|
+
*/
|
|
822
|
+
session?: Buffer | Uint8Array;
|
|
823
|
+
/** Issue (server) / ask for (client, DTLS 1.2) session tickets. Default true. */
|
|
824
|
+
sessionTickets?: boolean;
|
|
825
|
+
/** Older spelling of sessionTickets: false. */
|
|
826
|
+
noTickets?: boolean;
|
|
471
827
|
}
|
|
472
|
-
|
|
473
|
-
export
|
|
828
|
+
|
|
829
|
+
export interface DTLSSessionOptions extends DTLSCommonOptions {
|
|
830
|
+
isServer?: boolean;
|
|
831
|
+
SNICallback?: (servername: string, cb: (err: Error | null, ctx?: SecureContext | null) => void) => void;
|
|
832
|
+
/** 48 bytes. A server that resumes across connections shares one (createDTLSServer does). */
|
|
833
|
+
ticketKeys?: Buffer | Uint8Array;
|
|
834
|
+
/** Server, DTLS 1.2: HelloVerifyRequest cookie exchange (RFC 6347 §4.2.1). */
|
|
835
|
+
useCookies?: boolean;
|
|
836
|
+
/**
|
|
837
|
+
* Code points; default per version. Suites this library does not carry
|
|
838
|
+
* are skipped; a list with none it carries throws ("no cipher match").
|
|
839
|
+
*/
|
|
840
|
+
cipherSuites?: number[];
|
|
841
|
+
/** Largest reassembled handshake message accepted: at most the TLS limit (128 KB, or maxHandshakeSize). */
|
|
842
|
+
maxHandshakeMessageSize?: number;
|
|
843
|
+
/**
|
|
844
|
+
* Without `ca`: the platform trust store? Default false for DTLS — WebRTC
|
|
845
|
+
* peers are self-signed, checked by SDP fingerprint; with neither, no peer
|
|
846
|
+
* is authorized, so such a caller sets rejectUnauthorized: false.
|
|
847
|
+
*/
|
|
848
|
+
useDefaultCA?: boolean;
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
/** The DTLS state machine without a transport: you move the datagrams. */
|
|
852
|
+
export declare class DTLSSession {
|
|
853
|
+
constructor(options: DTLSSessionOptions);
|
|
854
|
+
|
|
855
|
+
/**
|
|
856
|
+
* Hand in one received UDP datagram. Never throws: a malformed one is
|
|
857
|
+
* dropped or ends the session. True when it held a record that
|
|
858
|
+
* authenticated and is the newest yet — the condition (RFC 9146 §6) for
|
|
859
|
+
* taking a new peer address with Connection IDs.
|
|
860
|
+
*/
|
|
861
|
+
feedDatagram(datagram: Uint8Array | Buffer): boolean;
|
|
862
|
+
/** Application data; before 'connect' it is refused ('error'). */
|
|
863
|
+
send(data: Uint8Array | Buffer | string): void;
|
|
864
|
+
/** close_notify, then 'close'. */
|
|
865
|
+
close(): void;
|
|
866
|
+
|
|
867
|
+
readonly state: 'idle' | 'handshaking' | 'connected' | 'closed';
|
|
868
|
+
readonly connected: boolean;
|
|
869
|
+
/** 0xFEFD (DTLS 1.2) or 0xFEFC (DTLS 1.3) once negotiated, else null. */
|
|
870
|
+
readonly version: number | null;
|
|
871
|
+
/** The TLSSession underneath. */
|
|
872
|
+
readonly tls: TLSSession;
|
|
873
|
+
|
|
874
|
+
isSessionReused(): boolean;
|
|
875
|
+
/** The last 'session' Buffer, or undefined — as TLSSocket#getSession. */
|
|
876
|
+
getSession(): Buffer | undefined;
|
|
877
|
+
/** Change the path MTU; for messages fragmented from now on. RangeError outside [128, 65507]. */
|
|
878
|
+
setMTU(mtu: number): void;
|
|
879
|
+
getMTU(): number;
|
|
880
|
+
/** Where every flight's timer starts from now on — a fixed schedule, as the option given. RangeError outside [10, 60000] ms. */
|
|
881
|
+
setInitialRetransmitTimeout(ms: number): void;
|
|
882
|
+
|
|
883
|
+
/** DTLS 1.3 KeyUpdate (RFC 9147 §8); requestPeer asks the peer to update too. */
|
|
884
|
+
requestKeyUpdate(requestPeer?: boolean): void;
|
|
885
|
+
getWriteEpoch(): number | null;
|
|
886
|
+
getReadEpoch(): number | null;
|
|
887
|
+
|
|
888
|
+
/** RFC 5705 / RFC 8446 §7.5. DTLS-SRTP: exportKeyingMaterial(60, 'EXTRACTOR-dtls_srtp'), no context. */
|
|
889
|
+
exportKeyingMaterial(length: number, label: string, context?: Uint8Array | Buffer): Uint8Array | null;
|
|
890
|
+
/** The negotiated DTLS-SRTP profile, or null. */
|
|
891
|
+
getSelectedSrtpProfile(): number | null;
|
|
892
|
+
getRemoteExtensions(): Array<{ type: number; name: string | null; data: Uint8Array; value: any }>;
|
|
893
|
+
getRemoteExtension(type: number): { type: number; name: string | null; data: Uint8Array; value: any } | null;
|
|
894
|
+
getNegotiationResult(): NegotiationResult;
|
|
895
|
+
getALPN(): string | null;
|
|
896
|
+
/** Encrypted Client Hello: null, 'grease' (client), 'accepted', 'rejected'. */
|
|
897
|
+
getEchStatus(): 'grease' | 'accepted' | 'rejected' | null;
|
|
898
|
+
/** Server, ECH split mode: accepted by the client-facing server in front of this one (BoringSSL's SSL_ech_accepted is false here). */
|
|
899
|
+
isEchBackend(): boolean;
|
|
900
|
+
/** External PSK: the identity this connection was authenticated with, or null. */
|
|
901
|
+
getPskIdentity(): Uint8Array | null;
|
|
902
|
+
/** Connection IDs as they are now (NewConnectionId may have changed the peer's), or null. */
|
|
903
|
+
getConnectionIds(): ConnectionIds | null;
|
|
904
|
+
getPeerCertificate(): Array<{ cert: Buffer }> | null;
|
|
905
|
+
setKeyCert(context: SecureContext | SecureContextOptions): void;
|
|
906
|
+
getFinished(): Buffer | null;
|
|
907
|
+
getPeerFinished(): Buffer | null;
|
|
908
|
+
getJA4(opts?: FingerprintOptions): FingerprintResult | null;
|
|
909
|
+
getJA5(opts?: FingerprintOptions): FingerprintResult | null;
|
|
910
|
+
getJA4S(opts?: FingerprintOptions): FingerprintResult | null;
|
|
911
|
+
set_context(options: Record<string, any>): void;
|
|
912
|
+
|
|
913
|
+
/** A datagram to send. */
|
|
914
|
+
on(event: 'packet', listener: (datagram: Uint8Array) => void): void;
|
|
915
|
+
/** DTLS 1.3: a KeyUpdate took effect in this direction. */
|
|
916
|
+
on(event: 'keyUpdate', listener: (info: { direction: 'send' | 'receive'; epoch: number }) => void): void;
|
|
917
|
+
on(event: 'connect', listener: () => void): void;
|
|
918
|
+
/** Decrypted application data: a Buffer (a view of the record, not a copy), as node:tls gives. */
|
|
919
|
+
on(event: 'data', listener: (data: Buffer) => void): void;
|
|
920
|
+
on(event: 'error', listener: (err: Error) => void): void;
|
|
921
|
+
on(event: 'close', listener: () => void): void;
|
|
922
|
+
on(event: 'session', listener: (session: Buffer) => void): void;
|
|
923
|
+
on(event: 'clienthello', listener: (raw: Uint8Array, parsed: any) => void): void;
|
|
924
|
+
/** An alert from the peer (its warnings too). */
|
|
925
|
+
on(event: 'alert', listener: (alert: { level: number; description: number }) => void): void;
|
|
926
|
+
/** Connection IDs agreed, or the peer's moved (NewConnectionId). */
|
|
927
|
+
on(event: 'connectionId', listener: (ids: ConnectionIds) => void): void;
|
|
928
|
+
on(event: string, listener: (...args: any[]) => void): void;
|
|
929
|
+
off(event: string, listener: (...args: any[]) => void): void;
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
export interface DTLSSocketOptions extends DTLSCommonOptions {
|
|
933
|
+
isServer?: boolean;
|
|
934
|
+
/** The peer (a client's server; filled from the first datagram on a server). */
|
|
935
|
+
remoteAddress?: string;
|
|
936
|
+
remotePort?: number;
|
|
937
|
+
SNICallback?: DTLSSessionOptions['SNICallback'];
|
|
938
|
+
ticketKeys?: Buffer | Uint8Array;
|
|
939
|
+
useCookies?: boolean;
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
/** One DTLS connection over a UDP socket. */
|
|
943
|
+
export declare class DTLSSocket {
|
|
944
|
+
constructor(udpSocket: import('node:dgram').Socket, options: DTLSSocketOptions);
|
|
945
|
+
|
|
946
|
+
send(data: Uint8Array | Buffer | string): void;
|
|
947
|
+
close(): void;
|
|
948
|
+
/** Server side: what DTLSServer calls for this peer's datagrams. */
|
|
949
|
+
feedDatagram(datagram: Uint8Array | Buffer, rinfo?: { address: string; port: number }): void;
|
|
950
|
+
/**
|
|
951
|
+
* Send to another address from now on. With Connection IDs, for a peer
|
|
952
|
+
* reported at a new one ('remoteAddressChange'): not taken by itself —
|
|
953
|
+
* RFC 9146 §6 asks for a way of knowing the peer is there first.
|
|
954
|
+
*/
|
|
955
|
+
setRemoteAddress(address: string, port: number): void;
|
|
956
|
+
|
|
957
|
+
readonly state: DTLSSession['state'];
|
|
958
|
+
readonly connected: boolean;
|
|
959
|
+
readonly version: number | null;
|
|
960
|
+
readonly remoteAddress: string | null;
|
|
961
|
+
readonly remotePort: number | null;
|
|
962
|
+
/** The DTLSSession underneath. */
|
|
963
|
+
readonly session: DTLSSession;
|
|
964
|
+
|
|
965
|
+
isSessionReused(): boolean;
|
|
966
|
+
getSession(): Buffer | undefined;
|
|
967
|
+
setMTU(mtu: number): void;
|
|
968
|
+
getMTU(): number;
|
|
969
|
+
setInitialRetransmitTimeout(ms: number): void;
|
|
970
|
+
|
|
971
|
+
exportKeyingMaterial(length: number, label: string, context?: Uint8Array | Buffer): Uint8Array | null;
|
|
972
|
+
getSelectedSrtpProfile(): number | null;
|
|
973
|
+
getRemoteExtensions(): ReturnType<DTLSSession['getRemoteExtensions']>;
|
|
974
|
+
getRemoteExtension(type: number): ReturnType<DTLSSession['getRemoteExtension']>;
|
|
975
|
+
getNegotiationResult(): NegotiationResult;
|
|
976
|
+
getALPN(): string | null;
|
|
977
|
+
/** Encrypted Client Hello: null, 'grease' (client), 'accepted', 'rejected'. */
|
|
978
|
+
getEchStatus(): 'grease' | 'accepted' | 'rejected' | null;
|
|
979
|
+
/** Server, ECH split mode: accepted by the client-facing server in front of this one (BoringSSL's SSL_ech_accepted is false here). */
|
|
980
|
+
isEchBackend(): boolean;
|
|
981
|
+
/** External PSK: the identity (a Buffer, as TLSSocket's), or null. */
|
|
982
|
+
getPskIdentity(): Buffer | null;
|
|
983
|
+
getConnectionIds(): ConnectionIds | null;
|
|
984
|
+
getPeerCertificate(): Array<{ cert: Buffer }> | null;
|
|
985
|
+
setKeyCert(context: SecureContext | SecureContextOptions): void;
|
|
986
|
+
/** undefined (not null) when not available. */
|
|
987
|
+
getFinished(): Buffer | undefined;
|
|
988
|
+
getPeerFinished(): Buffer | undefined;
|
|
989
|
+
getJA4(opts?: FingerprintOptions): FingerprintResult | null;
|
|
990
|
+
getJA5(opts?: FingerprintOptions): FingerprintResult | null;
|
|
991
|
+
getJA4S(opts?: FingerprintOptions): FingerprintResult | null;
|
|
992
|
+
set_context(options: Record<string, any>): void;
|
|
993
|
+
|
|
994
|
+
/** Also emitted as 'secureConnect', right after 'connect'. */
|
|
995
|
+
on(event: 'connect' | 'secureConnect', listener: () => void): void;
|
|
996
|
+
/** Decrypted application data: a Buffer (a view of the record, not a copy), as node:tls gives. */
|
|
997
|
+
on(event: 'data', listener: (data: Buffer) => void): void;
|
|
998
|
+
on(event: 'error', listener: (err: Error) => void): void;
|
|
999
|
+
on(event: 'close', listener: () => void): void;
|
|
1000
|
+
on(event: 'session', listener: (session: Buffer) => void): void;
|
|
1001
|
+
on(event: 'clienthello', listener: (raw: Uint8Array, parsed: any) => void): void;
|
|
1002
|
+
on(event: 'alert', listener: (alert: { level: number; description: number }) => void): void;
|
|
1003
|
+
on(event: 'connectionId', listener: (ids: ConnectionIds) => void): void;
|
|
1004
|
+
/** Connection IDs: a datagram of this connection, the newest authenticated yet, from another address. */
|
|
1005
|
+
on(event: 'remoteAddressChange', listener: (to: { address: string; port: number }) => void): void;
|
|
1006
|
+
on(event: string, listener: (...args: any[]) => void): void;
|
|
1007
|
+
off(event: string, listener: (...args: any[]) => void): void;
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
/** Every DTLSSession option, for each connection (ca, requestCert, cipherSuites, ...). */
|
|
1011
|
+
export interface DTLSServerOptions extends Omit<DTLSSessionOptions, 'isServer' | 'connectionId'> {
|
|
1012
|
+
/** 48 bytes; one for every connection of this server (random if not given). */
|
|
1013
|
+
ticketKeys?: Buffer | Uint8Array;
|
|
1014
|
+
/** Connection IDs: each connection its own 8 random bytes — and found by it when its peer moves. */
|
|
1015
|
+
connectionId?: boolean;
|
|
1016
|
+
/** The UDP socket's receive/send buffers, bytes: 4 MB by default; 0 or false, the OS default. The kernel caps it at net.core.rmem_max. */
|
|
1017
|
+
socketBufferSize?: number | false;
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
/** createDTLSServer()'s: one UDP port, a DTLSSocket per peer address. */
|
|
1021
|
+
export interface DTLSServer {
|
|
1022
|
+
/**
|
|
1023
|
+
* An IPv6 `address`, an IPv6 socket; an IPv4 one, IPv4. None: '::',
|
|
1024
|
+
* dual-stack — IPv4 peers too, as '::ffff:a.b.c.d' — or 0.0.0.0 on a host
|
|
1025
|
+
* without IPv6 (as node:net).
|
|
1026
|
+
*/
|
|
1027
|
+
listen(port: number, address?: string, callback?: () => void): void;
|
|
1028
|
+
listen(port: number, callback?: () => void): void;
|
|
1029
|
+
/** close_notify to every connection, then the socket, once they have gone. */
|
|
1030
|
+
close(callback?: () => void): void;
|
|
1031
|
+
address(): { port: number; family: string; address: string } | null;
|
|
1032
|
+
/** A peer's handshake completed (also the connectionListener). */
|
|
1033
|
+
on(event: 'connection', listener: (socket: DTLSSocket) => void): void;
|
|
1034
|
+
/** A peer's connection failed. */
|
|
1035
|
+
on(event: 'clientError', listener: (err: Error, socket: DTLSSocket) => void): void;
|
|
1036
|
+
on(event: 'listening', listener: () => void): void;
|
|
1037
|
+
/** The UDP socket's error. */
|
|
1038
|
+
on(event: 'error', listener: (err: Error) => void): void;
|
|
1039
|
+
on(event: string, listener: (...args: any[]) => void): void;
|
|
1040
|
+
off(event: string, listener: (...args: any[]) => void): void;
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
/** Every DTLSSession option a client takes (cipherSuites, useDefaultCA, ...). */
|
|
1044
|
+
export interface ConnectDTLSOptions extends Omit<DTLSSessionOptions, 'isServer' | 'ticketKeys' | 'useCookies' | 'SNICallback'> {
|
|
1045
|
+
/** A name (resolved once — IPv4 or IPv6, whichever it has first) or an IP. Default '127.0.0.1'. */
|
|
1046
|
+
host?: string;
|
|
1047
|
+
hostname?: string;
|
|
1048
|
+
/** Default 4433. */
|
|
1049
|
+
port?: number;
|
|
1050
|
+
/** The UDP socket's receive/send buffers, bytes: 4 MB by default; 0 or false, the OS default. */
|
|
1051
|
+
socketBufferSize?: number | false;
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
export declare function createDTLSServer(options: DTLSServerOptions, connectionListener?: (socket: DTLSSocket) => void): DTLSServer;
|
|
1055
|
+
export declare function createDTLSServer(connectionListener?: (socket: DTLSSocket) => void): DTLSServer;
|
|
1056
|
+
/** A UDP socket of its own, closed with the connection. */
|
|
1057
|
+
export declare function connectDTLS(options: ConnectDTLSOptions, callback?: () => void): DTLSSocket;
|
|
474
1058
|
|
|
475
1059
|
// ======================== Default Export ========================
|
|
476
1060
|
|
|
@@ -493,6 +1077,18 @@ declare const _default: {
|
|
|
493
1077
|
crypto: typeof crypto;
|
|
494
1078
|
wire: typeof wire;
|
|
495
1079
|
record: typeof record;
|
|
1080
|
+
parseCiphers: typeof parseCiphers;
|
|
1081
|
+
parseEcdhCurve: typeof parseEcdhCurve;
|
|
1082
|
+
parseSigalgs: typeof parseSigalgs;
|
|
1083
|
+
parseTlsVersion: typeof parseTlsVersion;
|
|
1084
|
+
parseCertificateCompression: typeof parseCertificateCompression;
|
|
1085
|
+
precompressCertificate: typeof precompressCertificate;
|
|
1086
|
+
DEFAULT_SERVER_GROUPS: typeof DEFAULT_SERVER_GROUPS;
|
|
1087
|
+
DEFAULT_SIGNATURE_SCHEMES: typeof DEFAULT_SIGNATURE_SCHEMES;
|
|
1088
|
+
sessionInfo: typeof sessionInfo;
|
|
1089
|
+
certificateObject: typeof certificateObject;
|
|
1090
|
+
generateEchKey: typeof generateEchKey;
|
|
1091
|
+
checkEchKeys: typeof checkEchKeys;
|
|
496
1092
|
DTLSSession: typeof DTLSSession;
|
|
497
1093
|
DTLSSocket: typeof DTLSSocket;
|
|
498
1094
|
createDTLSServer: typeof createDTLSServer;
|