From 572bbdc339b154cb274dc44252ca2d6c11663712 Mon Sep 17 00:00:00 2001 From: Andrea Franz Date: Fri, 15 Mar 2019 10:26:38 +0100 Subject: [PATCH] parse sign response and calculate v --- command_set.go | 2 +- types/signature.go | 82 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 types/signature.go diff --git a/command_set.go b/command_set.go index 0096173..1ba9aa6 100644 --- a/command_set.go +++ b/command_set.go @@ -199,7 +199,7 @@ func (cs *CommandSet) Sign(data []byte) (*types.Signature, error) { return nil, err } - return types.ParseSignature(resp.Data) + return types.ParseSignature(data, resp.Data) } func (cs *CommandSet) mutualAuthenticate() error { diff --git a/types/signature.go b/types/signature.go new file mode 100644 index 0000000..1a28053 --- /dev/null +++ b/types/signature.go @@ -0,0 +1,82 @@ +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 +}