package audit import ( "bytes" "encoding/base64" "encoding/json" "errors" "io" "os" ) type keyDocument struct { Version int `json:"version"` Keys []struct { KeyID string `json:"key_id"` Secret string `json:"secret_base64url"` } `json:"keys"` } func LoadKeys(path string) (map[string][]byte, error) { raw, err := os.ReadFile(path) if err != nil { return nil, errors.New("read Bell audit key file") } var document keyDocument decoder := json.NewDecoder(bytes.NewReader(raw)) decoder.DisallowUnknownFields() if err := decoder.Decode(&document); err != nil || document.Version != 1 || len(document.Keys) == 0 { return nil, errors.New("invalid Bell audit key file") } var trailing any if err := decoder.Decode(&trailing); !errors.Is(err, io.EOF) { return nil, errors.New("invalid Bell audit key file") } values := make(map[string][]byte, len(document.Keys)) for _, item := range document.Keys { secret, err := base64.RawURLEncoding.DecodeString(item.Secret) if err != nil || !keyIDPattern.MatchString(item.KeyID) || len(secret) < 32 { return nil, errors.New("invalid Bell audit key") } if _, exists := values[item.KeyID]; exists { return nil, errors.New("duplicate Bell audit key ID") } values[item.KeyID] = secret } return values, nil }