nlcurl 0.1.0 → 0.2.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 +5 -13
- package/dist/cli/args.d.ts +37 -5
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +6 -17
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/index.d.ts +3 -3
- package/dist/cli/index.js +25 -10
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/output.d.ts +24 -7
- package/dist/cli/output.d.ts.map +1 -1
- package/dist/cli/output.js +24 -12
- package/dist/cli/output.js.map +1 -1
- package/dist/cookies/jar.d.ts +45 -13
- package/dist/cookies/jar.d.ts.map +1 -1
- package/dist/cookies/jar.js +88 -29
- package/dist/cookies/jar.js.map +1 -1
- package/dist/cookies/parser.d.ts +25 -3
- package/dist/cookies/parser.d.ts.map +1 -1
- package/dist/cookies/parser.js +12 -7
- package/dist/cookies/parser.js.map +1 -1
- package/dist/core/client.d.ts +49 -33
- package/dist/core/client.d.ts.map +1 -1
- package/dist/core/client.js +64 -38
- package/dist/core/client.js.map +1 -1
- package/dist/core/errors.d.ts +94 -6
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +95 -6
- package/dist/core/errors.js.map +1 -1
- package/dist/core/request.d.ts +96 -30
- package/dist/core/request.d.ts.map +1 -1
- package/dist/core/request.js +0 -3
- package/dist/core/request.js.map +1 -1
- package/dist/core/response.d.ts +92 -8
- package/dist/core/response.d.ts.map +1 -1
- package/dist/core/response.js +92 -7
- package/dist/core/response.js.map +1 -1
- package/dist/core/session.d.ts +109 -14
- package/dist/core/session.d.ts.map +1 -1
- package/dist/core/session.js +124 -46
- package/dist/core/session.js.map +1 -1
- package/dist/fingerprints/akamai.d.ts +11 -11
- package/dist/fingerprints/akamai.d.ts.map +1 -1
- package/dist/fingerprints/akamai.js +10 -14
- package/dist/fingerprints/akamai.js.map +1 -1
- package/dist/fingerprints/database.d.ts +14 -15
- package/dist/fingerprints/database.d.ts.map +1 -1
- package/dist/fingerprints/database.js +14 -19
- package/dist/fingerprints/database.js.map +1 -1
- package/dist/fingerprints/extensions.d.ts +121 -27
- package/dist/fingerprints/extensions.d.ts.map +1 -1
- package/dist/fingerprints/extensions.js +132 -49
- package/dist/fingerprints/extensions.js.map +1 -1
- package/dist/fingerprints/ja3.d.ts +34 -18
- package/dist/fingerprints/ja3.d.ts.map +1 -1
- package/dist/fingerprints/ja3.js +34 -18
- package/dist/fingerprints/ja3.js.map +1 -1
- package/dist/fingerprints/profiles/chrome.d.ts +21 -10
- package/dist/fingerprints/profiles/chrome.d.ts.map +1 -1
- package/dist/fingerprints/profiles/chrome.js +25 -22
- package/dist/fingerprints/profiles/chrome.js.map +1 -1
- package/dist/fingerprints/profiles/edge.d.ts +10 -7
- package/dist/fingerprints/profiles/edge.d.ts.map +1 -1
- package/dist/fingerprints/profiles/edge.js +10 -10
- package/dist/fingerprints/profiles/edge.js.map +1 -1
- package/dist/fingerprints/profiles/firefox.d.ts +11 -3
- package/dist/fingerprints/profiles/firefox.d.ts.map +1 -1
- package/dist/fingerprints/profiles/firefox.js +15 -14
- package/dist/fingerprints/profiles/firefox.js.map +1 -1
- package/dist/fingerprints/profiles/safari.d.ts +14 -3
- package/dist/fingerprints/profiles/safari.d.ts.map +1 -1
- package/dist/fingerprints/profiles/safari.js +16 -13
- package/dist/fingerprints/profiles/safari.js.map +1 -1
- package/dist/fingerprints/profiles/tor.d.ts +8 -7
- package/dist/fingerprints/profiles/tor.d.ts.map +1 -1
- package/dist/fingerprints/profiles/tor.js +8 -14
- package/dist/fingerprints/profiles/tor.js.map +1 -1
- package/dist/fingerprints/types.d.ts +70 -47
- package/dist/fingerprints/types.d.ts.map +1 -1
- package/dist/fingerprints/types.js +0 -7
- package/dist/fingerprints/types.js.map +1 -1
- package/dist/http/h1/client.d.ts +30 -9
- package/dist/http/h1/client.d.ts.map +1 -1
- package/dist/http/h1/client.js +152 -15
- package/dist/http/h1/client.js.map +1 -1
- package/dist/http/h1/encoder.d.ts +9 -6
- package/dist/http/h1/encoder.d.ts.map +1 -1
- package/dist/http/h1/encoder.js +8 -12
- package/dist/http/h1/encoder.js.map +1 -1
- package/dist/http/h1/parser.d.ts +68 -14
- package/dist/http/h1/parser.d.ts.map +1 -1
- package/dist/http/h1/parser.js +92 -37
- package/dist/http/h1/parser.js.map +1 -1
- package/dist/http/h2/client.d.ts +81 -14
- package/dist/http/h2/client.d.ts.map +1 -1
- package/dist/http/h2/client.js +465 -63
- package/dist/http/h2/client.js.map +1 -1
- package/dist/http/h2/frames.d.ts +103 -6
- package/dist/http/h2/frames.d.ts.map +1 -1
- package/dist/http/h2/frames.js +96 -17
- package/dist/http/h2/frames.js.map +1 -1
- package/dist/http/h2/hpack.d.ts +30 -5
- package/dist/http/h2/hpack.d.ts.map +1 -1
- package/dist/http/h2/hpack.js +39 -35
- package/dist/http/h2/hpack.js.map +1 -1
- package/dist/http/negotiator.d.ts +35 -12
- package/dist/http/negotiator.d.ts.map +1 -1
- package/dist/http/negotiator.js +89 -24
- package/dist/http/negotiator.js.map +1 -1
- package/dist/http/pool.d.ts +66 -17
- package/dist/http/pool.d.ts.map +1 -1
- package/dist/http/pool.js +47 -20
- package/dist/http/pool.js.map +1 -1
- package/dist/index.d.ts +2 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -13
- package/dist/index.js.map +1 -1
- package/dist/middleware/interceptor.d.ts +40 -8
- package/dist/middleware/interceptor.d.ts.map +1 -1
- package/dist/middleware/interceptor.js +28 -6
- package/dist/middleware/interceptor.js.map +1 -1
- package/dist/middleware/rate-limiter.d.ts +18 -5
- package/dist/middleware/rate-limiter.d.ts.map +1 -1
- package/dist/middleware/rate-limiter.js +12 -7
- package/dist/middleware/rate-limiter.js.map +1 -1
- package/dist/middleware/retry.d.ts +17 -5
- package/dist/middleware/retry.d.ts.map +1 -1
- package/dist/middleware/retry.js +13 -11
- package/dist/middleware/retry.js.map +1 -1
- package/dist/proxy/http-proxy.d.ts +17 -9
- package/dist/proxy/http-proxy.d.ts.map +1 -1
- package/dist/proxy/http-proxy.js +9 -13
- package/dist/proxy/http-proxy.js.map +1 -1
- package/dist/proxy/socks.d.ts +20 -9
- package/dist/proxy/socks.d.ts.map +1 -1
- package/dist/proxy/socks.js +20 -31
- package/dist/proxy/socks.js.map +1 -1
- package/dist/tls/constants.d.ts +74 -4
- package/dist/tls/constants.d.ts.map +1 -1
- package/dist/tls/constants.js +75 -21
- package/dist/tls/constants.js.map +1 -1
- package/dist/tls/node-engine.d.ts +17 -16
- package/dist/tls/node-engine.d.ts.map +1 -1
- package/dist/tls/node-engine.js +20 -27
- package/dist/tls/node-engine.js.map +1 -1
- package/dist/tls/stealth/client-hello.d.ts +32 -16
- package/dist/tls/stealth/client-hello.d.ts.map +1 -1
- package/dist/tls/stealth/client-hello.js +13 -37
- package/dist/tls/stealth/client-hello.js.map +1 -1
- package/dist/tls/stealth/engine.d.ts +18 -10
- package/dist/tls/stealth/engine.d.ts.map +1 -1
- package/dist/tls/stealth/engine.js +18 -24
- package/dist/tls/stealth/engine.js.map +1 -1
- package/dist/tls/stealth/handshake.d.ts +31 -17
- package/dist/tls/stealth/handshake.d.ts.map +1 -1
- package/dist/tls/stealth/handshake.js +173 -74
- package/dist/tls/stealth/handshake.js.map +1 -1
- package/dist/tls/stealth/key-schedule.d.ts +89 -32
- package/dist/tls/stealth/key-schedule.d.ts.map +1 -1
- package/dist/tls/stealth/key-schedule.js +62 -42
- package/dist/tls/stealth/key-schedule.js.map +1 -1
- package/dist/tls/stealth/record-layer.d.ts +76 -25
- package/dist/tls/stealth/record-layer.d.ts.map +1 -1
- package/dist/tls/stealth/record-layer.js +66 -36
- package/dist/tls/stealth/record-layer.js.map +1 -1
- package/dist/tls/types.d.ts +33 -25
- package/dist/tls/types.d.ts.map +1 -1
- package/dist/tls/types.js +0 -4
- package/dist/tls/types.js.map +1 -1
- package/dist/utils/buffer-reader.d.ts +99 -7
- package/dist/utils/buffer-reader.d.ts.map +1 -1
- package/dist/utils/buffer-reader.js +99 -7
- package/dist/utils/buffer-reader.js.map +1 -1
- package/dist/utils/buffer-writer.d.ts +99 -10
- package/dist/utils/buffer-writer.d.ts.map +1 -1
- package/dist/utils/buffer-writer.js +101 -12
- package/dist/utils/buffer-writer.js.map +1 -1
- package/dist/utils/encoding.d.ts +33 -8
- package/dist/utils/encoding.d.ts.map +1 -1
- package/dist/utils/encoding.js +58 -13
- package/dist/utils/encoding.js.map +1 -1
- package/dist/utils/logger.d.ts +61 -2
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +52 -4
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/url.d.ts +47 -7
- package/dist/utils/url.d.ts.map +1 -1
- package/dist/utils/url.js +47 -7
- package/dist/utils/url.js.map +1 -1
- package/dist/ws/client.d.ts +59 -15
- package/dist/ws/client.d.ts.map +1 -1
- package/dist/ws/client.js +34 -27
- package/dist/ws/client.js.map +1 -1
- package/dist/ws/frame.d.ts +43 -9
- package/dist/ws/frame.d.ts.map +1 -1
- package/dist/ws/frame.js +35 -19
- package/dist/ws/frame.js.map +1 -1
- package/package.json +2 -2
|
@@ -1,49 +1,143 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Builds the SNI (Server Name Indication) extension payload for the given
|
|
3
|
+
* hostname, encoded as a TLS `HostName` name list structure per RFC 6066.
|
|
3
4
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* extensions array in a declarative manner.
|
|
5
|
+
* @param {string} hostname - The ASCII server name to advertise.
|
|
6
|
+
* @returns {Buffer} Encoded SNI extension data.
|
|
7
7
|
*/
|
|
8
|
-
/** Build SNI extension data. RFC 6066 section 3. */
|
|
9
8
|
export declare function sniData(hostname: string): Buffer;
|
|
10
|
-
/**
|
|
9
|
+
/**
|
|
10
|
+
* Builds the `supported_versions` extension payload listing the given TLS
|
|
11
|
+
* version codes in the order provided.
|
|
12
|
+
*
|
|
13
|
+
* @param {number[]} versions - Ordered TLS version codes (e.g. `[0x0304, 0x0303]`).
|
|
14
|
+
* @returns {Buffer} Encoded supported_versions extension data.
|
|
15
|
+
*/
|
|
11
16
|
export declare function supportedVersionsData(versions: number[]): Buffer;
|
|
12
|
-
/**
|
|
17
|
+
/**
|
|
18
|
+
* Builds the `supported_groups` extension payload listing the given named
|
|
19
|
+
* group codes (elliptic curves and finite-field groups).
|
|
20
|
+
*
|
|
21
|
+
* @param {number[]} groups - Ordered named group codes (e.g. `[0x001d, 0x0017]`).
|
|
22
|
+
* @returns {Buffer} Encoded supported_groups extension data.
|
|
23
|
+
*/
|
|
13
24
|
export declare function supportedGroupsData(groups: number[]): Buffer;
|
|
14
|
-
/**
|
|
25
|
+
/**
|
|
26
|
+
* Builds the `ec_point_formats` extension payload specifying the supported
|
|
27
|
+
* EC point encoding formats.
|
|
28
|
+
*
|
|
29
|
+
* @param {number[]} formats - EC point format codes (e.g. `[0]` for uncompressed).
|
|
30
|
+
* @returns {Buffer} Encoded ec_point_formats extension data.
|
|
31
|
+
*/
|
|
15
32
|
export declare function ecPointFormatsData(formats: number[]): Buffer;
|
|
16
|
-
/**
|
|
33
|
+
/**
|
|
34
|
+
* Builds the `signature_algorithms` extension payload listing the supported
|
|
35
|
+
* signature scheme codes in the order provided.
|
|
36
|
+
*
|
|
37
|
+
* @param {number[]} algs - Ordered signature scheme codes (e.g. `[0x0403, 0x0804]`).
|
|
38
|
+
* @returns {Buffer} Encoded signature_algorithms extension data.
|
|
39
|
+
*/
|
|
17
40
|
export declare function signatureAlgorithmsData(algs: number[]): Buffer;
|
|
18
|
-
/**
|
|
41
|
+
/**
|
|
42
|
+
* Builds the ALPN (Application-Layer Protocol Negotiation) extension payload
|
|
43
|
+
* advertising the given protocol name strings in preference order.
|
|
44
|
+
*
|
|
45
|
+
* @param {string[]} protocols - Protocol names in preference order (e.g. `['h2', 'http/1.1']`).
|
|
46
|
+
* @returns {Buffer} Encoded ALPN extension data.
|
|
47
|
+
*/
|
|
19
48
|
export declare function alpnData(protocols: string[]): Buffer;
|
|
20
|
-
/**
|
|
49
|
+
/**
|
|
50
|
+
* Builds the `compress_certificate` extension payload listing the supported
|
|
51
|
+
* certificate compression algorithm codes (RFC 8879).
|
|
52
|
+
*
|
|
53
|
+
* @param {number[]} algorithms - Compression algorithm codes (e.g. `[2]` for brotli).
|
|
54
|
+
* @returns {Buffer} Encoded compress_certificate extension data.
|
|
55
|
+
*/
|
|
21
56
|
export declare function compressCertData(algorithms: number[]): Buffer;
|
|
22
|
-
/**
|
|
57
|
+
/**
|
|
58
|
+
* Builds the `psk_key_exchange_modes` extension payload specifying the
|
|
59
|
+
* supported PSK key exchange mode codes.
|
|
60
|
+
*
|
|
61
|
+
* @param {number[]} modes - PSK key exchange mode codes (e.g. `[1]` for psk_dhe_ke).
|
|
62
|
+
* @returns {Buffer} Encoded psk_key_exchange_modes extension data.
|
|
63
|
+
*/
|
|
23
64
|
export declare function pskKeyExchangeModesData(modes: number[]): Buffer;
|
|
24
|
-
/**
|
|
25
|
-
*
|
|
26
|
-
*
|
|
65
|
+
/**
|
|
66
|
+
* Returns an empty buffer as a placeholder for the `key_share` extension.
|
|
67
|
+
* The actual key share data is computed and injected at ClientHello build time
|
|
68
|
+
* by the handshake engine, which needs the private keys to complete the DH.
|
|
69
|
+
*
|
|
70
|
+
* @param {number[]} groups - Named group codes for which key shares will be generated.
|
|
71
|
+
* @returns {Buffer} Empty placeholder buffer.
|
|
72
|
+
*/
|
|
27
73
|
export declare function keySharePlaceholder(groups: number[]): Buffer;
|
|
28
|
-
/**
|
|
29
|
-
*
|
|
74
|
+
/**
|
|
75
|
+
* Builds the `status_request` extension payload requesting OCSP stapling
|
|
76
|
+
* from the server (RFC 6066 §8).
|
|
77
|
+
*
|
|
78
|
+
* @returns {Buffer} Encoded status_request extension data.
|
|
79
|
+
*/
|
|
30
80
|
export declare function statusRequestData(): Buffer;
|
|
31
|
-
/**
|
|
81
|
+
/**
|
|
82
|
+
* Returns an empty buffer for the `session_ticket` extension, signalling
|
|
83
|
+
* that the client supports TLS session tickets but has none to present.
|
|
84
|
+
*
|
|
85
|
+
* @returns {Buffer} Empty session_ticket extension payload.
|
|
86
|
+
*/
|
|
32
87
|
export declare function sessionTicketData(): Buffer;
|
|
33
|
-
/**
|
|
88
|
+
/**
|
|
89
|
+
* Returns an empty buffer for the `extended_master_secret` extension (RFC 7627),
|
|
90
|
+
* which signals support for the extended master secret computation.
|
|
91
|
+
*
|
|
92
|
+
* @returns {Buffer} Empty extended_master_secret extension payload.
|
|
93
|
+
*/
|
|
34
94
|
export declare function extendedMasterSecretData(): Buffer;
|
|
35
|
-
/**
|
|
95
|
+
/**
|
|
96
|
+
* Builds the `renegotiation_info` extension payload with an empty renegotiated
|
|
97
|
+
* connection field, indicating that this is an initial TLS handshake (RFC 5746).
|
|
98
|
+
*
|
|
99
|
+
* @returns {Buffer} Encoded renegotiation_info extension data (`[0x00]`).
|
|
100
|
+
*/
|
|
36
101
|
export declare function renegotiationInfoData(): Buffer;
|
|
37
|
-
/**
|
|
102
|
+
/**
|
|
103
|
+
* Returns an empty buffer for the `signed_certificate_timestamp` extension
|
|
104
|
+
* (RFC 6962), signalling SCT support without providing any timestamps.
|
|
105
|
+
*
|
|
106
|
+
* @returns {Buffer} Empty SCT extension payload.
|
|
107
|
+
*/
|
|
38
108
|
export declare function sctData(): Buffer;
|
|
39
|
-
/**
|
|
109
|
+
/**
|
|
110
|
+
* Builds the `record_size_limit` extension payload (RFC 8449) specifying the
|
|
111
|
+
* maximum plaintext record size the client is willing to receive.
|
|
112
|
+
*
|
|
113
|
+
* @param {number} limit - Maximum record size in bytes (typically 16384 for browsers).
|
|
114
|
+
* @returns {Buffer} Encoded record_size_limit extension data.
|
|
115
|
+
*/
|
|
40
116
|
export declare function recordSizeLimitData(limit: number): Buffer;
|
|
41
|
-
/**
|
|
117
|
+
/**
|
|
118
|
+
* Builds the `delegated_credentials` extension payload (RFC 9345) listing
|
|
119
|
+
* the signature algorithms acceptable for use with delegated credentials.
|
|
120
|
+
*
|
|
121
|
+
* @param {number[]} sigAlgs - Signature algorithm codes acceptable for delegated credentials.
|
|
122
|
+
* @returns {Buffer} Encoded delegated_credentials extension data.
|
|
123
|
+
*/
|
|
42
124
|
export declare function delegatedCredentialsData(sigAlgs: number[]): Buffer;
|
|
43
|
-
/**
|
|
125
|
+
/**
|
|
126
|
+
* Builds the `application_settings` (ALPS) extension payload for the given
|
|
127
|
+
* protocol names, a Chrome-specific extension that negotiates application-level
|
|
128
|
+
* settings over TLS.
|
|
129
|
+
*
|
|
130
|
+
* @param {string[]} protocols - ALPN protocol names to include in the ALPS extension.
|
|
131
|
+
* @returns {Buffer} Encoded application_settings extension data.
|
|
132
|
+
*/
|
|
44
133
|
export declare function applicationSettingsData(protocols: string[]): Buffer;
|
|
45
|
-
/**
|
|
46
|
-
*
|
|
47
|
-
*
|
|
134
|
+
/**
|
|
135
|
+
* Builds a synthetic Encrypted Client Hello (ECH) GREASE extension payload
|
|
136
|
+
* (draft-ietf-tls-esni). This does not perform real ECH; it emits a
|
|
137
|
+
* deterministic fake payload that matches the extension structure browsers send
|
|
138
|
+
* when the server does not advertise real ECH support.
|
|
139
|
+
*
|
|
140
|
+
* @returns {Buffer} Encoded ECH GREASE extension data.
|
|
141
|
+
*/
|
|
48
142
|
export declare function echGreaseData(): Buffer;
|
|
49
143
|
//# sourceMappingURL=extensions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extensions.d.ts","sourceRoot":"","sources":["../../src/fingerprints/extensions.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"extensions.d.ts","sourceRoot":"","sources":["../../src/fingerprints/extensions.ts"],"names":[],"mappings":"AAaA;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAShD;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAKhE;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAK5D;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,CAK5D;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAK9D;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,CAcpD;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,CAK7D;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAK/D;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAE5D;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAM1C;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,CAEjD;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,IAAI,MAAM,CAEhC;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIzD;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,CAKlE;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,CAcnE;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAgBtC"}
|
|
@@ -1,28 +1,28 @@
|
|
|
1
|
+
import { BufferWriter } from '../utils/buffer-writer.js';
|
|
1
2
|
/**
|
|
2
|
-
*
|
|
3
|
+
* Builds the SNI (Server Name Indication) extension payload for the given
|
|
4
|
+
* hostname, encoded as a TLS `HostName` name list structure per RFC 6066.
|
|
3
5
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* extensions array in a declarative manner.
|
|
6
|
+
* @param {string} hostname - The ASCII server name to advertise.
|
|
7
|
+
* @returns {Buffer} Encoded SNI extension data.
|
|
7
8
|
*/
|
|
8
|
-
import { BufferWriter } from '../utils/buffer-writer.js';
|
|
9
|
-
// ---- helpers ----
|
|
10
|
-
/** Build SNI extension data. RFC 6066 section 3. */
|
|
11
9
|
export function sniData(hostname) {
|
|
12
10
|
const host = Buffer.from(hostname, 'ascii');
|
|
13
11
|
const w = new BufferWriter(host.length + 16);
|
|
14
|
-
// ServerNameList length (2 bytes)
|
|
15
12
|
w.writeUInt16(host.length + 3 + 2);
|
|
16
|
-
// list length
|
|
17
13
|
w.writeUInt16(host.length + 3);
|
|
18
|
-
// name_type = host_name (0)
|
|
19
14
|
w.writeUInt8(0);
|
|
20
|
-
// host name length + data
|
|
21
15
|
w.writeUInt16(host.length);
|
|
22
16
|
w.writeBytes(host);
|
|
23
17
|
return w.toBuffer();
|
|
24
18
|
}
|
|
25
|
-
/**
|
|
19
|
+
/**
|
|
20
|
+
* Builds the `supported_versions` extension payload listing the given TLS
|
|
21
|
+
* version codes in the order provided.
|
|
22
|
+
*
|
|
23
|
+
* @param {number[]} versions - Ordered TLS version codes (e.g. `[0x0304, 0x0303]`).
|
|
24
|
+
* @returns {Buffer} Encoded supported_versions extension data.
|
|
25
|
+
*/
|
|
26
26
|
export function supportedVersionsData(versions) {
|
|
27
27
|
const w = new BufferWriter(1 + versions.length * 2);
|
|
28
28
|
w.writeUInt8(versions.length * 2);
|
|
@@ -30,7 +30,13 @@ export function supportedVersionsData(versions) {
|
|
|
30
30
|
w.writeUInt16(v);
|
|
31
31
|
return w.toBuffer();
|
|
32
32
|
}
|
|
33
|
-
/**
|
|
33
|
+
/**
|
|
34
|
+
* Builds the `supported_groups` extension payload listing the given named
|
|
35
|
+
* group codes (elliptic curves and finite-field groups).
|
|
36
|
+
*
|
|
37
|
+
* @param {number[]} groups - Ordered named group codes (e.g. `[0x001d, 0x0017]`).
|
|
38
|
+
* @returns {Buffer} Encoded supported_groups extension data.
|
|
39
|
+
*/
|
|
34
40
|
export function supportedGroupsData(groups) {
|
|
35
41
|
const w = new BufferWriter(2 + groups.length * 2);
|
|
36
42
|
w.writeUInt16(groups.length * 2);
|
|
@@ -38,7 +44,13 @@ export function supportedGroupsData(groups) {
|
|
|
38
44
|
w.writeUInt16(g);
|
|
39
45
|
return w.toBuffer();
|
|
40
46
|
}
|
|
41
|
-
/**
|
|
47
|
+
/**
|
|
48
|
+
* Builds the `ec_point_formats` extension payload specifying the supported
|
|
49
|
+
* EC point encoding formats.
|
|
50
|
+
*
|
|
51
|
+
* @param {number[]} formats - EC point format codes (e.g. `[0]` for uncompressed).
|
|
52
|
+
* @returns {Buffer} Encoded ec_point_formats extension data.
|
|
53
|
+
*/
|
|
42
54
|
export function ecPointFormatsData(formats) {
|
|
43
55
|
const w = new BufferWriter(1 + formats.length);
|
|
44
56
|
w.writeUInt8(formats.length);
|
|
@@ -46,7 +58,13 @@ export function ecPointFormatsData(formats) {
|
|
|
46
58
|
w.writeUInt8(f);
|
|
47
59
|
return w.toBuffer();
|
|
48
60
|
}
|
|
49
|
-
/**
|
|
61
|
+
/**
|
|
62
|
+
* Builds the `signature_algorithms` extension payload listing the supported
|
|
63
|
+
* signature scheme codes in the order provided.
|
|
64
|
+
*
|
|
65
|
+
* @param {number[]} algs - Ordered signature scheme codes (e.g. `[0x0403, 0x0804]`).
|
|
66
|
+
* @returns {Buffer} Encoded signature_algorithms extension data.
|
|
67
|
+
*/
|
|
50
68
|
export function signatureAlgorithmsData(algs) {
|
|
51
69
|
const w = new BufferWriter(2 + algs.length * 2);
|
|
52
70
|
w.writeUInt16(algs.length * 2);
|
|
@@ -54,7 +72,13 @@ export function signatureAlgorithmsData(algs) {
|
|
|
54
72
|
w.writeUInt16(a);
|
|
55
73
|
return w.toBuffer();
|
|
56
74
|
}
|
|
57
|
-
/**
|
|
75
|
+
/**
|
|
76
|
+
* Builds the ALPN (Application-Layer Protocol Negotiation) extension payload
|
|
77
|
+
* advertising the given protocol name strings in preference order.
|
|
78
|
+
*
|
|
79
|
+
* @param {string[]} protocols - Protocol names in preference order (e.g. `['h2', 'http/1.1']`).
|
|
80
|
+
* @returns {Buffer} Encoded ALPN extension data.
|
|
81
|
+
*/
|
|
58
82
|
export function alpnData(protocols) {
|
|
59
83
|
let totalLen = 0;
|
|
60
84
|
const bufs = protocols.map((p) => {
|
|
@@ -70,7 +94,13 @@ export function alpnData(protocols) {
|
|
|
70
94
|
}
|
|
71
95
|
return w.toBuffer();
|
|
72
96
|
}
|
|
73
|
-
/**
|
|
97
|
+
/**
|
|
98
|
+
* Builds the `compress_certificate` extension payload listing the supported
|
|
99
|
+
* certificate compression algorithm codes (RFC 8879).
|
|
100
|
+
*
|
|
101
|
+
* @param {number[]} algorithms - Compression algorithm codes (e.g. `[2]` for brotli).
|
|
102
|
+
* @returns {Buffer} Encoded compress_certificate extension data.
|
|
103
|
+
*/
|
|
74
104
|
export function compressCertData(algorithms) {
|
|
75
105
|
const w = new BufferWriter(1 + algorithms.length * 2);
|
|
76
106
|
w.writeUInt8(algorithms.length * 2);
|
|
@@ -78,7 +108,13 @@ export function compressCertData(algorithms) {
|
|
|
78
108
|
w.writeUInt16(a);
|
|
79
109
|
return w.toBuffer();
|
|
80
110
|
}
|
|
81
|
-
/**
|
|
111
|
+
/**
|
|
112
|
+
* Builds the `psk_key_exchange_modes` extension payload specifying the
|
|
113
|
+
* supported PSK key exchange mode codes.
|
|
114
|
+
*
|
|
115
|
+
* @param {number[]} modes - PSK key exchange mode codes (e.g. `[1]` for psk_dhe_ke).
|
|
116
|
+
* @returns {Buffer} Encoded psk_key_exchange_modes extension data.
|
|
117
|
+
*/
|
|
82
118
|
export function pskKeyExchangeModesData(modes) {
|
|
83
119
|
const w = new BufferWriter(1 + modes.length);
|
|
84
120
|
w.writeUInt8(modes.length);
|
|
@@ -86,46 +122,85 @@ export function pskKeyExchangeModesData(modes) {
|
|
|
86
122
|
w.writeUInt8(m);
|
|
87
123
|
return w.toBuffer();
|
|
88
124
|
}
|
|
89
|
-
/**
|
|
90
|
-
*
|
|
91
|
-
*
|
|
125
|
+
/**
|
|
126
|
+
* Returns an empty buffer as a placeholder for the `key_share` extension.
|
|
127
|
+
* The actual key share data is computed and injected at ClientHello build time
|
|
128
|
+
* by the handshake engine, which needs the private keys to complete the DH.
|
|
129
|
+
*
|
|
130
|
+
* @param {number[]} groups - Named group codes for which key shares will be generated.
|
|
131
|
+
* @returns {Buffer} Empty placeholder buffer.
|
|
132
|
+
*/
|
|
92
133
|
export function keySharePlaceholder(groups) {
|
|
93
|
-
// We will compute real key shares at handshake time.
|
|
94
|
-
// For fingerprinting purposes this is not hashed into JA3.
|
|
95
134
|
return Buffer.alloc(0);
|
|
96
135
|
}
|
|
97
|
-
/**
|
|
98
|
-
*
|
|
136
|
+
/**
|
|
137
|
+
* Builds the `status_request` extension payload requesting OCSP stapling
|
|
138
|
+
* from the server (RFC 6066 §8).
|
|
139
|
+
*
|
|
140
|
+
* @returns {Buffer} Encoded status_request extension data.
|
|
141
|
+
*/
|
|
99
142
|
export function statusRequestData() {
|
|
100
143
|
const w = new BufferWriter(5);
|
|
101
|
-
w.writeUInt8(1);
|
|
102
|
-
w.writeUInt16(0);
|
|
103
|
-
w.writeUInt16(0);
|
|
144
|
+
w.writeUInt8(1);
|
|
145
|
+
w.writeUInt16(0);
|
|
146
|
+
w.writeUInt16(0);
|
|
104
147
|
return w.toBuffer();
|
|
105
148
|
}
|
|
106
|
-
/**
|
|
149
|
+
/**
|
|
150
|
+
* Returns an empty buffer for the `session_ticket` extension, signalling
|
|
151
|
+
* that the client supports TLS session tickets but has none to present.
|
|
152
|
+
*
|
|
153
|
+
* @returns {Buffer} Empty session_ticket extension payload.
|
|
154
|
+
*/
|
|
107
155
|
export function sessionTicketData() {
|
|
108
156
|
return Buffer.alloc(0);
|
|
109
157
|
}
|
|
110
|
-
/**
|
|
158
|
+
/**
|
|
159
|
+
* Returns an empty buffer for the `extended_master_secret` extension (RFC 7627),
|
|
160
|
+
* which signals support for the extended master secret computation.
|
|
161
|
+
*
|
|
162
|
+
* @returns {Buffer} Empty extended_master_secret extension payload.
|
|
163
|
+
*/
|
|
111
164
|
export function extendedMasterSecretData() {
|
|
112
165
|
return Buffer.alloc(0);
|
|
113
166
|
}
|
|
114
|
-
/**
|
|
167
|
+
/**
|
|
168
|
+
* Builds the `renegotiation_info` extension payload with an empty renegotiated
|
|
169
|
+
* connection field, indicating that this is an initial TLS handshake (RFC 5746).
|
|
170
|
+
*
|
|
171
|
+
* @returns {Buffer} Encoded renegotiation_info extension data (`[0x00]`).
|
|
172
|
+
*/
|
|
115
173
|
export function renegotiationInfoData() {
|
|
116
174
|
return Buffer.from([0]);
|
|
117
175
|
}
|
|
118
|
-
/**
|
|
176
|
+
/**
|
|
177
|
+
* Returns an empty buffer for the `signed_certificate_timestamp` extension
|
|
178
|
+
* (RFC 6962), signalling SCT support without providing any timestamps.
|
|
179
|
+
*
|
|
180
|
+
* @returns {Buffer} Empty SCT extension payload.
|
|
181
|
+
*/
|
|
119
182
|
export function sctData() {
|
|
120
183
|
return Buffer.alloc(0);
|
|
121
184
|
}
|
|
122
|
-
/**
|
|
185
|
+
/**
|
|
186
|
+
* Builds the `record_size_limit` extension payload (RFC 8449) specifying the
|
|
187
|
+
* maximum plaintext record size the client is willing to receive.
|
|
188
|
+
*
|
|
189
|
+
* @param {number} limit - Maximum record size in bytes (typically 16384 for browsers).
|
|
190
|
+
* @returns {Buffer} Encoded record_size_limit extension data.
|
|
191
|
+
*/
|
|
123
192
|
export function recordSizeLimitData(limit) {
|
|
124
193
|
const w = new BufferWriter(2);
|
|
125
194
|
w.writeUInt16(limit);
|
|
126
195
|
return w.toBuffer();
|
|
127
196
|
}
|
|
128
|
-
/**
|
|
197
|
+
/**
|
|
198
|
+
* Builds the `delegated_credentials` extension payload (RFC 9345) listing
|
|
199
|
+
* the signature algorithms acceptable for use with delegated credentials.
|
|
200
|
+
*
|
|
201
|
+
* @param {number[]} sigAlgs - Signature algorithm codes acceptable for delegated credentials.
|
|
202
|
+
* @returns {Buffer} Encoded delegated_credentials extension data.
|
|
203
|
+
*/
|
|
129
204
|
export function delegatedCredentialsData(sigAlgs) {
|
|
130
205
|
const w = new BufferWriter(2 + sigAlgs.length * 2);
|
|
131
206
|
w.writeUInt16(sigAlgs.length * 2);
|
|
@@ -133,7 +208,14 @@ export function delegatedCredentialsData(sigAlgs) {
|
|
|
133
208
|
w.writeUInt16(a);
|
|
134
209
|
return w.toBuffer();
|
|
135
210
|
}
|
|
136
|
-
/**
|
|
211
|
+
/**
|
|
212
|
+
* Builds the `application_settings` (ALPS) extension payload for the given
|
|
213
|
+
* protocol names, a Chrome-specific extension that negotiates application-level
|
|
214
|
+
* settings over TLS.
|
|
215
|
+
*
|
|
216
|
+
* @param {string[]} protocols - ALPN protocol names to include in the ALPS extension.
|
|
217
|
+
* @returns {Buffer} Encoded application_settings extension data.
|
|
218
|
+
*/
|
|
137
219
|
export function applicationSettingsData(protocols) {
|
|
138
220
|
let totalLen = 0;
|
|
139
221
|
const bufs = protocols.map((p) => {
|
|
@@ -149,26 +231,27 @@ export function applicationSettingsData(protocols) {
|
|
|
149
231
|
}
|
|
150
232
|
return w.toBuffer();
|
|
151
233
|
}
|
|
152
|
-
/**
|
|
153
|
-
*
|
|
154
|
-
*
|
|
234
|
+
/**
|
|
235
|
+
* Builds a synthetic Encrypted Client Hello (ECH) GREASE extension payload
|
|
236
|
+
* (draft-ietf-tls-esni). This does not perform real ECH; it emits a
|
|
237
|
+
* deterministic fake payload that matches the extension structure browsers send
|
|
238
|
+
* when the server does not advertise real ECH support.
|
|
239
|
+
*
|
|
240
|
+
* @returns {Buffer} Encoded ECH GREASE extension data.
|
|
241
|
+
*/
|
|
155
242
|
export function echGreaseData() {
|
|
156
|
-
// Type = outer (0), followed by a random GREASE cipher suite and
|
|
157
|
-
// dummy payload. This mirrors Chrome's GREASE ECH behavior.
|
|
158
243
|
const w = new BufferWriter(8 + 32);
|
|
159
|
-
w.writeUInt8(0);
|
|
160
|
-
|
|
161
|
-
w.writeUInt16(
|
|
162
|
-
w.writeUInt16(0x0001);
|
|
163
|
-
w.
|
|
164
|
-
w.
|
|
165
|
-
w.writeUInt16(32); // enc length
|
|
244
|
+
w.writeUInt8(0);
|
|
245
|
+
w.writeUInt16(0x0020);
|
|
246
|
+
w.writeUInt16(0x0001);
|
|
247
|
+
w.writeUInt16(0x0001);
|
|
248
|
+
w.writeUInt8(0);
|
|
249
|
+
w.writeUInt16(32);
|
|
166
250
|
const enc = Buffer.alloc(32);
|
|
167
|
-
// Fill with random-looking but deterministic bytes for GREASE
|
|
168
251
|
for (let i = 0; i < 32; i++)
|
|
169
252
|
enc[i] = (i * 37 + 7) & 0xff;
|
|
170
253
|
w.writeBytes(enc);
|
|
171
|
-
w.writeUInt16(16);
|
|
254
|
+
w.writeUInt16(16);
|
|
172
255
|
const payload = Buffer.alloc(16);
|
|
173
256
|
for (let i = 0; i < 16; i++)
|
|
174
257
|
payload[i] = (i * 53 + 13) & 0xff;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extensions.js","sourceRoot":"","sources":["../../src/fingerprints/extensions.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"extensions.js","sourceRoot":"","sources":["../../src/fingerprints/extensions.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,32 +1,48 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* JA3 and JA3N fingerprint computation.
|
|
3
|
-
*
|
|
4
|
-
* JA3 hashes the TLS ClientHello parameters into a stable identifier
|
|
5
|
-
* that fingerprint detection systems use to identify client software.
|
|
6
|
-
*
|
|
7
|
-
* JA3 format: SSLVersion,Ciphers,Extensions,EllipticCurves,EllipticCurvePointFormats
|
|
8
|
-
* Each field is a dash-separated list of decimal values.
|
|
9
|
-
*
|
|
10
|
-
* GREASE values (RFC 8701) are excluded from the hash, matching the
|
|
11
|
-
* canonical JA3 specification.
|
|
12
|
-
*/
|
|
13
1
|
import type { TLSProfile } from './types.js';
|
|
14
2
|
/**
|
|
15
|
-
*
|
|
3
|
+
* Computes the JA3 string representation of a TLS profile. The string is a
|
|
4
|
+
* comma-separated tuple of `version`, cipher codes, extension type codes,
|
|
5
|
+
* supported-group codes, and EC point format codes, all encoded as
|
|
6
|
+
* dash-separated decimal lists (GREASE values filtered out).
|
|
7
|
+
*
|
|
8
|
+
* @param {TLSProfile} profile - The TLS profile to fingerprint.
|
|
9
|
+
* @returns {string} The JA3 fingerprint string.
|
|
16
10
|
*
|
|
17
|
-
*
|
|
11
|
+
* @example
|
|
12
|
+
* const str = ja3String(chromeLatest.tls);
|
|
13
|
+
* // => "771,4865-4866-...,0-23-...,29-23-24,0"
|
|
18
14
|
*/
|
|
19
15
|
export declare function ja3String(profile: TLSProfile): string;
|
|
20
16
|
/**
|
|
21
|
-
*
|
|
17
|
+
* Computes the MD5 hash of the JA3 string for the given TLS profile.
|
|
18
|
+
* The resulting 32-character hex digest is the canonical JA3 fingerprint
|
|
19
|
+
* used in network monitoring and fingerprinting detection.
|
|
20
|
+
*
|
|
21
|
+
* @param {TLSProfile} profile - The TLS profile to fingerprint.
|
|
22
|
+
* @returns {string} The 32-character lowercase hex JA3 MD5 hash.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* const hash = ja3Hash(chromeLatest.tls);
|
|
26
|
+
* // => "cd08e31494f9531f560d64c695473da9"
|
|
22
27
|
*/
|
|
23
28
|
export declare function ja3Hash(profile: TLSProfile): string;
|
|
24
29
|
/**
|
|
25
|
-
*
|
|
30
|
+
* Computes the JA3N (normalised) string for a TLS profile. Unlike
|
|
31
|
+
* {@link ja3String}, all numeric lists are sorted before joining, which
|
|
32
|
+
* makes the fingerprint order-independent and useful for comparing profiles
|
|
33
|
+
* that advertise the same capabilities in different orders.
|
|
26
34
|
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
35
|
+
* @param {TLSProfile} profile - The TLS profile to fingerprint.
|
|
36
|
+
* @returns {string} The JA3N fingerprint string with sorted field lists.
|
|
29
37
|
*/
|
|
30
38
|
export declare function ja3nString(profile: TLSProfile): string;
|
|
39
|
+
/**
|
|
40
|
+
* Computes the MD5 hash of the JA3N (normalised) string for the given TLS
|
|
41
|
+
* profile. JA3N hashes are order-independent, making them suitable for
|
|
42
|
+
* grouping profiles by capability set regardless of advertisement order.
|
|
43
|
+
*
|
|
44
|
+
* @param {TLSProfile} profile - The TLS profile to fingerprint.
|
|
45
|
+
* @returns {string} The 32-character lowercase hex JA3N MD5 hash.
|
|
46
|
+
*/
|
|
31
47
|
export declare function ja3nHash(profile: TLSProfile): string;
|
|
32
48
|
//# sourceMappingURL=ja3.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ja3.d.ts","sourceRoot":"","sources":["../../src/fingerprints/ja3.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ja3.d.ts","sourceRoot":"","sources":["../../src/fingerprints/ja3.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAY7C;;;;;;;;;;;;GAYG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM,CAUrD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM,CAEnD;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM,CAgBtD;AAED;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM,CAEpD"}
|
package/dist/fingerprints/ja3.js
CHANGED
|
@@ -1,15 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* JA3 and JA3N fingerprint computation.
|
|
3
|
-
*
|
|
4
|
-
* JA3 hashes the TLS ClientHello parameters into a stable identifier
|
|
5
|
-
* that fingerprint detection systems use to identify client software.
|
|
6
|
-
*
|
|
7
|
-
* JA3 format: SSLVersion,Ciphers,Extensions,EllipticCurves,EllipticCurvePointFormats
|
|
8
|
-
* Each field is a dash-separated list of decimal values.
|
|
9
|
-
*
|
|
10
|
-
* GREASE values (RFC 8701) are excluded from the hash, matching the
|
|
11
|
-
* canonical JA3 specification.
|
|
12
|
-
*/
|
|
13
1
|
import { createHash } from 'node:crypto';
|
|
14
2
|
import { GREASE_VALUES } from '../tls/constants.js';
|
|
15
3
|
const GREASE_SET = new Set(GREASE_VALUES);
|
|
@@ -20,9 +8,17 @@ function filterGrease(values) {
|
|
|
20
8
|
return values.filter((v) => !isGrease(v));
|
|
21
9
|
}
|
|
22
10
|
/**
|
|
23
|
-
*
|
|
11
|
+
* Computes the JA3 string representation of a TLS profile. The string is a
|
|
12
|
+
* comma-separated tuple of `version`, cipher codes, extension type codes,
|
|
13
|
+
* supported-group codes, and EC point format codes, all encoded as
|
|
14
|
+
* dash-separated decimal lists (GREASE values filtered out).
|
|
15
|
+
*
|
|
16
|
+
* @param {TLSProfile} profile - The TLS profile to fingerprint.
|
|
17
|
+
* @returns {string} The JA3 fingerprint string.
|
|
24
18
|
*
|
|
25
|
-
*
|
|
19
|
+
* @example
|
|
20
|
+
* const str = ja3String(chromeLatest.tls);
|
|
21
|
+
* // => "771,4865-4866-...,0-23-...,29-23-24,0"
|
|
26
22
|
*/
|
|
27
23
|
export function ja3String(profile) {
|
|
28
24
|
const version = profile.clientVersion;
|
|
@@ -33,16 +29,28 @@ export function ja3String(profile) {
|
|
|
33
29
|
return `${version},${ciphers},${extensions},${groups},${formats}`;
|
|
34
30
|
}
|
|
35
31
|
/**
|
|
36
|
-
*
|
|
32
|
+
* Computes the MD5 hash of the JA3 string for the given TLS profile.
|
|
33
|
+
* The resulting 32-character hex digest is the canonical JA3 fingerprint
|
|
34
|
+
* used in network monitoring and fingerprinting detection.
|
|
35
|
+
*
|
|
36
|
+
* @param {TLSProfile} profile - The TLS profile to fingerprint.
|
|
37
|
+
* @returns {string} The 32-character lowercase hex JA3 MD5 hash.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* const hash = ja3Hash(chromeLatest.tls);
|
|
41
|
+
* // => "cd08e31494f9531f560d64c695473da9"
|
|
37
42
|
*/
|
|
38
43
|
export function ja3Hash(profile) {
|
|
39
44
|
return createHash('md5').update(ja3String(profile)).digest('hex');
|
|
40
45
|
}
|
|
41
46
|
/**
|
|
42
|
-
*
|
|
47
|
+
* Computes the JA3N (normalised) string for a TLS profile. Unlike
|
|
48
|
+
* {@link ja3String}, all numeric lists are sorted before joining, which
|
|
49
|
+
* makes the fingerprint order-independent and useful for comparing profiles
|
|
50
|
+
* that advertise the same capabilities in different orders.
|
|
43
51
|
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
52
|
+
* @param {TLSProfile} profile - The TLS profile to fingerprint.
|
|
53
|
+
* @returns {string} The JA3N fingerprint string with sorted field lists.
|
|
46
54
|
*/
|
|
47
55
|
export function ja3nString(profile) {
|
|
48
56
|
const version = profile.clientVersion;
|
|
@@ -58,6 +66,14 @@ export function ja3nString(profile) {
|
|
|
58
66
|
const formats = (profile.ecPointFormats ?? []).sort((a, b) => a - b).join('-');
|
|
59
67
|
return `${version},${ciphers},${extensions},${groups},${formats}`;
|
|
60
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* Computes the MD5 hash of the JA3N (normalised) string for the given TLS
|
|
71
|
+
* profile. JA3N hashes are order-independent, making them suitable for
|
|
72
|
+
* grouping profiles by capability set regardless of advertisement order.
|
|
73
|
+
*
|
|
74
|
+
* @param {TLSProfile} profile - The TLS profile to fingerprint.
|
|
75
|
+
* @returns {string} The 32-character lowercase hex JA3N MD5 hash.
|
|
76
|
+
*/
|
|
61
77
|
export function ja3nHash(profile) {
|
|
62
78
|
return createHash('md5').update(ja3nString(profile)).digest('hex');
|
|
63
79
|
}
|