package sigcred import ( "fmt" "dehub.dev/src/dehub.git/typeobj" ) // CredentialUnion represents a credential, signifying a user's approval of a // payload. Exactly one field tagged with "type" should be set. type CredentialUnion struct { PGPSignature *CredentialPGPSignature `type:"pgp_signature"` // AccountID specifies the account which generated this CredentialUnion. // // NOTE that credentials produced by the direct implementations of Signifier // won't fill in this field, unless specifically documented. The Signifier // produced by the Signifier() method of SignifierUnion _will_ fill this // field in, however. AccountID string `yaml:"account,omitempty"` // AnonID specifies an identifier for the anonymous user which produced this // credential. This field is mutually exclusive with AccountID, and won't be // set by any Signifier implementation unless specifically documented. AnonID string `yaml:"-"` } // MarshalYAML implements the yaml.Marshaler interface. func (c CredentialUnion) MarshalYAML() (interface{}, error) { return typeobj.MarshalYAML(c) } // UnmarshalYAML implements the yaml.Unmarshaler interface. func (c *CredentialUnion) UnmarshalYAML(unmarshal func(interface{}) error) error { return typeobj.UnmarshalYAML(c, unmarshal) } // ErrNotSelfVerifying is returned from the SelfVerify method of CredentialUnion // when the credential does not implement the SelfVerifyingCredential interface. // It may also be returned from the SelfVerify method of the // SelfVerifyingCredential itself, if the credential can only self-verify under // certain circumstances. type ErrNotSelfVerifying struct { // Subject is a descriptor of the value which could not be verified. It may // be a type name or some other identifying piece of information. Subject string } func (e ErrNotSelfVerifying) Error() string { return fmt.Sprintf("%s cannot verify itself", e.Subject) } // SelfVerify will attempt to cast the credential as a SelfVerifyingCredential, // and returns the result of the SelfVerify method being called on it. func (c CredentialUnion) SelfVerify(data []byte) error { el, _, err := typeobj.Element(c) if err != nil { return err } else if selfVerifyingCred, ok := el.(SelfVerifyingCredential); !ok { return ErrNotSelfVerifying{Subject: fmt.Sprintf("credential of type %T", el)} } else if err := selfVerifyingCred.SelfVerify(data); err != nil { return fmt.Errorf("self-verifying credential of type %T: %w", el, err) } return nil } // SelfVerifyingCredential is one which is able to prove its own authenticity by // some means or another. It is not required for a Credential to implement this // interface. type SelfVerifyingCredential interface { // SelfVerify should return nil if the Credential has successfully verified // that it has accredited the given data, or an error describing why it // could not do so. It may return ErrNotSelfVerifying if the Credential can // only self-verify under certain circumstances, and those circumstances are // not met. SelfVerify(data []byte) error }