Loger's blog site

Loger's blog site,分享编程知识,顺便发发牢骚

0%

Golang封装ecdsa(ecc)相关工具类:密钥生成、序列化、签名、验签

通过Go语言封装一个椭圆曲线算法(ecdsa),方便自己使用。签名算法直接写死sha256了,有需要自行修改即可。

ecc_utils.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
package ecc

import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/sha256"
"crypto/x509"
"encoding/base64"
"encoding/hex"
"math/big"
"strings"
)

func GenKeyPair() (privateKey string, publicKey string, e error) {
priKey, e := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if e != nil {
return "", "", e
}
ecPrivateKey, e := x509.MarshalECPrivateKey(priKey)
if e != nil {
return "", "", e
}
privateKey = base64.StdEncoding.EncodeToString(ecPrivateKey)

X := priKey.X
Y := priKey.Y
xStr, e := X.MarshalText()
if e != nil {
return "", "", e
}
yStr, e := Y.MarshalText()
if e != nil {
return "", "", e
}
public := string(xStr) + "+" + string(yStr)
publicKey = base64.StdEncoding.EncodeToString([]byte(public))
return
}

func BuildPrivateKey(privateKeyStr string) (priKey *ecdsa.PrivateKey, e error) {
bytes, e := base64.StdEncoding.DecodeString(privateKeyStr)
if e != nil {
return nil, e
}
priKey, e = x509.ParseECPrivateKey(bytes)
if e != nil {
return nil, e
}
return
}

func BuildPublicKey(publicKeyStr string) (pubKey *ecdsa.PublicKey, e error) {
bytes, e := base64.StdEncoding.DecodeString(publicKeyStr)
if e != nil {
return nil, e
}
split := strings.Split(string(bytes), "+")
xStr := split[0]
yStr := split[1]
x := new(big.Int)
y := new(big.Int)
e = x.UnmarshalText([]byte(xStr))
if e != nil {
return nil, e
}
e = y.UnmarshalText([]byte(yStr))
if e != nil {
return nil, e
}
pub := ecdsa.PublicKey{Curve: elliptic.P256(), X: x, Y: y}
pubKey = &pub
return
}

func Sign(content string, privateKeyStr string) (signature string, e error) {
priKey, e := BuildPrivateKey(privateKeyStr)
if e != nil {
return "", e
}
r, s, e := ecdsa.Sign(rand.Reader, priKey, []byte(hash(content)))
if e != nil {
return "", e
}
rt, e := r.MarshalText()
st, e := s.MarshalText()
signStr := string(rt) + "+" + string(st)
signature = hex.EncodeToString([]byte(signStr))
return
}

func VerifySign(content string, signature string, publicKeyStr string) bool {
decodeSign, e := hex.DecodeString(signature)
if e != nil {
return false
}
split := strings.Split(string(decodeSign), "+")
rStr := split[0]
sStr := split[1]
rr := new(big.Int)
ss := new(big.Int)
e = rr.UnmarshalText([]byte(rStr))
e = ss.UnmarshalText([]byte(sStr))
pubKey, e := BuildPublicKey(publicKeyStr)
if e != nil {
return false
}
return ecdsa.Verify(pubKey, []byte(hash(content)), rr, ss)
}

// Hash算法,这里是sha256,可以根据需要自定义
func hash(data string) string {
sum := sha256.Sum256([]byte(data))
return base64.StdEncoding.EncodeToString(sum[:])
}

ecc_utils_test.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
package ecc

import "testing"

const pubKey = "MTEzODUyMzM5MzU4ODk1MzEzNzg3MzY2NzYwODUwMjE2MjQzNTE0OTc0NjkzMzM2NzA4OTYzNDY0MDk1MTUxMDkyMjY5MjM0NjE3NjMyKzc5NzY5NDM5NTI4NjcxMzc4OTQ3ODYyMzY0MjQ1ODg4ODA0MTEyMDgwOTM4MjgyNjI0MTY4NDUwNjE0NTg4MDc3MDk0MTUxNzk4NzM3"
const priKey = "MHcCAQEEIBC7/AKbbIHyVF4XJQmvqwrJMX8c8dU2JP6NcReYDlJ1oAoGCCqGSM49AwEHoUQDQgAE+7Yj9jOgDCRccssUMp1NVJExBrJCv6H8LsYUqS8lfSCwW+cdXcnmNDHM5Z2K05bJywyDIWU3f+53z0HK0I4/0Q=="
const content = "Happyjava not only java"
const signature = "36393733373630313538383036323831323937313232353733313837333336373132363935303734303237373233373433363139373530313438383239303532303635383433333733313336362b35363137383339343939383534303631323730373630343438313135333633383339333535303836313830343737333331383935333532383537333730363035313839383939353330363939"

func TestGenKeyPair(t *testing.T) {
privateKey, publicKey, e := GenKeyPair()
if e != nil {
t.Error(e)
return
}
t.Log("pubKey:", publicKey)
t.Log("priKey:", privateKey)
}

func TestBuildPublicKey(t *testing.T) {
publicKey, e := BuildPublicKey(pubKey)
if e != nil {
t.Error(e)
return
}
t.Log("publicKey:", publicKey)
}

func TestBuildPrivateKey(t *testing.T) {
privateKey, e := BuildPrivateKey(priKey)
if e != nil {
t.Error(e)
return
}
t.Log("privateKey:", privateKey)
}

func TestSign(t *testing.T) {
signature, e := Sign(content, priKey)
if e != nil {
t.Error(e)
} else {
t.Log("signature:", signature)
}
}

func TestVerifySign(t *testing.T) {
verify := VerifySign(content, signature, pubKey)
t.Log("verify:", verify)
}