Update 3rd party license information

This commit is contained in:
Andy Feller 2025-05-30 12:50:20 -04:00
parent bd24865076
commit 815c557f9a
1023 changed files with 158572 additions and 0 deletions

View file

@ -0,0 +1,108 @@
// block-a-key is a small utility for creating key blocklist entries.
package main
import (
"crypto"
"errors"
"flag"
"fmt"
"log"
"os"
"github.com/letsencrypt/boulder/core"
"github.com/letsencrypt/boulder/web"
)
const usageHelp = `
block-a-key is utility tool for generating a SHA256 hash of the SubjectPublicKeyInfo
from a certificate or a synthetic SubjectPublicKeyInfo generated from a JWK public key.
It outputs the Base64 encoding of that hash.
The produced encoded digest can be used with Boulder's key blocklist to block
any ACME account creation or certificate requests that use the same public
key.
If you already have an SPKI hash, and it's a SHA256 hash, you can add it directly
to the key blocklist. If it's in hex form you'll need to convert it to base64 first.
installation:
go install github.com/letsencrypt/boulder/test/block-a-key/...
usage:
block-a-key -cert <PEM encoded x509 certificate file>
block-a-key -jwk <JSON encoded JWK file>
output format:
# <filepath>
- "<base64 encoded SHA256 subject public key digest>"
examples:
$> block-a-key -jwk ./test/block-a-key/test/test.ecdsa.jwk.json
./test/block-a-key/test/test.ecdsa.jwk.json cuwGhNNI6nfob5aqY90e7BleU6l7rfxku4X3UTJ3Z7M=
$> block-a-key -cert ./test/block-a-key/test/test.rsa.cert.pem
./test/block-a-key/test/test.rsa.cert.pem Qebc1V3SkX3izkYRGNJilm9Bcuvf0oox4U2Rn+b4JOE=
`
// keyFromCert returns the public key from a PEM encoded certificate located in
// pemFile or returns an error.
func keyFromCert(pemFile string) (crypto.PublicKey, error) {
c, err := core.LoadCert(pemFile)
if err != nil {
return nil, err
}
return c.PublicKey, nil
}
// keyFromJWK returns the public key from a JSON encoded JOSE JWK located in
// jsonFile or returns an error.
func keyFromJWK(jsonFile string) (crypto.PublicKey, error) {
jwk, err := web.LoadJWK(jsonFile)
if err != nil {
return nil, err
}
return jwk.Key, nil
}
func main() {
certFileArg := flag.String("cert", "", "path to a PEM encoded X509 certificate file")
jwkFileArg := flag.String("jwk", "", "path to a JSON encoded JWK file")
flag.Usage = func() {
fmt.Fprintf(os.Stderr, "%s\n\n", usageHelp)
fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
flag.PrintDefaults()
}
flag.Parse()
if *certFileArg == "" && *jwkFileArg == "" {
log.Fatalf("error: a -cert or -jwk argument must be provided")
}
if *certFileArg != "" && *jwkFileArg != "" {
log.Fatalf("error: -cert and -jwk arguments are mutually exclusive")
}
var file string
var key crypto.PublicKey
var err error
if *certFileArg != "" {
file = *certFileArg
key, err = keyFromCert(file)
} else if *jwkFileArg != "" {
file = *jwkFileArg
key, err = keyFromJWK(file)
} else {
err = errors.New("unexpected command line state")
}
if err != nil {
log.Fatalf("error loading public key: %v", err)
}
spkiHash, err := core.KeyDigestB64(key)
if err != nil {
log.Fatalf("error computing spki hash: %v", err)
}
fmt.Printf(" # %s\n - %s\n", file, spkiHash)
}

View file

@ -0,0 +1,59 @@
package main
import (
"crypto"
"testing"
"github.com/letsencrypt/boulder/core"
"github.com/letsencrypt/boulder/test"
)
func TestKeyBlocking(t *testing.T) {
testCases := []struct {
name string
certPath string
jwkPath string
expected string
}{
// NOTE(@cpu): The JWKs and certificates were generated with the same
// keypair within an algorithm/parameter family. E.g. the RSA JWK public key
// matches the RSA certificate public key. The ECDSA JWK public key matches
// the ECDSA certificate public key.
{
name: "P-256 ECDSA JWK",
jwkPath: "test/test.ecdsa.jwk.json",
expected: "cuwGhNNI6nfob5aqY90e7BleU6l7rfxku4X3UTJ3Z7M=",
},
{
name: "2048 RSA JWK",
jwkPath: "test/test.rsa.jwk.json",
expected: "Qebc1V3SkX3izkYRGNJilm9Bcuvf0oox4U2Rn+b4JOE=",
},
{
name: "P-256 ECDSA Certificate",
certPath: "test/test.ecdsa.cert.pem",
expected: "cuwGhNNI6nfob5aqY90e7BleU6l7rfxku4X3UTJ3Z7M=",
},
{
name: "2048 RSA Certificate",
certPath: "test/test.rsa.cert.pem",
expected: "Qebc1V3SkX3izkYRGNJilm9Bcuvf0oox4U2Rn+b4JOE=",
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
var key crypto.PublicKey
var err error
if tc.jwkPath != "" {
key, err = keyFromJWK(tc.jwkPath)
} else {
key, err = keyFromCert(tc.certPath)
}
test.AssertNotError(t, err, "error getting key from input file")
spkiHash, err := core.KeyDigestB64(key)
test.AssertNotError(t, err, "error computing spki hash")
test.AssertEquals(t, spkiHash, tc.expected)
})
}
}

View file

@ -0,0 +1,7 @@
The test files in this directory can be recreated with the following small program:
https://gist.github.com/cpu/df50564a473b3e8556917eb80d99ea56
Crucially the public keys in the generated JWKs/Certs are shared within
algorithm/parameters. E.g. the ECDSA JWK has the same public key as the ECDSA
Cert.

View file

@ -0,0 +1,8 @@
-----BEGIN CERTIFICATE-----
MIH1MIGboAMCAQICAQEwCgYIKoZIzj0EAwIwADAiGA8wMDAxMDEwMTAwMDAwMFoY
DzAwMDEwMTAxMDAwMDAwWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE4LqG
kzIYWSgmyTS+B9Eet1xx1wpCKiSklMPnHfFp8eSHr1uNk6ilWv/s4AoKHSvMNAb/
1uPfxjlijEIjK2bOQKMCMAAwCgYIKoZIzj0EAwIDSQAwRgIhAJBK1/C1BYDnzSCu
cR2pE40d8dyrRuHKj8htO/fzRgCgAiEA0UG0Vda8w0Tp84AMlJpZHOx9QUbwExSl
oFEDADJ9WQM=
-----END CERTIFICATE-----

View file

@ -0,0 +1 @@
{"kty":"EC","crv":"P-256","alg":"ECDSA","x":"4LqGkzIYWSgmyTS-B9Eet1xx1wpCKiSklMPnHfFp8eQ","y":"h69bjZOopVr_7OAKCh0rzDQG_9bj38Y5YoxCIytmzkA"}

View file

@ -0,0 +1,16 @@
-----BEGIN CERTIFICATE-----
MIICgTCCAWmgAwIBAgIBATANBgkqhkiG9w0BAQsFADAAMCIYDzAwMDEwMTAxMDAw
MDAwWhgPMDAwMTAxMDEwMDAwMDBaMAAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
ggEKAoIBAQC+epImi+GdM4ypmQ7LeWSYbbX0AHeZJvRScp5+JvkVQNTIDjQGnYxw
7omOW1dkn0qGkQckFmvUmCHXuK6oF0GYOvRzEdOwb6KeTb+ONYQHGLirKU2bt+um
JxiB/9PMaV5yPwpyNVi0XV5Rr+BpHdV1i9lm542+4zwfWiYRKT1+tjpvicmyK0av
T/60U0kfeeSdAU0TcSFR4RDEw1fudXIRk7FPgd2GHjeJeAeMmLL4Vabr+uSecGpp
THdkbnPDV51WVPHcyoOV6rdicSEoqE9aoeMjQXZ6SntXGjY4pqlyuwjqocLZStEK
ztxp3D7eyeHub9nrCgp+UsxaWns1DtP3AgMBAAGjAjAAMA0GCSqGSIb3DQEBCwUA
A4IBAQA9sazSAm6umbleFWDrh3oyGaFBzYvRfeOAEquJky36qREjBWvrS2Yi66eX
L9Uoavr/CIk+U9qRPl81cHi5qsFBuDi+OKZzG32Uq7Rw8h+7f/9HVEUyVVy1p7v8
iqZvygU70NeT0cT91eSl6LV88BdjhbjI6Hk1+AVF6UPAmzkgJIFAwwUWa2HUT+Ni
nMxzRThuLyPbYt4clz6bGzk26LIdoByJH4pYabXh05OwalBJjMVR/4ek9blrVMAg
b4a7Eq/WXq+CVwWnb3oholDOJo3l/KwNuG6HD90JU0Vu4fipFqmsXhBHYVNVu94y
wJWm+dAtEeAcp8KfOv/IBMCjDkyt
-----END CERTIFICATE-----

View file

@ -0,0 +1 @@
{"kty":"RSA","alg":"RS256","n":"vnqSJovhnTOMqZkOy3lkmG219AB3mSb0UnKefib5FUDUyA40Bp2McO6JjltXZJ9KhpEHJBZr1Jgh17iuqBdBmDr0cxHTsG-ink2_jjWEBxi4qylNm7frpicYgf_TzGlecj8KcjVYtF1eUa_gaR3VdYvZZueNvuM8H1omESk9frY6b4nJsitGr0_-tFNJH3nknQFNE3EhUeEQxMNX7nVyEZOxT4Hdhh43iXgHjJiy-FWm6_rknnBqaUx3ZG5zw1edVlTx3MqDleq3YnEhKKhPWqHjI0F2ekp7Vxo2OKapcrsI6qHC2UrRCs7cadw-3snh7m_Z6woKflLMWlp7NQ7T9w","e":"AQAB"}