diff --git a/profiles/contributed_browser_profiles.go b/profiles/contributed_browser_profiles.go index 0848543..a434936 100644 --- a/profiles/contributed_browser_profiles.go +++ b/profiles/contributed_browser_profiles.go @@ -6,6 +6,116 @@ import ( "github.com/bogdanfinn/utls/dicttls" ) +var Chrome_131_PSK = ClientProfile{ + clientHelloId: tls.ClientHelloID{ + Client: "Chrome", + RandomExtensionOrder: false, + Version: "131", + Seed: nil, + SpecFactory: func() (tls.ClientHelloSpec, error) { + return tls.ClientHelloSpec{ + CipherSuites: []uint16{ + tls.GREASE_PLACEHOLDER, + tls.TLS_AES_128_GCM_SHA256, + tls.TLS_AES_256_GCM_SHA384, + tls.TLS_CHACHA20_POLY1305_SHA256, + tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, + tls.TLS_RSA_WITH_AES_128_GCM_SHA256, + tls.TLS_RSA_WITH_AES_256_GCM_SHA384, + tls.TLS_RSA_WITH_AES_128_CBC_SHA, + tls.TLS_RSA_WITH_AES_256_CBC_SHA, + }, + CompressionMethods: []byte{ + tls.CompressionNone, + }, + Extensions: []tls.TLSExtension{ + &tls.UtlsGREASEExtension{}, + &tls.SignatureAlgorithmsExtension{SupportedSignatureAlgorithms: []tls.SignatureScheme{ + tls.ECDSAWithP256AndSHA256, + tls.PSSWithSHA256, + tls.PKCS1WithSHA256, + tls.ECDSAWithP384AndSHA384, + tls.PSSWithSHA384, + tls.PKCS1WithSHA384, + tls.PSSWithSHA512, + tls.PKCS1WithSHA512, + }}, + tls.BoringGREASEECH(), + &tls.RenegotiationInfoExtension{ + Renegotiation: tls.RenegotiateOnceAsClient, + }, + &tls.SCTExtension{}, + &tls.UtlsCompressCertExtension{Algorithms: []tls.CertCompressionAlgo{ + tls.CertCompressionBrotli, + }}, + &tls.ALPNExtension{AlpnProtocols: []string{ + "h2", + "http/1.1", + }}, + &tls.StatusRequestExtension{}, + &tls.SupportedCurvesExtension{Curves: []tls.CurveID{ + tls.GREASE_PLACEHOLDER, + tls.X25519MLKEM768, + tls.X25519, + tls.CurveP256, + tls.CurveP384, + }}, + &tls.ApplicationSettingsExtension{SupportedProtocols: []string{ + "h2", + }}, + &tls.SupportedPointsExtension{SupportedPoints: []byte{ + tls.PointFormatUncompressed, + }}, + &tls.KeyShareExtension{KeyShares: []tls.KeyShare{ + {Group: tls.CurveID(tls.GREASE_PLACEHOLDER), Data: []byte{0}}, + {Group: tls.X25519MLKEM768}, + {Group: tls.X25519}, + }}, + &tls.SessionTicketExtension{}, + &tls.SupportedVersionsExtension{Versions: []uint16{ + tls.GREASE_PLACEHOLDER, + tls.VersionTLS13, + tls.VersionTLS12, + }}, + &tls.PSKKeyExchangeModesExtension{Modes: []uint8{ + tls.PskModeDHE, + }}, + &tls.SNIExtension{}, + &tls.ExtendedMasterSecretExtension{}, + &tls.UtlsGREASEExtension{}, + &tls.UtlsPreSharedKeyExtension{}, + }, + }, nil + }, + }, + settings: map[http2.SettingID]uint32{ + http2.SettingHeaderTableSize: 65536, + http2.SettingEnablePush: 0, + http2.SettingInitialWindowSize: 6291456, + http2.SettingMaxHeaderListSize: 262144, + }, + settingsOrder: []http2.SettingID{ + http2.SettingHeaderTableSize, + http2.SettingEnablePush, + http2.SettingInitialWindowSize, + http2.SettingMaxHeaderListSize, + }, + pseudoHeaderOrder: []string{ + ":method", + ":authority", + ":scheme", + ":path", + }, + connectionFlow: 15663105, +} + var Chrome_131 = ClientProfile{ clientHelloId: tls.ClientHelloID{ Client: "Chrome", diff --git a/profiles/profiles.go b/profiles/profiles.go index 32851ca..d88f2c4 100644 --- a/profiles/profiles.go +++ b/profiles/profiles.go @@ -24,6 +24,7 @@ var MappedTLSClients = map[string]ClientProfile{ "chrome_120": Chrome_120, "chrome_124": Chrome_124, "chrome_131": Chrome_131, + "chrome_131_PSK": Chrome_131_PSK, "safari_15_6_1": Safari_15_6_1, "safari_16_0": Safari_16_0, "safari_ipad_15_6": Safari_Ipad_15_6, diff --git a/tests/client_test.go b/tests/client_test.go index 597ad28..3795e71 100644 --- a/tests/client_test.go +++ b/tests/client_test.go @@ -14,6 +14,8 @@ import ( ) func TestClients(t *testing.T) { + t.Log("testing chrome 131") + chrome_131(t) t.Log("testing chrome 124") chrome_124(t) t.Log("testing chrome 120") @@ -78,6 +80,9 @@ func TestClients(t *testing.T) { t.Log("testing firefox 110") firefox_110(t) time.Sleep(2 * time.Second) + t.Log("testing firefox 124") + firefox_132(t) + time.Sleep(2 * time.Second) t.Log("testing opera 91") opera_91(t) } @@ -567,6 +572,31 @@ func chrome_124(t *testing.T) { compareResponse(t, "chrome", clientFingerprints[chrome][profiles.Chrome_124.GetClientHelloStr()], resp) } +func chrome_131(t *testing.T) { + options := []tls_client.HttpClientOption{ + tls_client.WithClientProfile(profiles.Chrome_131), + } + + client, err := tls_client.NewHttpClient(nil, options...) + if err != nil { + t.Fatal(err) + } + + req, err := http.NewRequest(http.MethodGet, peetApiEndpoint, nil) + if err != nil { + t.Fatal(err) + } + + req.Header = defaultHeader + + resp, err := client.Do(req) + if err != nil { + t.Fatal(err) + } + + compareResponse(t, "chrome", clientFingerprints[chrome][profiles.Chrome_131.GetClientHelloStr()], resp) +} + func chrome_120(t *testing.T) { options := []tls_client.HttpClientOption{ tls_client.WithClientProfile(profiles.Chrome_120), @@ -667,6 +697,31 @@ func firefox_110(t *testing.T) { compareResponse(t, "firefox", clientFingerprints[firefox][tls.HelloFirefox_110.Str()], resp) } +func firefox_132(t *testing.T) { + options := []tls_client.HttpClientOption{ + tls_client.WithClientProfile(profiles.Firefox_132), + } + + client, err := tls_client.NewHttpClient(nil, options...) + if err != nil { + t.Fatal(err) + } + + req, err := http.NewRequest(http.MethodGet, peetApiEndpoint, nil) + if err != nil { + t.Fatal(err) + } + + req.Header = defaultHeader + + resp, err := client.Do(req) + if err != nil { + t.Fatal(err) + } + + compareResponse(t, "firefox", clientFingerprints[firefox][profiles.Firefox_132.GetClientHelloStr()], resp) +} + func opera_91(t *testing.T) { options := []tls_client.HttpClientOption{ tls_client.WithClientProfile(profiles.Opera_91), diff --git a/tests/client_test_utils.go b/tests/client_test_utils.go index aa8f26e..952ea5f 100644 --- a/tests/client_test_utils.go +++ b/tests/client_test_utils.go @@ -82,6 +82,12 @@ const ( var clientFingerprints = map[string]map[string]map[string]string{ chrome: { + profiles.Chrome_131.GetClientHelloStr(): map[string]string{ + ja3String: "771,4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53,13-65037-65281-18-27-16-5-10-17513-11-51-35-43-45-0-23,4588-29-23-24,0", + ja3Hash: "a19ab9f02aacf42deddc1f2acb3d3f63", + akamaiFingerprint: "1:65536;2:0;4:6291456;6:262144|15663105|0|m,a,s,p", + akamaiFingerprintHash: "52d84b11737d980aef856699f885ca86", + }, profiles.Chrome_124.GetClientHelloStr(): map[string]string{ ja3String: "771,4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53,27-18-23-17513-16-43-13-11-0-35-10-65037-5-65281-45-51,25497-29-23-24,0", ja3Hash: "64aff24dbef210f33880d4f62e1493dd", @@ -210,6 +216,12 @@ var clientFingerprints = map[string]map[string]map[string]string{ akamaiFingerprint: "1:65536;4:131072;5:16384|12517377|3:0:0:201,5:0:0:101,7:0:0:1,9:0:7:1,11:0:3:1,13:0:0:241|m,p,a,s", akamaiFingerprintHash: "3d9132023bf26a71d40fe766e5c24c9d", }, + profiles.Firefox_132.GetClientHelloStr(): map[string]string{ + ja3String: "771,4865-4867-4866-49195-49199-52393-52392-49196-49200-49162-49161-49171-49172-156-157-47-53,0-23-65281-10-11-16-5-34-51-43-13-28-27-65037,4588-29-23-24-25-256-257,0", + ja3Hash: "a767f8ae9115cc5752e5cff59612e74f", + akamaiFingerprint: "1:65536;2:0;4:131072;5:16384;9:1|12517377|0|m,p,a,s", + akamaiFingerprintHash: "a80d4d15d0c3bdd7b34b39d61cdaf0f7", + }, }, opera: { tls.HelloOpera_89.Str(): map[string]string{