💾 Archived View for thrig.me › tech › ssl › certid.go captured on 2023-04-19 at 23:41:39.
-=-=-=-=-=-=-
// certid - calculate a fingerprint for a certificate, from amfora, // which is where certID and origCertID came from, via client/tofu.go package main import ( "crypto/sha256" "crypto/x509" "encoding/pem" "fmt" "io/ioutil" "log" "os" ) // certID returns a generic string representing a cert or domain. func certID(cert *x509.Certificate) string { h := sha256.New() h.Write(cert.RawSubjectPublicKeyInfo) // Better than cert.Raw, see #7 return fmt.Sprintf("%X", h.Sum(nil)) } // origCertID uses cert.Raw, which was used in v1.0.0 of the app. func origCertID(cert *x509.Certificate) string { h := sha256.New() h.Write(cert.Raw) return fmt.Sprintf("%X", h.Sum(nil)) } // tls.LoadX509KeyPair needs a private key, so instead we use the // following, which probably needs better error handling. notably // ParseCertificate likes to panic if you give this /dev/null, which is // maybe not so good a user experience func load_cert(file string) *x509.Certificate { content, err := ioutil.ReadFile(file) if err != nil { log.Fatalf("%v - '%s'", err, file) } if len(content) == 0 { log.Fatalf("empty file '%v'", file) } block, _ := pem.Decode([]byte(content)) cert, err := x509.ParseCertificate(block.Bytes) if err != nil { log.Fatalf("%v - '%s'", err, file) } return cert } func main() { var cert *x509.Certificate if len(os.Args) != 2 { fmt.Fprintln(os.Stderr, "Usage: certid certificate-file") os.Exit(64) } cert = load_cert(os.Args[1]) fmt.Println("old ", origCertID(cert)) fmt.Println("new ", certID(cert)) }