@browsercore/profiles 0.1.4 → 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 +111 -13
- package/dist/codes.d.ts +40 -0
- package/dist/codes.d.ts.map +1 -0
- package/dist/codes.js +111 -0
- package/dist/codes.js.map +1 -0
- package/dist/diff.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/profiles/chrome.d.ts +17 -4
- package/dist/profiles/chrome.d.ts.map +1 -1
- package/dist/profiles/chrome.js +68 -83
- package/dist/profiles/chrome.js.map +1 -1
- package/dist/profiles/edge.d.ts +2 -1
- package/dist/profiles/edge.d.ts.map +1 -1
- package/dist/profiles/edge.js +39 -41
- package/dist/profiles/edge.js.map +1 -1
- package/dist/profiles/firefox.d.ts +13 -3
- package/dist/profiles/firefox.d.ts.map +1 -1
- package/dist/profiles/firefox.js +48 -63
- package/dist/profiles/firefox.js.map +1 -1
- package/dist/profiles/safari.d.ts +6 -3
- package/dist/profiles/safari.d.ts.map +1 -1
- package/dist/profiles/safari.js +63 -46
- package/dist/profiles/safari.js.map +1 -1
- package/dist/registry.d.ts +4 -2
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +4 -2
- package/dist/registry.js.map +1 -1
- package/dist/utils.d.ts +2 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js.map +1 -1
- package/dist/validate.d.ts +8 -4
- package/dist/validate.d.ts.map +1 -1
- package/dist/validate.js +8 -72
- package/dist/validate.js.map +1 -1
- package/package.json +4 -6
package/README.md
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
# @browsercore/profiles
|
|
2
2
|
|
|
3
|
-
|
|
4
3
|
[](https://www.npmjs.com/package/@browsercore/profiles)
|
|
5
|
-
[](https://github.com/jverneuer/browsercore-profiles/blob/main/COVERAGE.md)
|
|
6
5
|
[](https://github.com/jverneuer/browsercore-profiles/actions/workflows/ci.yml)
|
|
7
6
|
|
|
8
|
-
Browser fingerprint definitions (TLS / HTTP/2 / HTTP/1.1). Pure data — no protocol implementation.
|
|
7
|
+
Browser fingerprint definitions (TLS / HTTP/2 / HTTP/1.1). Pure data — no protocol implementation lives here. Higher layers read these definitions and translate them into bytes, header order, and SETTINGS frames.
|
|
9
8
|
|
|
10
9
|
## Responsibility
|
|
11
10
|
|
|
12
|
-
Define WHAT a browser fingerprint looks like
|
|
11
|
+
Define WHAT a browser fingerprint looks like: ordered cipher suites, TLS extension order, GREASE behavior, HTTP/2 SETTINGS, and HTTP/1.1 header order. Adding a new Chrome version means adding a new entry here — protocol implementations never change.
|
|
13
12
|
|
|
14
13
|
## What it does NOT know about
|
|
15
14
|
|
|
@@ -18,34 +17,64 @@ Define WHAT a browser fingerprint looks like so that higher layers (tls, http1,
|
|
|
18
17
|
- Sockets or I/O
|
|
19
18
|
- Cookies
|
|
20
19
|
|
|
21
|
-
##
|
|
20
|
+
## Install
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install @browsercore/profiles
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Quick usage
|
|
22
27
|
|
|
23
28
|
```ts
|
|
24
29
|
import { getProfile, listProfiles, registerProfile } from "@browsercore/profiles";
|
|
30
|
+
import type { ProfileId } from "@browsercore/profiles";
|
|
25
31
|
|
|
26
32
|
const chrome = getProfile("chrome-140" as ProfileId);
|
|
27
33
|
console.log(chrome.tls.cipherSuites); // ordered cipher list
|
|
28
|
-
console.log(chrome.http2.settings);
|
|
34
|
+
console.log(chrome.http2.settings); // HTTP/2 SETTINGS frame values
|
|
29
35
|
|
|
30
|
-
const all = listProfiles(); // ["chrome-120", "chrome-128", ...]
|
|
36
|
+
const all = listProfiles(); // ["chrome-120", "chrome-128", ...] — insertion order
|
|
31
37
|
|
|
32
38
|
registerProfile(myCustomProfile); // extensibility hook
|
|
33
39
|
```
|
|
34
40
|
|
|
35
|
-
##
|
|
41
|
+
## Public API
|
|
36
42
|
|
|
37
43
|
| Export | Kind | Purpose |
|
|
38
44
|
| --- | --- | --- |
|
|
45
|
+
| `getProfile()` | function | Look up a profile by id (throws `UnknownProfileError` if absent) |
|
|
46
|
+
| `listProfiles()` | function | List every registered id, in insertion order |
|
|
47
|
+
| `registerProfile()` | function | Register or overwrite a custom profile at runtime |
|
|
48
|
+
| `diffProfiles()` | function | Field-by-field diff of two profiles, reporting each differing path |
|
|
49
|
+
| `DiffOptions` | interface | Diff tuning (e.g. order-sensitive vs. multiset array comparison) |
|
|
50
|
+
| `ProfileDiff` | interface | A single difference located by its dotted path |
|
|
51
|
+
| `buildExpectedClientHello()` | function | Project a profile's TLS fields onto expected wire codes |
|
|
52
|
+
| `validateProfileAgainstCapture()` | function | Validate a profile against a captured ClientHello |
|
|
53
|
+
| `ValidationResult` | interface | `{ ok, diffs }` outcome of validation |
|
|
54
|
+
| `TlsCapture` | interface | A captured ClientHello parsed out of a packet capture |
|
|
55
|
+
| `ClientHelloExpected` | interface | The wire values a profile's ClientHello should carry |
|
|
39
56
|
| `BrowserProfile` | interface | Complete fingerprint across TLS + HTTP/2 + HTTP/1.1 |
|
|
40
57
|
| `TlsProfile` | interface | Cipher order, extensions, GREASE, signature algorithms |
|
|
41
58
|
| `Http2Profile` | interface | SETTINGS, window sizes, priority |
|
|
59
|
+
| `Http2Settings` | interface | HTTP/2 numeric settings (RFC 9113 §6.5.1) |
|
|
60
|
+
| `Http2Priority` | interface | Stream priority descriptor |
|
|
42
61
|
| `Http1Profile` | interface | Default headers, header order, accept-encoding |
|
|
43
|
-
| `ProfileId` | branded
|
|
62
|
+
| `ProfileId` | branded type | Opaque profile identifier (`"chrome-140"`) |
|
|
44
63
|
| `ProfileName` | literal union | `"chrome" \| "firefox" \| "safari" \| "edge"` |
|
|
45
|
-
| `
|
|
46
|
-
| `
|
|
47
|
-
| `
|
|
64
|
+
| `ChromeProfiles` / `FirefoxProfiles` / `SafariProfiles` / `EdgeProfiles` | const maps | Per-browser profile definitions |
|
|
65
|
+
| `assertNever()` | function | Exhaustiveness check for switches over unions |
|
|
66
|
+
| `ProfileError` | class | Base typed error (matched on `kind`) |
|
|
48
67
|
| `UnknownProfileError` | class | Thrown when a profile id is not found |
|
|
68
|
+
| `ValidationError` | class | Thrown on an unknown profile value or bad capture |
|
|
69
|
+
|
|
70
|
+
## Shipped profiles
|
|
71
|
+
|
|
72
|
+
| Browser | Profiles |
|
|
73
|
+
| --- | --- |
|
|
74
|
+
| Chrome | `chrome-120`, `chrome-128`, `chrome-140` |
|
|
75
|
+
| Firefox | `firefox-120`, `firefox-128`, `firefox-135` |
|
|
76
|
+
| Safari | `safari-17`, `safari-18` |
|
|
77
|
+
| Edge | `edge-120`, `edge-128` |
|
|
49
78
|
|
|
50
79
|
## Dependency graph
|
|
51
80
|
|
|
@@ -53,4 +82,73 @@ registerProfile(myCustomProfile); // extensibility hook
|
|
|
53
82
|
@browsercore/profiles
|
|
54
83
|
```
|
|
55
84
|
|
|
56
|
-
No other `@browsercore/*` packages and no Node built-ins are imported. This is a pure data package.
|
|
85
|
+
No other `@browsercore/*` runtime packages and no Node built-ins are imported. This is a pure data package. `@browsercore/dev` is a dev-only dependency that supplies shared build / lint / test configuration (see [Shared config](#shared-config)).
|
|
86
|
+
|
|
87
|
+
## Source layout
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
src/
|
|
91
|
+
├─ index.ts Public API surface — re-exports from the rest of the package
|
|
92
|
+
├─ index.internal.ts Barrel re-exporting the per-browser profile maps
|
|
93
|
+
├─ registry.ts getProfile / listProfiles / registerProfile (Map-backed)
|
|
94
|
+
├─ diff.ts diffProfiles — field-by-field diff of two profiles
|
|
95
|
+
├─ validate.ts buildExpectedClientHello / validateProfileAgainstCapture
|
|
96
|
+
├─ codes.ts IANA TLS registry codes (cipher suites, groups, versions, sig schemes)
|
|
97
|
+
├─ errors.ts ProfileError / UnknownProfileError / ValidationError
|
|
98
|
+
├─ types.ts BrowserProfile + per-layer profile interfaces
|
|
99
|
+
├─ utils.ts assertNever / createId
|
|
100
|
+
└─ profiles/ Per-browser profile definitions
|
|
101
|
+
├─ chrome.ts chrome-120, chrome-128, chrome-140
|
|
102
|
+
├─ firefox.ts firefox-120, firefox-128, firefox-135
|
|
103
|
+
├─ safari.ts safari-17, safari-18
|
|
104
|
+
└─ edge.ts edge-120, edge-128
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Development
|
|
108
|
+
|
|
109
|
+
Requires **Node >= 26**. ESM only (`"type": "module"`).
|
|
110
|
+
|
|
111
|
+
```sh
|
|
112
|
+
npm install # installs @browsercore/dev (file:../dev) + siblings
|
|
113
|
+
npm run build # tsc -p tsconfig.build.json (emit to dist/)
|
|
114
|
+
npm run typecheck
|
|
115
|
+
npm run lint # oxlint --type-aware src/
|
|
116
|
+
npm test # vitest run
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Run a single test file:
|
|
120
|
+
|
|
121
|
+
```sh
|
|
122
|
+
npx vitest run tests/profiles.test.ts
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Run tests by name pattern:
|
|
126
|
+
|
|
127
|
+
```sh
|
|
128
|
+
npx vitest run -t "returns a known Chrome profile by id"
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Generate a coverage report:
|
|
132
|
+
|
|
133
|
+
```sh
|
|
134
|
+
npm test -- --coverage
|
|
135
|
+
node ../dev/bin/coverage-md.mjs # writes COVERAGE.md + coverage/badge.json
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Shared config
|
|
139
|
+
|
|
140
|
+
This package adopts `@browsercore/dev`, the shared config package for the
|
|
141
|
+
`@browsercore/*` family. Configuration is centralized — this repo only wires it in:
|
|
142
|
+
|
|
143
|
+
| Concern | Mechanism |
|
|
144
|
+
| --- | --- |
|
|
145
|
+
| TypeScript strict flags | `tsconfig.json` extends `@browsercore/dev/tsconfig.base.json` |
|
|
146
|
+
| Vitest config | `vitest.config.ts` calls `definePackageConfig({ name: "profiles" })` |
|
|
147
|
+
| Oxlint config | `oxlint.config.ts` extends `@browsercore/dev/oxlint` |
|
|
148
|
+
| Coverage report | `coverage-md` bin from `@browsercore/dev` |
|
|
149
|
+
|
|
150
|
+
`@browsercore/dev` is declared as a devDependency via `"@browsercore/dev": "file:../dev"`.
|
|
151
|
+
|
|
152
|
+
## License
|
|
153
|
+
|
|
154
|
+
MIT
|
package/dist/codes.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IANA TLS registry codes used to project profile names onto wire values.
|
|
3
|
+
*
|
|
4
|
+
* These are the canonical 2-byte codes from the IANA TLS parameter registries.
|
|
5
|
+
* Only the codes referenced by the shipped profiles are mapped here — an
|
|
6
|
+
* unknown name is a bug in a profile definition and surfaces as a
|
|
7
|
+
* {@link ValidationError} at projection time, so the tables double as an
|
|
8
|
+
* allow-list that keeps profile data honest.
|
|
9
|
+
*
|
|
10
|
+
* Registries:
|
|
11
|
+
* - Cipher suites: tls-parameters.xhtml#tls-parameters-4
|
|
12
|
+
* - Named groups: tls-parameters.xhtml#tls-parameters-8
|
|
13
|
+
* - Signature schemes: tls-parameters.xhtml#tls-parameters-16
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* The name Chrome/Edge use in their cipher list to mark a GREASE slot (RFC 8701).
|
|
17
|
+
* The real value is randomized per-connection (0x0a0a..0xfafa); validation accepts
|
|
18
|
+
* any GREASE-pattern byte pair at a slot marked with this placeholder.
|
|
19
|
+
*/
|
|
20
|
+
export declare const CIPHER_GREASE_PLACEHOLDER = "TLS_GREASE_RESERVED_0";
|
|
21
|
+
/** Selected IANA TLS Cipher Suite codes, keyed by the canonical suite name used in profiles. */
|
|
22
|
+
export declare const CIPHER_SUITE_CODES: Readonly<Record<string, number>>;
|
|
23
|
+
/** Selected IANA TLS Supported Groups (named groups) codes. */
|
|
24
|
+
export declare const NAMED_GROUP_CODES: Readonly<Record<string, number>>;
|
|
25
|
+
/** Selected IANA TLS SignatureScheme codes. */
|
|
26
|
+
export declare const SIGNATURE_SCHEME_CODES: Readonly<Record<string, number>>;
|
|
27
|
+
/** IANA TLS ProtocolVersion codes for the supported_versions extension. */
|
|
28
|
+
export declare const VERSION_CODES: Readonly<Record<string, number>>;
|
|
29
|
+
/**
|
|
30
|
+
* Map a cipher-suite name to its 2-byte IANA wire code.
|
|
31
|
+
*
|
|
32
|
+
* This is the single projection seam from a profile's cipher name to the bytes
|
|
33
|
+
* a ClientHello carries. It throws on an unknown name rather than returning a
|
|
34
|
+
* sentinel: 0x0000 would be ambiguous (it collides with
|
|
35
|
+
* TLS_EMPTY_RENEGOTIATION_INFO_SCSV), and a silent default would hide a bug in
|
|
36
|
+
* a profile definition. An unknown name is therefore always an error here,
|
|
37
|
+
* never a 0x0000 fallback.
|
|
38
|
+
*/
|
|
39
|
+
export declare function cipherSuiteToWire(name: string): number;
|
|
40
|
+
//# sourceMappingURL=codes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codes.d.ts","sourceRoot":"","sources":["../src/codes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,0BAA0B,CAAC;AAEjE,gGAAgG;AAChG,eAAO,MAAM,kBAAkB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAkC/D,CAAC;AAEF,+DAA+D;AAC/D,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAY9D,CAAC;AAEF,+CAA+C;AAC/C,eAAO,MAAM,sBAAsB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAanE,CAAC;AAEF,2EAA2E;AAC3E,eAAO,MAAM,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAK1D,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMtD"}
|
package/dist/codes.js
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IANA TLS registry codes used to project profile names onto wire values.
|
|
3
|
+
*
|
|
4
|
+
* These are the canonical 2-byte codes from the IANA TLS parameter registries.
|
|
5
|
+
* Only the codes referenced by the shipped profiles are mapped here — an
|
|
6
|
+
* unknown name is a bug in a profile definition and surfaces as a
|
|
7
|
+
* {@link ValidationError} at projection time, so the tables double as an
|
|
8
|
+
* allow-list that keeps profile data honest.
|
|
9
|
+
*
|
|
10
|
+
* Registries:
|
|
11
|
+
* - Cipher suites: tls-parameters.xhtml#tls-parameters-4
|
|
12
|
+
* - Named groups: tls-parameters.xhtml#tls-parameters-8
|
|
13
|
+
* - Signature schemes: tls-parameters.xhtml#tls-parameters-16
|
|
14
|
+
*/
|
|
15
|
+
import { ProfileError } from "./errors.js";
|
|
16
|
+
/**
|
|
17
|
+
* The name Chrome/Edge use in their cipher list to mark a GREASE slot (RFC 8701).
|
|
18
|
+
* The real value is randomized per-connection (0x0a0a..0xfafa); validation accepts
|
|
19
|
+
* any GREASE-pattern byte pair at a slot marked with this placeholder.
|
|
20
|
+
*/
|
|
21
|
+
export const CIPHER_GREASE_PLACEHOLDER = "TLS_GREASE_RESERVED_0";
|
|
22
|
+
/** Selected IANA TLS Cipher Suite codes, keyed by the canonical suite name used in profiles. */
|
|
23
|
+
export const CIPHER_SUITE_CODES = {
|
|
24
|
+
// GREASE: real value is randomized per-connection (0x0a0a..0xfafa). We use the
|
|
25
|
+
// first canonical GREASE code for the expected representation; validation
|
|
26
|
+
// accepts any GREASE-pattern value at a GREASE slot.
|
|
27
|
+
[CIPHER_GREASE_PLACEHOLDER]: 0x0a0a,
|
|
28
|
+
TLS_AES_128_GCM_SHA256: 0x1301,
|
|
29
|
+
TLS_AES_256_GCM_SHA384: 0x1302,
|
|
30
|
+
TLS_CHACHA20_POLY1305_SHA256: 0x1303,
|
|
31
|
+
TLS_AES_128_CCM_SHA256: 0x1304,
|
|
32
|
+
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: 0xc02b,
|
|
33
|
+
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: 0xc02f,
|
|
34
|
+
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: 0xc02c,
|
|
35
|
+
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: 0xc030,
|
|
36
|
+
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: 0xcca9,
|
|
37
|
+
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: 0xcca8,
|
|
38
|
+
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: 0xc013,
|
|
39
|
+
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: 0xc014,
|
|
40
|
+
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: 0xc009,
|
|
41
|
+
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: 0xc00a,
|
|
42
|
+
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: 0xc023,
|
|
43
|
+
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: 0xc024,
|
|
44
|
+
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: 0xc027,
|
|
45
|
+
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: 0xc028,
|
|
46
|
+
TLS_RSA_WITH_AES_128_GCM_SHA256: 0x009c,
|
|
47
|
+
TLS_RSA_WITH_AES_256_GCM_SHA384: 0x009d,
|
|
48
|
+
TLS_RSA_WITH_AES_128_CBC_SHA: 0x002f,
|
|
49
|
+
TLS_RSA_WITH_AES_256_CBC_SHA: 0x0035,
|
|
50
|
+
TLS_RSA_WITH_AES_128_CBC_SHA256: 0x003c,
|
|
51
|
+
TLS_RSA_WITH_AES_256_CBC_SHA256: 0x003d,
|
|
52
|
+
// Safari legacy tail: 3DES ciphers (RFC 3268). BoringSSL dropped these, but
|
|
53
|
+
// curl-impersonate restores them so Safari's ClientHello matches byte-for-byte.
|
|
54
|
+
TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: 0xc008,
|
|
55
|
+
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: 0xc012,
|
|
56
|
+
TLS_RSA_WITH_3DES_EDE_CBC_SHA: 0x000a,
|
|
57
|
+
};
|
|
58
|
+
/** Selected IANA TLS Supported Groups (named groups) codes. */
|
|
59
|
+
export const NAMED_GROUP_CODES = {
|
|
60
|
+
x25519: 0x001d,
|
|
61
|
+
secp256r1: 0x0017,
|
|
62
|
+
secp384r1: 0x0018,
|
|
63
|
+
secp521r1: 0x0019,
|
|
64
|
+
ffdhe2048: 0x0100,
|
|
65
|
+
ffdhe3072: 0x0101,
|
|
66
|
+
// Chrome 124+ adds the hybrid post-quantum group. The draft Kyber768 code
|
|
67
|
+
// (0x6399) shipped in Chrome 124–130; the final MLKEM768 code (0x11ec) has
|
|
68
|
+
// been used since Chrome 131. Both appear at the front of the group list.
|
|
69
|
+
X25519Kyber768: 0x6399,
|
|
70
|
+
X25519MLKEM768: 0x11ec,
|
|
71
|
+
};
|
|
72
|
+
/** Selected IANA TLS SignatureScheme codes. */
|
|
73
|
+
export const SIGNATURE_SCHEME_CODES = {
|
|
74
|
+
ecdsa_secp256r1_sha256: 0x0403,
|
|
75
|
+
ecdsa_secp384r1_sha384: 0x0503,
|
|
76
|
+
ecdsa_secp521r1_sha512: 0x0603,
|
|
77
|
+
ecdsa_sha1: 0x0203,
|
|
78
|
+
rsa_pss_rsae_sha256: 0x0804,
|
|
79
|
+
rsa_pss_rsae_sha384: 0x0805,
|
|
80
|
+
rsa_pss_rsae_sha512: 0x0806,
|
|
81
|
+
rsa_pkcs1_sha256: 0x0401,
|
|
82
|
+
rsa_pkcs1_sha384: 0x0501,
|
|
83
|
+
rsa_pkcs1_sha512: 0x0601,
|
|
84
|
+
rsa_pkcs1_sha1: 0x0201,
|
|
85
|
+
ed25519: 0x0807,
|
|
86
|
+
};
|
|
87
|
+
/** IANA TLS ProtocolVersion codes for the supported_versions extension. */
|
|
88
|
+
export const VERSION_CODES = {
|
|
89
|
+
"TLS 1.3": 0x0304,
|
|
90
|
+
"TLS 1.2": 0x0303,
|
|
91
|
+
"TLS 1.1": 0x0302,
|
|
92
|
+
"TLS 1.0": 0x0301,
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* Map a cipher-suite name to its 2-byte IANA wire code.
|
|
96
|
+
*
|
|
97
|
+
* This is the single projection seam from a profile's cipher name to the bytes
|
|
98
|
+
* a ClientHello carries. It throws on an unknown name rather than returning a
|
|
99
|
+
* sentinel: 0x0000 would be ambiguous (it collides with
|
|
100
|
+
* TLS_EMPTY_RENEGOTIATION_INFO_SCSV), and a silent default would hide a bug in
|
|
101
|
+
* a profile definition. An unknown name is therefore always an error here,
|
|
102
|
+
* never a 0x0000 fallback.
|
|
103
|
+
*/
|
|
104
|
+
export function cipherSuiteToWire(name) {
|
|
105
|
+
const code = CIPHER_SUITE_CODES[name];
|
|
106
|
+
if (code === undefined) {
|
|
107
|
+
throw new ProfileError("UnknownCipherSuite", `Unknown cipher suite: ${name}`);
|
|
108
|
+
}
|
|
109
|
+
return code;
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=codes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codes.js","sourceRoot":"","sources":["../src/codes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C;;;;GAIG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,uBAAuB,CAAC;AAEjE,gGAAgG;AAChG,MAAM,CAAC,MAAM,kBAAkB,GAAqC;IAChE,+EAA+E;IAC/E,0EAA0E;IAC1E,qDAAqD;IACrD,CAAC,yBAAyB,CAAC,EAAE,MAAM;IACnC,sBAAsB,EAAE,MAAM;IAC9B,sBAAsB,EAAE,MAAM;IAC9B,4BAA4B,EAAE,MAAM;IACpC,sBAAsB,EAAE,MAAM;IAC9B,uCAAuC,EAAE,MAAM;IAC/C,qCAAqC,EAAE,MAAM;IAC7C,uCAAuC,EAAE,MAAM;IAC/C,qCAAqC,EAAE,MAAM;IAC7C,6CAA6C,EAAE,MAAM;IACrD,2CAA2C,EAAE,MAAM;IACnD,kCAAkC,EAAE,MAAM;IAC1C,kCAAkC,EAAE,MAAM;IAC1C,oCAAoC,EAAE,MAAM;IAC5C,oCAAoC,EAAE,MAAM;IAC5C,uCAAuC,EAAE,MAAM;IAC/C,uCAAuC,EAAE,MAAM;IAC/C,qCAAqC,EAAE,MAAM;IAC7C,qCAAqC,EAAE,MAAM;IAC7C,+BAA+B,EAAE,MAAM;IACvC,+BAA+B,EAAE,MAAM;IACvC,4BAA4B,EAAE,MAAM;IACpC,4BAA4B,EAAE,MAAM;IACpC,+BAA+B,EAAE,MAAM;IACvC,+BAA+B,EAAE,MAAM;IACvC,4EAA4E;IAC5E,gFAAgF;IAChF,qCAAqC,EAAE,MAAM;IAC7C,mCAAmC,EAAE,MAAM;IAC3C,6BAA6B,EAAE,MAAM;CACxC,CAAC;AAEF,+DAA+D;AAC/D,MAAM,CAAC,MAAM,iBAAiB,GAAqC;IAC/D,MAAM,EAAE,MAAM;IACd,SAAS,EAAE,MAAM;IACjB,SAAS,EAAE,MAAM;IACjB,SAAS,EAAE,MAAM;IACjB,SAAS,EAAE,MAAM;IACjB,SAAS,EAAE,MAAM;IACjB,0EAA0E;IAC1E,2EAA2E;IAC3E,0EAA0E;IAC1E,cAAc,EAAE,MAAM;IACtB,cAAc,EAAE,MAAM;CACzB,CAAC;AAEF,+CAA+C;AAC/C,MAAM,CAAC,MAAM,sBAAsB,GAAqC;IACpE,sBAAsB,EAAE,MAAM;IAC9B,sBAAsB,EAAE,MAAM;IAC9B,sBAAsB,EAAE,MAAM;IAC9B,UAAU,EAAE,MAAM;IAClB,mBAAmB,EAAE,MAAM;IAC3B,mBAAmB,EAAE,MAAM;IAC3B,mBAAmB,EAAE,MAAM;IAC3B,gBAAgB,EAAE,MAAM;IACxB,gBAAgB,EAAE,MAAM;IACxB,gBAAgB,EAAE,MAAM;IACxB,cAAc,EAAE,MAAM;IACtB,OAAO,EAAE,MAAM;CAClB,CAAC;AAEF,2EAA2E;AAC3E,MAAM,CAAC,MAAM,aAAa,GAAqC;IAC3D,SAAS,EAAE,MAAM;IACjB,SAAS,EAAE,MAAM;IACjB,SAAS,EAAE,MAAM;IACjB,SAAS,EAAE,MAAM;CACpB,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC1C,MAAM,IAAI,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;IACtC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACrB,MAAM,IAAI,YAAY,CAAC,oBAAoB,EAAE,yBAAyB,IAAI,EAAE,CAAC,CAAC;IAClF,CAAC;IACD,OAAO,IAAI,CAAC;AAChB,CAAC"}
|
package/dist/diff.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diff.js","sourceRoot":"","sources":["../src/diff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;
|
|
1
|
+
{"version":3,"file":"diff.js","sourceRoot":"","sources":["../src/diff.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -9,7 +9,8 @@ export { getProfile, listProfiles, registerProfile, } from "./registry.js";
|
|
|
9
9
|
export { diffProfiles, } from "./diff.js";
|
|
10
10
|
export type { DiffOptions, ProfileDiff, } from "./diff.js";
|
|
11
11
|
export { buildExpectedClientHello, validateProfileAgainstCapture, ValidationError, } from "./validate.js";
|
|
12
|
-
export type { TlsCapture, ClientHelloExpected, } from "./validate.js";
|
|
12
|
+
export type { TlsCapture, ClientHelloExpected, ValidationResult, } from "./validate.js";
|
|
13
|
+
export { cipherSuiteToWire, CIPHER_GREASE_PLACEHOLDER, CIPHER_SUITE_CODES, NAMED_GROUP_CODES, SIGNATURE_SCHEME_CODES, VERSION_CODES, } from "./codes.js";
|
|
13
14
|
export { ChromeProfiles, FirefoxProfiles, SafariProfiles, EdgeProfiles, } from "./index.internal.js";
|
|
14
15
|
export { ProfileError, UnknownProfileError, } from "./errors.js";
|
|
15
16
|
export type { BrowserProfile, Http1Profile, Http2Profile, Http2Settings, Http2Priority, ProfileId, ProfileName, TlsProfile, } from "./types.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACH,UAAU,EACV,YAAY,EACZ,eAAe,GAClB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACH,YAAY,GACf,MAAM,WAAW,CAAC;AAEnB,YAAY,EACR,WAAW,EACX,WAAW,GACd,MAAM,WAAW,CAAC;AAEnB,OAAO,EACH,wBAAwB,EACxB,6BAA6B,EAC7B,eAAe,GAClB,MAAM,eAAe,CAAC;AAEvB,YAAY,EACR,UAAU,EACV,mBAAmB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACH,UAAU,EACV,YAAY,EACZ,eAAe,GAClB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACH,YAAY,GACf,MAAM,WAAW,CAAC;AAEnB,YAAY,EACR,WAAW,EACX,WAAW,GACd,MAAM,WAAW,CAAC;AAEnB,OAAO,EACH,wBAAwB,EACxB,6BAA6B,EAC7B,eAAe,GAClB,MAAM,eAAe,CAAC;AAEvB,YAAY,EACR,UAAU,EACV,mBAAmB,EACnB,gBAAgB,GACnB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACH,iBAAiB,EACjB,yBAAyB,EACzB,kBAAkB,EAClB,iBAAiB,EACjB,sBAAsB,EACtB,aAAa,GAChB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACH,cAAc,EACd,eAAe,EACf,cAAc,EACd,YAAY,GACf,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACH,YAAY,EACZ,mBAAmB,GACtB,MAAM,aAAa,CAAC;AAErB,YAAY,EACR,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,aAAa,EACb,SAAS,EACT,WAAW,EACX,UAAU,GACb,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
export { getProfile, listProfiles, registerProfile, } from "./registry.js";
|
|
9
9
|
export { diffProfiles, } from "./diff.js";
|
|
10
10
|
export { buildExpectedClientHello, validateProfileAgainstCapture, ValidationError, } from "./validate.js";
|
|
11
|
+
export { cipherSuiteToWire, CIPHER_GREASE_PLACEHOLDER, CIPHER_SUITE_CODES, NAMED_GROUP_CODES, SIGNATURE_SCHEME_CODES, VERSION_CODES, } from "./codes.js";
|
|
11
12
|
export { ChromeProfiles, FirefoxProfiles, SafariProfiles, EdgeProfiles, } from "./index.internal.js";
|
|
12
13
|
export { ProfileError, UnknownProfileError, } from "./errors.js";
|
|
13
14
|
export { assertNever } from "./utils.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACH,UAAU,EACV,YAAY,EACZ,eAAe,GAClB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACH,YAAY,GACf,MAAM,WAAW,CAAC;AAOnB,OAAO,EACH,wBAAwB,EACxB,6BAA6B,EAC7B,eAAe,GAClB,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACH,UAAU,EACV,YAAY,EACZ,eAAe,GAClB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACH,YAAY,GACf,MAAM,WAAW,CAAC;AAOnB,OAAO,EACH,wBAAwB,EACxB,6BAA6B,EAC7B,eAAe,GAClB,MAAM,eAAe,CAAC;AAQvB,OAAO,EACH,iBAAiB,EACjB,yBAAyB,EACzB,kBAAkB,EAClB,iBAAiB,EACjB,sBAAsB,EACtB,aAAa,GAChB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACH,cAAc,EACd,eAAe,EACf,cAAc,EACd,YAAY,GACf,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACH,YAAY,EACZ,mBAAmB,GACtB,MAAM,aAAa,CAAC;AAarB,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -1,10 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Chrome fingerprint definitions.
|
|
3
3
|
*
|
|
4
|
-
* TLS values
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* TLS values are byte-accurate against real curl-impersonate ClientHello
|
|
5
|
+
* captures. The authoritative ground truth is the lwthiker/curl-impersonate
|
|
6
|
+
* wire captures (testing-worktree/captures/_probe/output/chrome*.json) together
|
|
7
|
+
* with their reported ja3 / ja4 / peetprint fingerprints. Every value here is
|
|
8
|
+
* verified against those captures:
|
|
9
|
+
*
|
|
10
|
+
* - chrome-120: ja3 698f6d684588ddc1217dfb4454916129, peetprint
|
|
11
|
+
* 8ad9325e12f531d2983b78860de7b0ec (no post-quantum group).
|
|
12
|
+
* - chrome-124..130: X25519Kyber768 (0x6399) added to supported_groups.
|
|
13
|
+
* - chrome-131+: X25519MLKEM768 (0x11ec) replaces Kyber768; the
|
|
14
|
+
* application_settings extension moves from 17513 to 17613.
|
|
15
|
+
*
|
|
16
|
+
* Chrome permutes its extension order at runtime (tls_permute_extensions), so
|
|
17
|
+
* `extensionOrder` stores the canonical pre-permutation seed that
|
|
18
|
+
* curl-impersonate configures — matching the peetprint's normalized order.
|
|
19
|
+
* GREASE slots are tracked separately via the `grease` flag; the runtime
|
|
20
|
+
* randomizes the actual 0x?a?a values per RFC 8701.
|
|
8
21
|
*/
|
|
9
22
|
import type { BrowserProfile } from "../types.js";
|
|
10
23
|
export declare const chrome120: BrowserProfile;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chrome.d.ts","sourceRoot":"","sources":["../../src/profiles/chrome.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"chrome.d.ts","sourceRoot":"","sources":["../../src/profiles/chrome.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAa,MAAM,aAAa,CAAC;AAwF7D,eAAO,MAAM,SAAS,EAAE,cA+BvB,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,cA+BvB,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,cA+BvB,CAAC;AAEF,eAAO,MAAM,cAAc;;;;CAIjB,CAAC"}
|
package/dist/profiles/chrome.js
CHANGED
|
@@ -1,19 +1,39 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Chrome fingerprint definitions.
|
|
3
3
|
*
|
|
4
|
-
* TLS values
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* TLS values are byte-accurate against real curl-impersonate ClientHello
|
|
5
|
+
* captures. The authoritative ground truth is the lwthiker/curl-impersonate
|
|
6
|
+
* wire captures (testing-worktree/captures/_probe/output/chrome*.json) together
|
|
7
|
+
* with their reported ja3 / ja4 / peetprint fingerprints. Every value here is
|
|
8
|
+
* verified against those captures:
|
|
9
|
+
*
|
|
10
|
+
* - chrome-120: ja3 698f6d684588ddc1217dfb4454916129, peetprint
|
|
11
|
+
* 8ad9325e12f531d2983b78860de7b0ec (no post-quantum group).
|
|
12
|
+
* - chrome-124..130: X25519Kyber768 (0x6399) added to supported_groups.
|
|
13
|
+
* - chrome-131+: X25519MLKEM768 (0x11ec) replaces Kyber768; the
|
|
14
|
+
* application_settings extension moves from 17513 to 17613.
|
|
15
|
+
*
|
|
16
|
+
* Chrome permutes its extension order at runtime (tls_permute_extensions), so
|
|
17
|
+
* `extensionOrder` stores the canonical pre-permutation seed that
|
|
18
|
+
* curl-impersonate configures — matching the peetprint's normalized order.
|
|
19
|
+
* GREASE slots are tracked separately via the `grease` flag; the runtime
|
|
20
|
+
* randomizes the actual 0x?a?a values per RFC 8701.
|
|
8
21
|
*/
|
|
9
22
|
/** TLS 1.3 GREASE placeholder cipher (0x?a?a) Chrome inserts at the top of the list. */
|
|
10
23
|
const GREASE = "TLS_GREASE_RESERVED_0";
|
|
24
|
+
/**
|
|
25
|
+
* Canonical (pre-permutation) Chrome extension order.
|
|
26
|
+
*
|
|
27
|
+
* Mirrors the peetprint-normalized order `0-10-11-13-16-APP_SETTINGS-18-23-27-
|
|
28
|
+
* 35-43-45-5-51-65037-65281`. The only version-dependent slot is the
|
|
29
|
+
* application_settings extension: 17513 (application_settings_old) through
|
|
30
|
+
* chrome ~131, then 17613 (application_settings) from chrome ~132 onward.
|
|
31
|
+
*/
|
|
32
|
+
const chromeExtensionOrder = (appSettings) => [
|
|
33
|
+
0, 10, 11, 13, 16, appSettings, 18, 23, 27, 35, 43, 45, 5, 51, 65037, 65281,
|
|
34
|
+
];
|
|
11
35
|
const chromeTlsBase = {
|
|
12
|
-
extensionOrder: [
|
|
13
|
-
0, 10, 11, 13, 16, 17513, 18, 23, 27, 35, 41, 43, 45, 5, 51, 65281,
|
|
14
|
-
],
|
|
15
36
|
supportedVersions: ["TLS 1.3", "TLS 1.2"],
|
|
16
|
-
keyShareGroups: ["x25519", "secp256r1"],
|
|
17
37
|
signatureAlgorithms: [
|
|
18
38
|
"ecdsa_secp256r1_sha256",
|
|
19
39
|
"rsa_pss_rsae_sha256",
|
|
@@ -21,6 +41,8 @@ const chromeTlsBase = {
|
|
|
21
41
|
"ecdsa_secp384r1_sha384",
|
|
22
42
|
"rsa_pss_rsae_sha384",
|
|
23
43
|
"rsa_pkcs1_sha384",
|
|
44
|
+
"rsa_pss_rsae_sha512",
|
|
45
|
+
"rsa_pkcs1_sha512",
|
|
24
46
|
],
|
|
25
47
|
grease: true,
|
|
26
48
|
};
|
|
@@ -30,6 +52,14 @@ const chromeHttp2Base = {
|
|
|
30
52
|
headerTableSize: 65536,
|
|
31
53
|
weight: 256,
|
|
32
54
|
};
|
|
55
|
+
const chromeHttp2Settings = {
|
|
56
|
+
headerTableSize: 65536,
|
|
57
|
+
enablePush: false,
|
|
58
|
+
maxConcurrentStreams: 100,
|
|
59
|
+
initialWindowSize: 6291456,
|
|
60
|
+
maxFrameSize: 16384,
|
|
61
|
+
maxHeaderListSize: 262144,
|
|
62
|
+
};
|
|
33
63
|
const chromeHttp1Base = {
|
|
34
64
|
connection: "keep-alive",
|
|
35
65
|
acceptEncoding: "gzip, deflate, br",
|
|
@@ -50,40 +80,37 @@ const chromeHttp1Base = {
|
|
|
50
80
|
"accept-language",
|
|
51
81
|
],
|
|
52
82
|
};
|
|
83
|
+
const chromeCipherSuites = [
|
|
84
|
+
GREASE,
|
|
85
|
+
"TLS_AES_128_GCM_SHA256",
|
|
86
|
+
"TLS_AES_256_GCM_SHA384",
|
|
87
|
+
"TLS_CHACHA20_POLY1305_SHA256",
|
|
88
|
+
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
|
89
|
+
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
|
90
|
+
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
|
|
91
|
+
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
|
|
92
|
+
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
|
|
93
|
+
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
|
|
94
|
+
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
|
|
95
|
+
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
|
|
96
|
+
"TLS_RSA_WITH_AES_128_GCM_SHA256",
|
|
97
|
+
"TLS_RSA_WITH_AES_256_GCM_SHA384",
|
|
98
|
+
"TLS_RSA_WITH_AES_128_CBC_SHA",
|
|
99
|
+
"TLS_RSA_WITH_AES_256_CBC_SHA",
|
|
100
|
+
];
|
|
53
101
|
export const chrome120 = {
|
|
54
102
|
id: "chrome-120",
|
|
55
103
|
name: "chrome",
|
|
56
104
|
version: "120.0.6099.71",
|
|
57
105
|
tls: {
|
|
58
106
|
...chromeTlsBase,
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
"TLS_AES_256_GCM_SHA384",
|
|
63
|
-
"TLS_CHACHA20_POLY1305_SHA256",
|
|
64
|
-
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
|
65
|
-
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
|
66
|
-
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
|
|
67
|
-
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
|
|
68
|
-
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
|
|
69
|
-
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
|
|
70
|
-
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
|
|
71
|
-
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
|
|
72
|
-
"TLS_RSA_WITH_AES_128_GCM_SHA256",
|
|
73
|
-
"TLS_RSA_WITH_AES_256_GCM_SHA384",
|
|
74
|
-
"TLS_RSA_WITH_AES_128_CBC_SHA",
|
|
75
|
-
"TLS_RSA_WITH_AES_256_CBC_SHA",
|
|
76
|
-
],
|
|
107
|
+
extensionOrder: chromeExtensionOrder(17513),
|
|
108
|
+
keyShareGroups: ["x25519", "secp256r1", "secp384r1"],
|
|
109
|
+
cipherSuites: chromeCipherSuites,
|
|
77
110
|
},
|
|
78
111
|
http2: {
|
|
79
112
|
...chromeHttp2Base,
|
|
80
|
-
settings:
|
|
81
|
-
headerTableSize: 65536,
|
|
82
|
-
enablePush: false,
|
|
83
|
-
maxConcurrentStreams: 100,
|
|
84
|
-
initialWindowSize: 6291456,
|
|
85
|
-
maxFrameSize: 16384,
|
|
86
|
-
},
|
|
113
|
+
settings: chromeHttp2Settings,
|
|
87
114
|
},
|
|
88
115
|
http1: {
|
|
89
116
|
...chromeHttp1Base,
|
|
@@ -108,34 +135,13 @@ export const chrome128 = {
|
|
|
108
135
|
version: "128.0.6613.137",
|
|
109
136
|
tls: {
|
|
110
137
|
...chromeTlsBase,
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
"TLS_AES_256_GCM_SHA384",
|
|
115
|
-
"TLS_CHACHA20_POLY1305_SHA256",
|
|
116
|
-
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
|
117
|
-
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
|
118
|
-
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
|
|
119
|
-
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
|
|
120
|
-
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
|
|
121
|
-
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
|
|
122
|
-
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
|
|
123
|
-
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
|
|
124
|
-
"TLS_RSA_WITH_AES_128_GCM_SHA256",
|
|
125
|
-
"TLS_RSA_WITH_AES_256_GCM_SHA384",
|
|
126
|
-
"TLS_RSA_WITH_AES_128_CBC_SHA",
|
|
127
|
-
"TLS_RSA_WITH_AES_256_CBC_SHA",
|
|
128
|
-
],
|
|
138
|
+
extensionOrder: chromeExtensionOrder(17513),
|
|
139
|
+
keyShareGroups: ["X25519Kyber768", "x25519", "secp256r1", "secp384r1"],
|
|
140
|
+
cipherSuites: chromeCipherSuites,
|
|
129
141
|
},
|
|
130
142
|
http2: {
|
|
131
143
|
...chromeHttp2Base,
|
|
132
|
-
settings:
|
|
133
|
-
headerTableSize: 65536,
|
|
134
|
-
enablePush: false,
|
|
135
|
-
maxConcurrentStreams: 100,
|
|
136
|
-
initialWindowSize: 6291456,
|
|
137
|
-
maxFrameSize: 16384,
|
|
138
|
-
},
|
|
144
|
+
settings: chromeHttp2Settings,
|
|
139
145
|
},
|
|
140
146
|
http1: {
|
|
141
147
|
...chromeHttp1Base,
|
|
@@ -160,34 +166,13 @@ export const chrome140 = {
|
|
|
160
166
|
version: "140.0.7339.18",
|
|
161
167
|
tls: {
|
|
162
168
|
...chromeTlsBase,
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
"TLS_AES_256_GCM_SHA384",
|
|
167
|
-
"TLS_CHACHA20_POLY1305_SHA256",
|
|
168
|
-
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
|
169
|
-
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
|
170
|
-
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
|
|
171
|
-
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
|
|
172
|
-
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
|
|
173
|
-
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
|
|
174
|
-
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
|
|
175
|
-
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
|
|
176
|
-
"TLS_RSA_WITH_AES_128_GCM_SHA256",
|
|
177
|
-
"TLS_RSA_WITH_AES_256_GCM_SHA384",
|
|
178
|
-
"TLS_RSA_WITH_AES_128_CBC_SHA",
|
|
179
|
-
"TLS_RSA_WITH_AES_256_CBC_SHA",
|
|
180
|
-
],
|
|
169
|
+
extensionOrder: chromeExtensionOrder(17613),
|
|
170
|
+
keyShareGroups: ["X25519MLKEM768", "x25519", "secp256r1", "secp384r1"],
|
|
171
|
+
cipherSuites: chromeCipherSuites,
|
|
181
172
|
},
|
|
182
173
|
http2: {
|
|
183
174
|
...chromeHttp2Base,
|
|
184
|
-
settings:
|
|
185
|
-
headerTableSize: 65536,
|
|
186
|
-
enablePush: false,
|
|
187
|
-
maxConcurrentStreams: 100,
|
|
188
|
-
initialWindowSize: 6291456,
|
|
189
|
-
maxFrameSize: 16384,
|
|
190
|
-
},
|
|
175
|
+
settings: chromeHttp2Settings,
|
|
191
176
|
},
|
|
192
177
|
http1: {
|
|
193
178
|
...chromeHttp1Base,
|