@browsercore/testing 0.1.2 → 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 -0
- package/captures/DIVERGENCE_REPORT.md +325 -0
- package/captures/IMPERSIONATION_GAPS_REPORT.md +367 -0
- package/captures/README.md +56 -0
- package/captures/REVIEW_FINDINGS.md +71 -0
- package/captures/_probe/analyze.py +67 -0
- package/captures/_probe/capture_bytes.py +127 -0
- package/captures/_probe/chrome131_determinism.py +32 -0
- package/captures/_probe/diagnose_capture.py +59 -0
- package/captures/_probe/golden_analysis.py +91 -0
- package/captures/_probe/inspect_golden.py +55 -0
- package/captures/_probe/inspect_sv.py +16 -0
- package/captures/_probe/make_golden.py +170 -0
- package/captures/_probe/output/chrome100.json +219 -0
- package/captures/_probe/output/chrome101.json +219 -0
- package/captures/_probe/output/chrome104.json +219 -0
- package/captures/_probe/output/chrome107.json +220 -0
- package/captures/_probe/output/chrome110.json +220 -0
- package/captures/_probe/output/chrome116.json +220 -0
- package/captures/_probe/output/chrome119.json +219 -0
- package/captures/_probe/output/chrome120.json +219 -0
- package/captures/_probe/output/chrome123.json +223 -0
- package/captures/_probe/output/chrome124.json +224 -0
- package/captures/_probe/output/chrome131.json +224 -0
- package/captures/_probe/output/chrome131_fresh.json +224 -0
- package/captures/_probe/output/chrome133a.json +224 -0
- package/captures/_probe/output/chrome136.json +224 -0
- package/captures/_probe/output/chrome99.json +219 -0
- package/captures/_probe/output/edge101.json +219 -0
- package/captures/_probe/output/edge99.json +219 -0
- package/captures/_probe/output/firefox133.json +227 -0
- package/captures/_probe/output/firefox135.json +230 -0
- package/captures/_probe/output/safari155.json +210 -0
- package/captures/_probe/output/safari170.json +214 -0
- package/captures/_probe/output/safari170_fresh.json +214 -0
- package/captures/_probe/output/safari180.json +216 -0
- package/captures/_probe/output/safari180_ios.json +216 -0
- package/captures/_probe/output/safari184.json +215 -0
- package/captures/_probe/output/safari260.json +211 -0
- package/captures/_probe/output/summary.json +2520 -0
- package/captures/_probe/parse_existing_settings.py +15 -0
- package/captures/_probe/peetprint.py +39 -0
- package/captures/_probe/probe.py +137 -0
- package/captures/_probe/raw_bytes/chrome-131_client_hello.bin +0 -0
- package/captures/_probe/raw_bytes/chrome-131_client_hello.hex +32 -0
- package/captures/_probe/raw_bytes/firefox-133_client_hello.bin +0 -0
- package/captures/_probe/raw_bytes/firefox-133_client_hello.hex +32 -0
- package/captures/_probe/raw_bytes/safari-17_client_hello.bin +0 -0
- package/captures/_probe/raw_bytes/safari-17_client_hello.hex +32 -0
- package/captures/_probe/relay_capture.py +137 -0
- package/captures/_probe/socks_capture.py +138 -0
- package/captures/_probe/validate_fresh.py +66 -0
- package/captures/_probe/validate_golden.py +97 -0
- package/captures/_probe/verify_capture.py +68 -0
- package/captures/chrome-131/http2/settings.bin +0 -0
- package/captures/chrome-131/http2/settings.meta.json +9 -0
- package/captures/chrome-131/oracle_capture.reference.json +224 -0
- package/captures/chrome-131/tls/client_hello.bin +0 -0
- package/captures/chrome-131/tls/client_hello.meta.json +20 -0
- package/captures/chrome-140/http2/settings.bin +0 -0
- package/captures/chrome-140/http2/settings.meta.json +9 -0
- package/captures/chrome-140/tls/client_hello.bin +0 -0
- package/captures/chrome-140/tls/client_hello.meta.json +12 -0
- package/captures/firefox-128/tls/client_hello.bin +0 -0
- package/captures/firefox-128/tls/client_hello.meta.json +12 -0
- package/captures/firefox-133/http2/settings.bin +0 -0
- package/captures/firefox-133/http2/settings.meta.json +9 -0
- package/captures/firefox-133/oracle_capture.reference.json +227 -0
- package/captures/firefox-133/tls/client_hello.bin +0 -0
- package/captures/firefox-133/tls/client_hello.meta.json +20 -0
- package/captures/safari-17/http2/settings.bin +0 -0
- package/captures/safari-17/http2/settings.meta.json +9 -0
- package/captures/safari-17/oracle_capture.reference.json +214 -0
- package/captures/safari-17/tls/client_hello.bin +0 -0
- package/captures/safari-17/tls/client_hello.meta.json +20 -0
- package/dist/bench/bench.d.ts +22 -6
- package/dist/bench/bench.d.ts.map +1 -1
- package/dist/bench/bench.js +105 -10
- package/dist/bench/bench.js.map +1 -1
- package/dist/captures/manifest.d.ts.map +1 -1
- package/dist/captures/manifest.js +2 -3
- package/dist/captures/manifest.js.map +1 -1
- package/dist/categories/compression.d.ts +5 -2
- package/dist/categories/compression.d.ts.map +1 -1
- package/dist/categories/compression.js +54 -6
- package/dist/categories/compression.js.map +1 -1
- package/dist/categories/cookies.d.ts +3 -2
- package/dist/categories/cookies.d.ts.map +1 -1
- package/dist/categories/cookies.js +228 -11
- package/dist/categories/cookies.js.map +1 -1
- package/dist/categories/redirects.d.ts +8 -2
- package/dist/categories/redirects.d.ts.map +1 -1
- package/dist/categories/redirects.js +97 -12
- package/dist/categories/redirects.js.map +1 -1
- package/dist/e2e/cert-gen.d.ts +30 -0
- package/dist/e2e/cert-gen.d.ts.map +1 -0
- package/dist/e2e/cert-gen.js +158 -0
- package/dist/e2e/cert-gen.js.map +1 -0
- package/dist/e2e/parse-clienthello.d.ts +177 -0
- package/dist/e2e/parse-clienthello.d.ts.map +1 -0
- package/dist/e2e/parse-clienthello.js +343 -0
- package/dist/e2e/parse-clienthello.js.map +1 -0
- package/dist/e2e/sink-server.d.ts +109 -0
- package/dist/e2e/sink-server.d.ts.map +1 -0
- package/dist/e2e/sink-server.js +292 -0
- package/dist/e2e/sink-server.js.map +1 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/fingerprint/index.d.ts +5 -2
- package/dist/fingerprint/index.d.ts.map +1 -1
- package/dist/fingerprint/index.js +3 -2
- package/dist/fingerprint/index.js.map +1 -1
- package/dist/fingerprint/ja3.d.ts.map +1 -1
- package/dist/fingerprint/ja3.js +33 -4
- package/dist/fingerprint/ja3.js.map +1 -1
- package/dist/fingerprint/ja4-errors.d.ts +17 -0
- package/dist/fingerprint/ja4-errors.d.ts.map +1 -0
- package/dist/fingerprint/ja4-errors.js +20 -0
- package/dist/fingerprint/ja4-errors.js.map +1 -0
- package/dist/fingerprint/ja4-reader.d.ts +44 -0
- package/dist/fingerprint/ja4-reader.d.ts.map +1 -0
- package/dist/fingerprint/ja4-reader.js +112 -0
- package/dist/fingerprint/ja4-reader.js.map +1 -0
- package/dist/fingerprint/ja4.d.ts +11 -43
- package/dist/fingerprint/ja4.d.ts.map +1 -1
- package/dist/fingerprint/ja4.js +54 -141
- package/dist/fingerprint/ja4.js.map +1 -1
- package/dist/fingerprint/ja4h.d.ts +46 -0
- package/dist/fingerprint/ja4h.d.ts.map +1 -0
- package/dist/fingerprint/ja4h.js +50 -0
- package/dist/fingerprint/ja4h.js.map +1 -0
- package/dist/golden/golden.d.ts +15 -1
- package/dist/golden/golden.d.ts.map +1 -1
- package/dist/golden/golden.js +35 -22
- package/dist/golden/golden.js.map +1 -1
- package/dist/index.d.ts +17 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +26 -1
- package/dist/index.js.map +1 -1
- package/dist/reference/browser-provider.d.ts +33 -0
- package/dist/reference/browser-provider.d.ts.map +1 -0
- package/dist/reference/browser-provider.js +60 -0
- package/dist/reference/browser-provider.js.map +1 -0
- package/dist/reference/curl-provider.d.ts +40 -0
- package/dist/reference/curl-provider.d.ts.map +1 -0
- package/dist/reference/curl-provider.js +96 -0
- package/dist/reference/curl-provider.js.map +1 -0
- package/dist/reference/dump.d.ts +42 -0
- package/dist/reference/dump.d.ts.map +1 -0
- package/dist/reference/dump.js +102 -0
- package/dist/reference/dump.js.map +1 -0
- package/dist/reference/node-reference.d.ts.map +1 -1
- package/dist/reference/node-reference.js +2 -5
- package/dist/reference/node-reference.js.map +1 -1
- package/dist/reference/reference-errors.d.ts +36 -0
- package/dist/reference/reference-errors.d.ts.map +1 -0
- package/dist/reference/reference-errors.js +43 -0
- package/dist/reference/reference-errors.js.map +1 -0
- package/dist/reference/reference-types.d.ts +33 -0
- package/dist/reference/reference-types.d.ts.map +1 -0
- package/dist/reference/reference-types.js +9 -0
- package/dist/reference/reference-types.js.map +1 -0
- package/dist/reference/reference.d.ts +14 -77
- package/dist/reference/reference.d.ts.map +1 -1
- package/dist/reference/reference.js +43 -207
- package/dist/reference/reference.js.map +1 -1
- package/dist/rfc/rfcTests.d.ts +46 -8
- package/dist/rfc/rfcTests.d.ts.map +1 -1
- package/dist/rfc/rfcTests.js +203 -16
- package/dist/rfc/rfcTests.js.map +1 -1
- package/dist/types.d.ts +2 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils.d.ts +3 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +11 -5
- package/dist/utils.js.map +1 -1
- package/package.json +61 -50
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
{
|
|
2
|
+
"donate": "Please consider donating to keep this API running. Visit https://tls.peet.ws",
|
|
3
|
+
"ip": "92.218.110.236:59822",
|
|
4
|
+
"http_version": "h2",
|
|
5
|
+
"method": "GET",
|
|
6
|
+
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:133.0) Gecko/20100101 Firefox/133.0",
|
|
7
|
+
"tls": {
|
|
8
|
+
"ciphers": [
|
|
9
|
+
"TLS_AES_128_GCM_SHA256",
|
|
10
|
+
"TLS_CHACHA20_POLY1305_SHA256",
|
|
11
|
+
"TLS_AES_256_GCM_SHA384",
|
|
12
|
+
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
|
13
|
+
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
|
14
|
+
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
|
|
15
|
+
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
|
|
16
|
+
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
|
|
17
|
+
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
|
|
18
|
+
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
|
|
19
|
+
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
|
|
20
|
+
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
|
|
21
|
+
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
|
|
22
|
+
"TLS_RSA_WITH_AES_128_GCM_SHA256",
|
|
23
|
+
"TLS_RSA_WITH_AES_256_GCM_SHA384",
|
|
24
|
+
"TLS_RSA_WITH_AES_128_CBC_SHA",
|
|
25
|
+
"TLS_RSA_WITH_AES_256_CBC_SHA"
|
|
26
|
+
],
|
|
27
|
+
"extensions": [
|
|
28
|
+
{
|
|
29
|
+
"name": "server_name (0)",
|
|
30
|
+
"server_name": "tls.peet.ws"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"name": "extended_master_secret (23)",
|
|
34
|
+
"master_secret_data": "",
|
|
35
|
+
"extended_master_secret_data": ""
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"name": "extensionRenegotiationInfo (boringssl) (65281)",
|
|
39
|
+
"data": "00"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"name": "supported_groups (10)",
|
|
43
|
+
"supported_groups": [
|
|
44
|
+
"X25519MLKEM768 (4588)",
|
|
45
|
+
"X25519 (29)",
|
|
46
|
+
"P-256 (23)",
|
|
47
|
+
"P-384 (24)",
|
|
48
|
+
"P-521 (25)",
|
|
49
|
+
"ffdhe2048 (256)",
|
|
50
|
+
"ffdhe3072 (257)"
|
|
51
|
+
]
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"name": "ec_point_formats (11)",
|
|
55
|
+
"elliptic_curves_point_formats": [
|
|
56
|
+
"0x00"
|
|
57
|
+
]
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"name": "session_ticket (35)",
|
|
61
|
+
"data": ""
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"name": "application_layer_protocol_negotiation (16)",
|
|
65
|
+
"protocols": [
|
|
66
|
+
"h2",
|
|
67
|
+
"http/1.1"
|
|
68
|
+
]
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"name": "status_request (5)",
|
|
72
|
+
"status_request": {
|
|
73
|
+
"certificate_status_type": "OSCP (1)",
|
|
74
|
+
"responder_id_list_length": 0,
|
|
75
|
+
"request_extensions_length": 0
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"name": "delegated_credentials (34)",
|
|
80
|
+
"signature_hash_algorithms": [
|
|
81
|
+
"ecdsa_secp256r1_sha256",
|
|
82
|
+
"ecdsa_secp384r1_sha384",
|
|
83
|
+
"ecdsa_secp521r1_sha512",
|
|
84
|
+
"ecdsa_sha1"
|
|
85
|
+
]
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"name": "key_share (51)",
|
|
89
|
+
"shared_keys": [
|
|
90
|
+
{
|
|
91
|
+
"X25519MLKEM768 (4588)": "0bfbcfdd99b65a5abdfc8324e1302227179ff629af1e21302ea377d6618c6c0b9adc06b6252a062749869cb706dcba8f5ef71bbb208285254a1935496570932cb13900e2252237aa2ed2ca060a2cd10b3cc5aac305ab8c1527c0e9ac217af317e314c404a770d936a9f1426a207acf217710966127f0e55f7344aa7c6a7ed4e128d6dabc567cc7a2ec8a825748244bc39d78717c25ce76c52a88bb392fd85e2fc35f4fbba6d9f5185922584009b70fdbbcfe89814f2063adc99ee4aaaf145b27ca2c7f0d341d40318d729c29db839a8a6a0c788c0f69586243284aafb8be9a816b02d845393987887bb74778168fe5c0b3500c9cd0619f025027e390b4c7b525c79e644a84354bc959768ca39788e355b9a7889a72b00b98b2888de59cf825afdaf6383f8362b74abba1a2b6d3219198d91df583ba48d381fe0004fdd5c6b7a037d64786ee7227d4a47e4c746738332fb6350a5dd9312fc38f309012f5e7870c1c5f53e39b0a609d86333700c510850898ed6c3e34053de620655e07349b515c67b234dc7860bd25b674613e8c755a83da5bc4602681eb7b7a653a54176ba48a6034080598c4602f806b2537b864e60402507d429c84de98009fc692ef5742dbc750a9fb4724994b04f80beed89ceef365b8652affa6c550da700ec11c620495e66435182c0c2adb2f22988193b68072b2c6b088466eba39796659cb19a037f515704a2338c574ca863b81db5696fa0cdd87282f1b9b7cabca1e1b3719c3a51d93beeda563e71c313b5ba3eab60716b4180ff72b5d768e1ef11a30b3b16ce7a0c3e96a9a2acc3d5707ec2a21f34b6866e0a27bc67ec326cb30d46e5a5426d8988126d86281a188e84ac9388cc700114497e213248459fcf09243e86992a08221abcf12aa4d5513495c5c444e1440db8cb0721289b461385197662200833894a999e286285c46fe06293d8bbdcf880612628d5c876d20f389070ac5bea7c451c79a47d7a0d7f89bb3411b3d3283e94a4053677073342d38c7927a760a33a00a8926ae0fbc0503052c935359f7e49189524cdce394f0ba47e315be61296a1a26bdde364008d66a8d84868e245e648b7c93d42972811a31cb47ac24ae060250571cb624b1918719591ee32074754aea34a55cc796a9076c6fa20129a43773b69fa0941845084afb8bb4ed8509c0db03572672f9d60d2102854d2787d6eaa0353378dc7788013139f0cc1e3029b731323a41e24bfc860f5c01a949a024597644a0084453bc7c57b7a6b268adf5c00e2200623b267324c46c1b2caff3445109d278249962b20a34ccf4b9543c346732b3442657b6a3c3326ca6a8ccbf1c758fef83b07fbc36e2c647c82b8f64887dfedc77f61a12dba88a08334ba4536186063b7c4c9f22056f88fb623768b72579cc82627b13f1985cec0120465a142756af71098237ae072bbe816317e1d213fd7408657bc3447b457f996da3e66e5473a15f9a72299a74d93c1acf4559a6211cde8c8b065b1227090dbb68215cea239f427608bb971551247eacbc1ff287c172183c98989c093d5e9c2643c80e5743514accb511e9265fc772d0bb11e29344bce91913c18bb12c807e45cd9d66bb1491762d2a0fbc850c3fcb1e87869615af5e648c623d1862131b8a90212df65b4c672775d0e56903cc3ceb942cdca1f71fa336b65af6899400a7dff5549976ad018a8b694e53"
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"X25519 (29)": "e8e5bf70e4071c2f4987a554eb0241df993c727bf72365744cc308e2ad9ac300"
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"P-256 (23)": "04b34a0cfadee6f73b21e4a16c65c616c7d6cd1ee53a8d5418938acf682ba8b05cfff08ea7d3d9948b3adeda6bac0bf9b0a1ac3a4dde6390b552c8b48b7b1320c3"
|
|
98
|
+
}
|
|
99
|
+
]
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"name": "supported_versions (43)",
|
|
103
|
+
"versions": [
|
|
104
|
+
"TLS 1.3",
|
|
105
|
+
"TLS 1.2"
|
|
106
|
+
]
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"name": "signature_algorithms (13)",
|
|
110
|
+
"signature_algorithms": [
|
|
111
|
+
"ecdsa_secp256r1_sha256",
|
|
112
|
+
"ecdsa_secp384r1_sha384",
|
|
113
|
+
"ecdsa_secp521r1_sha512",
|
|
114
|
+
"rsa_pss_rsae_sha256",
|
|
115
|
+
"rsa_pss_rsae_sha384",
|
|
116
|
+
"rsa_pss_rsae_sha512",
|
|
117
|
+
"rsa_pkcs1_sha256",
|
|
118
|
+
"rsa_pkcs1_sha384",
|
|
119
|
+
"rsa_pkcs1_sha512",
|
|
120
|
+
"ecdsa_sha1",
|
|
121
|
+
"rsa_pkcs1_sha1"
|
|
122
|
+
]
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"name": "psk_key_exchange_modes (45)",
|
|
126
|
+
"PSK_Key_Exchange_Mode": "PSK with (EC)DHE key establishment (psk_dhe_ke) (1)"
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"name": "record_size_limit (28)",
|
|
130
|
+
"data": "0fa1"
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
"name": "compress_certificate (27)",
|
|
134
|
+
"algorithms": [
|
|
135
|
+
"zlib (1)",
|
|
136
|
+
"brotli (2)",
|
|
137
|
+
"zstd (3)"
|
|
138
|
+
]
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
"name": "extensionEncryptedClientHello (boringssl) (65037)",
|
|
142
|
+
"data": "0000010001080020bf740cf3d11fdbdce1c03df9af65170e6311134064a91e08b45c86bfdffa394c00d0623f007f6bcea5ac3a1d3bade746d793c0d381889ed49d1232a1d0a75e0746ece6a5f2d7d6050e8d367c4c20dcaa9f0f42d32e8af36e326df3bce1cab73329dfe522be8d54f7ef553de6e172a073ae638e4cb1f027d69c67e2c9cb2491efbf07897e2a81f4118e449d30ad3757550f1c90de121362cf09bcb039ecf3bae41635799eecef72c9cb3d9faf5fd6a4d5da55963b795f1b16257d896c0f1218349ff3b6ac549fcc19a923cdb9726dbfc14b024d0a4eef79224e10c90b840f556f58966a63da59a886e62a985c87e03552a3c3"
|
|
143
|
+
}
|
|
144
|
+
],
|
|
145
|
+
"tls_version_record": "771",
|
|
146
|
+
"tls_version_negotiated": "772",
|
|
147
|
+
"ja3": "771,4865-4867-4866-49195-49199-52393-52392-49196-49200-49162-49161-49171-49172-156-157-47-53,0-23-65281-10-11-35-16-5-34-51-43-13-45-28-27-65037,4588-29-23-24-25-256-257,0",
|
|
148
|
+
"ja3_hash": "2d692a4485ca2f5f2b10ecb2d2909ad3",
|
|
149
|
+
"ja4": "t13d1716h2_5b57614c22b0_eeeea6562960",
|
|
150
|
+
"ja4_r": "t13d1716h2_002f,0035,009c,009d,1301,1302,1303,c009,c00a,c013,c014,c02b,c02c,c02f,c030,cca8,cca9_0005,000a,000b,000d,0017,001b,001c,0022,0023,002b,002d,0033,fe0d,ff01_0403,0503,0603,0804,0805,0806,0401,0501,0601,0203,0201",
|
|
151
|
+
"peetprint": "772-771|2-1.1|4588-29-23-24-25-256-257|1027-1283-1539-2052-2053-2054-1025-1281-1537-515-513|1|1-2-3|4865-4867-4866-49195-49199-52393-52392-49196-49200-49162-49161-49171-49172-156-157-47-53|0-10-11-13-16-23-27-28-34-35-43-45-5-51-65037-65281",
|
|
152
|
+
"peetprint_hash": "199f9cf4a47bfc51995a9f3942190094",
|
|
153
|
+
"client_random": "3841c1cad281ebd8d99db482413d3747d7558529bc794cde38cef3185df77e95",
|
|
154
|
+
"session_id": "e6d682d2d9f4f548c100a2ed301d99bcc80c5c44613a93740b31f90e461861cd"
|
|
155
|
+
},
|
|
156
|
+
"http2": {
|
|
157
|
+
"akamai_fingerprint": "1:65536;2:0;4:131072;5:16384|12517377|0|m,p,a,s",
|
|
158
|
+
"akamai_fingerprint_hash": "6ea73faa8fc5aac76bded7bd238f6433",
|
|
159
|
+
"sent_frames": [
|
|
160
|
+
{
|
|
161
|
+
"frame_type": "SETTINGS",
|
|
162
|
+
"length": 24,
|
|
163
|
+
"settings": [
|
|
164
|
+
"HEADER_TABLE_SIZE = 65536",
|
|
165
|
+
"ENABLE_PUSH = 0",
|
|
166
|
+
"INITIAL_WINDOW_SIZE = 131072",
|
|
167
|
+
"MAX_FRAME_SIZE = 16384"
|
|
168
|
+
]
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
"frame_type": "WINDOW_UPDATE",
|
|
172
|
+
"length": 4,
|
|
173
|
+
"increment": 12517377
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
"frame_type": "HEADERS",
|
|
177
|
+
"stream_id": 1,
|
|
178
|
+
"length": 288,
|
|
179
|
+
"headers": [
|
|
180
|
+
":method: GET",
|
|
181
|
+
":path: /api/all",
|
|
182
|
+
":authority: tls.peet.ws",
|
|
183
|
+
":scheme: https",
|
|
184
|
+
"user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:133.0) Gecko/20100101 Firefox/133.0",
|
|
185
|
+
"accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
|
|
186
|
+
"accept-language: en-US,en;q=0.5",
|
|
187
|
+
"accept-encoding: gzip, deflate, br, zstd",
|
|
188
|
+
"upgrade-insecure-requests: 1",
|
|
189
|
+
"sec-fetch-dest: document",
|
|
190
|
+
"sec-fetch-mode: navigate",
|
|
191
|
+
"sec-fetch-site: none",
|
|
192
|
+
"sec-fetch-user: ?1",
|
|
193
|
+
"priority: u=0, i",
|
|
194
|
+
"te: trailers"
|
|
195
|
+
],
|
|
196
|
+
"flags": [
|
|
197
|
+
"EndStream (0x1)",
|
|
198
|
+
"EndHeaders (0x4)",
|
|
199
|
+
"Priority (0x20)"
|
|
200
|
+
],
|
|
201
|
+
"priority": {
|
|
202
|
+
"weight": 256,
|
|
203
|
+
"depends_on": 0,
|
|
204
|
+
"exclusive": 0
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
]
|
|
208
|
+
},
|
|
209
|
+
"tcpip": {
|
|
210
|
+
"cap_length": 539,
|
|
211
|
+
"dst_port": 443,
|
|
212
|
+
"src_port": 59822,
|
|
213
|
+
"ip": {
|
|
214
|
+
"tos": 74,
|
|
215
|
+
"ttl": 44,
|
|
216
|
+
"ip_version": 4,
|
|
217
|
+
"dst_ip": "205.185.123.167",
|
|
218
|
+
"src_ip": "92.218.110.236"
|
|
219
|
+
},
|
|
220
|
+
"tcp": {
|
|
221
|
+
"ack": 1843036805,
|
|
222
|
+
"checksum": 42157,
|
|
223
|
+
"seq": 4211318257,
|
|
224
|
+
"window": 2061
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"source": "curl-impersonate",
|
|
3
|
+
"profile": "firefox-133",
|
|
4
|
+
"protocol": "tls",
|
|
5
|
+
"record": "client_hello",
|
|
6
|
+
"description": "TLS 1.3 ClientHello generated by curl-impersonate against tls.peet.ws impersonating firefox133. Captured via transparent SOCKS5 relay with correct SNI. Fields below are intentionally randomized per RFC 8446/8701 and must be masked during golden comparison (Cat 14).",
|
|
7
|
+
"randomizedFields": [
|
|
8
|
+
{
|
|
9
|
+
"byteOffset": 12,
|
|
10
|
+
"length": 32,
|
|
11
|
+
"reason": "random"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"byteOffset": 114,
|
|
15
|
+
"length": 1683,
|
|
16
|
+
"reason": "grease"
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
"createdAt": "2026-08-04T00:28:49Z"
|
|
20
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"source": "curl-impersonate",
|
|
3
|
+
"profile": "safari-17",
|
|
4
|
+
"protocol": "http2",
|
|
5
|
+
"record": "settings",
|
|
6
|
+
"description": "First HTTP/2 SETTINGS frame sent by curl-impersonate safari170. HTTP/2 SETTINGS are not randomized, so the ignore-list is empty.",
|
|
7
|
+
"randomizedFields": [],
|
|
8
|
+
"createdAt": "2026-08-04T00:28:49Z"
|
|
9
|
+
}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
{
|
|
2
|
+
"donate": "Please consider donating to keep this API running. Visit https://tls.peet.ws",
|
|
3
|
+
"ip": "92.218.110.236:63765",
|
|
4
|
+
"http_version": "h2",
|
|
5
|
+
"method": "GET",
|
|
6
|
+
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15",
|
|
7
|
+
"tls": {
|
|
8
|
+
"ciphers": [
|
|
9
|
+
"TLS_GREASE (0x6A6A)",
|
|
10
|
+
"TLS_AES_128_GCM_SHA256",
|
|
11
|
+
"TLS_AES_256_GCM_SHA384",
|
|
12
|
+
"TLS_CHACHA20_POLY1305_SHA256",
|
|
13
|
+
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
|
|
14
|
+
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
|
15
|
+
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
|
|
16
|
+
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
|
|
17
|
+
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
|
18
|
+
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
|
|
19
|
+
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
|
|
20
|
+
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
|
|
21
|
+
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
|
|
22
|
+
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
|
|
23
|
+
"TLS_RSA_WITH_AES_256_GCM_SHA384",
|
|
24
|
+
"TLS_RSA_WITH_AES_128_GCM_SHA256",
|
|
25
|
+
"TLS_RSA_WITH_AES_256_CBC_SHA",
|
|
26
|
+
"TLS_RSA_WITH_AES_128_CBC_SHA",
|
|
27
|
+
"TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
|
|
28
|
+
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
|
|
29
|
+
"TLS_RSA_WITH_3DES_EDE_CBC_SHA"
|
|
30
|
+
],
|
|
31
|
+
"extensions": [
|
|
32
|
+
{
|
|
33
|
+
"name": "TLS_GREASE (0xaaaa)"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"name": "server_name (0)",
|
|
37
|
+
"server_name": "tls.peet.ws"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"name": "extended_master_secret (23)",
|
|
41
|
+
"master_secret_data": "",
|
|
42
|
+
"extended_master_secret_data": ""
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"name": "extensionRenegotiationInfo (boringssl) (65281)",
|
|
46
|
+
"data": "00"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"name": "supported_groups (10)",
|
|
50
|
+
"supported_groups": [
|
|
51
|
+
"TLS_GREASE (0x5a5a)",
|
|
52
|
+
"X25519 (29)",
|
|
53
|
+
"P-256 (23)",
|
|
54
|
+
"P-384 (24)",
|
|
55
|
+
"P-521 (25)"
|
|
56
|
+
]
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"name": "ec_point_formats (11)",
|
|
60
|
+
"elliptic_curves_point_formats": [
|
|
61
|
+
"0x00"
|
|
62
|
+
]
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"name": "application_layer_protocol_negotiation (16)",
|
|
66
|
+
"protocols": [
|
|
67
|
+
"h2",
|
|
68
|
+
"http/1.1"
|
|
69
|
+
]
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"name": "status_request (5)",
|
|
73
|
+
"status_request": {
|
|
74
|
+
"certificate_status_type": "OSCP (1)",
|
|
75
|
+
"responder_id_list_length": 0,
|
|
76
|
+
"request_extensions_length": 0
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"name": "signature_algorithms (13)",
|
|
81
|
+
"signature_algorithms": [
|
|
82
|
+
"ecdsa_secp256r1_sha256",
|
|
83
|
+
"rsa_pss_rsae_sha256",
|
|
84
|
+
"rsa_pkcs1_sha256",
|
|
85
|
+
"ecdsa_secp384r1_sha384",
|
|
86
|
+
"ecdsa_sha1",
|
|
87
|
+
"rsa_pss_rsae_sha384",
|
|
88
|
+
"rsa_pss_rsae_sha384",
|
|
89
|
+
"rsa_pkcs1_sha384",
|
|
90
|
+
"rsa_pss_rsae_sha512",
|
|
91
|
+
"rsa_pkcs1_sha512",
|
|
92
|
+
"rsa_pkcs1_sha1"
|
|
93
|
+
]
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"name": "signed_certificate_timestamp (18)"
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"name": "key_share (51)",
|
|
100
|
+
"shared_keys": [
|
|
101
|
+
{
|
|
102
|
+
"TLS_GREASE (0x5a5a)": "00"
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"X25519 (29)": "4abbb4b6658ce3fac151869628a7dabaefa5845a6c586ec45189d0aaaa308034"
|
|
106
|
+
}
|
|
107
|
+
]
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"name": "psk_key_exchange_modes (45)",
|
|
111
|
+
"PSK_Key_Exchange_Mode": "PSK with (EC)DHE key establishment (psk_dhe_ke) (1)"
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"name": "supported_versions (43)",
|
|
115
|
+
"versions": [
|
|
116
|
+
"TLS_GREASE (0x6a6a)",
|
|
117
|
+
"TLS 1.3",
|
|
118
|
+
"TLS 1.2",
|
|
119
|
+
"TLS 1.1",
|
|
120
|
+
"TLS 1.0"
|
|
121
|
+
]
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"name": "compress_certificate (27)",
|
|
125
|
+
"algorithms": [
|
|
126
|
+
"zlib (1)"
|
|
127
|
+
]
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
"name": "TLS_GREASE (0xfafa)"
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
"name": "padding (21)",
|
|
134
|
+
"padding_data_length": 390
|
|
135
|
+
}
|
|
136
|
+
],
|
|
137
|
+
"tls_version_record": "771",
|
|
138
|
+
"tls_version_negotiated": "772",
|
|
139
|
+
"ja3": "771,4865-4866-4867-49196-49195-52393-49200-49199-52392-49162-49161-49172-49171-157-156-53-47-49160-49170-10,0-23-65281-10-11-16-5-13-18-51-45-43-27-21,29-23-24-25,0",
|
|
140
|
+
"ja3_hash": "773906b0efdefa24a7f2b8eb6985bf37",
|
|
141
|
+
"ja4": "t13d2014h2_a09f3c656075_874d27d7ca63",
|
|
142
|
+
"ja4_r": "t13d2014h2_000a,002f,0035,009c,009d,1301,1302,1303,c008,c009,c00a,c012,c013,c014,c02b,c02c,c02f,c030,cca8,cca9_0005,000a,000b,000d,0012,0017,001b,002b,002d,0033,ff01_0403,0804,0401,0503,0203,0805,0805,0501,0806,0601,0201",
|
|
143
|
+
"peetprint": "GREASE-772-771-770-769|2-1.1|GREASE-29-23-24-25|1027-2052-1025-1283-515-2053-2053-1281-2054-1537-513|1|1|GREASE-4865-4866-4867-49196-49195-52393-49200-49199-52392-49162-49161-49172-49171-157-156-53-47-49160-49170-10|0-10-11-13-16-18-21-23-27-43-45-5-51-65281-GREASE-GREASE",
|
|
144
|
+
"peetprint_hash": "b2bafdc69377086c3416be278fd21121",
|
|
145
|
+
"client_random": "c9fba7116934f8045e9311add6745a43debae0d727493b41be0fd5909f8074a2",
|
|
146
|
+
"session_id": "113d41a2e1318188ca74b730a72f9e11e127d72c9b2139b32156dffd507298d6"
|
|
147
|
+
},
|
|
148
|
+
"http2": {
|
|
149
|
+
"akamai_fingerprint": "2:0;4:4194304;3:100|10485760|0|m,s,p,a",
|
|
150
|
+
"akamai_fingerprint_hash": "959a7e813b79b909a1a0b00a38e8bba3",
|
|
151
|
+
"sent_frames": [
|
|
152
|
+
{
|
|
153
|
+
"frame_type": "SETTINGS",
|
|
154
|
+
"length": 18,
|
|
155
|
+
"settings": [
|
|
156
|
+
"ENABLE_PUSH = 0",
|
|
157
|
+
"INITIAL_WINDOW_SIZE = 4194304",
|
|
158
|
+
"MAX_CONCURRENT_STREAMS = 100"
|
|
159
|
+
]
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
"frame_type": "WINDOW_UPDATE",
|
|
163
|
+
"length": 4,
|
|
164
|
+
"increment": 10485760
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
"frame_type": "HEADERS",
|
|
168
|
+
"stream_id": 1,
|
|
169
|
+
"length": 247,
|
|
170
|
+
"headers": [
|
|
171
|
+
":method: GET",
|
|
172
|
+
":scheme: https",
|
|
173
|
+
":path: /api/all",
|
|
174
|
+
":authority: tls.peet.ws",
|
|
175
|
+
"accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
|
|
176
|
+
"sec-fetch-site: none",
|
|
177
|
+
"accept-encoding: gzip, deflate, br",
|
|
178
|
+
"sec-fetch-mode: navigate",
|
|
179
|
+
"user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15",
|
|
180
|
+
"accept-language: en-US,en;q=0.9",
|
|
181
|
+
"sec-fetch-dest: document"
|
|
182
|
+
],
|
|
183
|
+
"flags": [
|
|
184
|
+
"EndStream (0x1)",
|
|
185
|
+
"EndHeaders (0x4)",
|
|
186
|
+
"Priority (0x20)"
|
|
187
|
+
],
|
|
188
|
+
"priority": {
|
|
189
|
+
"weight": 255,
|
|
190
|
+
"depends_on": 0,
|
|
191
|
+
"exclusive": 0
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
]
|
|
195
|
+
},
|
|
196
|
+
"tcpip": {
|
|
197
|
+
"cap_length": 583,
|
|
198
|
+
"dst_port": 443,
|
|
199
|
+
"src_port": 63765,
|
|
200
|
+
"ip": {
|
|
201
|
+
"tos": 74,
|
|
202
|
+
"ttl": 44,
|
|
203
|
+
"ip_version": 4,
|
|
204
|
+
"dst_ip": "205.185.123.167",
|
|
205
|
+
"src_ip": "92.218.110.236"
|
|
206
|
+
},
|
|
207
|
+
"tcp": {
|
|
208
|
+
"ack": 4175661838,
|
|
209
|
+
"checksum": 2612,
|
|
210
|
+
"seq": 373147202,
|
|
211
|
+
"window": 2061
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"source": "curl-impersonate",
|
|
3
|
+
"profile": "safari-17",
|
|
4
|
+
"protocol": "tls",
|
|
5
|
+
"record": "client_hello",
|
|
6
|
+
"description": "TLS 1.3 ClientHello generated by curl-impersonate against tls.peet.ws impersonating safari170. Captured via transparent SOCKS5 relay with correct SNI. Fields below are intentionally randomized per RFC 8446/8701 and must be masked during golden comparison (Cat 14).",
|
|
7
|
+
"randomizedFields": [
|
|
8
|
+
{
|
|
9
|
+
"byteOffset": 12,
|
|
10
|
+
"length": 32,
|
|
11
|
+
"reason": "random"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"byteOffset": 122,
|
|
15
|
+
"length": 395,
|
|
16
|
+
"reason": "grease"
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
"createdAt": "2026-08-04T00:28:49Z"
|
|
20
|
+
}
|
package/dist/bench/bench.d.ts
CHANGED
|
@@ -1,18 +1,34 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Benchmark suite for protocol operations.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Benchmarks here measure operations that need no live server — capture
|
|
5
|
+
* parsing, fingerprint computation, golden comparison, and compression
|
|
6
|
+
* round-trips — so they run in CI. Live TLS-handshake / HTTP/2-request
|
|
7
|
+
* benchmarks (which require a functional protocol stack + loopback server)
|
|
8
|
+
* remain a future addition; see docs/TEST-SUITE.md (Phase 10) for the full
|
|
9
|
+
* roadmap.
|
|
10
|
+
*
|
|
11
|
+
* Each benchmark runs `iterations` repetitions, collects per-iteration
|
|
12
|
+
* timings in microseconds, and reports p50/p95/p99 latency plus average
|
|
13
|
+
* throughput.
|
|
6
14
|
*/
|
|
7
15
|
import type { BenchStats } from "../types.js";
|
|
8
|
-
/**
|
|
9
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Benchmark the TLS ClientHello fingerprint computation (JA3 + JA4) over
|
|
18
|
+
* `iterations` runs against the chrome-140 golden capture. Reports
|
|
19
|
+
* p50/p95/p99 latency in milliseconds.
|
|
20
|
+
*/
|
|
21
|
+
export declare function benchmarkTlsHandshake(iterations: number, _options?: {
|
|
10
22
|
host?: string;
|
|
11
23
|
port?: number;
|
|
12
24
|
profile?: string;
|
|
13
25
|
}): BenchStats;
|
|
14
|
-
/**
|
|
15
|
-
|
|
26
|
+
/**
|
|
27
|
+
* Benchmark the golden-comparison path (load + byte-compare) over
|
|
28
|
+
* `iterations` runs. This exercises the Category 14 packet-capture
|
|
29
|
+
* comparison core. Reports p50/p95/p99 latency in milliseconds.
|
|
30
|
+
*/
|
|
31
|
+
export declare function benchmarkHttp2Request(iterations: number, _options?: {
|
|
16
32
|
host?: string;
|
|
17
33
|
port?: number;
|
|
18
34
|
path?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bench.d.ts","sourceRoot":"","sources":["../../src/bench/bench.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"bench.d.ts","sourceRoot":"","sources":["../../src/bench/bench.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAoD9C;;;;GAIG;AACH,wBAAgB,qBAAqB,CACjC,UAAU,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9D,UAAU,CAqBZ;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACjC,UAAU,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7E,UAAU,CA0BZ"}
|
package/dist/bench/bench.js
CHANGED
|
@@ -1,19 +1,114 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Benchmark suite for protocol operations.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Benchmarks here measure operations that need no live server — capture
|
|
5
|
+
* parsing, fingerprint computation, golden comparison, and compression
|
|
6
|
+
* round-trips — so they run in CI. Live TLS-handshake / HTTP/2-request
|
|
7
|
+
* benchmarks (which require a functional protocol stack + loopback server)
|
|
8
|
+
* remain a future addition; see docs/TEST-SUITE.md (Phase 10) for the full
|
|
9
|
+
* roadmap.
|
|
10
|
+
*
|
|
11
|
+
* Each benchmark runs `iterations` repetitions, collects per-iteration
|
|
12
|
+
* timings in microseconds, and reports p50/p95/p99 latency plus average
|
|
13
|
+
* throughput.
|
|
14
|
+
*/
|
|
15
|
+
import { readFileSync } from "node:fs";
|
|
16
|
+
import { join } from "node:path";
|
|
17
|
+
import { computeJa3, computeJa4 } from "../fingerprint/index.js";
|
|
18
|
+
import { compareBytes } from "../utils.js";
|
|
19
|
+
import { compression } from "@browsercore/compression";
|
|
20
|
+
const here = import.meta.dirname;
|
|
21
|
+
// src/bench -> package root -> captures/
|
|
22
|
+
const capturesDir = join(here, "..", "..", "captures");
|
|
23
|
+
/** Deterministic payload: byte[i] = i % 256 (reproducible, never random). */
|
|
24
|
+
function detBuffer(length) {
|
|
25
|
+
const bytes = new Uint8Array(length);
|
|
26
|
+
for (let i = 0; i < length; i++) {
|
|
27
|
+
bytes[i] = i % 256;
|
|
28
|
+
}
|
|
29
|
+
return bytes;
|
|
30
|
+
}
|
|
31
|
+
/** High-resolution timestamp in microseconds (browser-safe fallback). */
|
|
32
|
+
function nowUs() {
|
|
33
|
+
return performance.now() * 1000;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Run `fn` for `iterations` repetitions and return the per-iteration timings
|
|
37
|
+
* in microseconds, sorted ascending. The warm-up iteration is discarded to
|
|
38
|
+
* eliminate first-call JIT / cache effects.
|
|
6
39
|
*/
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
40
|
+
function measure(iterations, fn) {
|
|
41
|
+
// Warm-up.
|
|
42
|
+
fn();
|
|
43
|
+
const timings = [];
|
|
44
|
+
for (let i = 0; i < iterations; i++) {
|
|
45
|
+
const start = nowUs();
|
|
46
|
+
fn();
|
|
47
|
+
timings.push(nowUs() - start);
|
|
48
|
+
}
|
|
49
|
+
timings.sort((a, b) => a - b);
|
|
50
|
+
return timings;
|
|
51
|
+
}
|
|
52
|
+
/** Read a percentile (0..1) from a sorted array of samples. */
|
|
53
|
+
function percentile(sorted, p) {
|
|
54
|
+
if (sorted.length === 0) {
|
|
55
|
+
return 0;
|
|
56
|
+
}
|
|
57
|
+
const idx = Math.min(sorted.length - 1, Math.ceil(p * sorted.length) - 1);
|
|
58
|
+
return sorted[Math.max(0, idx)] ?? 0;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Benchmark the TLS ClientHello fingerprint computation (JA3 + JA4) over
|
|
62
|
+
* `iterations` runs against the chrome-140 golden capture. Reports
|
|
63
|
+
* p50/p95/p99 latency in milliseconds.
|
|
64
|
+
*/
|
|
65
|
+
export function benchmarkTlsHandshake(iterations, _options) {
|
|
10
66
|
void _options;
|
|
11
|
-
|
|
67
|
+
// Load the chrome-140 golden capture once; the benchmark measures the
|
|
68
|
+
// parsing + fingerprinting cost, not the live handshake (which needs a
|
|
69
|
+
// functional TLS stack + loopback server — future work).
|
|
70
|
+
const bytes = readFileSync(join(capturesDir, "chrome-140", "tls", "client_hello.bin"));
|
|
71
|
+
const iters = Math.max(1, iterations);
|
|
72
|
+
const timings = measure(iters, () => {
|
|
73
|
+
computeJa3(bytes);
|
|
74
|
+
computeJa4(bytes);
|
|
75
|
+
});
|
|
76
|
+
const avgMs = timings.reduce((a, b) => a + b, 0) / timings.length / 1000;
|
|
77
|
+
return {
|
|
78
|
+
iterations: iters,
|
|
79
|
+
avgMs,
|
|
80
|
+
p50: percentile(timings, 0.5) / 1000,
|
|
81
|
+
p95: percentile(timings, 0.95) / 1000,
|
|
82
|
+
p99: percentile(timings, 0.99) / 1000,
|
|
83
|
+
};
|
|
12
84
|
}
|
|
13
|
-
/**
|
|
14
|
-
|
|
15
|
-
|
|
85
|
+
/**
|
|
86
|
+
* Benchmark the golden-comparison path (load + byte-compare) over
|
|
87
|
+
* `iterations` runs. This exercises the Category 14 packet-capture
|
|
88
|
+
* comparison core. Reports p50/p95/p99 latency in milliseconds.
|
|
89
|
+
*/
|
|
90
|
+
export function benchmarkHttp2Request(iterations, _options) {
|
|
16
91
|
void _options;
|
|
17
|
-
|
|
92
|
+
// The HTTP/2 SETTINGS frame is small and deterministic — ideal for
|
|
93
|
+
// repeated comparison benchmarking without a live server.
|
|
94
|
+
const bytes = readFileSync(join(capturesDir, "chrome-140", "http2", "settings.bin"));
|
|
95
|
+
const iters = Math.max(1, iterations);
|
|
96
|
+
// Pre-compress a payload for the compression round-trip sub-benchmark.
|
|
97
|
+
const payload = detBuffer(8192);
|
|
98
|
+
const compressed = compression.gzip(payload);
|
|
99
|
+
const timings = measure(iters, () => {
|
|
100
|
+
// Golden comparison path: compare the SETTINGS bytes against themselves.
|
|
101
|
+
compareBytes(bytes, bytes);
|
|
102
|
+
// Compression round-trip: representative of per-request work.
|
|
103
|
+
compression.gunzip(compressed);
|
|
104
|
+
});
|
|
105
|
+
const avgMs = timings.reduce((a, b) => a + b, 0) / timings.length / 1000;
|
|
106
|
+
return {
|
|
107
|
+
iterations: iters,
|
|
108
|
+
avgMs,
|
|
109
|
+
p50: percentile(timings, 0.5) / 1000,
|
|
110
|
+
p95: percentile(timings, 0.95) / 1000,
|
|
111
|
+
p99: percentile(timings, 0.99) / 1000,
|
|
112
|
+
};
|
|
18
113
|
}
|
|
19
114
|
//# sourceMappingURL=bench.js.map
|