// Copyright 2024 Matthew Rich . All rights reserved. package config import ( "context" "encoding/json" "github.com/ProtonMail/go-crypto/openpgp" "io" "strings" "strconv" "gopkg.in/yaml.v3" "decl/internal/data" "decl/internal/codec" "fmt" "log/slog" ) type OpenPGPSignature struct { KeyRing string `json:"keyring,omitempty" yaml:"keyring,omitempty"` Signature string `json:"signature,omitempty" yaml:"signature,omitempty"` entities openpgp.EntityList } func NewOpenPGPSignature() *OpenPGPSignature { o := &OpenPGPSignature{} return o } func (o *OpenPGPSignature) URI() string { return fmt.Sprintf("%s://%s", o.Type(), "") } func (o *OpenPGPSignature) SetURI(uri string) error { return nil } func (o *OpenPGPSignature) SetParsedURI(uri data.URIParser) error { return nil } func (o *OpenPGPSignature) Read(ctx context.Context) (yamlData []byte, err error) { pemReader := io.NopCloser(strings.NewReader(o.KeyRing)) o.entities, err = openpgp.ReadArmoredKeyRing(pemReader) return } func (o *OpenPGPSignature) Load(r io.Reader) (err error) { err = codec.NewYAMLDecoder(r).Decode(o) if err == nil { _, err = o.Read(context.Background()) } return err } func (o *OpenPGPSignature) LoadYAML(yamlData string) (err error) { err = codec.NewYAMLStringDecoder(yamlData).Decode(o) slog.Info("OpenPGP.LoadYAML()", "keyring", len(o.KeyRing), "err", err) if err == nil { _, err = o.Read(context.Background()) } return err } func (o *OpenPGPSignature) UnmarshalJSON(data []byte) error { if unmarshalErr := json.Unmarshal(data, o); unmarshalErr != nil { return unmarshalErr } //o.NewReadConfigCommand() return nil } func (o *OpenPGPSignature) UnmarshalYAML(value *yaml.Node) error { type decodeOpenPGP OpenPGPSignature if unmarshalErr := value.Decode((*decodeOpenPGP)(o)); unmarshalErr != nil { return unmarshalErr } return nil } func (o *OpenPGPSignature) Clone() data.Configuration { jsonGeneric, _ := json.Marshal(o) clone := NewOpenPGPSignature() if unmarshalErr := json.Unmarshal(jsonGeneric, &clone); unmarshalErr != nil { panic(unmarshalErr) } return clone } func (o *OpenPGPSignature) Type() string { return "openpgp" } func (o *OpenPGPSignature) GetEntityIndex(key string) (index int, field string, err error) { values := strings.SplitN(key, ".", 2) if len(values) == 2 { if index, err = strconv.Atoi(values[0]); err == nil { field = values[1] } } else { err = data.ErrUnknownConfigurationKey } return } func (o *OpenPGPSignature) GetValue(name string) (result any, err error) { index, field, err := o.GetEntityIndex(name) if len(o.entities) > index && err == nil { switch field { case "PublicKey": return o.entities[index].PrimaryKey, err case "PrivateKey": return o.entities[index].PrimaryKey, err } } err = data.ErrUnknownConfigurationKey return } // Expected key: 0.PrivateKey func (o *OpenPGPSignature) Has(key string) (ok bool) { index, field, err := o.GetEntityIndex(key) if len(o.entities) > index && err == nil { switch field { case "PublicKey": ok = o.entities[index].PrimaryKey != nil case "PrivateKey": ok = o.entities[index].PrimaryKey != nil } } return }