diff options
-rw-r--r-- | bin-src/crtsh-pem2html.go | 90 |
1 files changed, 76 insertions, 14 deletions
diff --git a/bin-src/crtsh-pem2html.go b/bin-src/crtsh-pem2html.go index 2c9debb..432020e 100644 --- a/bin-src/crtsh-pem2html.go +++ b/bin-src/crtsh-pem2html.go @@ -51,18 +51,20 @@ var tmpl = template.Must(template.New("pem2html"). <th>Logged</th> <th>NotBefore</th> <th>NotAfter</th> - <th>Type</th> <th>Subject.CN</th> <th>Issuer.O</th> + <th>SCTs</th> </tr> {{range $cert := .certs}} <tr> - <td style="background-color: {{$cert.Updated | green}}"><a target="_blank" href="{{$cert.Url}}">{{$cert.Updated | date}}</a></td> - <td style="background-color: {{$cert.X509.NotBefore | green}}"><a target="_blank" href="{{$cert.Url}}">{{$cert.X509.NotBefore | date}}</a></td> - <td style="background-color: {{$cert.X509.NotAfter | red }}"><a target="_blank" href="{{$cert.Url}}">{{$cert.X509.NotAfter | date}}</a></td> - <td><a target="_blank" href="{{$cert.Url}}">{{$cert.X509 | rfc6962type}}</a></td> - <td><a target="_blank" href="{{$cert.Url}}">{{$cert.X509.Subject.CommonName}}</a></td> - <td><a target="_blank" href="{{$cert.Url}}">{{$cert.X509.Issuer.Organization}}</a></td> + <td style="background-color: {{$cert.Updated | green}}"><a target="_blank" href="{{$cert.Main.Url}}">{{$cert.Updated | date}}</a></td> + <td style="background-color: {{$cert.Main.X509.NotBefore | green}}"><a target="_blank" href="{{$cert.Main.Url}}">{{$cert.Main.X509.NotBefore | date}}</a></td> + <td style="background-color: {{$cert.Main.X509.NotAfter | red }}"><a target="_blank" href="{{$cert.Main.Url}}">{{$cert.Main.X509.NotAfter | date}}</a></td> + <td><a target="_blank" href="{{$cert.Main.Url}}">{{$cert.Main.X509.Subject.CommonName}}</a></td> + <td><a target="_blank" href="{{$cert.Main.Url}}">{{$cert.Main.X509.Issuer.Organization}}</a></td> + <td>{{range $i, $sct := $cert.Precerts}} + <a target="_blank" href="{{$sct.Url}}">[{{$i}}]</a> + {{end}}</td> </tr> {{end}} </table> @@ -109,21 +111,75 @@ type Cert struct { X509 *x509.Certificate } -type Certs []Cert +// A CertSet is a set of certificates all sharing the same +// SerialNumber. Normally, this will be 1 regular certificate, and +// any number of pre-certificates. +type CertSet []Cert + +// Given a list of certificates all sharing the same serial number, +// return a list of CertSets. If there are multiple regular +// certificates, it returns a seprate CertSet for each. +func NewCertSet(certs []Cert) []CertSet { + if len(certs) == 0 { + return nil + } + var retCerts []Cert + var retPrecerts []Cert + for _, cert := range certs { + if util.IsPrecertificate(cert.X509) { + retPrecerts = append(retPrecerts, cert) + } else { + retCerts = append(retCerts, cert) + } + } + if len(retCerts) == 0 { + return []CertSet{CertSet(retPrecerts)} + } + ret := make([]CertSet, len(retCerts)) + for i := range ret { + ret[i] = append(CertSet{retCerts[i]}, retPrecerts...) + } + return ret +} + +func (certs CertSet) Main() Cert { + //if util.IsPrecertificate(certs[0].X509) { + // return Cert{X509: new(x509.Certificate)} + //} + return certs[0] +} + +func (certs CertSet) Precerts() []Cert { + return certs[1:] +} + +// Updated returns the most recent "Updated" timestamp of any of the +// certificates in the CertSet. +func (certs CertSet) Updated() time.Time { + ret := certs[0].Updated + for _, cert := range certs { + if cert.Updated.After(ret) { + ret = cert.Updated + } + } + return ret +} + +type CertList []CertSet // Len is the number of elements in the collection. -func (l Certs) Len() int { +func (l CertList) Len() int { return len(l) } // Less reports whether the element with // index i should sort before the element with index j. -func (l Certs) Less(i, j int) bool { - return l[i].Updated.After(l[j].Updated) +func (l CertList) Less(i, j int) bool { + return l[i].Updated().After(l[j].Updated()) } // Swap swaps the elements with indexes i and j. -func (l Certs) Swap(i, j int) { +func (l CertList) Swap(i, j int) { tmp := l[i] l[i] = l[j] l[j] = tmp @@ -133,7 +189,7 @@ func main() { data, err := ioutil.ReadAll(os.Stdin) handleErr(err, "Error reading stdin: %v\n") - var certs Certs + bySerial := make(map[string][]Cert) for len(data) > 0 { var certPem *pem.Block certPem, data = pem.Decode(data) @@ -152,7 +208,13 @@ func main() { cert.X509, err = x509.ParseCertificate(certPem.Bytes) handleErr(err, "Error parsing cert: %v\n") - certs = append(certs, cert) + serial := fmt.Sprintf("%036x", cert.X509.SerialNumber) + bySerial[serial] = append(bySerial[serial], cert) + } + + var certs CertList + for _, set := range bySerial { + certs = append(certs, NewCertSet(set)...) } sort.Sort(certs) |