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.
Files changed (197) hide show
  1. package/README.md +5 -13
  2. package/dist/cli/args.d.ts +37 -5
  3. package/dist/cli/args.d.ts.map +1 -1
  4. package/dist/cli/args.js +6 -17
  5. package/dist/cli/args.js.map +1 -1
  6. package/dist/cli/index.d.ts +3 -3
  7. package/dist/cli/index.js +25 -10
  8. package/dist/cli/index.js.map +1 -1
  9. package/dist/cli/output.d.ts +24 -7
  10. package/dist/cli/output.d.ts.map +1 -1
  11. package/dist/cli/output.js +24 -12
  12. package/dist/cli/output.js.map +1 -1
  13. package/dist/cookies/jar.d.ts +45 -13
  14. package/dist/cookies/jar.d.ts.map +1 -1
  15. package/dist/cookies/jar.js +88 -29
  16. package/dist/cookies/jar.js.map +1 -1
  17. package/dist/cookies/parser.d.ts +25 -3
  18. package/dist/cookies/parser.d.ts.map +1 -1
  19. package/dist/cookies/parser.js +12 -7
  20. package/dist/cookies/parser.js.map +1 -1
  21. package/dist/core/client.d.ts +49 -33
  22. package/dist/core/client.d.ts.map +1 -1
  23. package/dist/core/client.js +64 -38
  24. package/dist/core/client.js.map +1 -1
  25. package/dist/core/errors.d.ts +94 -6
  26. package/dist/core/errors.d.ts.map +1 -1
  27. package/dist/core/errors.js +95 -6
  28. package/dist/core/errors.js.map +1 -1
  29. package/dist/core/request.d.ts +96 -30
  30. package/dist/core/request.d.ts.map +1 -1
  31. package/dist/core/request.js +0 -3
  32. package/dist/core/request.js.map +1 -1
  33. package/dist/core/response.d.ts +92 -8
  34. package/dist/core/response.d.ts.map +1 -1
  35. package/dist/core/response.js +92 -7
  36. package/dist/core/response.js.map +1 -1
  37. package/dist/core/session.d.ts +109 -14
  38. package/dist/core/session.d.ts.map +1 -1
  39. package/dist/core/session.js +124 -46
  40. package/dist/core/session.js.map +1 -1
  41. package/dist/fingerprints/akamai.d.ts +11 -11
  42. package/dist/fingerprints/akamai.d.ts.map +1 -1
  43. package/dist/fingerprints/akamai.js +10 -14
  44. package/dist/fingerprints/akamai.js.map +1 -1
  45. package/dist/fingerprints/database.d.ts +14 -15
  46. package/dist/fingerprints/database.d.ts.map +1 -1
  47. package/dist/fingerprints/database.js +14 -19
  48. package/dist/fingerprints/database.js.map +1 -1
  49. package/dist/fingerprints/extensions.d.ts +121 -27
  50. package/dist/fingerprints/extensions.d.ts.map +1 -1
  51. package/dist/fingerprints/extensions.js +132 -49
  52. package/dist/fingerprints/extensions.js.map +1 -1
  53. package/dist/fingerprints/ja3.d.ts +34 -18
  54. package/dist/fingerprints/ja3.d.ts.map +1 -1
  55. package/dist/fingerprints/ja3.js +34 -18
  56. package/dist/fingerprints/ja3.js.map +1 -1
  57. package/dist/fingerprints/profiles/chrome.d.ts +21 -10
  58. package/dist/fingerprints/profiles/chrome.d.ts.map +1 -1
  59. package/dist/fingerprints/profiles/chrome.js +25 -22
  60. package/dist/fingerprints/profiles/chrome.js.map +1 -1
  61. package/dist/fingerprints/profiles/edge.d.ts +10 -7
  62. package/dist/fingerprints/profiles/edge.d.ts.map +1 -1
  63. package/dist/fingerprints/profiles/edge.js +10 -10
  64. package/dist/fingerprints/profiles/edge.js.map +1 -1
  65. package/dist/fingerprints/profiles/firefox.d.ts +11 -3
  66. package/dist/fingerprints/profiles/firefox.d.ts.map +1 -1
  67. package/dist/fingerprints/profiles/firefox.js +15 -14
  68. package/dist/fingerprints/profiles/firefox.js.map +1 -1
  69. package/dist/fingerprints/profiles/safari.d.ts +14 -3
  70. package/dist/fingerprints/profiles/safari.d.ts.map +1 -1
  71. package/dist/fingerprints/profiles/safari.js +16 -13
  72. package/dist/fingerprints/profiles/safari.js.map +1 -1
  73. package/dist/fingerprints/profiles/tor.d.ts +8 -7
  74. package/dist/fingerprints/profiles/tor.d.ts.map +1 -1
  75. package/dist/fingerprints/profiles/tor.js +8 -14
  76. package/dist/fingerprints/profiles/tor.js.map +1 -1
  77. package/dist/fingerprints/types.d.ts +70 -47
  78. package/dist/fingerprints/types.d.ts.map +1 -1
  79. package/dist/fingerprints/types.js +0 -7
  80. package/dist/fingerprints/types.js.map +1 -1
  81. package/dist/http/h1/client.d.ts +30 -9
  82. package/dist/http/h1/client.d.ts.map +1 -1
  83. package/dist/http/h1/client.js +152 -15
  84. package/dist/http/h1/client.js.map +1 -1
  85. package/dist/http/h1/encoder.d.ts +9 -6
  86. package/dist/http/h1/encoder.d.ts.map +1 -1
  87. package/dist/http/h1/encoder.js +8 -12
  88. package/dist/http/h1/encoder.js.map +1 -1
  89. package/dist/http/h1/parser.d.ts +68 -14
  90. package/dist/http/h1/parser.d.ts.map +1 -1
  91. package/dist/http/h1/parser.js +92 -37
  92. package/dist/http/h1/parser.js.map +1 -1
  93. package/dist/http/h2/client.d.ts +81 -14
  94. package/dist/http/h2/client.d.ts.map +1 -1
  95. package/dist/http/h2/client.js +465 -63
  96. package/dist/http/h2/client.js.map +1 -1
  97. package/dist/http/h2/frames.d.ts +103 -6
  98. package/dist/http/h2/frames.d.ts.map +1 -1
  99. package/dist/http/h2/frames.js +96 -17
  100. package/dist/http/h2/frames.js.map +1 -1
  101. package/dist/http/h2/hpack.d.ts +30 -5
  102. package/dist/http/h2/hpack.d.ts.map +1 -1
  103. package/dist/http/h2/hpack.js +39 -35
  104. package/dist/http/h2/hpack.js.map +1 -1
  105. package/dist/http/negotiator.d.ts +35 -12
  106. package/dist/http/negotiator.d.ts.map +1 -1
  107. package/dist/http/negotiator.js +89 -24
  108. package/dist/http/negotiator.js.map +1 -1
  109. package/dist/http/pool.d.ts +66 -17
  110. package/dist/http/pool.d.ts.map +1 -1
  111. package/dist/http/pool.js +47 -20
  112. package/dist/http/pool.js.map +1 -1
  113. package/dist/index.d.ts +2 -3
  114. package/dist/index.d.ts.map +1 -1
  115. package/dist/index.js +0 -13
  116. package/dist/index.js.map +1 -1
  117. package/dist/middleware/interceptor.d.ts +40 -8
  118. package/dist/middleware/interceptor.d.ts.map +1 -1
  119. package/dist/middleware/interceptor.js +28 -6
  120. package/dist/middleware/interceptor.js.map +1 -1
  121. package/dist/middleware/rate-limiter.d.ts +18 -5
  122. package/dist/middleware/rate-limiter.d.ts.map +1 -1
  123. package/dist/middleware/rate-limiter.js +12 -7
  124. package/dist/middleware/rate-limiter.js.map +1 -1
  125. package/dist/middleware/retry.d.ts +17 -5
  126. package/dist/middleware/retry.d.ts.map +1 -1
  127. package/dist/middleware/retry.js +13 -11
  128. package/dist/middleware/retry.js.map +1 -1
  129. package/dist/proxy/http-proxy.d.ts +17 -9
  130. package/dist/proxy/http-proxy.d.ts.map +1 -1
  131. package/dist/proxy/http-proxy.js +9 -13
  132. package/dist/proxy/http-proxy.js.map +1 -1
  133. package/dist/proxy/socks.d.ts +20 -9
  134. package/dist/proxy/socks.d.ts.map +1 -1
  135. package/dist/proxy/socks.js +20 -31
  136. package/dist/proxy/socks.js.map +1 -1
  137. package/dist/tls/constants.d.ts +74 -4
  138. package/dist/tls/constants.d.ts.map +1 -1
  139. package/dist/tls/constants.js +75 -21
  140. package/dist/tls/constants.js.map +1 -1
  141. package/dist/tls/node-engine.d.ts +17 -16
  142. package/dist/tls/node-engine.d.ts.map +1 -1
  143. package/dist/tls/node-engine.js +20 -27
  144. package/dist/tls/node-engine.js.map +1 -1
  145. package/dist/tls/stealth/client-hello.d.ts +32 -16
  146. package/dist/tls/stealth/client-hello.d.ts.map +1 -1
  147. package/dist/tls/stealth/client-hello.js +13 -37
  148. package/dist/tls/stealth/client-hello.js.map +1 -1
  149. package/dist/tls/stealth/engine.d.ts +18 -10
  150. package/dist/tls/stealth/engine.d.ts.map +1 -1
  151. package/dist/tls/stealth/engine.js +18 -24
  152. package/dist/tls/stealth/engine.js.map +1 -1
  153. package/dist/tls/stealth/handshake.d.ts +31 -17
  154. package/dist/tls/stealth/handshake.d.ts.map +1 -1
  155. package/dist/tls/stealth/handshake.js +173 -74
  156. package/dist/tls/stealth/handshake.js.map +1 -1
  157. package/dist/tls/stealth/key-schedule.d.ts +89 -32
  158. package/dist/tls/stealth/key-schedule.d.ts.map +1 -1
  159. package/dist/tls/stealth/key-schedule.js +62 -42
  160. package/dist/tls/stealth/key-schedule.js.map +1 -1
  161. package/dist/tls/stealth/record-layer.d.ts +76 -25
  162. package/dist/tls/stealth/record-layer.d.ts.map +1 -1
  163. package/dist/tls/stealth/record-layer.js +66 -36
  164. package/dist/tls/stealth/record-layer.js.map +1 -1
  165. package/dist/tls/types.d.ts +33 -25
  166. package/dist/tls/types.d.ts.map +1 -1
  167. package/dist/tls/types.js +0 -4
  168. package/dist/tls/types.js.map +1 -1
  169. package/dist/utils/buffer-reader.d.ts +99 -7
  170. package/dist/utils/buffer-reader.d.ts.map +1 -1
  171. package/dist/utils/buffer-reader.js +99 -7
  172. package/dist/utils/buffer-reader.js.map +1 -1
  173. package/dist/utils/buffer-writer.d.ts +99 -10
  174. package/dist/utils/buffer-writer.d.ts.map +1 -1
  175. package/dist/utils/buffer-writer.js +101 -12
  176. package/dist/utils/buffer-writer.js.map +1 -1
  177. package/dist/utils/encoding.d.ts +33 -8
  178. package/dist/utils/encoding.d.ts.map +1 -1
  179. package/dist/utils/encoding.js +58 -13
  180. package/dist/utils/encoding.js.map +1 -1
  181. package/dist/utils/logger.d.ts +61 -2
  182. package/dist/utils/logger.d.ts.map +1 -1
  183. package/dist/utils/logger.js +52 -4
  184. package/dist/utils/logger.js.map +1 -1
  185. package/dist/utils/url.d.ts +47 -7
  186. package/dist/utils/url.d.ts.map +1 -1
  187. package/dist/utils/url.js +47 -7
  188. package/dist/utils/url.js.map +1 -1
  189. package/dist/ws/client.d.ts +59 -15
  190. package/dist/ws/client.d.ts.map +1 -1
  191. package/dist/ws/client.js +34 -27
  192. package/dist/ws/client.js.map +1 -1
  193. package/dist/ws/frame.d.ts +43 -9
  194. package/dist/ws/frame.d.ts.map +1 -1
  195. package/dist/ws/frame.js +35 -19
  196. package/dist/ws/frame.js.map +1 -1
  197. package/package.json +2 -2
@@ -1,49 +1,143 @@
1
1
  /**
2
- * Extension data builders.
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
- * These helpers produce raw extension_data bytes for various TLS
5
- * extensions. They are used by browser profiles to populate the
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
- /** Build supported_versions extension data (for ClientHello). */
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
- /** Build supported_groups extension data. */
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
- /** Build ec_point_formats extension data. */
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
- /** Build signature_algorithms extension data. */
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
- /** Build ALPN extension data. */
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
- /** Build compress_certificate extension data. */
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
- /** Build psk_key_exchange_modes extension data. */
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
- /** Build key_share extension data. Actual key material is filled at
25
- * handshake time; this returns a placeholder structure with the
26
- * correct groups. */
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
- /** Status request (OCSP) extension data -- single responder, no IDs,
29
- * no extensions (the common case). */
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
- /** Session ticket extension data (empty, requests new ticket). */
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
- /** Extended master secret extension (empty data). */
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
- /** Renegotiation info extension (initial handshake -- single 0 byte). */
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
- /** Signed certificate timestamp extension (empty request). */
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
- /** Record size limit extension data. */
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
- /** Delegated credentials extension data. */
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
- /** Application settings (ALPS) extension data. */
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
- /** Encrypted client hello (ECH) -- outer extension with a GREASE
46
- * payload so the extension shows in the fingerprint but does not
47
- * require real ECH config. */
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":"AAAA;;;;;;GAMG;AAgBH,qDAAqD;AACrD,wBAAgB,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAahD;AAED,iEAAiE;AACjE,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAKhE;AAED,6CAA6C;AAC7C,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAK5D;AAED,6CAA6C;AAC7C,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,CAK5D;AAED,iDAAiD;AACjD,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAK9D;AAED,iCAAiC;AACjC,wBAAgB,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,CAcpD;AAED,iDAAiD;AACjD,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,CAK7D;AAED,mDAAmD;AACnD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAK/D;AAED;;sBAEsB;AACtB,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAI5D;AAED;uCACuC;AACvC,wBAAgB,iBAAiB,IAAI,MAAM,CAM1C;AAED,kEAAkE;AAClE,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,qDAAqD;AACrD,wBAAgB,wBAAwB,IAAI,MAAM,CAEjD;AAED,yEAAyE;AACzE,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED,8DAA8D;AAC9D,wBAAgB,OAAO,IAAI,MAAM,CAEhC;AAED,wCAAwC;AACxC,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIzD;AAED,4CAA4C;AAC5C,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,CAKlE;AAED,kDAAkD;AAClD,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,CAcnE;AAED;;+BAE+B;AAC/B,wBAAgB,aAAa,IAAI,MAAM,CAoBtC"}
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
- * Extension data builders.
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
- * These helpers produce raw extension_data bytes for various TLS
5
- * extensions. They are used by browser profiles to populate the
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
- /** Build supported_versions extension data (for ClientHello). */
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
- /** Build supported_groups extension data. */
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
- /** Build ec_point_formats extension data. */
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
- /** Build signature_algorithms extension data. */
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
- /** Build ALPN extension data. */
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
- /** Build compress_certificate extension data. */
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
- /** Build psk_key_exchange_modes extension data. */
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
- /** Build key_share extension data. Actual key material is filled at
90
- * handshake time; this returns a placeholder structure with the
91
- * correct groups. */
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
- /** Status request (OCSP) extension data -- single responder, no IDs,
98
- * no extensions (the common case). */
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); // status_type = ocsp
102
- w.writeUInt16(0); // responder_id_list length
103
- w.writeUInt16(0); // request_extensions length
144
+ w.writeUInt8(1);
145
+ w.writeUInt16(0);
146
+ w.writeUInt16(0);
104
147
  return w.toBuffer();
105
148
  }
106
- /** Session ticket extension data (empty, requests new ticket). */
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
- /** Extended master secret extension (empty data). */
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
- /** Renegotiation info extension (initial handshake -- single 0 byte). */
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
- /** Signed certificate timestamp extension (empty request). */
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
- /** Record size limit extension data. */
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
- /** Delegated credentials extension data. */
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
- /** Application settings (ALPS) extension data. */
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
- /** Encrypted client hello (ECH) -- outer extension with a GREASE
153
- * payload so the extension shows in the fingerprint but does not
154
- * require real ECH config. */
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); // ECHClientHelloType = outer
160
- // HpkeCipherSuite
161
- w.writeUInt16(0x0020); // KEM: DHKEM(X25519, HKDF-SHA256)
162
- w.writeUInt16(0x0001); // KDF: HKDF-SHA256
163
- w.writeUInt16(0x0001); // AEAD: AES-128-GCM
164
- w.writeUInt8(0); // config_id
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); // payload length
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":"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"}
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
- * Build the raw JA3 string from TLS profile parameters.
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
- * The string is not hashed -- call `ja3Hash` for the MD5 digest.
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
- * Compute the JA3 hash (MD5 of the JA3 string).
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
- * Compute JA3N (normalized) hash.
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
- * JA3N sorts the cipher suites and extensions before hashing,
28
- * reducing sensitivity to ordering differences.
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":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAY7C;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM,CAUrD;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM,CAEnD;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM,CAgBtD;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM,CAEpD"}
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"}
@@ -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
- * Build the raw JA3 string from TLS profile parameters.
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
- * The string is not hashed -- call `ja3Hash` for the MD5 digest.
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
- * Compute the JA3 hash (MD5 of the JA3 string).
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
- * Compute JA3N (normalized) hash.
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
- * JA3N sorts the cipher suites and extensions before hashing,
45
- * reducing sensitivity to ordering differences.
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
  }