diff --git a/.github/workflows/autodoc.yml b/.github/workflows/autodoc.yml index 6460d1e59..4e747f824 100644 --- a/.github/workflows/autodoc.yml +++ b/.github/workflows/autodoc.yml @@ -13,7 +13,7 @@ jobs: if: github.event.pull_request.merged == true steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Process markdown files run: | find . -name '*.md' | xargs perl tools/autodoc.pl diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 6f4b49a6c..793cc0448 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -13,7 +13,7 @@ jobs: name: "Test [ Go ${{ matrix.go }} / JSON Backend ${{ matrix.json_backend }} ]" steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Cache Go modules uses: actions/cache@v3 with: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3311e3944..29dba0b29 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,7 +15,7 @@ jobs: name: "Test [ Go ${{ matrix.go }} / Tags ${{ matrix.go_tags }} ]" steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Cache Go modules uses: actions/cache@v3 with: diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index e9a65fd19..26cf4a6b4 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -40,7 +40,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL diff --git a/.github/workflows/dependabot.yml b/.github/workflows/dependabot.yml index 984b4d6d8..de9619f51 100644 --- a/.github/workflows/dependabot.yml +++ b/.github/workflows/dependabot.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - run: | make tidy - run: | diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 72fabee73..7ced60a76 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -5,7 +5,7 @@ jobs: name: lint runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/setup-go@v4 with: go-version: 1.19 diff --git a/.github/workflows/smoke.yml b/.github/workflows/smoke.yml index 6e4fad8f5..d88341df2 100644 --- a/.github/workflows/smoke.yml +++ b/.github/workflows/smoke.yml @@ -18,7 +18,7 @@ jobs: name: "Smoke [ Go ${{ matrix.go }} / Tags ${{ matrix.go_tags }} ]" steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Check documentation generator run: | find . -name '*.md' | xargs env AUTODOC_DRYRUN=1 perl tools/autodoc.pl diff --git a/deps.bzl b/deps.bzl index fa850553b..b5b43e6f1 100644 --- a/deps.bzl +++ b/deps.bzl @@ -122,8 +122,8 @@ def go_dependencies(): name = "org_golang_x_crypto", build_file_proto_mode = "disable_global", importpath = "golang.org/x/crypto", - sum = "h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=", - version = "v0.12.0", + sum = "h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=", + version = "v0.13.0", ) go_repository( name = "org_golang_x_mod", @@ -152,23 +152,23 @@ def go_dependencies(): name = "org_golang_x_sys", build_file_proto_mode = "disable_global", importpath = "golang.org/x/sys", - sum = "h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=", - version = "v0.11.0", + sum = "h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=", + version = "v0.12.0", ) go_repository( name = "org_golang_x_term", build_file_proto_mode = "disable_global", importpath = "golang.org/x/term", - sum = "h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0=", - version = "v0.11.0", + sum = "h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU=", + version = "v0.12.0", ) go_repository( name = "org_golang_x_text", build_file_proto_mode = "disable_global", importpath = "golang.org/x/text", - sum = "h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=", - version = "v0.12.0", + sum = "h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=", + version = "v0.13.0", ) go_repository( name = "org_golang_x_tools", diff --git a/examples/go.mod b/examples/go.mod index 867076a18..738e61809 100644 --- a/examples/go.mod +++ b/examples/go.mod @@ -9,4 +9,4 @@ require ( replace github.com/cloudflare/circl v1.0.0 => github.com/cloudflare/circl v1.0.1-0.20210104183656-96a0695de3c3 -replace github.com/lestrrat-go/jwx/v2 v2.0.11 => github.com/lestrrat-go/jwx/v2 v2.0.12-0.20230824024517-a077c65f16eb +replace github.com/lestrrat-go/jwx/v2 v2.0.11 => ../ \ No newline at end of file diff --git a/examples/go.sum b/examples/go.sum index 480afbf86..8bdc85cf3 100644 --- a/examples/go.sum +++ b/examples/go.sum @@ -38,8 +38,8 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= -golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= -golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= +golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -61,21 +61,21 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= diff --git a/examples/jwk_comparison_example_test.go b/examples/jwk_comparison_example_test.go new file mode 100644 index 000000000..7f78f251f --- /dev/null +++ b/examples/jwk_comparison_example_test.go @@ -0,0 +1,53 @@ +package examples + +import ( + "crypto/rand" + "crypto/rsa" + "fmt" + + "github.com/lestrrat-go/jwx/v2/jwk" +) + +func ExampleJWK_Comparison() { + genKey := func() (jwk.Key, error) { + raw, err := rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + return nil, fmt.Errorf("failed to generate new RSA private key: %s", err) + } + + key, err := jwk.FromRaw(raw) + if err != nil { + return nil, fmt.Errorf("failed to create RSA key: %s", err) + } + if _, ok := key.(jwk.RSAPrivateKey); !ok { + return nil, fmt.Errorf("expected jwk.SymmetricKey, got %T", key) + } + + return key, nil + } + + k1, err := genKey() + if err != nil { + fmt.Printf("failed to generate key 1: %T", err) + return + } + k2, err := genKey() + if err != nil { + fmt.Printf("failed to generate key 2: %T", err) + return + } + + // This comparison only compares Thumbprints of each key. It does NOT take into + // account fields that could differ even when thumbprints match. For example, + // it is totally possible to have a key with the same thumbprint, but different + // Key IDs, or key usages. + if jwk.Equal(k1, k2) { + fmt.Printf("k1 and k2 should be different") + return + } + + if !jwk.Equal(k1, k1) { + fmt.Printf("k1 and k1 should be equal") + return + } +} diff --git a/examples/jwk_example_test.go b/examples/jwk_example_test.go index 505ed2d6d..21804203a 100644 --- a/examples/jwk_example_test.go +++ b/examples/jwk_example_test.go @@ -27,7 +27,7 @@ func ExampleJWK_Usage() { log.Printf("%s", jsonbuf) } - for it := set.Iterate(context.Background()); it.Next(context.Background()); { + for it := set.Keys(context.Background()); it.Next(context.Background()); { pair := it.Pair() key := pair.Value.(jwk.Key) diff --git a/go.mod b/go.mod index c49dc1483..ea2f0a30b 100644 --- a/go.mod +++ b/go.mod @@ -11,5 +11,5 @@ require ( github.com/lestrrat-go/option v1.0.1 github.com/segmentio/asm v1.2.0 github.com/stretchr/testify v1.8.4 - golang.org/x/crypto v0.12.0 + golang.org/x/crypto v0.13.0 ) diff --git a/go.sum b/go.sum index 967b33243..ac6e2155e 100644 --- a/go.sum +++ b/go.sum @@ -32,8 +32,8 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= -golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= +golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -52,19 +52,19 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= diff --git a/jwk/README.md b/jwk/README.md index 85fb0a4b4..611585787 100644 --- a/jwk/README.md +++ b/jwk/README.md @@ -137,7 +137,7 @@ func ExampleJWK_Usage() { log.Printf("%s", jsonbuf) } - for it := set.Iterate(context.Background()); it.Next(context.Background()); { + for it := set.Keys(context.Background()); it.Next(context.Background()); { pair := it.Pair() key := pair.Value.(jwk.Key) diff --git a/jwk/jwk.go b/jwk/jwk.go index 8bb2910c7..5ad3b47de 100644 --- a/jwk/jwk.go +++ b/jwk/jwk.go @@ -508,3 +508,20 @@ type KeySpec struct { RawFromKey ChainedRawFromKeyer KeyFromRaw ChainedKeyFromRawer } + +// Equal compares two keys and returns true if they are equal. The comparison +// is solely done against the thumbprints of k1 and k2. It is possible for keys +// that have, for example, different key IDs, key usage, etc, to be considered equal. +func Equal(k1, k2 Key) bool { + h := crypto.SHA256 + tp1, err := k1.Thumbprint(h) + if err != nil { + return false // can't report error + } + tp2, err := k2.Thumbprint(h) + if err != nil { + return false // can't report error + } + + return bytes.Equal(tp1, tp2) +} diff --git a/jwk/options.yaml b/jwk/options.yaml index 3f7b6e2a1..6dfbded42 100644 --- a/jwk/options.yaml +++ b/jwk/options.yaml @@ -4,7 +4,7 @@ interfaces: - name: CacheOption comment: | CacheOption is a type of Option that can be passed to the - `jwk.Cache` object. + the `jwk.NewCache()` function. - name: AssignKeyIDOption - name: FetchOption methods: @@ -13,8 +13,8 @@ interfaces: - registerOption comment: | FetchOption is a type of Option that can be passed to `jwk.Fetch()` - FetchOption also implements the `CacheOption`, and thus can - safely be passed to `(*jwk.Cache).Configure()` + FetchOption also implements the `RegisterOption`, and thus can + safely be passed to `(*jwk.Cache).Register()` - name: ParseOption methods: - fetchOption diff --git a/jwk/options_gen.go b/jwk/options_gen.go index 644b24711..2aac86fc6 100644 --- a/jwk/options_gen.go +++ b/jwk/options_gen.go @@ -25,7 +25,7 @@ type assignKeyIDOption struct { func (*assignKeyIDOption) assignKeyIDOption() {} // CacheOption is a type of Option that can be passed to the -// `jwk.Cache` object. +// the `jwk.NewCache()` function. type CacheOption interface { Option cacheOption() @@ -38,8 +38,8 @@ type cacheOption struct { func (*cacheOption) cacheOption() {} // FetchOption is a type of Option that can be passed to `jwk.Fetch()` -// FetchOption also implements the `CacheOption`, and thus can -// safely be passed to `(*jwk.Cache).Configure()` +// FetchOption also implements the `RegisterOption`, and thus can +// safely be passed to `(*jwk.Cache).Register()` type FetchOption interface { Option fetchOption()