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

  • 2020 年 3 月 27 日
  • 筆記

通过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)  }    复制代码