mirror of
https://github.com/MetaCubeX/mihomo.git
synced 2025-12-19 16:30:07 +08:00
Some checks are pending
Test / test (1.20, macos-13) (push) Waiting to run
Test / test (1.20, macos-latest) (push) Waiting to run
Test / test (1.20, ubuntu-24.04-arm) (push) Waiting to run
Test / test (1.20, ubuntu-latest) (push) Waiting to run
Test / test (1.20, windows-latest) (push) Waiting to run
Test / test (1.21, macos-13) (push) Waiting to run
Test / test (1.21, macos-latest) (push) Waiting to run
Test / test (1.21, ubuntu-24.04-arm) (push) Waiting to run
Test / test (1.21, ubuntu-latest) (push) Waiting to run
Test / test (1.21, windows-latest) (push) Waiting to run
Test / test (1.22, macos-13) (push) Waiting to run
Test / test (1.22, macos-latest) (push) Waiting to run
Test / test (1.22, ubuntu-24.04-arm) (push) Waiting to run
Test / test (1.22, ubuntu-latest) (push) Waiting to run
Test / test (1.22, windows-latest) (push) Waiting to run
Test / test (1.23, macos-13) (push) Waiting to run
Test / test (1.23, macos-latest) (push) Waiting to run
Test / test (1.23, ubuntu-24.04-arm) (push) Waiting to run
Test / test (1.23, ubuntu-latest) (push) Waiting to run
Test / test (1.23, windows-latest) (push) Waiting to run
Test / test (1.24, macos-13) (push) Waiting to run
Test / test (1.24, macos-latest) (push) Waiting to run
Test / test (1.24, ubuntu-24.04-arm) (push) Waiting to run
Test / test (1.24, ubuntu-latest) (push) Waiting to run
Test / test (1.24, windows-latest) (push) Waiting to run
Test / test (1.25, macos-13) (push) Waiting to run
Test / test (1.25, macos-latest) (push) Waiting to run
Test / test (1.25, ubuntu-24.04-arm) (push) Waiting to run
Test / test (1.25, ubuntu-latest) (push) Waiting to run
Test / test (1.25, windows-latest) (push) Waiting to run
Trigger CMFA Update / trigger-CMFA-update (push) Waiting to run
77 lines
2.5 KiB
Go
77 lines
2.5 KiB
Go
package ca
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/sha256"
|
|
"crypto/x509"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// NewFingerprintVerifier returns a function that verifies whether a certificate's SHA-256 fingerprint matches the given one.
|
|
func NewFingerprintVerifier(fingerprint string, time func() time.Time) (func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error, error) {
|
|
switch fingerprint {
|
|
case "chrome", "firefox", "safari", "ios", "android", "edge", "360", "qq", "random", "randomized": // WTF???
|
|
return nil, fmt.Errorf("`fingerprint` is used for TLS certificate pinning. If you need to specify the browser fingerprint, use `client-fingerprint`")
|
|
}
|
|
fingerprint = strings.TrimSpace(strings.Replace(fingerprint, ":", "", -1))
|
|
fpByte, err := hex.DecodeString(fingerprint)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("fingerprint string decode error: %w", err)
|
|
}
|
|
|
|
if len(fpByte) != 32 {
|
|
return nil, fmt.Errorf("fingerprint string length error,need sha256 fingerprint")
|
|
}
|
|
|
|
return func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
|
|
// ssl pining
|
|
for i, rawCert := range rawCerts {
|
|
hash := sha256.Sum256(rawCert)
|
|
if bytes.Equal(fpByte, hash[:]) {
|
|
if i > 0 {
|
|
|
|
// When the fingerprint matches a non-leaf certificate,
|
|
// the certificate chain validity is verified using the certificate as the trusted root certificate.
|
|
//
|
|
// Currently, we do not verify that the SNI matches the certificate's DNS name,
|
|
// but we do verify the validity of the child certificate,
|
|
// including the issuance time and whether the child certificate was issued by the parent certificate.
|
|
|
|
certs := make([]*x509.Certificate, i+1) // stop at i
|
|
for j := range certs {
|
|
cert, err := x509.ParseCertificate(rawCerts[j])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
certs[j] = cert
|
|
}
|
|
opts := x509.VerifyOptions{
|
|
Roots: x509.NewCertPool(),
|
|
Intermediates: x509.NewCertPool(),
|
|
}
|
|
if time != nil {
|
|
opts.CurrentTime = time()
|
|
}
|
|
opts.Roots.AddCert(certs[i])
|
|
for _, cert := range certs[1:] {
|
|
opts.Intermediates.AddCert(cert)
|
|
}
|
|
_, err := certs[0].Verify(opts)
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
}
|
|
return errNotMatch
|
|
}, nil
|
|
}
|
|
|
|
// CalculateFingerprint computes the SHA-256 fingerprint of the given DER-encoded certificate and returns it as a hex string.
|
|
func CalculateFingerprint(certDER []byte) string {
|
|
hash := sha256.Sum256(certDER)
|
|
return hex.EncodeToString(hash[:])
|
|
}
|