@@ -2,13 +2,15 @@ package types
22
33import (
44 "bytes"
5+ "errors"
56
67 "github.com/ethereum/go-ethereum/crypto"
78 "github.com/status-im/keycard-go/apdu"
89)
910
1011var (
1112 TagSignatureTemplate = uint8 (0xA0 )
13+ TagRawSignature = uint8 (0x80 )
1214)
1315
1416type Signature struct {
@@ -19,40 +21,59 @@ type Signature struct {
1921}
2022
2123func ParseSignature (message , resp []byte ) (* Signature , error ) {
22- pubKey , err := apdu .FindTag (resp , apdu.Tag {TagSignatureTemplate }, apdu.Tag {0x80 })
24+ // check for old template first because TagRawSignature matches the pubkey tag
25+ template , err := apdu .FindTag (resp , apdu.Tag {TagSignatureTemplate })
26+ if err == nil {
27+ return parseLegacySignature (message , template )
28+ }
29+
30+ sig , err := apdu .FindTag (resp , apdu.Tag {TagRawSignature })
31+
2332 if err != nil {
2433 return nil , err
2534 }
2635
27- r , err := apdu .FindTagN (resp , 0 , apdu.Tag {TagSignatureTemplate }, apdu.Tag {0x30 }, apdu.Tag {0x02 })
36+ return ParseRecoverableSignature (message , sig )
37+ }
38+
39+ func ParseRecoverableSignature (message , sig []byte ) (* Signature , error ) {
40+ if len (sig ) != 65 {
41+ return nil , errors .New ("invalid signature" )
42+ }
43+
44+ pubKey , err := crypto .Ecrecover (message , sig )
2845 if err != nil {
2946 return nil , err
3047 }
3148
49+ return & Signature {
50+ pubKey : pubKey ,
51+ r : sig [0 :32 ],
52+ s : sig [32 :64 ],
53+ v : sig [64 ],
54+ }, nil
55+ }
56+
57+ func DERSignatureToRS (tlv []byte ) ([]byte , []byte , error ) {
58+ r , err := apdu .FindTagN (tlv , 0 , apdu.Tag {0x30 }, apdu.Tag {0x02 })
59+ if err != nil {
60+ return nil , nil , err
61+ }
62+
3263 if len (r ) > 32 {
3364 r = r [len (r )- 32 :]
3465 }
3566
36- s , err := apdu .FindTagN (resp , 1 , apdu. Tag { TagSignatureTemplate } , apdu.Tag {0x30 }, apdu.Tag {0x02 })
67+ s , err := apdu .FindTagN (tlv , 1 , apdu.Tag {0x30 }, apdu.Tag {0x02 })
3768 if err != nil {
38- return nil , err
69+ return nil , nil , err
3970 }
4071
4172 if len (s ) > 32 {
4273 s = s [len (s )- 32 :]
4374 }
4475
45- v , err := calculateV (message , pubKey , r , s )
46- if err != nil {
47- return nil , err
48- }
49-
50- return & Signature {
51- pubKey : pubKey ,
52- r : r ,
53- s : s ,
54- v : v ,
55- }, nil
76+ return r , s , nil
5677}
5778
5879func (s * Signature ) PubKey () []byte {
@@ -71,9 +92,33 @@ func (s *Signature) V() byte {
7192 return s .v
7293}
7394
95+ func parseLegacySignature (message , template []byte ) (* Signature , error ) {
96+ pubKey , err := apdu .FindTag (template , apdu.Tag {0x80 })
97+ if err != nil {
98+ return nil , err
99+ }
100+
101+ r , s , err := DERSignatureToRS (template )
102+ if err != nil {
103+ return nil , err
104+ }
105+
106+ v , err := calculateV (message , pubKey , r , s )
107+ if err != nil {
108+ return nil , err
109+ }
110+
111+ return & Signature {
112+ pubKey : pubKey ,
113+ r : r ,
114+ s : s ,
115+ v : v ,
116+ }, nil
117+ }
118+
74119func calculateV (message , pubKey , r , s []byte ) (v byte , err error ) {
75120 rs := append (r , s ... )
76- for i := 0 ; i < 2 ; i ++ {
121+ for i := 0 ; i < 4 ; i ++ {
77122 v = byte (i )
78123 sig := append (rs , v )
79124 rec , err := crypto .Ecrecover (message , sig )
0 commit comments