通过Go语言封装一个椭圆曲线算法(ecdsa),方便自己使用。签名算法直接写死sha256了,有需要自行修改即可。
ecc_utils.go
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
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)
}
复制代码