nlcurl 0.6.0 → 0.8.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 (354) hide show
  1. package/README.md +143 -140
  2. package/dist/cache/groups.d.ts +75 -0
  3. package/dist/cache/groups.d.ts.map +1 -0
  4. package/dist/cache/groups.js +118 -0
  5. package/dist/cache/groups.js.map +1 -0
  6. package/dist/cache/no-vary-search.d.ts +33 -0
  7. package/dist/cache/no-vary-search.d.ts.map +1 -0
  8. package/dist/cache/no-vary-search.js +148 -0
  9. package/dist/cache/no-vary-search.js.map +1 -0
  10. package/dist/cache/range.d.ts +120 -0
  11. package/dist/cache/range.d.ts.map +1 -0
  12. package/dist/cache/range.js +193 -0
  13. package/dist/cache/range.js.map +1 -0
  14. package/dist/cache/store.d.ts +111 -0
  15. package/dist/cache/store.d.ts.map +1 -0
  16. package/dist/cache/store.js +414 -0
  17. package/dist/cache/store.js.map +1 -0
  18. package/dist/cache/types.d.ts +69 -0
  19. package/dist/cache/types.d.ts.map +1 -0
  20. package/dist/cache/types.js +2 -0
  21. package/dist/cache/types.js.map +1 -0
  22. package/dist/cli/args.d.ts +4 -37
  23. package/dist/cli/args.d.ts.map +1 -1
  24. package/dist/cli/args.js +3 -4
  25. package/dist/cli/args.js.map +1 -1
  26. package/dist/cli/index.d.ts +0 -5
  27. package/dist/cli/index.d.ts.map +1 -1
  28. package/dist/cli/index.js +1 -6
  29. package/dist/cli/index.js.map +1 -1
  30. package/dist/cli/output.d.ts +14 -20
  31. package/dist/cli/output.d.ts.map +1 -1
  32. package/dist/cli/output.js +14 -20
  33. package/dist/cli/output.js.map +1 -1
  34. package/dist/cookies/jar.d.ts +33 -31
  35. package/dist/cookies/jar.d.ts.map +1 -1
  36. package/dist/cookies/jar.js +69 -33
  37. package/dist/cookies/jar.js.map +1 -1
  38. package/dist/cookies/parser.d.ts +14 -16
  39. package/dist/cookies/parser.d.ts.map +1 -1
  40. package/dist/cookies/parser.js +30 -13
  41. package/dist/cookies/parser.js.map +1 -1
  42. package/dist/cookies/psl-data.d.ts +1 -1
  43. package/dist/cookies/psl-data.js +1 -1
  44. package/dist/cookies/public-suffix.d.ts +5 -27
  45. package/dist/cookies/public-suffix.d.ts.map +1 -1
  46. package/dist/cookies/public-suffix.js +5 -37
  47. package/dist/cookies/public-suffix.js.map +1 -1
  48. package/dist/core/auth.d.ts +30 -0
  49. package/dist/core/auth.d.ts.map +1 -0
  50. package/dist/core/auth.js +34 -0
  51. package/dist/core/auth.js.map +1 -0
  52. package/dist/core/client.d.ts +28 -40
  53. package/dist/core/client.d.ts.map +1 -1
  54. package/dist/core/client.js +34 -41
  55. package/dist/core/client.js.map +1 -1
  56. package/dist/core/errors.d.ts +64 -88
  57. package/dist/core/errors.d.ts.map +1 -1
  58. package/dist/core/errors.js +64 -88
  59. package/dist/core/errors.js.map +1 -1
  60. package/dist/core/request.d.ts +63 -85
  61. package/dist/core/request.d.ts.map +1 -1
  62. package/dist/core/response.d.ts +64 -59
  63. package/dist/core/response.d.ts.map +1 -1
  64. package/dist/core/response.js +70 -52
  65. package/dist/core/response.js.map +1 -1
  66. package/dist/core/session.d.ts +81 -70
  67. package/dist/core/session.d.ts.map +1 -1
  68. package/dist/core/session.js +198 -71
  69. package/dist/core/session.js.map +1 -1
  70. package/dist/core/validation.d.ts +44 -42
  71. package/dist/core/validation.d.ts.map +1 -1
  72. package/dist/core/validation.js +47 -58
  73. package/dist/core/validation.js.map +1 -1
  74. package/dist/dns/cache.d.ts +59 -0
  75. package/dist/dns/cache.d.ts.map +1 -0
  76. package/dist/dns/cache.js +99 -0
  77. package/dist/dns/cache.js.map +1 -0
  78. package/dist/dns/codec.d.ts +39 -0
  79. package/dist/dns/codec.d.ts.map +1 -0
  80. package/dist/dns/codec.js +238 -0
  81. package/dist/dns/codec.js.map +1 -0
  82. package/dist/dns/doh-resolver.d.ts +38 -0
  83. package/dist/dns/doh-resolver.d.ts.map +1 -0
  84. package/dist/dns/doh-resolver.js +191 -0
  85. package/dist/dns/doh-resolver.js.map +1 -0
  86. package/dist/dns/dot-resolver.d.ts +89 -0
  87. package/dist/dns/dot-resolver.d.ts.map +1 -0
  88. package/dist/dns/dot-resolver.js +158 -0
  89. package/dist/dns/dot-resolver.js.map +1 -0
  90. package/dist/dns/https-rr.d.ts +40 -0
  91. package/dist/dns/https-rr.d.ts.map +1 -0
  92. package/dist/dns/https-rr.js +109 -0
  93. package/dist/dns/https-rr.js.map +1 -0
  94. package/dist/dns/types.d.ts +82 -0
  95. package/dist/dns/types.d.ts.map +1 -0
  96. package/dist/dns/types.js +23 -0
  97. package/dist/dns/types.js.map +1 -0
  98. package/dist/fingerprints/akamai.d.ts +3 -11
  99. package/dist/fingerprints/akamai.d.ts.map +1 -1
  100. package/dist/fingerprints/akamai.js +3 -11
  101. package/dist/fingerprints/akamai.js.map +1 -1
  102. package/dist/fingerprints/database.d.ts +6 -14
  103. package/dist/fingerprints/database.d.ts.map +1 -1
  104. package/dist/fingerprints/database.js +6 -14
  105. package/dist/fingerprints/database.js.map +1 -1
  106. package/dist/fingerprints/extensions.d.ts +56 -71
  107. package/dist/fingerprints/extensions.d.ts.map +1 -1
  108. package/dist/fingerprints/extensions.js +58 -71
  109. package/dist/fingerprints/extensions.js.map +1 -1
  110. package/dist/fingerprints/ja3.d.ts +12 -30
  111. package/dist/fingerprints/ja3.d.ts.map +1 -1
  112. package/dist/fingerprints/ja3.js +12 -30
  113. package/dist/fingerprints/ja3.js.map +1 -1
  114. package/dist/fingerprints/ja4.d.ts +18 -0
  115. package/dist/fingerprints/ja4.d.ts.map +1 -0
  116. package/dist/fingerprints/ja4.js +83 -0
  117. package/dist/fingerprints/ja4.js.map +1 -0
  118. package/dist/fingerprints/profiles/chrome.d.ts +18 -21
  119. package/dist/fingerprints/profiles/chrome.d.ts.map +1 -1
  120. package/dist/fingerprints/profiles/chrome.js +35 -31
  121. package/dist/fingerprints/profiles/chrome.js.map +1 -1
  122. package/dist/fingerprints/profiles/edge.d.ts +7 -10
  123. package/dist/fingerprints/profiles/edge.d.ts.map +1 -1
  124. package/dist/fingerprints/profiles/edge.js +7 -10
  125. package/dist/fingerprints/profiles/edge.js.map +1 -1
  126. package/dist/fingerprints/profiles/firefox.d.ts +8 -11
  127. package/dist/fingerprints/profiles/firefox.d.ts.map +1 -1
  128. package/dist/fingerprints/profiles/firefox.js +8 -11
  129. package/dist/fingerprints/profiles/firefox.js.map +1 -1
  130. package/dist/fingerprints/profiles/safari.d.ts +11 -14
  131. package/dist/fingerprints/profiles/safari.d.ts.map +1 -1
  132. package/dist/fingerprints/profiles/safari.js +11 -14
  133. package/dist/fingerprints/profiles/safari.js.map +1 -1
  134. package/dist/fingerprints/profiles/tor.d.ts +5 -8
  135. package/dist/fingerprints/profiles/tor.d.ts.map +1 -1
  136. package/dist/fingerprints/profiles/tor.js +5 -8
  137. package/dist/fingerprints/profiles/tor.js.map +1 -1
  138. package/dist/fingerprints/types.d.ts +42 -73
  139. package/dist/fingerprints/types.d.ts.map +1 -1
  140. package/dist/hsts/store.d.ts +39 -0
  141. package/dist/hsts/store.d.ts.map +1 -0
  142. package/dist/hsts/store.js +163 -0
  143. package/dist/hsts/store.js.map +1 -0
  144. package/dist/hsts/types.d.ts +24 -0
  145. package/dist/hsts/types.d.ts.map +1 -0
  146. package/dist/hsts/types.js +2 -0
  147. package/dist/hsts/types.js.map +1 -0
  148. package/dist/http/alt-svc.d.ts +67 -0
  149. package/dist/http/alt-svc.d.ts.map +1 -0
  150. package/dist/http/alt-svc.js +186 -0
  151. package/dist/http/alt-svc.js.map +1 -0
  152. package/dist/http/early-hints.d.ts +23 -0
  153. package/dist/http/early-hints.d.ts.map +1 -0
  154. package/dist/http/early-hints.js +33 -0
  155. package/dist/http/early-hints.js.map +1 -0
  156. package/dist/http/form-data.d.ts +17 -35
  157. package/dist/http/form-data.d.ts.map +1 -1
  158. package/dist/http/form-data.js +12 -34
  159. package/dist/http/form-data.js.map +1 -1
  160. package/dist/http/h1/client.d.ts +14 -26
  161. package/dist/http/h1/client.d.ts.map +1 -1
  162. package/dist/http/h1/client.js +29 -22
  163. package/dist/http/h1/client.js.map +1 -1
  164. package/dist/http/h1/encoder.d.ts +10 -17
  165. package/dist/http/h1/encoder.d.ts.map +1 -1
  166. package/dist/http/h1/encoder.js +10 -17
  167. package/dist/http/h1/encoder.js.map +1 -1
  168. package/dist/http/h1/parser.d.ts +22 -59
  169. package/dist/http/h1/parser.d.ts.map +1 -1
  170. package/dist/http/h1/parser.js +15 -47
  171. package/dist/http/h1/parser.js.map +1 -1
  172. package/dist/http/h2/client.d.ts +18 -59
  173. package/dist/http/h2/client.d.ts.map +1 -1
  174. package/dist/http/h2/client.js +29 -64
  175. package/dist/http/h2/client.js.map +1 -1
  176. package/dist/http/h2/frames.d.ts +53 -84
  177. package/dist/http/h2/frames.d.ts.map +1 -1
  178. package/dist/http/h2/frames.js +48 -76
  179. package/dist/http/h2/frames.js.map +1 -1
  180. package/dist/http/h2/hpack.d.ts +16 -35
  181. package/dist/http/h2/hpack.d.ts.map +1 -1
  182. package/dist/http/h2/hpack.js +16 -35
  183. package/dist/http/h2/hpack.js.map +1 -1
  184. package/dist/http/h3/detection.d.ts +15 -0
  185. package/dist/http/h3/detection.d.ts.map +1 -0
  186. package/dist/http/h3/detection.js +41 -0
  187. package/dist/http/h3/detection.js.map +1 -0
  188. package/dist/http/negotiator.d.ts +43 -33
  189. package/dist/http/negotiator.d.ts.map +1 -1
  190. package/dist/http/negotiator.js +99 -41
  191. package/dist/http/negotiator.js.map +1 -1
  192. package/dist/http/pool.d.ts +34 -64
  193. package/dist/http/pool.d.ts.map +1 -1
  194. package/dist/http/pool.js +22 -41
  195. package/dist/http/pool.js.map +1 -1
  196. package/dist/http/resumable-upload.d.ts +76 -0
  197. package/dist/http/resumable-upload.d.ts.map +1 -0
  198. package/dist/http/resumable-upload.js +104 -0
  199. package/dist/http/resumable-upload.js.map +1 -0
  200. package/dist/http/trailers.d.ts +29 -0
  201. package/dist/http/trailers.d.ts.map +1 -0
  202. package/dist/http/trailers.js +57 -0
  203. package/dist/http/trailers.js.map +1 -0
  204. package/dist/index.d.ts +36 -8
  205. package/dist/index.d.ts.map +1 -1
  206. package/dist/index.js +32 -1
  207. package/dist/index.js.map +1 -1
  208. package/dist/middleware/interceptor.d.ts +13 -32
  209. package/dist/middleware/interceptor.d.ts.map +1 -1
  210. package/dist/middleware/interceptor.js +11 -16
  211. package/dist/middleware/interceptor.js.map +1 -1
  212. package/dist/middleware/rate-limiter.d.ts +8 -17
  213. package/dist/middleware/rate-limiter.d.ts.map +1 -1
  214. package/dist/middleware/rate-limiter.js +15 -12
  215. package/dist/middleware/rate-limiter.js.map +1 -1
  216. package/dist/middleware/retry-after.d.ts +15 -0
  217. package/dist/middleware/retry-after.d.ts.map +1 -0
  218. package/dist/middleware/retry-after.js +36 -0
  219. package/dist/middleware/retry-after.js.map +1 -0
  220. package/dist/middleware/retry.d.ts +9 -18
  221. package/dist/middleware/retry.d.ts.map +1 -1
  222. package/dist/middleware/retry.js +12 -9
  223. package/dist/middleware/retry.js.map +1 -1
  224. package/dist/proxy/auth.d.ts +73 -0
  225. package/dist/proxy/auth.d.ts.map +1 -0
  226. package/dist/proxy/auth.js +128 -0
  227. package/dist/proxy/auth.js.map +1 -0
  228. package/dist/proxy/env-proxy.d.ts +11 -0
  229. package/dist/proxy/env-proxy.d.ts.map +1 -0
  230. package/dist/proxy/env-proxy.js +56 -0
  231. package/dist/proxy/env-proxy.js.map +1 -0
  232. package/dist/proxy/http-proxy.d.ts +13 -18
  233. package/dist/proxy/http-proxy.d.ts.map +1 -1
  234. package/dist/proxy/http-proxy.js +24 -14
  235. package/dist/proxy/http-proxy.js.map +1 -1
  236. package/dist/proxy/socks.d.ts +13 -20
  237. package/dist/proxy/socks.d.ts.map +1 -1
  238. package/dist/proxy/socks.js +6 -9
  239. package/dist/proxy/socks.js.map +1 -1
  240. package/dist/sse/parser.d.ts +47 -0
  241. package/dist/sse/parser.d.ts.map +1 -0
  242. package/dist/sse/parser.js +139 -0
  243. package/dist/sse/parser.js.map +1 -0
  244. package/dist/tls/constants.d.ts +15 -74
  245. package/dist/tls/constants.d.ts.map +1 -1
  246. package/dist/tls/constants.js +15 -74
  247. package/dist/tls/constants.js.map +1 -1
  248. package/dist/tls/ct.d.ts +78 -0
  249. package/dist/tls/ct.d.ts.map +1 -0
  250. package/dist/tls/ct.js +175 -0
  251. package/dist/tls/ct.js.map +1 -0
  252. package/dist/tls/early-data.d.ts +45 -0
  253. package/dist/tls/early-data.d.ts.map +1 -0
  254. package/dist/tls/early-data.js +46 -0
  255. package/dist/tls/early-data.js.map +1 -0
  256. package/dist/tls/ech.d.ts +130 -0
  257. package/dist/tls/ech.d.ts.map +1 -0
  258. package/dist/tls/ech.js +353 -0
  259. package/dist/tls/ech.js.map +1 -0
  260. package/dist/tls/keylog.d.ts +34 -0
  261. package/dist/tls/keylog.d.ts.map +1 -0
  262. package/dist/tls/keylog.js +64 -0
  263. package/dist/tls/keylog.js.map +1 -0
  264. package/dist/tls/node-engine.d.ts +15 -14
  265. package/dist/tls/node-engine.d.ts.map +1 -1
  266. package/dist/tls/node-engine.js +54 -14
  267. package/dist/tls/node-engine.js.map +1 -1
  268. package/dist/tls/ocsp.d.ts +55 -0
  269. package/dist/tls/ocsp.d.ts.map +1 -0
  270. package/dist/tls/ocsp.js +131 -0
  271. package/dist/tls/ocsp.js.map +1 -0
  272. package/dist/tls/pin-verification.d.ts +10 -0
  273. package/dist/tls/pin-verification.d.ts.map +1 -0
  274. package/dist/tls/pin-verification.js +28 -0
  275. package/dist/tls/pin-verification.js.map +1 -0
  276. package/dist/tls/session-cache.d.ts +58 -0
  277. package/dist/tls/session-cache.d.ts.map +1 -0
  278. package/dist/tls/session-cache.js +76 -0
  279. package/dist/tls/session-cache.js.map +1 -0
  280. package/dist/tls/stealth/client-hello.d.ts +34 -32
  281. package/dist/tls/stealth/client-hello.d.ts.map +1 -1
  282. package/dist/tls/stealth/client-hello.js +116 -11
  283. package/dist/tls/stealth/client-hello.js.map +1 -1
  284. package/dist/tls/stealth/engine.d.ts +5 -15
  285. package/dist/tls/stealth/engine.d.ts.map +1 -1
  286. package/dist/tls/stealth/engine.js +163 -47
  287. package/dist/tls/stealth/engine.js.map +1 -1
  288. package/dist/tls/stealth/handshake.d.ts +23 -32
  289. package/dist/tls/stealth/handshake.d.ts.map +1 -1
  290. package/dist/tls/stealth/handshake.js +112 -27
  291. package/dist/tls/stealth/handshake.js.map +1 -1
  292. package/dist/tls/stealth/key-schedule.d.ts +59 -86
  293. package/dist/tls/stealth/key-schedule.d.ts.map +1 -1
  294. package/dist/tls/stealth/key-schedule.js +46 -58
  295. package/dist/tls/stealth/key-schedule.js.map +1 -1
  296. package/dist/tls/stealth/record-layer.d.ts +52 -75
  297. package/dist/tls/stealth/record-layer.d.ts.map +1 -1
  298. package/dist/tls/stealth/record-layer.js +47 -63
  299. package/dist/tls/stealth/record-layer.js.map +1 -1
  300. package/dist/tls/stealth/tls12-handshake.d.ts +30 -0
  301. package/dist/tls/stealth/tls12-handshake.d.ts.map +1 -0
  302. package/dist/tls/stealth/tls12-handshake.js +470 -0
  303. package/dist/tls/stealth/tls12-handshake.js.map +1 -0
  304. package/dist/tls/types.d.ts +46 -48
  305. package/dist/tls/types.d.ts.map +1 -1
  306. package/dist/utils/buffer-reader.d.ts +26 -81
  307. package/dist/utils/buffer-reader.d.ts.map +1 -1
  308. package/dist/utils/buffer-reader.js +26 -81
  309. package/dist/utils/buffer-reader.js.map +1 -1
  310. package/dist/utils/buffer-writer.d.ts +30 -66
  311. package/dist/utils/buffer-writer.d.ts.map +1 -1
  312. package/dist/utils/buffer-writer.js +30 -66
  313. package/dist/utils/buffer-writer.js.map +1 -1
  314. package/dist/utils/compression.d.ts +18 -0
  315. package/dist/utils/compression.d.ts.map +1 -0
  316. package/dist/utils/compression.js +34 -0
  317. package/dist/utils/compression.js.map +1 -0
  318. package/dist/utils/dictionary-transport.d.ts +97 -0
  319. package/dist/utils/dictionary-transport.d.ts.map +1 -0
  320. package/dist/utils/dictionary-transport.js +171 -0
  321. package/dist/utils/dictionary-transport.js.map +1 -0
  322. package/dist/utils/encoding.d.ts +12 -28
  323. package/dist/utils/encoding.d.ts.map +1 -1
  324. package/dist/utils/encoding.js +77 -40
  325. package/dist/utils/encoding.js.map +1 -1
  326. package/dist/utils/happy-eyeballs.d.ts +20 -7
  327. package/dist/utils/happy-eyeballs.d.ts.map +1 -1
  328. package/dist/utils/happy-eyeballs.js +57 -25
  329. package/dist/utils/happy-eyeballs.js.map +1 -1
  330. package/dist/utils/logger.d.ts +54 -81
  331. package/dist/utils/logger.d.ts.map +1 -1
  332. package/dist/utils/logger.js +92 -64
  333. package/dist/utils/logger.js.map +1 -1
  334. package/dist/utils/tcp-fast-open.d.ts +30 -0
  335. package/dist/utils/tcp-fast-open.d.ts.map +1 -0
  336. package/dist/utils/tcp-fast-open.js +36 -0
  337. package/dist/utils/tcp-fast-open.js.map +1 -0
  338. package/dist/utils/url.d.ts +18 -25
  339. package/dist/utils/url.d.ts.map +1 -1
  340. package/dist/utils/url.js +18 -25
  341. package/dist/utils/url.js.map +1 -1
  342. package/dist/ws/client.d.ts +35 -52
  343. package/dist/ws/client.d.ts.map +1 -1
  344. package/dist/ws/client.js +92 -37
  345. package/dist/ws/client.js.map +1 -1
  346. package/dist/ws/frame.d.ts +27 -42
  347. package/dist/ws/frame.d.ts.map +1 -1
  348. package/dist/ws/frame.js +25 -37
  349. package/dist/ws/frame.js.map +1 -1
  350. package/dist/ws/permessage-deflate.d.ts +53 -0
  351. package/dist/ws/permessage-deflate.d.ts.map +1 -0
  352. package/dist/ws/permessage-deflate.js +140 -0
  353. package/dist/ws/permessage-deflate.js.map +1 -0
  354. package/package.json +62 -62
@@ -0,0 +1,353 @@
1
+ import { randomBytes, createHmac, createCipheriv, generateKeyPairSync, diffieHellman, createPrivateKey, createPublicKey } from "node:crypto";
2
+ /**
3
+ * Parse a serialized ECHConfigList into structured parameters.
4
+ *
5
+ * @param {Buffer} data - Raw ECHConfigList buffer.
6
+ * @returns {ECHParameters|null} Parsed parameters, or `null` if the data is invalid.
7
+ */
8
+ export function parseECHConfigList(data) {
9
+ if (data.length < 4)
10
+ return null;
11
+ const totalLength = data.readUInt16BE(0);
12
+ if (totalLength + 2 > data.length)
13
+ return null;
14
+ const configs = [];
15
+ let offset = 2;
16
+ while (offset + 4 <= 2 + totalLength) {
17
+ const version = data.readUInt16BE(offset);
18
+ offset += 2;
19
+ const configLength = data.readUInt16BE(offset);
20
+ offset += 2;
21
+ if (offset + configLength > 2 + totalLength)
22
+ break;
23
+ const contents = data.subarray(offset, offset + configLength);
24
+ const publicName = extractPublicName(contents);
25
+ configs.push({
26
+ version,
27
+ length: configLength,
28
+ contents,
29
+ publicName,
30
+ });
31
+ offset += configLength;
32
+ }
33
+ if (configs.length === 0)
34
+ return null;
35
+ const outerSNI = configs[0].publicName;
36
+ return {
37
+ echConfigList: data,
38
+ outerSNI,
39
+ configs,
40
+ };
41
+ }
42
+ function extractPublicName(contents) {
43
+ if (contents.length < 7)
44
+ return "";
45
+ let offset = 0;
46
+ offset += 1;
47
+ offset += 2;
48
+ if (offset + 2 > contents.length)
49
+ return "";
50
+ const pkLen = contents.readUInt16BE(offset);
51
+ offset += 2 + pkLen;
52
+ if (offset + 2 > contents.length)
53
+ return "";
54
+ const csLen = contents.readUInt16BE(offset);
55
+ offset += 2 + csLen;
56
+ if (offset >= contents.length)
57
+ return "";
58
+ offset += 1;
59
+ if (offset >= contents.length)
60
+ return "";
61
+ const nameLen = contents[offset];
62
+ offset += 1;
63
+ if (offset + nameLen > contents.length)
64
+ return "";
65
+ return contents.subarray(offset, offset + nameLen).toString("ascii");
66
+ }
67
+ /**
68
+ * Generate a GREASE Encrypted Client Hello extension payload.
69
+ *
70
+ * @returns {Buffer} Random GREASE ECH extension data.
71
+ */
72
+ export function generateGreaseECH() {
73
+ const payloadLen = 128 + Math.floor(Math.random() * 64);
74
+ const buf = Buffer.alloc(1 + 4 + 1 + 2 + 32 + 2 + payloadLen);
75
+ let offset = 0;
76
+ buf[offset++] = 0x00;
77
+ buf.writeUInt16BE(0x0001, offset);
78
+ offset += 2;
79
+ buf.writeUInt16BE(0x0001, offset);
80
+ offset += 2;
81
+ buf[offset++] = randomBytes(1)[0];
82
+ const enc = randomBytes(32);
83
+ buf.writeUInt16BE(32, offset);
84
+ offset += 2;
85
+ enc.copy(buf, offset);
86
+ offset += 32;
87
+ const payload = randomBytes(payloadLen);
88
+ buf.writeUInt16BE(payloadLen, offset);
89
+ offset += 2;
90
+ payload.copy(buf, offset);
91
+ return buf;
92
+ }
93
+ /**
94
+ * Parse the HPKE key configuration from ECHConfig contents.
95
+ *
96
+ * @param {Buffer} contents - Raw contents buffer of an ECHConfig entry.
97
+ * @returns {HpkeKeyConfig|null} Parsed HPKE key config, or `null` if malformed.
98
+ */
99
+ export function parseHpkeKeyConfig(contents) {
100
+ if (contents.length < 7)
101
+ return null;
102
+ let offset = 0;
103
+ const configId = contents[offset];
104
+ offset += 1;
105
+ const kemId = contents.readUInt16BE(offset);
106
+ offset += 2;
107
+ if (offset + 2 > contents.length)
108
+ return null;
109
+ const pkLen = contents.readUInt16BE(offset);
110
+ offset += 2;
111
+ if (offset + pkLen > contents.length)
112
+ return null;
113
+ const publicKey = Buffer.from(contents.subarray(offset, offset + pkLen));
114
+ offset += pkLen;
115
+ if (offset + 2 > contents.length)
116
+ return null;
117
+ const csLen = contents.readUInt16BE(offset);
118
+ offset += 2;
119
+ const cipherSuites = [];
120
+ const csEnd = offset + csLen;
121
+ while (offset + 4 <= csEnd) {
122
+ const kdfId = contents.readUInt16BE(offset);
123
+ offset += 2;
124
+ const aeadId = contents.readUInt16BE(offset);
125
+ offset += 2;
126
+ cipherSuites.push({ kdfId, aeadId });
127
+ }
128
+ return { configId, kemId, publicKey, cipherSuites };
129
+ }
130
+ /**
131
+ * Extract the maximum name length field from ECHConfig contents.
132
+ *
133
+ * @param {Buffer} contents - Raw ECHConfig contents.
134
+ * @returns {number} Maximum name length, or `0` if unparseable.
135
+ */
136
+ export function getMaxNameLength(contents) {
137
+ if (contents.length < 7)
138
+ return 0;
139
+ let offset = 0;
140
+ offset += 1;
141
+ offset += 2;
142
+ if (offset + 2 > contents.length)
143
+ return 0;
144
+ const pkLen = contents.readUInt16BE(offset);
145
+ offset += 2 + pkLen;
146
+ if (offset + 2 > contents.length)
147
+ return 0;
148
+ const csLen = contents.readUInt16BE(offset);
149
+ offset += 2 + csLen;
150
+ if (offset >= contents.length)
151
+ return 0;
152
+ return contents[offset];
153
+ }
154
+ function hpkeHkdfExtract(salt, ikm) {
155
+ const s = salt.length === 0 ? Buffer.alloc(32) : salt;
156
+ return Buffer.from(createHmac("sha256", s).update(ikm).digest());
157
+ }
158
+ function hpkeHkdfExpand(prk, info, length) {
159
+ const N = Math.ceil(length / 32);
160
+ const okm = Buffer.alloc(N * 32);
161
+ let T = Buffer.alloc(0);
162
+ for (let i = 1; i <= N; i++) {
163
+ const hmac = createHmac("sha256", prk);
164
+ hmac.update(T);
165
+ hmac.update(info);
166
+ hmac.update(Buffer.from([i]));
167
+ T = Buffer.from(hmac.digest());
168
+ T.copy(okm, (i - 1) * 32);
169
+ }
170
+ return okm.subarray(0, length);
171
+ }
172
+ function labeledExtract(suiteId, salt, label, ikm) {
173
+ const hpkeV1 = Buffer.from("HPKE-v1", "ascii");
174
+ const labelBuf = Buffer.from(label, "ascii");
175
+ const labeledIkm = Buffer.concat([hpkeV1, suiteId, labelBuf, ikm]);
176
+ return hpkeHkdfExtract(salt, labeledIkm);
177
+ }
178
+ function labeledExpand(suiteId, prk, label, info, length) {
179
+ const hpkeV1 = Buffer.from("HPKE-v1", "ascii");
180
+ const labelBuf = Buffer.from(label, "ascii");
181
+ const lenBuf = Buffer.alloc(2);
182
+ lenBuf.writeUInt16BE(length);
183
+ const labeledInfo = Buffer.concat([lenBuf, hpkeV1, suiteId, labelBuf, info]);
184
+ return hpkeHkdfExpand(prk, labeledInfo, length);
185
+ }
186
+ function buildX25519PKCS8(raw) {
187
+ return Buffer.concat([Buffer.from([0x30, 0x2e, 0x02, 0x01, 0x00, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x6e, 0x04, 0x22, 0x04, 0x20]), raw]);
188
+ }
189
+ function buildX25519SPKI(raw) {
190
+ return Buffer.concat([Buffer.from([0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x6e, 0x03, 0x21, 0x00]), raw]);
191
+ }
192
+ function dhkemX25519Encap(pkR) {
193
+ const kp = generateKeyPairSync("x25519");
194
+ const pkEDer = Buffer.from(kp.publicKey.export({ type: "spki", format: "der" }));
195
+ const skEDer = Buffer.from(kp.privateKey.export({ type: "pkcs8", format: "der" }));
196
+ const pkE = Buffer.from(pkEDer.subarray(pkEDer.length - 32));
197
+ const skE = Buffer.from(skEDer.subarray(skEDer.length - 32));
198
+ const privKey = createPrivateKey({ key: buildX25519PKCS8(skE), format: "der", type: "pkcs8" });
199
+ const pubKey = createPublicKey({ key: buildX25519SPKI(pkR), format: "der", type: "spki" });
200
+ const dh = Buffer.from(diffieHellman({ privateKey: privKey, publicKey: pubKey }));
201
+ const enc = Buffer.from(pkE);
202
+ const kemContext = Buffer.concat([enc, pkR]);
203
+ const kemSuiteId = Buffer.from([0x4b, 0x45, 0x4d, 0x00, 0x20]);
204
+ const prk = labeledExtract(kemSuiteId, Buffer.alloc(0), "shared_secret", dh);
205
+ const sharedSecret = labeledExpand(kemSuiteId, prk, "shared_secret", kemContext, 32);
206
+ return { sharedSecret, enc };
207
+ }
208
+ function aeadParams(aeadId) {
209
+ switch (aeadId) {
210
+ case 0x0001:
211
+ return { Nk: 16, Nn: 12 };
212
+ case 0x0002:
213
+ return { Nk: 32, Nn: 12 };
214
+ case 0x0003:
215
+ return { Nk: 32, Nn: 12 };
216
+ default:
217
+ throw new Error(`Unsupported HPKE AEAD: 0x${aeadId.toString(16)}`);
218
+ }
219
+ }
220
+ function aeadAlgorithm(aeadId) {
221
+ switch (aeadId) {
222
+ case 0x0001:
223
+ return "aes-128-gcm";
224
+ case 0x0002:
225
+ return "aes-256-gcm";
226
+ case 0x0003:
227
+ return "chacha20-poly1305";
228
+ default:
229
+ throw new Error(`Unsupported HPKE AEAD: 0x${aeadId.toString(16)}`);
230
+ }
231
+ }
232
+ function hpkeKeyScheduleS(kemId, kdfId, aeadId, sharedSecret, info) {
233
+ const suiteId = Buffer.alloc(10);
234
+ suiteId.write("HPKE", 0, "ascii");
235
+ suiteId.writeUInt16BE(kemId, 4);
236
+ suiteId.writeUInt16BE(kdfId, 6);
237
+ suiteId.writeUInt16BE(aeadId, 8);
238
+ const { Nk, Nn } = aeadParams(aeadId);
239
+ const pskIdHash = labeledExtract(suiteId, Buffer.alloc(0), "psk_id_hash", Buffer.alloc(0));
240
+ const infoHash = labeledExtract(suiteId, Buffer.alloc(0), "info_hash", info);
241
+ const ksContext = Buffer.concat([Buffer.from([0x00]), pskIdHash, infoHash]);
242
+ const secret = labeledExtract(suiteId, sharedSecret, "secret", Buffer.alloc(0));
243
+ const key = labeledExpand(suiteId, secret, "key", ksContext, Nk);
244
+ const baseNonce = labeledExpand(suiteId, secret, "base_nonce", ksContext, Nn);
245
+ return { key, baseNonce };
246
+ }
247
+ function hpkeSeal(key, baseNonce, aad, plaintext, aeadId) {
248
+ const alg = aeadAlgorithm(aeadId);
249
+ const cipher = createCipheriv(alg, key, baseNonce, { authTagLength: 16 });
250
+ cipher.setAAD(aad);
251
+ const encrypted = cipher.update(plaintext);
252
+ const final = cipher.final();
253
+ const tag = cipher.getAuthTag();
254
+ return Buffer.concat([encrypted, final, tag]);
255
+ }
256
+ /**
257
+ * Build the outer ECH extension data for a ClientHello.
258
+ *
259
+ * @param {number} kdfId - KDF identifier.
260
+ * @param {number} aeadId - AEAD identifier.
261
+ * @param {number} configId - ECH config ID.
262
+ * @param {Buffer} enc - HPKE encapsulated key.
263
+ * @param {Buffer} payload - Encrypted inner ClientHello payload.
264
+ * @returns {Buffer} Serialized ECH outer extension bytes.
265
+ */
266
+ export function buildECHOuterExtData(kdfId, aeadId, configId, enc, payload) {
267
+ const len = 1 + 2 + 2 + 1 + 2 + enc.length + 2 + payload.length;
268
+ const buf = Buffer.alloc(len);
269
+ let off = 0;
270
+ buf[off++] = 0x00;
271
+ buf.writeUInt16BE(kdfId, off);
272
+ off += 2;
273
+ buf.writeUInt16BE(aeadId, off);
274
+ off += 2;
275
+ buf[off++] = configId;
276
+ buf.writeUInt16BE(enc.length, off);
277
+ off += 2;
278
+ enc.copy(buf, off);
279
+ off += enc.length;
280
+ buf.writeUInt16BE(payload.length, off);
281
+ off += 2;
282
+ payload.copy(buf, off);
283
+ return buf;
284
+ }
285
+ /**
286
+ * Extract the first raw ECHConfig entry from a serialized ECHConfigList.
287
+ *
288
+ * @param {Buffer} echConfigList - Full serialized ECHConfigList buffer.
289
+ * @returns {Buffer | null} Raw config bytes, or `null` if the list is too short.
290
+ */
291
+ export function extractFirstECHConfigRaw(echConfigList) {
292
+ if (echConfigList.length < 6)
293
+ return null;
294
+ const totalLength = echConfigList.readUInt16BE(0);
295
+ if (totalLength + 2 > echConfigList.length)
296
+ return null;
297
+ const _version = echConfigList.readUInt16BE(2);
298
+ const configLength = echConfigList.readUInt16BE(4);
299
+ if (6 + configLength > echConfigList.length)
300
+ return null;
301
+ return Buffer.from(echConfigList.subarray(2, 6 + configLength));
302
+ }
303
+ /**
304
+ * Encrypt an inner ClientHello body using HPKE for Encrypted Client Hello.
305
+ *
306
+ * @param {Buffer} innerCHBody - Serialized inner ClientHello body.
307
+ * @param {Buffer} outerCHAAD - Additional authenticated data from the outer ClientHello.
308
+ * @param {ECHConfig} config - Parsed ECH configuration entry.
309
+ * @param {Buffer} configRaw - Raw bytes of the ECH configuration.
310
+ * @returns {{ extensionData: Buffer; enc: Buffer; kdfId: number; aeadId: number; configId: number }} Extension data, encapsulated key, and algorithm identifiers.
311
+ */
312
+ export function echEncryptInner(innerCHBody, outerCHAAD, config, configRaw) {
313
+ const hpkeConfig = parseHpkeKeyConfig(config.contents);
314
+ if (!hpkeConfig)
315
+ throw new Error("Invalid ECHConfig: cannot parse HPKE key config");
316
+ if (hpkeConfig.kemId !== 0x0020) {
317
+ throw new Error(`Unsupported KEM: 0x${hpkeConfig.kemId.toString(16)} (only DHKEM(X25519, HKDF-SHA256) = 0x0020)`);
318
+ }
319
+ const suite = hpkeConfig.cipherSuites.find((cs) => cs.kdfId === 0x0001 && (cs.aeadId === 0x0001 || cs.aeadId === 0x0003));
320
+ if (!suite)
321
+ throw new Error("No supported HPKE cipher suite in ECHConfig");
322
+ const hpkeInfo = Buffer.concat([Buffer.from("tls ech\x00", "ascii"), configRaw]);
323
+ const { sharedSecret, enc } = dhkemX25519Encap(hpkeConfig.publicKey);
324
+ const { key, baseNonce } = hpkeKeyScheduleS(hpkeConfig.kemId, suite.kdfId, suite.aeadId, sharedSecret, hpkeInfo);
325
+ const payload = hpkeSeal(key, baseNonce, outerCHAAD, innerCHBody, suite.aeadId);
326
+ const extensionData = buildECHOuterExtData(suite.kdfId, suite.aeadId, hpkeConfig.configId, enc, payload);
327
+ return { extensionData, enc, kdfId: suite.kdfId, aeadId: suite.aeadId, configId: hpkeConfig.configId };
328
+ }
329
+ /**
330
+ * Parse ECH retry configuration from a server's EncryptedExtensions.
331
+ *
332
+ * @param {Buffer} data - Serialized ECHConfigList from the retry_configs extension.
333
+ * @returns {ECHParameters | null} Parsed retry parameters, or `null` if invalid.
334
+ */
335
+ export function parseECHRetryConfigs(data) {
336
+ return parseECHConfigList(data);
337
+ }
338
+ /**
339
+ * Determine whether an ECH retry should be attempted.
340
+ *
341
+ * @param {number} retryCount - Number of retries already attempted.
342
+ * @param {number} maxRetries - Maximum allowed retries.
343
+ * @param {ECHParameters | null} retryConfigs - Retry ECH configs from the server.
344
+ * @returns {boolean} `true` if another retry is warranted.
345
+ */
346
+ export function shouldRetryECH(retryCount, maxRetries, retryConfigs) {
347
+ if (retryCount >= maxRetries)
348
+ return false;
349
+ if (!retryConfigs || retryConfigs.configs.length === 0)
350
+ return false;
351
+ return true;
352
+ }
353
+ //# sourceMappingURL=ech.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ech.js","sourceRoot":"","sources":["../../src/tls/ech.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Return the SSLKEYLOGFILE path from the environment or explicit override.
3
+ *
4
+ * @returns {string|undefined} File path string, or `undefined` if not configured.
5
+ */
6
+ export declare function getKeylogFile(): string | undefined;
7
+ /**
8
+ * Append a single NSS key-log line to the SSLKEYLOGFILE.
9
+ *
10
+ * @param {string} line - Key-log line without trailing newline.
11
+ */
12
+ export declare function writeKeylogLine(line: string): void;
13
+ /**
14
+ * Log a TLS master secret in NSS key-log format.
15
+ *
16
+ * @param {Buffer} clientRandom - 32-byte client random from the handshake.
17
+ * @param {Buffer} masterSecret - Derived master secret.
18
+ */
19
+ export declare function logMasterSecret(clientRandom: Buffer, masterSecret: Buffer): void;
20
+ /**
21
+ * Log a TLS 1.3 traffic secret in NSS key-log format.
22
+ *
23
+ * @param {string} label - Secret label (e.g. `"CLIENT_HANDSHAKE_TRAFFIC_SECRET"`).
24
+ * @param {Buffer} clientRandom - 32-byte client random.
25
+ * @param {Buffer} secret - Derived traffic secret.
26
+ */
27
+ export declare function logTrafficSecret(label: string, clientRandom: Buffer, secret: Buffer): void;
28
+ /**
29
+ * Explicitly set or clear the SSLKEYLOGFILE path.
30
+ *
31
+ * @param {string|undefined} path - File path, or `undefined` to disable key logging.
32
+ */
33
+ export declare function setKeylogFile(path: string | undefined): void;
34
+ //# sourceMappingURL=keylog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keylog.d.ts","sourceRoot":"","sources":["../../src/tls/keylog.ts"],"names":[],"mappings":"AAOA;;;;GAIG;AACH,wBAAgB,aAAa,IAAI,MAAM,GAAG,SAAS,CAMlD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAWlD;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAEhF;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAE1F;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAG5D"}
@@ -0,0 +1,64 @@
1
+ import { appendFileSync, existsSync } from "node:fs";
2
+ import { dirname } from "node:path";
3
+ import { mkdirSync } from "node:fs";
4
+ let _keylogFile;
5
+ let _initialized = false;
6
+ /**
7
+ * Return the SSLKEYLOGFILE path from the environment or explicit override.
8
+ *
9
+ * @returns {string|undefined} File path string, or `undefined` if not configured.
10
+ */
11
+ export function getKeylogFile() {
12
+ if (!_initialized) {
13
+ _initialized = true;
14
+ _keylogFile = process.env["SSLKEYLOGFILE"];
15
+ }
16
+ return _keylogFile;
17
+ }
18
+ /**
19
+ * Append a single NSS key-log line to the SSLKEYLOGFILE.
20
+ *
21
+ * @param {string} line - Key-log line without trailing newline.
22
+ */
23
+ export function writeKeylogLine(line) {
24
+ const file = getKeylogFile();
25
+ if (!file)
26
+ return;
27
+ try {
28
+ const dir = dirname(file);
29
+ if (!existsSync(dir)) {
30
+ mkdirSync(dir, { recursive: true });
31
+ }
32
+ appendFileSync(file, line + "\n", { encoding: "utf-8" });
33
+ }
34
+ catch { }
35
+ }
36
+ /**
37
+ * Log a TLS master secret in NSS key-log format.
38
+ *
39
+ * @param {Buffer} clientRandom - 32-byte client random from the handshake.
40
+ * @param {Buffer} masterSecret - Derived master secret.
41
+ */
42
+ export function logMasterSecret(clientRandom, masterSecret) {
43
+ writeKeylogLine(`CLIENT_RANDOM ${clientRandom.toString("hex")} ${masterSecret.toString("hex")}`);
44
+ }
45
+ /**
46
+ * Log a TLS 1.3 traffic secret in NSS key-log format.
47
+ *
48
+ * @param {string} label - Secret label (e.g. `"CLIENT_HANDSHAKE_TRAFFIC_SECRET"`).
49
+ * @param {Buffer} clientRandom - 32-byte client random.
50
+ * @param {Buffer} secret - Derived traffic secret.
51
+ */
52
+ export function logTrafficSecret(label, clientRandom, secret) {
53
+ writeKeylogLine(`${label} ${clientRandom.toString("hex")} ${secret.toString("hex")}`);
54
+ }
55
+ /**
56
+ * Explicitly set or clear the SSLKEYLOGFILE path.
57
+ *
58
+ * @param {string|undefined} path - File path, or `undefined` to disable key logging.
59
+ */
60
+ export function setKeylogFile(path) {
61
+ _keylogFile = path;
62
+ _initialized = true;
63
+ }
64
+ //# sourceMappingURL=keylog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keylog.js","sourceRoot":"","sources":["../../src/tls/keylog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEpC,IAAI,WAA+B,CAAC;AACpC,IAAI,YAAY,GAAG,KAAK,CAAC;AAEzB;;;;GAIG;AACH,MAAM,UAAU,aAAa;IAC3B,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,YAAY,GAAG,IAAI,CAAC;QACpB,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAC7C,CAAC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,MAAM,IAAI,GAAG,aAAa,EAAE,CAAC;IAC7B,IAAI,CAAC,IAAI;QAAE,OAAO;IAElB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAC1B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACrB,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACtC,CAAC;QACD,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;IAC3D,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;AACZ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,YAAoB,EAAE,YAAoB;IACxE,eAAe,CAAC,iBAAiB,YAAY,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,YAAY,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AACnG,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAa,EAAE,YAAoB,EAAE,MAAc;IAClF,eAAe,CAAC,GAAG,KAAK,IAAI,YAAY,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AACxF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,IAAwB;IACpD,WAAW,GAAG,IAAI,CAAC;IACnB,YAAY,GAAG,IAAI,CAAC;AACtB,CAAC"}
@@ -1,22 +1,23 @@
1
1
  import type { ITLSEngine, TLSConnectOptions, TLSSocket } from "./types.js";
2
2
  import type { BrowserProfile } from "../fingerprints/types.js";
3
- /**
4
- * TLS engine that delegates to Node.js’s built-in `tls` module. Provides
5
- * standard TLS connectivity with optional browser-profile cipher and curve
6
- * configuration, but does not reproduce the exact ClientHello byte sequence
7
- * of a real browser. Use {@link StealthTLSEngine} when full fingerprint
8
- * fidelity is required.
9
- */
3
+ import { TLSSessionCache } from "./session-cache.js";
4
+ /** TLS engine backed by Node.js native `tls` module. */
10
5
  export declare class NodeTLSEngine implements ITLSEngine {
6
+ private readonly sessionCache;
11
7
  /**
12
- * Establishes a TLS connection to the given host and port using Node.js’s
13
- * native `tls.connect()`. When a `profile` is supplied the cipher list,
14
- * ECDH curves, and signature algorithms are overridden to match that profile.
8
+ * Create a Node.js TLS engine.
15
9
  *
16
- * @param {TLSConnectOptions} options - Connection parameters.
17
- * @param {BrowserProfile} [profile] - Optional browser profile to apply cipher/curve overrides.
18
- * @returns {Promise<TLSSocket>} Resolves with the connected TLS duplex stream.
19
- * @throws {TLSError} If the handshake fails, times out, or the connection is aborted.
10
+ * @param {TLSSessionCache} [sessionCache] - Optional session ticket cache for resumption.
11
+ */
12
+ constructor(sessionCache?: TLSSessionCache);
13
+ /** Return the session ticket cache used by this engine. */
14
+ getSessionCache(): TLSSessionCache;
15
+ /**
16
+ * Connect to a remote host over TLS using Node.js built-in facilities.
17
+ *
18
+ * @param {TLSConnectOptions} options - TLS connection options.
19
+ * @param {BrowserProfile} [profile] - Optional browser profile for cipher and curve ordering.
20
+ * @returns {Promise<TLSSocket>} Connected TLS socket.
20
21
  */
21
22
  connect(options: TLSConnectOptions, profile?: BrowserProfile): Promise<TLSSocket>;
22
23
  }
@@ -1 +1 @@
1
- {"version":3,"file":"node-engine.d.ts","sourceRoot":"","sources":["../../src/tls/node-engine.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAqB,SAAS,EAAE,MAAM,YAAY,CAAC;AAC9F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAmF/D;;;;;;GAMG;AACH,qBAAa,aAAc,YAAW,UAAU;IAC9C;;;;;;;;;OASG;IACG,OAAO,CAAC,OAAO,EAAE,iBAAiB,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,SAAS,CAAC;CAiHxF"}
1
+ {"version":3,"file":"node-engine.d.ts","sourceRoot":"","sources":["../../src/tls/node-engine.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAqB,SAAS,EAAE,MAAM,YAAY,CAAC;AAC9F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAG/D,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAmFrD,wDAAwD;AACxD,qBAAa,aAAc,YAAW,UAAU;IAC9C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAkB;IAE/C;;;;OAIG;gBACS,YAAY,CAAC,EAAE,eAAe;IAI1C,2DAA2D;IAC3D,eAAe,IAAI,eAAe;IAIlC;;;;;;OAMG;IACG,OAAO,CAAC,OAAO,EAAE,iBAAiB,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,SAAS,CAAC;CAuJxF"}
@@ -1,6 +1,9 @@
1
1
  import * as tls from "node:tls";
2
2
  import { CipherSuite, NamedGroup, SignatureScheme } from "./constants.js";
3
3
  import { TLSError } from "../core/errors.js";
4
+ import { TLSSessionCache } from "./session-cache.js";
5
+ import { verifyPinnedPublicKey } from "./pin-verification.js";
6
+ import { getKeylogFile, writeKeylogLine } from "./keylog.js";
4
7
  const CIPHER_NAME = new Map([
5
8
  [CipherSuite.TLS_AES_128_GCM_SHA256, "TLS_AES_128_GCM_SHA256"],
6
9
  [CipherSuite.TLS_AES_256_GCM_SHA384, "TLS_AES_256_GCM_SHA384"],
@@ -76,23 +79,27 @@ function buildSigalgs(algs) {
76
79
  .filter((n) => n !== undefined)
77
80
  .join(":");
78
81
  }
79
- /**
80
- * TLS engine that delegates to Node.js’s built-in `tls` module. Provides
81
- * standard TLS connectivity with optional browser-profile cipher and curve
82
- * configuration, but does not reproduce the exact ClientHello byte sequence
83
- * of a real browser. Use {@link StealthTLSEngine} when full fingerprint
84
- * fidelity is required.
85
- */
82
+ /** TLS engine backed by Node.js native `tls` module. */
86
83
  export class NodeTLSEngine {
84
+ sessionCache;
87
85
  /**
88
- * Establishes a TLS connection to the given host and port using Node.js’s
89
- * native `tls.connect()`. When a `profile` is supplied the cipher list,
90
- * ECDH curves, and signature algorithms are overridden to match that profile.
86
+ * Create a Node.js TLS engine.
91
87
  *
92
- * @param {TLSConnectOptions} options - Connection parameters.
93
- * @param {BrowserProfile} [profile] - Optional browser profile to apply cipher/curve overrides.
94
- * @returns {Promise<TLSSocket>} Resolves with the connected TLS duplex stream.
95
- * @throws {TLSError} If the handshake fails, times out, or the connection is aborted.
88
+ * @param {TLSSessionCache} [sessionCache] - Optional session ticket cache for resumption.
89
+ */
90
+ constructor(sessionCache) {
91
+ this.sessionCache = sessionCache ?? new TLSSessionCache();
92
+ }
93
+ /** Return the session ticket cache used by this engine. */
94
+ getSessionCache() {
95
+ return this.sessionCache;
96
+ }
97
+ /**
98
+ * Connect to a remote host over TLS using Node.js built-in facilities.
99
+ *
100
+ * @param {TLSConnectOptions} options - TLS connection options.
101
+ * @param {BrowserProfile} [profile] - Optional browser profile for cipher and curve ordering.
102
+ * @returns {Promise<TLSSocket>} Connected TLS socket.
96
103
  */
97
104
  async connect(options, profile) {
98
105
  return new Promise((resolve, reject) => {
@@ -123,6 +130,9 @@ export class NodeTLSEngine {
123
130
  if (options.ca) {
124
131
  tlsOpts.ca = options.ca;
125
132
  }
133
+ if (options.echConfigList) {
134
+ tlsOpts["encryptedClientHello"] = options.echConfigList;
135
+ }
126
136
  if (profile) {
127
137
  const { ciphers, ciphersuites } = buildCipherString(profile.tls.cipherSuites);
128
138
  tlsOpts.ciphers = ciphers;
@@ -134,8 +144,21 @@ export class NodeTLSEngine {
134
144
  if (options.socket) {
135
145
  tlsOpts.socket = options.socket;
136
146
  }
147
+ if (getKeylogFile()) {
148
+ tlsOpts["enableTrace"] = false;
149
+ }
150
+ const origin = `${options.servername ?? options.host}:${options.port}`;
151
+ const cached = this.sessionCache.get(origin);
152
+ if (cached) {
153
+ tlsOpts.session = cached.ticket;
154
+ }
137
155
  const timeoutMs = options.timeout ?? 30_000;
138
156
  const socket = tls.connect(tlsOpts);
157
+ if (getKeylogFile()) {
158
+ socket.on("keylog", (line) => {
159
+ writeKeylogLine(line.toString("ascii").trimEnd());
160
+ });
161
+ }
139
162
  let settled = false;
140
163
  let timer;
141
164
  if (timeoutMs > 0) {
@@ -169,13 +192,30 @@ export class NodeTLSEngine {
169
192
  settled = true;
170
193
  if (timer)
171
194
  clearTimeout(timer);
195
+ if (options.pinnedPublicKey) {
196
+ try {
197
+ const peerCert = socket.getPeerCertificate(true);
198
+ if (peerCert && peerCert.raw) {
199
+ verifyPinnedPublicKey(peerCert.raw, options.pinnedPublicKey);
200
+ }
201
+ }
202
+ catch (err) {
203
+ socket.destroy();
204
+ reject(err instanceof Error ? err : new TLSError(String(err)));
205
+ return;
206
+ }
207
+ }
172
208
  const cipher = socket.getCipher();
173
209
  const proto = socket.getProtocol();
174
210
  const connectionInfo = {
175
211
  version: proto ?? "unknown",
176
212
  alpnProtocol: socket.alpnProtocol || null,
177
213
  cipher: cipher?.name ?? "unknown",
214
+ resumed: socket.isSessionReused(),
178
215
  };
216
+ socket.on("session", (session) => {
217
+ this.sessionCache.set(origin, session, undefined, socket.alpnProtocol || undefined);
218
+ });
179
219
  const tlsSocket = Object.assign(socket, {
180
220
  connectionInfo,
181
221
  destroyTLS() {