@joclaim/tls 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/README.md +221 -0
- package/lib/crypto/common.d.ts +3 -0
- package/lib/crypto/common.js +26 -0
- package/lib/crypto/index.d.ts +3 -0
- package/lib/crypto/index.js +4 -0
- package/lib/crypto/insecure-rand.d.ts +1 -0
- package/lib/crypto/insecure-rand.js +9 -0
- package/lib/crypto/pure-js.d.ts +2 -0
- package/lib/crypto/pure-js.js +144 -0
- package/lib/crypto/webcrypto.d.ts +3 -0
- package/lib/crypto/webcrypto.js +310 -0
- package/lib/index.d.ts +4 -0
- package/lib/index.js +4 -0
- package/lib/make-tls-client.d.ts +74 -0
- package/lib/make-tls-client.js +657 -0
- package/lib/scripts/build-jsc.d.ts +1 -0
- package/lib/scripts/build-jsc.js +20 -0
- package/lib/scripts/ca-template.d.ts +5 -0
- package/lib/scripts/ca-template.js +6 -0
- package/lib/scripts/fallbacks/crypto.d.ts +4 -0
- package/lib/scripts/fallbacks/crypto.js +2 -0
- package/lib/scripts/handshake.d.ts +1 -0
- package/lib/scripts/handshake.js +61 -0
- package/lib/scripts/jsc.d.ts +28 -0
- package/lib/scripts/jsc.js +92 -0
- package/lib/scripts/update-ca-certs.d.ts +1 -0
- package/lib/scripts/update-ca-certs.js +29 -0
- package/lib/types/crypto.d.ts +62 -0
- package/lib/types/crypto.js +1 -0
- package/lib/types/index.d.ts +15 -0
- package/lib/types/index.js +4 -0
- package/lib/types/logger.d.ts +6 -0
- package/lib/types/logger.js +1 -0
- package/lib/types/tls.d.ts +141 -0
- package/lib/types/tls.js +1 -0
- package/lib/types/x509.d.ts +32 -0
- package/lib/types/x509.js +1 -0
- package/lib/utils/additional-root-cas.d.ts +1 -0
- package/lib/utils/additional-root-cas.js +197 -0
- package/lib/utils/client-hello.d.ts +23 -0
- package/lib/utils/client-hello.js +167 -0
- package/lib/utils/constants.d.ts +239 -0
- package/lib/utils/constants.js +244 -0
- package/lib/utils/decryption-utils.d.ts +64 -0
- package/lib/utils/decryption-utils.js +166 -0
- package/lib/utils/finish-messages.d.ts +11 -0
- package/lib/utils/finish-messages.js +49 -0
- package/lib/utils/generics.d.ts +35 -0
- package/lib/utils/generics.js +146 -0
- package/lib/utils/index.d.ts +18 -0
- package/lib/utils/index.js +18 -0
- package/lib/utils/key-share.d.ts +13 -0
- package/lib/utils/key-share.js +72 -0
- package/lib/utils/key-update.d.ts +2 -0
- package/lib/utils/key-update.js +14 -0
- package/lib/utils/logger.d.ts +2 -0
- package/lib/utils/logger.js +15 -0
- package/lib/utils/make-queue.d.ts +3 -0
- package/lib/utils/make-queue.js +22 -0
- package/lib/utils/mozilla-root-cas.d.ts +5 -0
- package/lib/utils/mozilla-root-cas.js +4459 -0
- package/lib/utils/packets.d.ts +51 -0
- package/lib/utils/packets.js +148 -0
- package/lib/utils/parse-alert.d.ts +7 -0
- package/lib/utils/parse-alert.js +28 -0
- package/lib/utils/parse-certificate.d.ts +29 -0
- package/lib/utils/parse-certificate.js +188 -0
- package/lib/utils/parse-client-hello.d.ts +11 -0
- package/lib/utils/parse-client-hello.js +39 -0
- package/lib/utils/parse-extensions.d.ts +11 -0
- package/lib/utils/parse-extensions.js +74 -0
- package/lib/utils/parse-server-hello.d.ts +10 -0
- package/lib/utils/parse-server-hello.js +52 -0
- package/lib/utils/session-ticket.d.ts +17 -0
- package/lib/utils/session-ticket.js +51 -0
- package/lib/utils/wrapped-record.d.ts +25 -0
- package/lib/utils/wrapped-record.js +191 -0
- package/lib/utils/x509.d.ts +5 -0
- package/lib/utils/x509.js +124 -0
- package/package.json +82 -0
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
import { cbc as aesCbc } from '@noble/ciphers/aes';
|
|
2
|
+
import { chacha20poly1305 } from '@noble/ciphers/chacha';
|
|
3
|
+
import { ECDSASigValue } from '@peculiar/asn1-ecc';
|
|
4
|
+
import { AsnParser } from '@peculiar/asn1-schema';
|
|
5
|
+
import { webcrypto } from 'crypto';
|
|
6
|
+
import { PKCS1_KEM } from 'micro-rsa-dsa-dh/rsa.js';
|
|
7
|
+
import { asciiToUint8Array, concatenateUint8Arrays } from "../utils/generics.js";
|
|
8
|
+
import { parseRsaPublicKeyFromAsn1 } from "./common.js";
|
|
9
|
+
const subtle = webcrypto.subtle;
|
|
10
|
+
const X25519_PRIVATE_KEY_DER_PREFIX = new Uint8Array([
|
|
11
|
+
48, 46, 2, 1, 0, 48, 5, 6, 3, 43, 101, 110, 4, 34, 4, 32
|
|
12
|
+
]);
|
|
13
|
+
const P384_PRIVATE_KEY_DER_PREFIX = new Uint8Array([
|
|
14
|
+
0x30, 0x81, 0xb6, 0x02, 0x01, 0x00, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22, 0x04, 0x81, 0x9e, 0x30, 0x81, 0x9b, 0x02, 0x01, 0x01, 0x04, 0x30
|
|
15
|
+
]);
|
|
16
|
+
const P256_PRIVATE_KEY_DER_PREFIX = new Uint8Array([
|
|
17
|
+
0x30, 0x81, 0xb6, 0x02, 0x01, 0x00, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22, 0x04, 0x81, 0x9e, 0x30, 0x81, 0x9b, 0x02, 0x01, 0x01, 0x04, 0x30
|
|
18
|
+
]);
|
|
19
|
+
const SHARED_KEY_LEN_MAP = {
|
|
20
|
+
'X25519': 32,
|
|
21
|
+
'P-384': 48,
|
|
22
|
+
'P-256': 32,
|
|
23
|
+
};
|
|
24
|
+
const AUTH_TAG_BYTE_LENGTH = 16;
|
|
25
|
+
export const webcryptoCrypto = {
|
|
26
|
+
importKey(alg, raw, ...args) {
|
|
27
|
+
let subtleArgs;
|
|
28
|
+
let keyUsages;
|
|
29
|
+
let keyType = 'raw';
|
|
30
|
+
switch (alg) {
|
|
31
|
+
case 'AES-256-GCM':
|
|
32
|
+
case 'AES-128-GCM':
|
|
33
|
+
subtleArgs = {
|
|
34
|
+
name: 'AES-GCM',
|
|
35
|
+
length: alg === 'AES-256-GCM' ? 256 : 128
|
|
36
|
+
};
|
|
37
|
+
keyUsages = ['encrypt', 'decrypt'];
|
|
38
|
+
break;
|
|
39
|
+
case 'AES-128-CBC':
|
|
40
|
+
subtleArgs = {
|
|
41
|
+
name: 'AES-CBC',
|
|
42
|
+
length: 128
|
|
43
|
+
};
|
|
44
|
+
keyUsages = ['encrypt', 'decrypt'];
|
|
45
|
+
break;
|
|
46
|
+
case 'CHACHA20-POLY1305':
|
|
47
|
+
// chaCha20 is not supported by webcrypto
|
|
48
|
+
// so we "fake" create a key
|
|
49
|
+
return raw;
|
|
50
|
+
case 'SHA-1':
|
|
51
|
+
case 'SHA-256':
|
|
52
|
+
case 'SHA-384':
|
|
53
|
+
subtleArgs = {
|
|
54
|
+
name: 'HMAC',
|
|
55
|
+
hash: { name: alg }
|
|
56
|
+
};
|
|
57
|
+
keyUsages = ['sign', 'verify'];
|
|
58
|
+
break;
|
|
59
|
+
case 'P-384':
|
|
60
|
+
case 'P-256':
|
|
61
|
+
subtleArgs = {
|
|
62
|
+
name: 'ECDH',
|
|
63
|
+
namedCurve: alg,
|
|
64
|
+
};
|
|
65
|
+
keyUsages = [];
|
|
66
|
+
if (args[0] === 'private') {
|
|
67
|
+
keyUsages = ['deriveBits'];
|
|
68
|
+
keyType = 'pkcs8';
|
|
69
|
+
const prefix = alg === 'P-256'
|
|
70
|
+
? P256_PRIVATE_KEY_DER_PREFIX
|
|
71
|
+
: P384_PRIVATE_KEY_DER_PREFIX;
|
|
72
|
+
raw = concatenateUint8Arrays([
|
|
73
|
+
prefix,
|
|
74
|
+
raw
|
|
75
|
+
]);
|
|
76
|
+
}
|
|
77
|
+
break;
|
|
78
|
+
case 'X25519':
|
|
79
|
+
subtleArgs = { name: 'X25519' };
|
|
80
|
+
keyUsages = [];
|
|
81
|
+
if (args[0] === 'private') {
|
|
82
|
+
keyUsages = ['deriveBits'];
|
|
83
|
+
keyType = 'pkcs8';
|
|
84
|
+
raw = concatenateUint8Arrays([
|
|
85
|
+
X25519_PRIVATE_KEY_DER_PREFIX,
|
|
86
|
+
raw
|
|
87
|
+
]);
|
|
88
|
+
}
|
|
89
|
+
break;
|
|
90
|
+
case 'RSA-PSS-SHA256':
|
|
91
|
+
keyType = 'spki';
|
|
92
|
+
keyUsages = ['verify'];
|
|
93
|
+
subtleArgs = {
|
|
94
|
+
name: 'RSA-PSS',
|
|
95
|
+
hash: 'SHA-256'
|
|
96
|
+
};
|
|
97
|
+
break;
|
|
98
|
+
case 'RSA-PKCS1-SHA512':
|
|
99
|
+
case 'RSA-PKCS1-SHA256':
|
|
100
|
+
case 'RSA-PKCS1-SHA384':
|
|
101
|
+
case 'RSA-PKCS1-SHA1':
|
|
102
|
+
keyType = 'spki';
|
|
103
|
+
keyUsages = ['verify'];
|
|
104
|
+
subtleArgs = {
|
|
105
|
+
name: 'RSASSA-PKCS1-v1_5',
|
|
106
|
+
hash: getHashAlgorithm(alg),
|
|
107
|
+
};
|
|
108
|
+
break;
|
|
109
|
+
case 'RSA-PCKS1_5':
|
|
110
|
+
return parseRsaPublicKeyFromAsn1(raw);
|
|
111
|
+
case 'ECDSA-SECP256R1-SHA256':
|
|
112
|
+
case 'ECDSA-SECP256R1-SHA384':
|
|
113
|
+
case 'ECDSA-SECP384R1-SHA384':
|
|
114
|
+
case 'ECDSA-SECP384R1-SHA256':
|
|
115
|
+
keyType = 'spki';
|
|
116
|
+
keyUsages = ['verify'];
|
|
117
|
+
subtleArgs = {
|
|
118
|
+
name: 'ECDSA',
|
|
119
|
+
namedCurve: alg.includes('P256') ? 'P-256' : 'P-384',
|
|
120
|
+
};
|
|
121
|
+
break;
|
|
122
|
+
default:
|
|
123
|
+
throw new Error(`Unsupported algorithm ${alg}`);
|
|
124
|
+
}
|
|
125
|
+
return subtle
|
|
126
|
+
.importKey(keyType, raw, subtleArgs, true, keyUsages);
|
|
127
|
+
},
|
|
128
|
+
async exportKey(key) {
|
|
129
|
+
// handle ChaCha20-Poly1305, RSA-PCKS1_5
|
|
130
|
+
// as that's already a Uint8Array
|
|
131
|
+
if (key instanceof Uint8Array) {
|
|
132
|
+
return key;
|
|
133
|
+
}
|
|
134
|
+
if (key.type === 'private'
|
|
135
|
+
&& (key.algorithm.name === 'X25519'
|
|
136
|
+
|| key.algorithm.name === 'ECDH')) {
|
|
137
|
+
const form = toUint8Array(await subtle.exportKey('pkcs8', key));
|
|
138
|
+
const algPrefix = key.algorithm.name === 'X25519'
|
|
139
|
+
? X25519_PRIVATE_KEY_DER_PREFIX
|
|
140
|
+
: P384_PRIVATE_KEY_DER_PREFIX;
|
|
141
|
+
return form.slice(algPrefix.length);
|
|
142
|
+
}
|
|
143
|
+
return toUint8Array(await subtle.exportKey('raw', key));
|
|
144
|
+
},
|
|
145
|
+
async generateKeyPair(alg) {
|
|
146
|
+
let genKeyArgs;
|
|
147
|
+
switch (alg) {
|
|
148
|
+
case 'P-384':
|
|
149
|
+
case 'P-256':
|
|
150
|
+
genKeyArgs = {
|
|
151
|
+
name: 'ECDH',
|
|
152
|
+
namedCurve: alg,
|
|
153
|
+
};
|
|
154
|
+
break;
|
|
155
|
+
case 'X25519':
|
|
156
|
+
genKeyArgs = { name: 'X25519' };
|
|
157
|
+
break;
|
|
158
|
+
default:
|
|
159
|
+
throw new Error(`Unsupported algorithm ${alg}`);
|
|
160
|
+
}
|
|
161
|
+
const keyPair = await subtle.generateKey(genKeyArgs, true, ['deriveBits']);
|
|
162
|
+
return {
|
|
163
|
+
pubKey: keyPair.publicKey,
|
|
164
|
+
privKey: keyPair.privateKey,
|
|
165
|
+
};
|
|
166
|
+
},
|
|
167
|
+
async calculateSharedSecret(alg, privateKey, publicKey) {
|
|
168
|
+
const genKeyName = alg === 'X25519' ? 'X25519' : 'ECDH';
|
|
169
|
+
const key = await subtle.deriveBits({ name: genKeyName, public: publicKey }, privateKey, 8 * SHARED_KEY_LEN_MAP[alg]);
|
|
170
|
+
return toUint8Array(key);
|
|
171
|
+
},
|
|
172
|
+
randomBytes(length) {
|
|
173
|
+
const buffer = new Uint8Array(length);
|
|
174
|
+
return webcrypto.getRandomValues(buffer);
|
|
175
|
+
},
|
|
176
|
+
asymmetricEncrypt(cipherSuite, { publicKey, data }) {
|
|
177
|
+
if (cipherSuite !== 'RSA-PCKS1_5') {
|
|
178
|
+
throw new Error(`Unsupported cipher suite ${cipherSuite}`);
|
|
179
|
+
}
|
|
180
|
+
return PKCS1_KEM.encrypt(publicKey, data);
|
|
181
|
+
},
|
|
182
|
+
async encrypt(cipherSuite, { iv, data, key }) {
|
|
183
|
+
const name = cipherSuite === 'AES-128-CBC' ? 'AES-CBC' : '';
|
|
184
|
+
return toUint8Array(await subtle.encrypt({ name, iv }, key, data))
|
|
185
|
+
.slice(0, data.length);
|
|
186
|
+
},
|
|
187
|
+
async decrypt(cipherSuite, { key, iv, data }) {
|
|
188
|
+
if (cipherSuite !== 'AES-128-CBC') {
|
|
189
|
+
throw new Error(`Unsupported cipher suite: ${cipherSuite}`);
|
|
190
|
+
}
|
|
191
|
+
const rawKey = key instanceof Uint8Array
|
|
192
|
+
? key
|
|
193
|
+
: await this.exportKey(key);
|
|
194
|
+
const cipher = aesCbc(rawKey, iv, { disablePadding: true });
|
|
195
|
+
const decrypted = cipher.decrypt(data);
|
|
196
|
+
return decrypted;
|
|
197
|
+
},
|
|
198
|
+
async authenticatedEncrypt(cipherSuite, { iv, aead, key, data }) {
|
|
199
|
+
let ciphertext;
|
|
200
|
+
if (cipherSuite === 'CHACHA20-POLY1305') {
|
|
201
|
+
const rawKey = key instanceof Uint8Array
|
|
202
|
+
? key
|
|
203
|
+
: await this.exportKey(key);
|
|
204
|
+
const cipher = chacha20poly1305(rawKey, iv, aead);
|
|
205
|
+
ciphertext = cipher.encrypt(data);
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
ciphertext = toUint8Array(await subtle.encrypt({ name: 'AES-GCM', iv, additionalData: aead }, key, data));
|
|
209
|
+
}
|
|
210
|
+
return {
|
|
211
|
+
ciphertext: ciphertext.slice(0, -AUTH_TAG_BYTE_LENGTH),
|
|
212
|
+
authTag: ciphertext.slice(-AUTH_TAG_BYTE_LENGTH),
|
|
213
|
+
};
|
|
214
|
+
},
|
|
215
|
+
async authenticatedDecrypt(cipherSuite, { iv, aead, key, data, authTag }) {
|
|
216
|
+
if (!authTag) {
|
|
217
|
+
throw new Error('authTag is required');
|
|
218
|
+
}
|
|
219
|
+
const ciphertext = concatenateUint8Arrays([data, authTag]);
|
|
220
|
+
let plaintext;
|
|
221
|
+
if (cipherSuite === 'CHACHA20-POLY1305') {
|
|
222
|
+
const rawKey = key instanceof Uint8Array
|
|
223
|
+
? key
|
|
224
|
+
: await this.exportKey(key);
|
|
225
|
+
const cipher = chacha20poly1305(rawKey, iv, aead);
|
|
226
|
+
plaintext = cipher.decrypt(ciphertext);
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
plaintext = toUint8Array(await subtle.decrypt({ name: 'AES-GCM', iv, additionalData: aead }, key, ciphertext));
|
|
230
|
+
}
|
|
231
|
+
return { plaintext };
|
|
232
|
+
},
|
|
233
|
+
async verify(alg, { data, signature, publicKey }) {
|
|
234
|
+
let verifyArgs;
|
|
235
|
+
switch (alg) {
|
|
236
|
+
case 'RSA-PSS-SHA256':
|
|
237
|
+
verifyArgs = { name: 'RSA-PSS', saltLength: 32 };
|
|
238
|
+
break;
|
|
239
|
+
case 'RSA-PKCS1-SHA512':
|
|
240
|
+
case 'RSA-PKCS1-SHA256':
|
|
241
|
+
case 'RSA-PKCS1-SHA384':
|
|
242
|
+
case 'RSA-PKCS1-SHA1':
|
|
243
|
+
verifyArgs = { name: 'RSASSA-PKCS1-v1_5' };
|
|
244
|
+
break;
|
|
245
|
+
case 'ECDSA-SECP256R1-SHA256':
|
|
246
|
+
case 'ECDSA-SECP256R1-SHA384':
|
|
247
|
+
case 'ECDSA-SECP384R1-SHA256':
|
|
248
|
+
case 'ECDSA-SECP384R1-SHA384':
|
|
249
|
+
signature = convertASN1toRS(signature);
|
|
250
|
+
verifyArgs = { name: 'ECDSA', hash: getHashAlgorithm(alg) };
|
|
251
|
+
break;
|
|
252
|
+
default:
|
|
253
|
+
throw new Error(`Unsupported algorithm ${alg}`);
|
|
254
|
+
}
|
|
255
|
+
return subtle.verify(verifyArgs, publicKey, signature, data);
|
|
256
|
+
},
|
|
257
|
+
async hash(alg, data) {
|
|
258
|
+
return toUint8Array(await subtle.digest(alg, data));
|
|
259
|
+
},
|
|
260
|
+
async hmac(alg, key, data) {
|
|
261
|
+
return toUint8Array(await subtle.sign({ name: 'HMAC', hash: alg }, key, data));
|
|
262
|
+
},
|
|
263
|
+
// extract & expand logic referenced from:
|
|
264
|
+
// https://github.com/futoin/util-js-hkdf/blob/master/hkdf.js
|
|
265
|
+
async extract(alg, hashLength, ikm, salt) {
|
|
266
|
+
salt = typeof salt === 'string' ? asciiToUint8Array(salt) : salt;
|
|
267
|
+
if (!salt.length) {
|
|
268
|
+
salt = new Uint8Array(hashLength);
|
|
269
|
+
}
|
|
270
|
+
const key = await this.importKey(alg, salt);
|
|
271
|
+
return this.hmac(alg, key, ikm);
|
|
272
|
+
},
|
|
273
|
+
};
|
|
274
|
+
function toUint8Array(buffer) {
|
|
275
|
+
return new Uint8Array(buffer);
|
|
276
|
+
}
|
|
277
|
+
// mostly from ChatGPT
|
|
278
|
+
function convertASN1toRS(signatureBytes) {
|
|
279
|
+
const data = AsnParser.parse(signatureBytes, ECDSASigValue);
|
|
280
|
+
const r = cleanBigNum(new Uint8Array(data.r));
|
|
281
|
+
const s = cleanBigNum(new Uint8Array(data.s));
|
|
282
|
+
return concatenateUint8Arrays([r, s]);
|
|
283
|
+
}
|
|
284
|
+
function cleanBigNum(bn) {
|
|
285
|
+
if (bn.length > 32 && bn[0] === 0) {
|
|
286
|
+
bn = bn.slice(1);
|
|
287
|
+
}
|
|
288
|
+
else if (bn.length < 32) {
|
|
289
|
+
bn = concatenateUint8Arrays([
|
|
290
|
+
new Uint8Array(32 - bn.length).fill(0),
|
|
291
|
+
bn
|
|
292
|
+
]);
|
|
293
|
+
}
|
|
294
|
+
return bn;
|
|
295
|
+
}
|
|
296
|
+
function getHashAlgorithm(sig) {
|
|
297
|
+
if (sig.endsWith('SHA256')) {
|
|
298
|
+
return 'SHA-256';
|
|
299
|
+
}
|
|
300
|
+
else if (sig.endsWith('SHA384')) {
|
|
301
|
+
return 'SHA-384';
|
|
302
|
+
}
|
|
303
|
+
else if (sig.endsWith('SHA512')) {
|
|
304
|
+
return 'SHA-512';
|
|
305
|
+
}
|
|
306
|
+
else if (sig.endsWith('SHA1')) {
|
|
307
|
+
return 'SHA-1';
|
|
308
|
+
}
|
|
309
|
+
throw new Error(`Unsupported signature algorithm: ${sig}`);
|
|
310
|
+
}
|
package/lib/index.d.ts
ADDED
package/lib/index.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { TLSClientOptions, TLSHandshakeOptions, TLSKeyType, TLSPacketWithType, TLSSessionTicket } from './types/index.ts';
|
|
2
|
+
export declare function makeTLSClient({ host, verifyServerCertificate, rootCAs, logger: _logger, cipherSuites, namedCurves, supportedProtocolVersions, signatureAlgorithms, applicationLayerProtocols, fetchCertificateBytes, write, onRead, onApplicationData, onSessionTicket, onTlsEnd, onHandshake, onRecvCertificates }: TLSClientOptions): {
|
|
3
|
+
getMetadata(): {
|
|
4
|
+
cipherSuite: "TLS_CHACHA20_POLY1305_SHA256" | "TLS_AES_256_GCM_SHA384" | "TLS_AES_128_GCM_SHA256" | "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" | "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" | "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" | "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" | "TLS_RSA_WITH_AES_128_GCM_SHA256" | "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" | "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" | "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA" | "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA" | undefined;
|
|
5
|
+
keyType: TLSKeyType | undefined;
|
|
6
|
+
version: "TLS1_3" | "TLS1_2" | undefined;
|
|
7
|
+
selectedAlpn: string | undefined;
|
|
8
|
+
};
|
|
9
|
+
hasEnded(): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Get the current traffic keys
|
|
12
|
+
*/
|
|
13
|
+
getKeys(): {
|
|
14
|
+
recordSendCount: number;
|
|
15
|
+
recordRecvCount: number;
|
|
16
|
+
type: "TLS1_3";
|
|
17
|
+
masterSecret: Uint8Array<ArrayBufferLike>;
|
|
18
|
+
clientSecret: Uint8Array<ArrayBuffer>;
|
|
19
|
+
serverSecret: Uint8Array<ArrayBuffer>;
|
|
20
|
+
clientEncKey: unknown;
|
|
21
|
+
serverEncKey: unknown;
|
|
22
|
+
clientIv: Uint8Array<ArrayBuffer>;
|
|
23
|
+
serverIv: Uint8Array<ArrayBuffer>;
|
|
24
|
+
} | {
|
|
25
|
+
recordSendCount: number;
|
|
26
|
+
recordRecvCount: number;
|
|
27
|
+
type: "TLS1_2";
|
|
28
|
+
masterSecret: Uint8Array<ArrayBuffer>;
|
|
29
|
+
clientMacKey: unknown;
|
|
30
|
+
serverMacKey: unknown;
|
|
31
|
+
clientEncKey: unknown;
|
|
32
|
+
serverEncKey: unknown;
|
|
33
|
+
clientIv: Uint8Array<ArrayBuffer>;
|
|
34
|
+
serverIv: Uint8Array<ArrayBuffer>;
|
|
35
|
+
serverSecret: Uint8Array<ArrayBuffer>;
|
|
36
|
+
clientSecret: Uint8Array<ArrayBuffer>;
|
|
37
|
+
} | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* Session ID used to connect to the server
|
|
40
|
+
*/
|
|
41
|
+
getSessionId(): Uint8Array<ArrayBufferLike>;
|
|
42
|
+
isHandshakeDone(): boolean;
|
|
43
|
+
getPskFromTicket(ticket: TLSSessionTicket): Promise<{
|
|
44
|
+
identity: Uint8Array<ArrayBufferLike>;
|
|
45
|
+
ticketAge: number;
|
|
46
|
+
finishKey: unknown;
|
|
47
|
+
resumeMasterSecret: Uint8Array<ArrayBuffer>;
|
|
48
|
+
earlySecret: Uint8Array<ArrayBufferLike>;
|
|
49
|
+
cipherSuite: "TLS_CHACHA20_POLY1305_SHA256" | "TLS_AES_256_GCM_SHA384" | "TLS_AES_128_GCM_SHA256" | "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" | "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" | "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" | "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" | "TLS_RSA_WITH_AES_128_GCM_SHA256" | "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" | "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" | "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA" | "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA";
|
|
50
|
+
}>;
|
|
51
|
+
/**
|
|
52
|
+
* Start the handshake with the server
|
|
53
|
+
*/
|
|
54
|
+
startHandshake(opts?: TLSHandshakeOptions): Promise<void>;
|
|
55
|
+
/**
|
|
56
|
+
* Handle bytes received from the server.
|
|
57
|
+
* Could be a complete or partial TLS packet
|
|
58
|
+
*/
|
|
59
|
+
handleReceivedBytes(data: Uint8Array): Promise<void>;
|
|
60
|
+
/**
|
|
61
|
+
* Handle a complete TLS packet received
|
|
62
|
+
* from the server
|
|
63
|
+
*/
|
|
64
|
+
handleReceivedPacket: (pkt: TLSPacketWithType) => Promise<unknown>;
|
|
65
|
+
/**
|
|
66
|
+
* Utilise the KeyUpdate handshake message to update
|
|
67
|
+
* the traffic keys. Available only in TLS 1.3
|
|
68
|
+
* @param requestUpdateFromServer should the server be requested to
|
|
69
|
+
* update its keys as well
|
|
70
|
+
*/
|
|
71
|
+
updateTrafficKeys(requestUpdateFromServer?: boolean): Promise<void>;
|
|
72
|
+
write(data: Uint8Array): Promise<void>;
|
|
73
|
+
end: (error?: Error) => Promise<void>;
|
|
74
|
+
};
|