1package main
2
3import (
4 "crypto"
5 "crypto/x509"
6 "encoding/base64"
7 "encoding/pem"
8 "fmt"
9 "log"
10 "os"
11
12 "github.com/go-jose/go-jose/v4"
13)
14
15func thumbprint(jwk jose.JSONWebKey) string {
16 sum, err := jwk.Thumbprint(crypto.SHA256) // RFC 7638 over the required members
17 if err != nil {
18 log.Fatal(err)
19 }
20 return base64.RawURLEncoding.EncodeToString(sum)
21}
22
23func main() {
24 // From a JWK: kid, use and alg are parsed but do not enter the thumbprint
25 for _, name := range []string{"ec.jwk.json", "rsa.jwk.json", "okp.jwk.json"} {
26 data, err := os.ReadFile(name)
27 if err != nil {
28 log.Fatal(err)
29 }
30 var jwk jose.JSONWebKey
31 if err := jwk.UnmarshalJSON(data); err != nil {
32 log.Fatal(err)
33 }
34 fmt.Printf("%s: %s\n", name, thumbprint(jwk))
35 }
36
37 // From a PEM public key: wrap the parsed crypto.PublicKey
38 for _, name := range []string{"ec.pub.pem", "rsa.pub.pem", "okp.pub.pem"} {
39 data, err := os.ReadFile(name)
40 if err != nil {
41 log.Fatal(err)
42 }
43 block, _ := pem.Decode(data)
44 if block == nil {
45 log.Fatalf("%s: no PEM block", name)
46 }
47 key, err := x509.ParsePKIXPublicKey(block.Bytes)
48 if err != nil {
49 log.Fatal(err)
50 }
51 fmt.Printf("%s: %s\n", name, thumbprint(jose.JSONWebKey{Key: key}))
52 }
53}
54