Go-ecc數字簽名詳解與代碼


Go-數字簽名詳解與Rsa數字簽名代碼中已經講了數字簽名的原理,就不重複了git

Ecc簽名的Go實現

crypto/ecdsa包

func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error)

使用私鑰對任意長度的hash值(必須是較大信息的hash結果)進行簽名,返回簽名結果(一對大整數)。私鑰的安全性取決於密碼讀取器的熵度(隨機程度)。golang

func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool

使用公鑰驗證hash值和兩個大整數r、s構成的簽名,並返回簽名是否合法。安全

簽名

  • 使用sha256.Sum356獲取摘要
  • 使用ecdsa.Sign進行簽名
  • 對r s進行序列化

// Ecc 簽名
// plainText 明文
// priPath 私鑰路徑
// 返回 簽名結果ide

func ECCSign(plainText []byte,priPath string) ([]byte,[]byte,error) {
	// get pem.Block
	block,err := util.GetKey(priPath)
	if err != nil{
		_, file, line, _ := runtime.Caller(0)
		return nil,nil,util.Error(file,line+1,err.Error())
	}
	// x509
	priKey,err := x509.ParseECPrivateKey(block.Bytes)
	if err != nil{
		_, file, line, _ := runtime.Caller(0)
		return nil,nil,util.Error(file,line+1,err.Error())
	}
	hashText := sha256.Sum256(plainText)
	// sign
	r,s,err := ecdsa.Sign(rand.Reader,priKey,hashText[:])
	if err != nil{
		_, file, line, _ := runtime.Caller(0)
		return nil,nil,util.Error(file,line+1,err.Error())
	}
	// marshal
	rText,err := r.MarshalText()
	if err != nil{
		_, file, line, _ := runtime.Caller(0)
		return nil,nil,util.Error(file,line+1,err.Error())
	}
	sText,err := s.MarshalText()
	if err != nil{
		_, file, line, _ := runtime.Caller(0)
		return nil,nil,util.Error(file,line+1,err.Error())
	}
	return rText,sText,nil
}

驗證簽名

  • -使用sha256.Sum356獲取摘要
  • 對r s進行反序列化
  • 使用ecdsa.Verify進行簽名認證

// ECC 簽名驗證
// plainText 明文
// rText,sText 簽名
// pubPath公鑰文件路徑
// 返回 驗簽結果 錯誤測試

func ECCVerify(plainText,rText,sText []byte,pubPath string) (bool,error) {
	// get pem.Block
	block,err := util.GetKey(pubPath)
	if err != nil{
		_, file, line, _ := runtime.Caller(0)
		return false,util.Error(file,line+1,err.Error())
	}
	// x509
	pubInter,err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil{
		_, file, line, _ := runtime.Caller(0)
		return false,util.Error(file,line+1,err.Error())
	}
	// assert
	pubKey := pubInter.(*ecdsa.PublicKey)
	hashText := sha256.Sum256(plainText)
	var r,s big.Int
	// unmarshal
	err = r.UnmarshalText(rText)
	if err != nil{
		_, file, line, _ := runtime.Caller(0)
		return false,util.Error(file,line+1,err.Error())
	}
	err = s.UnmarshalText(sText)
	if err != nil{
		_, file, line, _ := runtime.Caller(0)
		return false,util.Error(file,line+1,err.Error())
	}
	// verify
	ok := ecdsa.Verify(pubKey,hashText[:],&r,&s)
	return ok,nil
}

測試代碼

plainText := []byte("張華考上了北京大學;李萍進了中等技術學校;我在百貨公司當售貨員:咱們都有美好的將來")
	rText,sText, _ := ECCSign(plainText,"./eccPrivate.pem")
	ok, err := ECCVerify(plainText,rText,sText,"./eccPublic.pem")
	fmt.Println(err)
	fmt.Printf("驗證成功? %t",ok)
截圖

在這裏插入圖片描述
所有代碼放到了gitee.com/frankyu365/gocryptospa

參考

《現代密碼學教程 谷利澤 楊義先等》
Go標準庫-crypto/ecdsa
Go-標準庫-crypto/sha256code

相關文章
相關標籤/搜索