Skip to content

Instantly share code, notes, and snippets.

@xkdvSrPD
Forked from hsqStephenZhang/main.go
Last active April 8, 2025 08:11
Show Gist options
  • Save xkdvSrPD/1558e37031e5ca970200900bd22ace53 to your computer and use it in GitHub Desktop.
Save xkdvSrPD/1558e37031e5ca970200900bd22ace53 to your computer and use it in GitHub Desktop.
golang utls fingerprint
// to start the project:
// go mod init
// go get -u github.com/imroc/req/v3
// 在Xray中,使用vsion且设置TLs指纹为safari时,对其JA4指纹sha512后,后六位是
package main
import (
"crypto/sha512"
"encoding/hex"
"encoding/json"
"flag"
"fmt"
"io/ioutil"
"os"
"github.com/imroc/req/v3"
tls "github.com/refraction-networking/utls"
)
func main() {
// Define a command-line argument to accept the desired fingerprint
fingerprintArg := flag.String("fingerprint", "chrome", "Specify the fingerprint (e.g., chrome, edge, firefox, safari)")
flag.Parse()
// Map of fingerprints to their corresponding utls ClientHelloID
fingerprintMap := map[string]tls.ClientHelloID{
"chrome": tls.HelloChrome_115_PQ,
"edge": tls.HelloEdge_106,
"firefox": tls.HelloFirefox_105,
"safari": tls.HelloSafari_16_0,
"ios": tls.HelloIOS_14,
}
// Match the provided argument to a fingerprint
fingerprintID, exists := fingerprintMap[*fingerprintArg]
if !exists {
fmt.Fprintf(os.Stderr, "Invalid fingerprint: %s\n", *fingerprintArg)
fmt.Fprintf(os.Stderr, "Available fingerprints: chrome, edge, firefox, safari\n")
os.Exit(1)
}
// Create the HTTP client with the specified fingerprint
client := req.C().
SetUserAgent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36").
SetTLSFingerprint(fingerprintID)
// Make a GET request
res, err := client.R().Get("https://tls.peet.ws/api/all")
if err != nil {
fmt.Printf("Request failed: %v\n", err)
os.Exit(1)
}
// Print the response
fmt.Println(res)
// Read the response body into a string
responseBody, err := ioutil.ReadAll(res.Body)
if err != nil {
fmt.Printf("Failed to read response body: %v\n", err)
os.Exit(1)
}
defer res.Body.Close() // Close the response body after reading
// Convert the response body to a string
responseBodyStr := string(responseBody)
// Extract the JA4 fingerprint
ja4, err := extractJA4Fingerprint(responseBodyStr)
if err != nil {
fmt.Printf("Failed to extract JA4 fingerprint: %v\n", err)
os.Exit(1)
}
// Compute the SHA-512 hash of the JA4 fingerprint
sha512Hash := computeSHA512(ja4)
// Output the results
fmt.Printf("JA4 Fingerprint: %s\n", ja4)
fmt.Printf("SHA-512 Hash: %s\n", sha512Hash)
fmt.Printf("Last Six Characters: %s\n", getLastSixCharacters(sha512Hash))
}
// extractJA4Fingerprint extracts the JA4 fingerprint from the response body
func extractJA4Fingerprint(responseBody string) (string, error) {
// Parse the response body as JSON
var result map[string]interface{}
if err := json.Unmarshal([]byte(responseBody), &result); err != nil {
return "", fmt.Errorf("failed to parse JSON response: %v", err)
}
// Extract the TLS section
tlsData, ok := result["tls"].(map[string]interface{})
if !ok {
return "", fmt.Errorf("no TLS data found in the response")
}
// Extract the ja4 field
ja4, ok := tlsData["ja4"].(string)
if !ok {
return "", fmt.Errorf("no ja4 field found in the TLS data")
}
return ja4, nil
}
// computeSHA512 computes the SHA-512 hash of a given string
func computeSHA512(input string) string {
hasher := sha512.New()
hasher.Write([]byte(input))
hashBytes := hasher.Sum(nil)
return hex.EncodeToString(hashBytes)
}
// getLastSixCharacters returns the last six characters of a string
func getLastSixCharacters(input string) string {
if len(input) < 6 {
return input
}
return input[len(input)-6:]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment