package jwk import ( "fmt" "sync" "sync/atomic" ) var strictKeyUsage = atomic.Bool{} var keyUsageNames = map[string]struct{}{} var muKeyUsageName sync.RWMutex // RegisterKeyUsage registers a possible value that can be used for KeyUsageType. // Normally, key usage (or the "use" field in a JWK) is either "sig" or "enc", // but other values may be used. // // While this module only works with "sig" and "enc", it is possible that // systems choose to use other values. This function allows users to register // new values to be accepted as valid key usage types. Values are case sensitive. // // Furthermore, the check against registered values can be completely turned off // by setting the global option `jwk.WithStrictKeyUsage(false)`. func RegisterKeyUsage(v string) { muKeyUsageName.Lock() defer muKeyUsageName.Unlock() keyUsageNames[v] = struct{}{} } func UnregisterKeyUsage(v string) { muKeyUsageName.Lock() defer muKeyUsageName.Unlock() delete(keyUsageNames, v) } func init() { strictKeyUsage.Store(true) RegisterKeyUsage("sig") RegisterKeyUsage("enc") } func isValidUsage(v string) bool { // This function can return true if strictKeyUsage is false if !strictKeyUsage.Load() { return true } muKeyUsageName.RLock() defer muKeyUsageName.RUnlock() _, ok := keyUsageNames[v] return ok } func (k KeyUsageType) String() string { return string(k) } func (k *KeyUsageType) Accept(v any) error { switch v := v.(type) { case KeyUsageType: if !isValidUsage(v.String()) { return fmt.Errorf("invalid key usage type: %q", v) } *k = v return nil case string: if !isValidUsage(v) { return fmt.Errorf("invalid key usage type: %q", v) } *k = KeyUsageType(v) return nil } return fmt.Errorf("invalid Go type for key usage type: %T", v) }