119 lines
2.3 KiB
Go
119 lines
2.3 KiB
Go
package types
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"io"
|
|
"math"
|
|
|
|
cbg "github.com/whyrusleeping/cbor-gen"
|
|
)
|
|
|
|
type SigType byte
|
|
|
|
const (
|
|
SigTypeUnknown = SigType(math.MaxUint8)
|
|
|
|
SigTypeEd25519 = SigType(iota)
|
|
)
|
|
|
|
func (t SigType) Name() (string, error) {
|
|
switch t {
|
|
case SigTypeUnknown:
|
|
return "unknown", nil
|
|
case SigTypeEd25519:
|
|
return "ed25519", nil
|
|
default:
|
|
return "", fmt.Errorf("invalid signature type: %d", t)
|
|
}
|
|
}
|
|
|
|
const SignatureMaxLength = 200
|
|
|
|
type Signature struct {
|
|
Type SigType
|
|
Data []byte
|
|
}
|
|
|
|
func (s *Signature) Equals(o *Signature) bool {
|
|
if s == nil || o == nil {
|
|
return s == o
|
|
}
|
|
return s.Type == o.Type && bytes.Equal(s.Data, o.Data)
|
|
}
|
|
|
|
func (s *Signature) MarshalCBOR(w io.Writer) error {
|
|
if s == nil {
|
|
_, err := w.Write(cbg.CborNull)
|
|
return err
|
|
}
|
|
|
|
header := cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(s.Data)+1))
|
|
if _, err := w.Write(header); err != nil {
|
|
return err
|
|
}
|
|
if _, err := w.Write([]byte{byte(s.Type)}); err != nil {
|
|
return err
|
|
}
|
|
if _, err := w.Write(s.Data); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *Signature) UnmarshalCBOR(br io.Reader) error {
|
|
maj, l, err := cbg.CborReadHeader(br)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if maj != cbg.MajByteString {
|
|
return fmt.Errorf("not a byte string")
|
|
}
|
|
if l > SignatureMaxLength {
|
|
return fmt.Errorf("string too long")
|
|
}
|
|
if l == 0 {
|
|
return fmt.Errorf("string empty")
|
|
}
|
|
buf := make([]byte, l)
|
|
if _, err = io.ReadFull(br, buf); err != nil {
|
|
return err
|
|
}
|
|
switch SigType(buf[0]) {
|
|
default:
|
|
return fmt.Errorf("invalid signature type in cbor input: %d", buf[0])
|
|
case SigTypeEd25519:
|
|
s.Type = SigTypeEd25519
|
|
}
|
|
s.Data = buf[1:]
|
|
return nil
|
|
}
|
|
|
|
func (s *Signature) MarshalBinary() ([]byte, error) {
|
|
bs := make([]byte, len(s.Data)+1)
|
|
bs[0] = byte(s.Type)
|
|
copy(bs[1:], s.Data)
|
|
return bs, nil
|
|
}
|
|
|
|
func (s *Signature) UnmarshalBinary(bs []byte) error {
|
|
if len(bs) > SignatureMaxLength {
|
|
return fmt.Errorf("invalid signature bytes, too long (%d)", len(bs))
|
|
}
|
|
if len(bs) == 0 {
|
|
return fmt.Errorf("invalid signature bytes of length 0")
|
|
}
|
|
switch SigType(bs[0]) {
|
|
default:
|
|
// Do not error during unmarshal but leave a standard value.
|
|
// unmarshal(marshal(zero valued sig)) is valuable for test
|
|
// and type needs to be checked by caller anyway.
|
|
s.Type = SigTypeUnknown
|
|
case SigTypeEd25519:
|
|
s.Type = SigTypeEd25519
|
|
}
|
|
s.Data = bs[1:]
|
|
return nil
|
|
}
|