package sigcred import ( "dehub.dev/src/dehub.git/fs" "dehub.dev/src/dehub.git/typeobj" ) // Signifier reprsents a single signing method being defined in the Config. Only // one field should be set on each Signifier. type Signifier struct { PGPPublicKey *SignifierPGP `type:"pgp_public_key"` // PGPPublicKeyFile is deprecated, only PGPPublicKey should be used PGPPublicKeyFile *SignifierPGPFile `type:"pgp_public_key_file"` } // MarshalYAML implements the yaml.Marshaler interface. func (s Signifier) MarshalYAML() (interface{}, error) { return typeobj.MarshalYAML(s) } // UnmarshalYAML implements the yaml.Unmarshaler interface. func (s *Signifier) UnmarshalYAML(unmarshal func(interface{}) error) error { if err := typeobj.UnmarshalYAML(s, unmarshal); err != nil { return err } // TODO deprecate PGPPublicKeyFile if s.PGPPublicKeyFile != nil { s.PGPPublicKey = &SignifierPGP{Path: s.PGPPublicKeyFile.Path} s.PGPPublicKeyFile = nil } return nil } // Interface returns the SignifierInterface instance encapsulated by this // Signifier object. // // accountID is given so as to automatically fill the AccountID field of // Credentials returned from Sign, since the underlying implementation doesn't // know what account it's signing for. func (s Signifier) Interface(accountID string) (SignifierInterface, error) { el, _, err := typeobj.Element(s) if err != nil { return nil, err } return accountSignifier(accountID, el.(SignifierInterface)), nil } // SignifierInterface describes the methods that all Signifiers must implement. type SignifierInterface interface { // Sign returns a Credential containing a signature of the given data. // // tree can be used to find the Signifier at a particular snapshot. Sign(fs fs.FS, data []byte) (Credential, error) // Signed returns true if the Signifier was used to sign the Credential. Signed(fs fs.FS, cred Credential) (bool, error) // Verify asserts that the Signifier produced the given Credential for the // given data set, or returns an error. // // tree can be used to find the Signifier at a particular snapshot. Verify(fs fs.FS, data []byte, cred Credential) error } type signifierMiddleware struct { SignifierInterface signCallback func(*Credential) } func (sm signifierMiddleware) Sign(fs fs.FS, data []byte) (Credential, error) { cred, err := sm.SignifierInterface.Sign(fs, data) if err != nil || sm.signCallback == nil { return cred, err } sm.signCallback(&cred) return cred, nil } // accountSignifier wraps a SignifierInterface to always set the accountID field // on Credentials it produces via the Sign method. // // TODO accountSignifier shouldn't be necessary, it's very ugly. Which indicates // that Credential probably shouldn't have AccountID on it, which makes sense. // Some refactoring is required here. func accountSignifier(accountID string, sigInt SignifierInterface) SignifierInterface { return signifierMiddleware{ SignifierInterface: sigInt, signCallback: func(cred *Credential) { cred.AccountID = accountID }, } }