This repository has been archived by the owner on Jan 4, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 5
/
signature.go
125 lines (110 loc) · 3.17 KB
/
signature.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package types
import (
"bytes"
"crypto/ecdsa"
"fmt"
"log"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
)
const (
typeEIP712 = 2
typeEthSign = 3
)
type Signature struct {
V byte
R common.Hash
S common.Hash
}
func SignHash(orderHash common.Hash, privateKey *ecdsa.PrivateKey) (string, error) {
return SignHashEIP712(orderHash, privateKey)
}
func SignHashEIP712(orderHash common.Hash, privateKey *ecdsa.PrivateKey) (string, error) {
sigBytes, err := crypto.Sign(orderHash.Bytes(), privateKey)
if err != nil {
return "", err
}
signature := make([]byte, 66)
signature[0] = sigBytes[64] + 27
copy(signature[1:33], sigBytes[0:32])
copy(signature[33:65], sigBytes[32:64])
signature[65] = typeEIP712
return hexutil.Encode(signature), nil
}
func SignHashEthSign(orderHash common.Hash, privateKey *ecdsa.PrivateKey) (string, error) {
magicMessage := crypto.Keccak256(
[]byte("\x19Ethereum Signed Message:\n32"),
orderHash.Bytes(),
)
sigBytes, err := crypto.Sign(magicMessage, privateKey)
if err != nil {
return "", err
}
signature := make([]byte, 66)
signature[0] = sigBytes[64] + 27
copy(signature[1:33], sigBytes[0:32])
copy(signature[33:65], sigBytes[32:64])
signature[65] = typeEthSign
return hexutil.Encode(signature), nil
}
func VerifySignature(signature []byte, address common.Address, hash common.Hash) bool {
if len(signature) != 66 {
if len(signature) != 65 {
log.Printf("Invalid length: %v", len(signature))
return false
}
return VerifySignatureEthSign(append(signature, typeEthSign), address, hash)
}
if signature[65] == typeEIP712 {
return VerifySignatureEIP712(signature, address, hash)
}
if signature[65] == typeEthSign {
return VerifySignatureEthSign(signature, address, hash)
}
return false
}
func VerifySignatureEIP712(signature []byte, address common.Address, hash common.Hash) bool {
if len(signature) != 66 {
log.Printf("Invalid length: %v", len(signature))
return false
}
sigBytes := make([]byte, len(signature))
copy(sigBytes, signature)
v := sigBytes[0]
r := sigBytes[1:33]
s := sigBytes[33:65]
if v < 27 {
return false
}
pub, err := crypto.Ecrecover(hash.Bytes(), append(append(r, s...), v-27))
if err != nil {
log.Println(err.Error())
return false
}
recoverAddress := common.BytesToAddress(crypto.Keccak256(pub[1:])[12:])
return bytes.Equal(address[:], recoverAddress[:])
}
func VerifySignatureEthSign(signature []byte, address common.Address, hash common.Hash) bool {
if len(signature) != 66 {
log.Printf("Invalid length: %v", len(signature))
return false
}
sigBytes := make([]byte, len(signature))
copy(sigBytes, signature)
v := sigBytes[0]
r := sigBytes[1:33]
s := sigBytes[33:65]
if v < 27 {
return false
}
hashedBytes := append([]byte(fmt.Sprintf("\x19Ethereum Signed Message:\n%v", len(hash[:]))), hash[:]...)
signedBytes := crypto.Keccak256(hashedBytes)
pub, err := crypto.Ecrecover(signedBytes, append(append(r, s...), v-27))
if err != nil {
log.Println(err.Error())
return false
}
recoverAddress := common.BytesToAddress(crypto.Keccak256(pub[1:])[12:])
return bytes.Equal(address[:], recoverAddress[:])
}