main.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. package main
  2. import (
  3. "encoding/csv"
  4. "io"
  5. "net/http"
  6. "os"
  7. "path/filepath"
  8. "strings"
  9. "github.com/sagernet/sing-box/log"
  10. "golang.org/x/exp/slices"
  11. )
  12. func main() {
  13. err := updateMozillaIncludedRootCAs()
  14. if err != nil {
  15. log.Error(err)
  16. }
  17. err = updateChromeIncludedRootCAs()
  18. if err != nil {
  19. log.Error(err)
  20. }
  21. }
  22. func updateMozillaIncludedRootCAs() error {
  23. response, err := http.Get("https://ccadb.my.salesforce-sites.com/mozilla/IncludedCACertificateReportPEMCSV")
  24. if err != nil {
  25. return err
  26. }
  27. defer response.Body.Close()
  28. reader := csv.NewReader(response.Body)
  29. header, err := reader.Read()
  30. if err != nil {
  31. return err
  32. }
  33. geoIndex := slices.Index(header, "Geographic Focus")
  34. certIndex := slices.Index(header, "PEM Info")
  35. pemBundle := strings.Builder{}
  36. for {
  37. record, err := reader.Read()
  38. if err == io.EOF {
  39. break
  40. } else if err != nil {
  41. return err
  42. }
  43. if record[geoIndex] == "China" {
  44. continue
  45. }
  46. cert := record[certIndex]
  47. cert = cert[1 : len(cert)-1]
  48. pemBundle.WriteString(cert)
  49. pemBundle.WriteString("\n")
  50. }
  51. return writeGeneratedCertificateBundle("mozilla", "mozillaIncluded", pemBundle.String())
  52. }
  53. func fetchChinaFingerprints() (map[string]bool, error) {
  54. response, err := http.Get("https://ccadb.my.salesforce-sites.com/ccadb/AllCertificateRecordsCSVFormatv4")
  55. if err != nil {
  56. return nil, err
  57. }
  58. defer response.Body.Close()
  59. reader := csv.NewReader(response.Body)
  60. header, err := reader.Read()
  61. if err != nil {
  62. return nil, err
  63. }
  64. countryIndex := slices.Index(header, "Country")
  65. fingerprintIndex := slices.Index(header, "SHA-256 Fingerprint")
  66. chinaFingerprints := make(map[string]bool)
  67. for {
  68. record, err := reader.Read()
  69. if err == io.EOF {
  70. break
  71. } else if err != nil {
  72. return nil, err
  73. }
  74. if record[countryIndex] == "China" {
  75. chinaFingerprints[record[fingerprintIndex]] = true
  76. }
  77. }
  78. return chinaFingerprints, nil
  79. }
  80. func updateChromeIncludedRootCAs() error {
  81. chinaFingerprints, err := fetchChinaFingerprints()
  82. if err != nil {
  83. return err
  84. }
  85. response, err := http.Get("https://ccadb.my.salesforce-sites.com/ccadb/RootCACertificatesIncludedByRSReportCSV")
  86. if err != nil {
  87. return err
  88. }
  89. defer response.Body.Close()
  90. reader := csv.NewReader(response.Body)
  91. header, err := reader.Read()
  92. if err != nil {
  93. return err
  94. }
  95. statusIndex := slices.Index(header, "Google Chrome Status")
  96. certIndex := slices.Index(header, "X.509 Certificate (PEM)")
  97. fingerprintIndex := slices.Index(header, "SHA-256 Fingerprint")
  98. pemBundle := strings.Builder{}
  99. for {
  100. record, err := reader.Read()
  101. if err == io.EOF {
  102. break
  103. } else if err != nil {
  104. return err
  105. }
  106. if record[statusIndex] != "Included" {
  107. continue
  108. }
  109. if chinaFingerprints[record[fingerprintIndex]] {
  110. continue
  111. }
  112. cert := record[certIndex]
  113. if len(cert) > 0 && cert[0] == '\'' {
  114. cert = cert[1 : len(cert)-1]
  115. }
  116. pemBundle.WriteString(cert)
  117. pemBundle.WriteString("\n")
  118. }
  119. return writeGeneratedCertificateBundle("chrome", "chromeIncluded", pemBundle.String())
  120. }
  121. func writeGeneratedCertificateBundle(name string, variableName string, pemBundle string) error {
  122. goSource := `// Code generated by 'make update_certificates'. DO NOT EDIT.
  123. package certificate
  124. import (
  125. "crypto/x509"
  126. _ "embed"
  127. )
  128. //go:embed ` + name + `.pem
  129. var ` + variableName + `PEM string
  130. var ` + variableName + ` *x509.CertPool
  131. func init() {
  132. ` + variableName + ` = x509.NewCertPool()
  133. ` + variableName + `.AppendCertsFromPEM([]byte(` + variableName + `PEM))
  134. }
  135. `
  136. err := os.WriteFile(filepath.Join("common/certificate", name+".pem"), []byte(pemBundle), 0o644)
  137. if err != nil {
  138. return err
  139. }
  140. return os.WriteFile(filepath.Join("common/certificate", name+".go"), []byte(goSource), 0o644)
  141. }