Files
releases/internal/jwx/jwk/jwk.go
T
Anders Eknert e43ef0a979 Use any in place of interface{} (#7566)
Earlier this evening I tried to run the Go
[modernize](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/modernize)
analyzer on OPA. That didn't go as planned:

- https://github.com/golang/go/issues/73661
- https://github.com/golang/go/issues/73663

While we wait for that to be fixed, I figured an old-fashioned
search-and-replace across the repo may work for at least the
`interface{}` to `any` conversion. That should help make it easier
to see the other fixes as applied by the modernize tool once it has
had those issues resolved.

Signed-off-by: Anders Eknert <anders@styra.com>
2025-05-12 13:57:48 +02:00

154 lines
3.7 KiB
Go

// Package jwk implements JWK as described in https://tools.ietf.org/html/rfc7517
package jwk
import (
"crypto/ecdsa"
"crypto/rsa"
"encoding/json"
"errors"
"fmt"
"github.com/open-policy-agent/opa/internal/jwx/jwa"
)
// GetPublicKey returns the public key based on the private key type.
// For rsa key types *rsa.PublicKey is returned; for ecdsa key types *ecdsa.PublicKey;
// for byte slice (raw) keys, the key itself is returned. If the corresponding
// public key cannot be deduced, an error is returned
func GetPublicKey(key any) (any, error) {
if key == nil {
return nil, errors.New("jwk.New requires a non-nil key")
}
switch v := key.(type) {
// Mental note: although Public() is defined in both types,
// you can not coalesce the clauses for rsa.PrivateKey and
// ecdsa.PrivateKey, as then `v` becomes any
// b/c the compiler cannot deduce the exact type.
case *rsa.PrivateKey:
return v.Public(), nil
case *ecdsa.PrivateKey:
return v.Public(), nil
case []byte:
return v, nil
default:
return nil, fmt.Errorf("invalid key type %T", key)
}
}
// GetKeyTypeFromKey creates a jwk.Key from the given key.
func GetKeyTypeFromKey(key any) jwa.KeyType {
switch key.(type) {
case *rsa.PrivateKey, *rsa.PublicKey:
return jwa.RSA
case *ecdsa.PrivateKey, *ecdsa.PublicKey:
return jwa.EC
case []byte:
return jwa.OctetSeq
default:
return jwa.InvalidKeyType
}
}
// New creates a jwk.Key from the given key.
func New(key any) (Key, error) {
if key == nil {
return nil, errors.New("jwk.New requires a non-nil key")
}
switch v := key.(type) {
case *rsa.PrivateKey:
return newRSAPrivateKey(v)
case *rsa.PublicKey:
return newRSAPublicKey(v)
case *ecdsa.PrivateKey:
return newECDSAPrivateKey(v)
case *ecdsa.PublicKey:
return newECDSAPublicKey(v)
case []byte:
return newSymmetricKey(v)
default:
return nil, fmt.Errorf("invalid key type %T", key)
}
}
func parse(jwkSrc string) (*Set, error) {
var jwkKeySet Set
var jwkKey Key
rawKeySetJSON := &RawKeySetJSON{}
err := json.Unmarshal([]byte(jwkSrc), rawKeySetJSON)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal JWK Set: %w", err)
}
if len(rawKeySetJSON.Keys) == 0 {
// It might be a single key
rawKeyJSON := &RawKeyJSON{}
err := json.Unmarshal([]byte(jwkSrc), rawKeyJSON)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal JWK: %w", err)
}
jwkKey, err = rawKeyJSON.GenerateKey()
if err != nil {
return nil, fmt.Errorf("failed to generate key: %w", err)
}
// Add to set
jwkKeySet.Keys = append(jwkKeySet.Keys, jwkKey)
} else {
for i := range rawKeySetJSON.Keys {
rawKeyJSON := rawKeySetJSON.Keys[i]
if rawKeyJSON.Algorithm != nil && *rawKeyJSON.Algorithm == jwa.Unsupported {
continue
}
jwkKey, err = rawKeyJSON.GenerateKey()
if err != nil {
return nil, fmt.Errorf("failed to generate key: %w", err)
}
jwkKeySet.Keys = append(jwkKeySet.Keys, jwkKey)
}
}
return &jwkKeySet, nil
}
// ParseBytes parses JWK from the incoming byte buffer.
func ParseBytes(buf []byte) (*Set, error) {
return parse(string(buf))
}
// ParseString parses JWK from the incoming string.
func ParseString(s string) (*Set, error) {
return parse(s)
}
// GenerateKey creates an internal representation of a key from a raw JWK JSON
func (r *RawKeyJSON) GenerateKey() (Key, error) {
var key Key
switch r.KeyType {
case jwa.RSA:
if r.D != nil {
key = &RSAPrivateKey{}
} else {
key = &RSAPublicKey{}
}
case jwa.EC:
if r.D != nil {
key = &ECDSAPrivateKey{}
} else {
key = &ECDSAPublicKey{}
}
case jwa.OctetSeq:
key = &SymmetricKey{}
default:
return nil, errors.New("unrecognized key type")
}
err := key.GenerateKey(r)
if err != nil {
return nil, fmt.Errorf("failed to generate key from JWK: %w", err)
}
return key, nil
}