recovery.go raw
1 package secp
2
3 import (
4 "fmt"
5 )
6
7 // SignRecoverable creates a recoverable ECDSA signature
8 func (c *Context) SignRecoverable(msg32 []byte, seckey []byte) (sig []byte, err error) {
9 if ecdsaSignRecoverable == nil {
10 err = fmt.Errorf("recovery module not available")
11 return
12 }
13
14 if len(msg32) != 32 {
15 err = fmt.Errorf("message must be 32 bytes")
16 return
17 }
18
19 if len(seckey) != PrivateKeySize {
20 err = fmt.Errorf("private key must be %d bytes", PrivateKeySize)
21 return
22 }
23
24 sig = make([]byte, RecoverableSignatureSize)
25 ret := ecdsaSignRecoverable(c.ctx, &sig[0], &msg32[0], &seckey[0], 0, 0)
26 if ret != 1 {
27 err = fmt.Errorf("failed to create recoverable signature")
28 return
29 }
30
31 return
32 }
33
34 // SerializeRecoverableSignatureCompact serializes a recoverable signature
35 func (c *Context) SerializeRecoverableSignatureCompact(sig []byte) (output64 []byte, recid int32, err error) {
36 if ecdsaRecoverableSignatureSerializeCompact == nil {
37 err = fmt.Errorf("recovery module not available")
38 return
39 }
40
41 if len(sig) != RecoverableSignatureSize {
42 err = fmt.Errorf("recoverable signature must be %d bytes", RecoverableSignatureSize)
43 return
44 }
45
46 output64 = make([]byte, 64)
47 ret := ecdsaRecoverableSignatureSerializeCompact(c.ctx, &output64[0], &recid, &sig[0])
48 if ret != 1 {
49 err = fmt.Errorf("failed to serialize recoverable signature")
50 return
51 }
52
53 return
54 }
55
56 // ParseRecoverableSignatureCompact parses a compact recoverable signature
57 func (c *Context) ParseRecoverableSignatureCompact(input64 []byte, recid int32) (sig []byte, err error) {
58 if ecdsaRecoverableSignatureParseCompact == nil {
59 err = fmt.Errorf("recovery module not available")
60 return
61 }
62
63 if len(input64) != 64 {
64 err = fmt.Errorf("compact signature must be 64 bytes")
65 return
66 }
67
68 if recid < 0 || recid > 3 {
69 err = fmt.Errorf("recovery id must be 0-3")
70 return
71 }
72
73 sig = make([]byte, RecoverableSignatureSize)
74 ret := ecdsaRecoverableSignatureParseCompact(c.ctx, &sig[0], &input64[0], recid)
75 if ret != 1 {
76 err = fmt.Errorf("failed to parse recoverable signature")
77 return
78 }
79
80 return
81 }
82
83 // Recover recovers a public key from a recoverable signature
84 func (c *Context) Recover(sig []byte, msg32 []byte) (pubkey []byte, err error) {
85 if ecdsaRecover == nil {
86 err = fmt.Errorf("recovery module not available")
87 return
88 }
89
90 if len(sig) != RecoverableSignatureSize {
91 err = fmt.Errorf("recoverable signature must be %d bytes", RecoverableSignatureSize)
92 return
93 }
94
95 if len(msg32) != 32 {
96 err = fmt.Errorf("message must be 32 bytes")
97 return
98 }
99
100 pubkey = make([]byte, PublicKeySize)
101 ret := ecdsaRecover(c.ctx, &pubkey[0], &sig[0], &msg32[0])
102 if ret != 1 {
103 err = fmt.Errorf("failed to recover public key")
104 return
105 }
106
107 return
108 }
109