1package main
2
3import (
4 "bytes"
5 "crypto"
6 "crypto/sha256"
7 "crypto/x509"
8 "encoding/base64"
9 "encoding/pem"
10 "fmt"
11 "log"
12 "os"
13 "strings"
14)
15
16func main() {
17 certPEM, err := os.ReadFile("cert.pem")
18 if err != nil {
19 log.Fatal(err)
20 }
21 block, _ := pem.Decode(certPEM)
22 if block == nil || block.Type != "CERTIFICATE" {
23 log.Fatal("cert.pem: no CERTIFICATE block")
24 }
25 cert, err := x509.ParseCertificate(block.Bytes)
26 if err != nil {
27 log.Fatal(err)
28 }
29
30 // RawSubjectPublicKeyInfo: the SPKI bytes exactly as they appear in the certificate
31 spki := cert.RawSubjectPublicKeyInfo
32 pem.Encode(os.Stdout, &pem.Block{Type: "PUBLIC KEY", Bytes: spki})
33
34 sum := sha256.Sum256(spki)
35 hexPairs := make([]string, len(sum))
36 for i, b := range sum {
37 hexPairs[i] = fmt.Sprintf("%02x", b)
38 }
39 fmt.Println("SPKI SHA-256:", strings.Join(hexPairs, ":"))
40 fmt.Println("SPKI pin (base64):", base64.StdEncoding.EncodeToString(sum[:]))
41
42 // cert.PublicKey is the parsed key (*ecdsa.PublicKey here); MarshalPKIXPublicKey re-encodes it
43 remarshaled, err := x509.MarshalPKIXPublicKey(cert.PublicKey)
44 if err != nil {
45 log.Fatal(err)
46 }
47 fmt.Println("MarshalPKIXPublicKey gives the same bytes:", bytes.Equal(remarshaled, spki))
48
49 // Does key.pem belong to this certificate?
50 keyPEM, err := os.ReadFile("key.pem")
51 if err != nil {
52 log.Fatal(err)
53 }
54 keyBlock, _ := pem.Decode(keyPEM)
55 key, err := x509.ParsePKCS8PrivateKey(keyBlock.Bytes)
56 if err != nil {
57 log.Fatal(err)
58 }
59 pub := key.(crypto.Signer).Public().(interface{ Equal(crypto.PublicKey) bool })
60 fmt.Println("key.pem matches:", pub.Equal(cert.PublicKey))
61}
62