package types import ( "bytes" "github.com/ethereum/go-ethereum/crypto" "github.com/status-im/keycard-go/apdu" ) var ( TagSignatureTemplate = uint8(0xA0) ) type Signature struct { pubKey []byte r []byte s []byte v byte } func ParseSignature(message, resp []byte) (*Signature, error) { pubKey, err := apdu.FindTag(resp, TagSignatureTemplate, uint8(0x80)) if err != nil { return nil, err } r, err := apdu.FindTagN(resp, 0, TagSignatureTemplate, uint8(0x30), uint8(0x02)) if err != nil { return nil, err } if len(r) > 32 { r = r[len(r)-32:] } s, err := apdu.FindTagN(resp, 1, TagSignatureTemplate, uint8(0x30), uint8(0x02)) if err != nil { return nil, err } v, err := calculateV(message, pubKey, r, s) if err != nil { return nil, err } return &Signature{ pubKey: pubKey, r: r, s: s, v: v, }, nil } func (s *Signature) R() []byte { return s.r } func (s *Signature) S() []byte { return s.s } func (s *Signature) V() byte { return s.v } func calculateV(message, pubKey, r, s []byte) (v byte, err error) { rs := append(r, s...) for i := 0; i < 2; i++ { v = byte(i) sig := append(rs, v) rec, err := crypto.Ecrecover(message, sig) if err != nil { return v, err } if bytes.Equal(pubKey, rec) { return v, nil } } return v, err }