Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for printing SCTs #277

Merged
merged 13 commits into from
Jun 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
certigo
certigo.exe
/gen-known-logs
man/
shell/
12 changes: 2 additions & 10 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,23 +1,15 @@
module github.com/square/certigo

require (
github.com/Masterminds/goutils v1.1.0 // indirect
github.com/Masterminds/semver v1.4.2 // indirect
github.com/Masterminds/sprig v2.22.0+incompatible
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc // indirect
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf // indirect
github.com/fatih/color v1.13.0
github.com/google/uuid v1.0.0 // indirect
github.com/huandu/xstrings v1.2.0 // indirect
github.com/imdario/mergo v0.3.6 // indirect
github.com/google/certificate-transparency-go v1.1.3
github.com/mattn/go-colorable v0.1.12
github.com/mitchellh/copystructure v1.0.0 // indirect
github.com/mwitkow/go-http-dialer v0.0.0-20161116154839-378f744fb2b8
github.com/stretchr/testify v1.7.5
golang.org/x/crypto v0.0.0-20220214200702-86341886e292
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4
gopkg.in/alecthomas/kingpin.v2 v2.2.6
gopkg.in/asn1-ber.v1 v1.0.0-20170511165959-379148ca0225
gopkg.in/yaml.v2 v2.4.0 // indirect
)

go 1.13
1,485 changes: 1,473 additions & 12 deletions go.sum

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions internal/gen-known-logs/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.PHONY: ctlogs

ctlogs:
go run github.com/square/certigo/internal/gen-known-logs --package lib > ../../lib/ctlogs.go
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this be a good candidate for go:generate? https://pkg.go.dev/cmd/go#hdr-Generate_Go_files_by_processing_source

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, good call. #279

go fmt ../../lib/ctlogs.go
9 changes: 9 additions & 0 deletions internal/gen-known-logs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# gen-known-logs

A tool for generating the list of CT logs that certigo uses for printing operator information and log URLs for SCTs.

Logs are fetched parsed from https://www.gstatic.com/ct/log_list/v2/all_logs_list.json, documented [here](https://github.com/google/certificate-transparency-community-site/blob/master/docs/google/known-logs.md).

## Usage

From the current directory (`certigo/internal/gen-known-logs`), run `make ctlogs`. This will fetch the list of logs and place generated code in [lib/ctlogs.go](../../lib/ctlogs.go).
69 changes: 69 additions & 0 deletions internal/gen-known-logs/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package main

import (
"encoding/json"
"flag"
"fmt"
"log"
"net/http"
"time"
)

var packageName = flag.String("package", "lib", "Package for the generated code")

// https://github.com/google/certificate-transparency-community-site/blob/master/docs/google/known-logs.md
const knownLogsAddr = "https://www.gstatic.com/ct/log_list/v2/all_logs_list.json"

type ctLog struct {
operator string
url string
}

func main() {
flag.Parse()

resp, err := http.Get(knownLogsAddr)
if err != nil {
log.Printf("Failed to fetch the list of known CT logs: %v", err)
return
}
defer resp.Body.Close()

var logs struct {
Operators []struct {
Name string `json:"name"`
Logs []struct {
ID string `json:"log_id"`
URL string `json:"url"`
} `json:"logs"`
} `json:"operators"`
}

if err := json.NewDecoder(resp.Body).Decode(&logs); err != nil {
log.Printf("Failed to parse the list of known CT logs: %v", err)
return
}

fmt.Printf(`// Autogenerated with github.com/square/certigo/internal/gen-known-logs
jdtw marked this conversation as resolved.
Show resolved Hide resolved
// Generated at %s
package %s

type ctLog struct {
operator string
url string
}

var knownLogs = map[string]*ctLog{
`, time.Now().Format(time.RFC3339), *packageName)
knownLogs := make(map[string]*ctLog)
for _, op := range logs.Operators {
for _, l := range op.Logs {
fmt.Printf("\t%q: {operator: %q, url: %q},\n", l.ID, op.Name, l.URL)
knownLogs[l.ID] = &ctLog{
operator: op.Name,
url: l.URL,
}
}
}
fmt.Println("}")
}
92 changes: 92 additions & 0 deletions lib/ct.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package lib

import (
"crypto/x509"
"encoding/asn1"
"encoding/base64"
"time"

cttls "github.com/google/certificate-transparency-go/tls"
ctx509 "github.com/google/certificate-transparency-go/x509"
ctutil "github.com/google/certificate-transparency-go/x509util"
)

func parseSCTList(cert *x509.Certificate) []*simpleSCT {
// ctutil contains a fork of crypto/x509 with support for SCTs. We must re-parse the
// whole certificate to get at them, so do a quick check to see if the SCT extension
// is present before re-parsing the cert unnecessarily.
if !hasSCTs(cert) {
return nil
}

var sctList []*simpleSCT
if scts, err := ctutil.ParseSCTsFromCertificate(cert.Raw); err == nil {
for _, sct := range scts {
id := sct.LogID.KeyID[:]
ssct := &simpleSCT{
Version: uint64(sct.SCTVersion),
LogID: id,
Timestamp: time.UnixMilli(int64(sct.Timestamp)),
SignatureAlgorithm: sctSignatureAlg(sct.Signature.Algorithm),
}
if log := getLogByID(id); log != nil {
ssct.LogOperator = log.operator
ssct.LogURL = log.url
}
sctList = append(sctList, ssct)
}
}
return sctList
}

func hasSCTs(cert *x509.Certificate) bool {
for _, e := range cert.Extensions {
if e.Id.Equal(asn1.ObjectIdentifier(ctx509.OIDExtensionCTSCT)) {
return true
}
}
return false
}

func getLogByID(id []byte) *ctLog {
b64 := base64.StdEncoding.EncodeToString(id)
return knownLogs[b64]
}

func sctSignatureAlg(alg cttls.SignatureAndHashAlgorithm) simpleSigAlg {
x509Alg := x509.UnknownSignatureAlgorithm
switch alg.Signature {
case cttls.RSA:
switch alg.Hash {
case cttls.MD5:
x509Alg = x509.MD5WithRSA
case cttls.SHA1:
x509Alg = x509.SHA1WithRSA
case cttls.SHA256:
x509Alg = x509.SHA256WithRSA
case cttls.SHA384:
x509Alg = x509.SHA384WithRSA
case cttls.SHA512:
x509Alg = x509.SHA512WithRSA
}
case cttls.DSA:
switch alg.Hash {
case cttls.SHA1:
x509Alg = x509.DSAWithSHA1
case cttls.SHA256:
x509Alg = x509.DSAWithSHA256
}
case cttls.ECDSA:
switch alg.Hash {
case cttls.SHA1:
x509Alg = x509.ECDSAWithSHA1
case cttls.SHA256:
x509Alg = x509.ECDSAWithSHA256
case cttls.SHA384:
x509Alg = x509.ECDSAWithSHA384
case cttls.SHA512:
x509Alg = x509.ECDSAWithSHA512
}
}
return simpleSigAlg(x509Alg)
}
120 changes: 120 additions & 0 deletions lib/ctlogs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// Autogenerated with github.com/square/certigo/internal/gen-known-logs
// Generated at 2022-06-29T17:31:27-07:00
package lib

type ctLog struct {
operator string
url string
}

var knownLogs = map[string]*ctLog{
"+tTJfMSe4vishcXqXOoJ0CINu/TknGtQZi/4aPhrjCg=": {operator: "Google", url: "https://ct.googleapis.com/logs/argon2017/"},
"pFASaQVaFVReYhGrN7wQP2KuVXakXksXFEU+GyIQaiU=": {operator: "Google", url: "https://ct.googleapis.com/logs/argon2018/"},
"Y/Lbzeg7zCzPC3KEJ1drM6SNYXePvXWmOLHHaFRL2I0=": {operator: "Google", url: "https://ct.googleapis.com/logs/argon2019/"},
"sh4FzIuizYogTodm+Su5iiUgZ2va+nDnsklTLe+LkF4=": {operator: "Google", url: "https://ct.googleapis.com/logs/argon2020/"},
"9lyUL9F3MCIUVBgIMJRWjuNNExkzv98MLyALzE7xZOM=": {operator: "Google", url: "https://ct.googleapis.com/logs/argon2021/"},
"KXm+8J45OSHwVnOfY6V35b5XfZxgCvj5TV0mXCVdx4Q=": {operator: "Google", url: "https://ct.googleapis.com/logs/argon2022/"},
"6D7Q2j71BjUy51covIlryQPTy9ERa+zraeF3fW0GvW4=": {operator: "Google", url: "https://ct.googleapis.com/logs/argon2023/"},
"sQzVWabWeEaBH335pRUyc5rEjXA76gMj2l04dVvArU4=": {operator: "Google", url: "https://ct.googleapis.com/logs/xenon2018/"},
"CEEUmABxUywWGQRgvPxH/cJlOvopLHKzf/hjrinMyfA=": {operator: "Google", url: "https://ct.googleapis.com/logs/xenon2019/"},
"B7dcG+V9aP/xsMYdIxXHuuZXfFeUt2ruvGE6GmnTohw=": {operator: "Google", url: "https://ct.googleapis.com/logs/xenon2020/"},
"fT7y+I//iFVoJMLAyp5SiXkrxQ54CX8uapdomX4i8Nc=": {operator: "Google", url: "https://ct.googleapis.com/logs/xenon2021/"},
"RqVV63X6kSAwtaKJafTzfREsQXS+/Um4havy/HD+bUc=": {operator: "Google", url: "https://ct.googleapis.com/logs/xenon2022/"},
"rfe++nz/EMiLnT2cHj4YarRnKV3PsQwkyoWGNOvcgoo=": {operator: "Google", url: "https://ct.googleapis.com/logs/xenon2023/"},
"aPaY+B9kgr46jO65KB1M/HFRXWeT1ETRCmesu09P+8Q=": {operator: "Google", url: "https://ct.googleapis.com/aviator/"},
"KTxRllTIOWW6qlD8WAfUt2+/WHopctykwwz05UVH9Hg=": {operator: "Google", url: "https://ct.googleapis.com/icarus/"},
"pLkJkLQYWBSHuxOizGdwCjw1mAT5G9+443fNDsgN3BA=": {operator: "Google", url: "https://ct.googleapis.com/pilot/"},
"7ku9t3XOYLrhQmkfq+GeZqMPfl+wctiDAMR7iXqo/cs=": {operator: "Google", url: "https://ct.googleapis.com/rocketeer/"},
"u9nfvB+KcbWTlCOXqpJ7RzhXlQqrUugakJZkNo4e0YU=": {operator: "Google", url: "https://ct.googleapis.com/skydiver/"},
"qJnYeAySkKr0YvMYgMz71SRR6XDQ+/WR73Ww2ZtkVoE=": {operator: "Google", url: "https://ct.googleapis.com/submariner/"},
"HQJLjrFJizRN/YfqPvwJlvdQbyNdHUlwYaR3PEOcJfs=": {operator: "Google", url: "https://ct.googleapis.com/daedalus/"},
"sMyD5aX5fWuvfAnMKEkEhyrH6IsTLGNQt8b9JuFsbHc=": {operator: "Google", url: "https://ct.googleapis.com/testtube/"},
"w78Dp+HKiEHGB7rj/0Jw/KXsRbGG675OLPP8d4Yw9fY=": {operator: "Google", url: "https://ct.googleapis.com/logs/crucible/"},
"UutLIl7IlpdIUGdfI+Q7wdAh4yFM5S7NX6h8IDzfygM=": {operator: "Google", url: "https://ct.googleapis.com/logs/solera2018/"},
"C3YOmouaaC+ImFsV6UdQGlZEa7qIMHhcOEKZQ4ZFDAA=": {operator: "Google", url: "https://ct.googleapis.com/logs/solera2019/"},
"H8cs5aG3mfQAw1m/+WyjkTVI6GRCIGEJUum6F3T3usc=": {operator: "Google", url: "https://ct.googleapis.com/logs/solera2020/"},
"o8mYRegKt84AFXs3Qt8CB90nKytgLs+Y7iwS25xa5+c=": {operator: "Google", url: "https://ct.googleapis.com/logs/solera2021/"},
"aXqvyhprU2+uISBQRt661+Dq6hPSQy5unY+zefK5qvM=": {operator: "Google", url: "https://ct.googleapis.com/logs/solera2022/"},
"+X6XuNM+96FZAqU6GeF5kOXcQGoDGCW6rZPpj5ucacs=": {operator: "Google", url: "https://ct.googleapis.com/logs/solera2023/"},
"H7w24ALt6X9AGZ6Gs1c7ikIX2AGHdGrQ2gOgYFTSDfQ=": {operator: "Cloudflare", url: "https://ct.cloudflare.com/logs/nimbus2017/"},
"23Sv7ssp7LH+yj5xbSzluaq7NveEcYPHXZ1PN7Yfv2Q=": {operator: "Cloudflare", url: "https://ct.cloudflare.com/logs/nimbus2018/"},
"dH7agzGtMxCRIZzOJU9CcMK//V5CIAjGNzV55hB7zFY=": {operator: "Cloudflare", url: "https://ct.cloudflare.com/logs/nimbus2019/"},
"Xqdz+d9WwOe1Nkh90EngMnqRmgyEoRIShBh1loFxRVg=": {operator: "Cloudflare", url: "https://ct.cloudflare.com/logs/nimbus2020/"},
"RJRlLrDuzq/EQAfYqP4owNrmgr7YyzG1P9MzlrW2gag=": {operator: "Cloudflare", url: "https://ct.cloudflare.com/logs/nimbus2021/"},
"QcjKsd8iRkoQxqE6CUKHXk4xixsD6+tLx2jwkGKWBvY=": {operator: "Cloudflare", url: "https://ct.cloudflare.com/logs/nimbus2022/"},
"ejKMVNi3LbYg6jjgUh7phBZwMhOFTTvSK8E6V6NS61I=": {operator: "Cloudflare", url: "https://ct.cloudflare.com/logs/nimbus2023/"},
"VhQGmi/XwuzT9eG9RLI+x0Z2ubyZEVzA75SYVdaJ0N0=": {operator: "DigiCert", url: "https://ct1.digicert-ct.com/log/"},
"h3W/51l8+IxDmV+9827/Vo1HVjb/SrVgwbTq/16ggw8=": {operator: "DigiCert", url: "https://ct2.digicert-ct.com/log/"},
"wRZK4Kdy0tQ5LcgKwQdw1PDEm96ZGkhAwfoHUWT2M2A=": {operator: "DigiCert", url: "https://yeti2018.ct.digicert.com/log/"},
"4mlLribo6UAJ6IYbtjuD1D7n/nSI+6SPKJMBnd3x2/4=": {operator: "DigiCert", url: "https://yeti2019.ct.digicert.com/log/"},
"8JWkWfIA0YJAEC0vk4iOrUv+HUfjmeHQNKawqKqOsnM=": {operator: "DigiCert", url: "https://yeti2020.ct.digicert.com/log/"},
"XNxDkv7mq0VEsV6a1FbmEDf71fpH3KFzlLJe5vbHDso=": {operator: "DigiCert", url: "https://yeti2021.ct.digicert.com/log/"},
"IkVFB1lVJFaWP6Ev8fdthuAjJmOtwEt/XcaDXG7iDwI=": {operator: "DigiCert", url: "https://yeti2022.ct.digicert.com/log/"},
"BZwB0yDgB4QTlYBJjRF8kDJmr69yULWvO0akPhGEDUo=": {operator: "DigiCert", url: "https://yeti2022-2.ct.digicert.com/log/"},
"Nc8ZG7+xbFe/D61MbULLu7YnICZR6j/hKu+oA8M71kw=": {operator: "DigiCert", url: "https://yeti2023.ct.digicert.com/log/"},
"SLDja9qmRzQP5WoC+p0w6xxSActW3SyB2bu/qznYhHM=": {operator: "DigiCert", url: "https://yeti2024.ct.digicert.com/log/"},
"fVkeEuF4KnscYWd8Xv340IdcFKBOlZ65Ay/ZDowuebg=": {operator: "DigiCert", url: "https://yeti2025.ct.digicert.com/log/"},
"b/FBtWR+QiL37wUs7658If1gjifSr1pun0uKN9ZjPuU=": {operator: "DigiCert", url: "https://nessie2018.ct.digicert.com/log/"},
"/kRhCLHQGreKYsz+q2qysrq/86va2ApNizDfLQAIgww=": {operator: "DigiCert", url: "https://nessie2019.ct.digicert.com/log/"},
"xlKg7EjOs/yrFwmSxDqHQTMJ6ABlomJSQBujNioXxWU=": {operator: "DigiCert", url: "https://nessie2020.ct.digicert.com/log/"},
"7sCV7o1yZA+S48O5G8cSo2lqCXtLahoUOOZHssvtxfk=": {operator: "DigiCert", url: "https://nessie2021.ct.digicert.com/log/"},
"UaOw9f0BeZxWbbg3eI8MpHrMGyfL956IQpoN/tSLBeU=": {operator: "DigiCert", url: "https://nessie2022.ct.digicert.com/log/"},
"s3N3B+GEUPhjhtYFqdwRCUp5LbFnDAuH3PADDnk2pZo=": {operator: "DigiCert", url: "https://nessie2023.ct.digicert.com/log/"},
"c9meiRtMlnigIH1HneayxhzQUV5xGSqMa4AQesF3crU=": {operator: "DigiCert", url: "https://nessie2024.ct.digicert.com/log/"},
"5tIxY0B3jMEQQQbXcbnOwdJA9paEhvu6hzId/R43jlA=": {operator: "DigiCert", url: "https://nessie2025.ct.digicert.com/log/"},
"3esdK3oNT6Ygi4GtgWhwfi6OnQHVXIiNPRHEzbbsvsw=": {operator: "DigiCert", url: "https://ct.ws.symantec.com/"},
"vHjh38X2PGhGSTNNoQ+hXwl5aSAJwIG08/aRfz7ZuKU=": {operator: "DigiCert", url: "https://vega.ws.symantec.com/"},
"p85KTmIH4K3e5f2qSx+GdodntdACpV1HMQ5+ZwqV6rI=": {operator: "DigiCert", url: "https://deneb.ws.symantec.com/"},
"FZcEiNe5l6Bb61JRKt7o0ui0oxZSZBIan6v71fha2T8=": {operator: "DigiCert", url: "https://sirius.ws.symantec.com/"},
"zbUXm3/BwEb+6jETaj+PAC5hgvr4iW/syLL1tatgSQA=": {operator: "Certly", url: "https://log.certly.io/"},
"dGG0oJz7PUHXUVlXWy52SaRFqNJ3CbDMVkpkgrfrQaM=": {operator: "Izenpe", url: "https://ct.izenpe.com/"},
"iUFEnHB0Lga5/JznsRa6ACSqNtWa9E8CBEBPAPfqhWY=": {operator: "Izenpe", url: "https://ct.izenpe.eus/"},
"nk/3PcPOIgtpIXyJnkaAdqv414Y21cz8haMadWKLqIs=": {operator: "WoSign", url: "https://ct.wosign.com/"},
"QbLcLonmPOSvG6e7Kb9oxt7m+fHMBH4w3/rjs7olkmM=": {operator: "WoSign", url: "https://ctlog.wosign.com/"},
"Y9AAYCbd4QuwYB9FJEaWXuK26izU+8layGalUK+Qdbc=": {operator: "WoSign", url: "https://ctlog2.wosign.com/"},
"yc+JCiEQnGZswXo+0GXJMNDgE1qf66ha8UIQuAckIao=": {operator: "Wang Shengnan", url: "https://ct.gdca.com.cn/"},
"kkow+Qkzb/Q11pk6EKx1osZBco5/wtZZrmGI/61AzgE=": {operator: "GDCA", url: "https://ctlog.gdca.com.cn/"},
"cX6nQgl1voSicjVT8Xd8Jt1Rr04QIUQJTZAZtGL7Zmg=": {operator: "GDCA", url: "https://log.gdca.com.cn/"},
"FDCNkMzQMBNQBcAcpSbYHoTodiTjm2JI4I9ySuo7tCo=": {operator: "GDCA", url: "https://log2.gdca.com.cn/"},
"23b9raxl59CVCIhuIVm9i5A1L1/q0+PcXiLrNQrMe5g=": {operator: "Sectigo", url: "https://dodo.ct.comodo.com/"},
"VYHUwhaQNgFK6gubVzxT8MDkOHhwJQgXL6OqHQcT0ww=": {operator: "Sectigo", url: "https://sabre.ct.comodo.com/"},
"b1N2rDHwMRnYmQCkURX/dxUcEdkCwQApBo2yCJo32RM=": {operator: "Sectigo", url: "https://mammoth.ct.comodo.com/"},
"rDua7X+pZ0dXFZ5tfVdWcvnZgQCUHpve/+yhMTt1eC0=": {operator: "Venafi", url: "https://ctlog.api.venafi.com/"},
"AwGd8/2FppqOvR+sxtqbpz5Gl3T+d/V5/FoIuDKMHWs=": {operator: "Venafi", url: "https://ctlog-gen2.api.venafi.com/"},
"pXesnO11SN2PAltnokEInfhuD0duwgPC7L7bGF8oJjg=": {operator: "CNNIC", url: "https://ctserver.cnnic.cn/"},
"NLtq1sPfnAPuqKSZ/3iRSGydXlysktAfe/0bzhnbSO8=": {operator: "StartCom", url: "https://ct.startssl.com/"},
"4BJ2KekEllZOPQFHmESYqkj4rbFmAOt5AqHvmQmQYnM=": {operator: "Beijing PuChuangSiDa Technology Ltd.", url: "https://www.certificatetransparency.cn/ct/"},
"U3tpo1ZDNanASQTjlZOywpjrjXpugwI2NcYnJIzWtEA=": {operator: "NORDUnet", url: "https://flimsy.ct.nordu.net:8080/"},
"qucLfzy41WbIbC8Wl5yfRF9pqw60U1WJsvd6AwEE880=": {operator: "NORDUnet", url: "https://plausible.ct.nordu.net/"},
"z1XiiSNJfDQNUgbQU1Ouslg0tS8fjclSaAnyEu/dfKY=": {operator: "SHECA", url: "http://ctlog.sheca.com/"},
"MtxZwtTEGWjVbhS8YayPDkXbOfrzwVWqQlL1AB+gxiM=": {operator: "SHECA", url: "https://ct.sheca.com/"},
"lgbALGkAM6odFF9ZxuJkjQVJ8N+WqrjbkVpw2OzzkKU=": {operator: "Akamai", url: "https://ct.akamai.com/"},
"OTdvVF97Rgf1l0LXaM1dJDe/NHO2U0pINLz3Lmgcg8k=": {operator: "Matt Palmer", url: "https://alpha.ctlogs.org/"},
"ZZszUPQ7EsxepatOx2XT/ebIgkN3d3jnIAP56yuMMSk=": {operator: "Let's Encrypt", url: "https://oak.ct.letsencrypt.org/2019/"},
"5xLysDd+GmL7jskMYYTx6ns3y1YdESZb8+DzS/JBVG4=": {operator: "Let's Encrypt", url: "https://oak.ct.letsencrypt.org/2020/"},
"lCC8Ho7VjWyIcx+CiyIsDdHaTV5sT5Q9YdtOL1hNosI=": {operator: "Let's Encrypt", url: "https://oak.ct.letsencrypt.org/2021/"},
"36Veq2iCTx9sre64X04+WurNohKkal6OOxLAIERcKnM=": {operator: "Let's Encrypt", url: "https://oak.ct.letsencrypt.org/2022/"},
"tz77JN+cTbp18jnFulj0bF38Qs96nzXEnh0JgSXttJk=": {operator: "Let's Encrypt", url: "https://oak.ct.letsencrypt.org/2023/"},
"hJ9ff1jSv3tU7L10YRzqRcScmPHWSBvG9p6MF08k888=": {operator: "Let's Encrypt", url: "https://testflume.ct.letsencrypt.org/2019/"},
"xj8iGMN9VqaqBrWW2o5T1NcVbR6brI5E0iAt5k1p2dw=": {operator: "Let's Encrypt", url: "https://testflume.ct.letsencrypt.org/2020/"},
"A+3x2pd2tvOMNB457Z1wenVwNpz5hE8yf+nhQTg2G2A=": {operator: "Let's Encrypt", url: "https://testflume.ct.letsencrypt.org/2021/"},
"Iyfv2jUlENvAGe9JGuP/HMWkebzjeHg2DuMYz/tk+Mg=": {operator: "Let's Encrypt", url: "https://testflume.ct.letsencrypt.org/2022/"},
"VTS3q1pqw6fL66ZUh7Ki1xtI9lD6F8UZfJegyyB288Y=": {operator: "Let's Encrypt", url: "https://testflume.ct.letsencrypt.org/2023/"},
"KWr6LVaLyg0uqESVaulyH8Nfo1Xs2plpOq/UWKca790=": {operator: "Let's Encrypt", url: "https://clicky.ct.letsencrypt.org/"},
"sLeEvIHA3cR1ROiD8FmFu5B30TTYq4iysuUzmAuOUIs=": {operator: "Up In The Air Consulting", url: "https://ct.filippo.io/behindthesofa/"},
"R0RHfHXeQm1cRO/UqSyWd1l/ZXqP4MrbxtYW7aSXxCU=": {operator: "Qihoo 360", url: "https://ct.browser.360.cn/2020/"},
"xtftntuOdPCnG01KmEvL66u9KMwf12Mp6IcmzUwlRmM=": {operator: "Qihoo 360", url: "https://ct.browser.360.cn/2021/"},
"ZjywnB/Nm6pidjzLU07sgFgSKAUHrGmkX804z0zHTPE=": {operator: "Qihoo 360", url: "https://ct.browser.360.cn/2022/"},
"4mR/bto0BQPGTU4QqGloH96cWizzsy1fIAuWNgWQiCM=": {operator: "Qihoo 360", url: "https://ct.browser.360.cn/2023/"},
"xc/lS2FRtJsULtJjvecykzY3mXmVUK5ENc0aaZfJw8M=": {operator: "Qihoo 360", url: "https://ct.browser.360.cn/v1/2020/"},
"SBRYfPKLCP5oP9K82UWZTC63TIroyH/OQpt80x1RvcQ=": {operator: "Qihoo 360", url: "https://ct.browser.360.cn/v1/2021/"},
"SRG41hTP09mfFtN2VF7huMz8UR9QnwgLoKCH2R367qk=": {operator: "Qihoo 360", url: "https://ct.browser.360.cn/v1/2022/"},
"tnQLEgAuAz/Q5+lB9Lo+4b/BSbUktM9ijVPv6h9AOo0=": {operator: "Qihoo 360", url: "https://ct.browser.360.cn/v1/2023/"},
"RTWUmNk6ieAoAwjTfWJtxCN1R1jc4DcANvurDt+Ka88=": {operator: "TrustAsia", url: "https://ct.trustasia.com/log1/"},
"pZWUO1NwvukG4AUNH7W7xqQOZfJlroUsdjY/rbIzNu0=": {operator: "TrustAsia", url: "https://ct.trustasia.com/log2020/"},
"qNxS9j1rJCXlMeN89ORKcU8UKiCAOw0E0uLuBmR5SiM=": {operator: "TrustAsia", url: "https://ct2021.trustasia.com/log2021/"},
"Z422Wz50Q7bzo3DV4TqxtDvgoNNR98p0IlDHxvpRqIo=": {operator: "TrustAsia", url: "https://ct.trustasia.com/log2021/"},
"w2X5s2VPMoPHnamOk9dBj1ure+MlLJjh0vBLuetCfSM=": {operator: "TrustAsia", url: "https://ct.trustasia.com/log2022/"},
"6H6nZgvCbPYALvVyXT/g4zG5OTu5L79Y6zuQSdr1Q1o=": {operator: "TrustAsia", url: "https://ct.trustasia.com/log2023/"},
"MG0pV2rSGp1K4SrK2KqKeDqmWjIRYKz/Ww7uTKMgHQU=": {operator: "TrustAsia", url: "https://ct2.trustasia.com/log2024/"},
}
Loading