Add nameid tool (#7586)

Adds a nameid tool to the boulder tools directory for SRE use. The
existing local and github CI framework correctly catches build failures
of this directory.

Examples of usage:
```
$ go run ./tools/nameid/nameid.go test/certs/webpki/int-ecdsa-c.cert.pem test/certs/webpki/int-rsa-a.cert.pem 
test/certs/webpki/int-ecdsa-c.cert.pem: 56560759852043581
test/certs/webpki/int-rsa-a.cert.pem: 29947985078257530

$ go run ./tools/nameid/nameid.go -s test/certs/webpki/int-ecdsa-c.cert.pem test/certs/webpki/int-rsa-a.cert.pem 
56560759852043581
29947985078257530
```

Fixes https://github.com/letsencrypt/boulder/issues/7469
This commit is contained in:
Phil Porada 2024-07-12 13:08:05 -04:00 committed by GitHub
parent ebb52990ca
commit b15e54db2b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 61 additions and 0 deletions

24
tools/nameid/README.md Normal file
View File

@ -0,0 +1,24 @@
# Overview
The `nameid` tool displays a statistically-unique small ID which can be computed
from both CA and end-entity certs to link them together into a validation chain.
It is computed as a truncated hash over the issuer Subject Name bytes. It should
only be used on issuer certificates e.g. [when the CA boolean is
asserted](https://www.rfc-editor.org/rfc/rfc5280#section-4.2.1.9) which in the
`//crypto/x509` `Certificate` struct is `IsCA: true`.
For implementation details, please see the `//issuance` package
[here](https://github.com/letsencrypt/boulder/blob/30c6e592f7f6825c2782b6a7d5da566979445674/issuance/issuer.go#L79-L83).
# Usage
```
# Display help
go run ./tools/nameid/nameid.go -h
# Output the certificate path and nameid, one per line
go run ./tools/nameid/nameid.go /path/to/cert1.pem /path/to/cert2.pem ...
# Output just the nameid, one per line
go run ./tools/nameid/nameid.go -s /path/to/cert1.pem /path/to/cert2.pem ...
```

37
tools/nameid/nameid.go Normal file
View File

@ -0,0 +1,37 @@
package main
import (
"flag"
"fmt"
"os"
"github.com/letsencrypt/boulder/issuance"
)
func usage() {
fmt.Printf("Usage: %s [OPTIONS] [ISSUER CERTIFICATE(S)]\n", os.Args[0])
}
func main() {
var shorthandFlag = flag.Bool("s", false, "Display only the nameid for each given issuer certificate")
flag.Parse()
if len(os.Args) <= 1 {
usage()
os.Exit(1)
}
for _, certFile := range flag.Args() {
issuer, err := issuance.LoadCertificate(certFile)
if err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err)
os.Exit(1)
}
if *shorthandFlag {
fmt.Println(issuer.NameID())
} else {
fmt.Printf("%s: %d\n", certFile, issuer.NameID())
}
}
}