golang-標準庫(crypto/ecdsa)

ecdsa包提供了非對稱加密算法ECDSA,ECDSA爲橢圓曲線加密算法,是基於橢圓方程公式,安全性要高於RSA。
這裏說下使用ecdsa的密匙生成和簽名校驗,不涉及原理;
go中ecdsa目前只有用私鑰加密,公鑰做校驗,沒有解密環節;目前可以應用於數字簽名;

基於RSA的基礎,本文直接貼出代碼,代碼有註釋,不做過多的闡述,加密算法都是別人爲我們封裝好的工具方法,具體原理不涉及

package main

import (
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/sha256"
	"crypto/x509"
	"encoding/pem"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"strings"
)

//隨機熵,用於加密安全
var randSign = "22220316zafes20180lk7zafes20180619zafepikas"

//隨機key,用於創建公鑰和私鑰
var randKey = "lk0f7279c18d439459435s714797c9680335a320"

var PriKey *ecdsa.PrivateKey
var PubKey *ecdsa.PublicKey

func init() {
	// 初始化生成私匙公匙
	priFile, _ := os.Create("ec-pri.pem")
	pubFile, _ := os.Create("ec-pub.pem")
	if err := generateKey(priFile, pubFile); err != nil {
		log.Println(err)
		os.Exit(1)
	}
	// 加載私匙公匙
	if err := loadKey(); err != nil {
		log.Println(err)
		os.Exit(1)
	}
}
func main() {

	// 預加密數據
	text := "hello dalgurak"
	// hash簽名
	hashText := sha256.New().Sum([]byte(text))
	// 加密私匙
	r, s, err := ecdsa.Sign(strings.NewReader(randSign), PriKey, hashText)
	if err != nil {
		log.Println(err)
		os.Exit(1)
	}

	// 公匙驗證hash的正確性
	b := ecdsa.Verify(PubKey, hashText, r, s)
	fmt.Println(b)
}

// 生成密匙對
func generateKey(priFile, pubFile *os.File) error {
	lenth := len(randKey)
	if lenth < 224/8 {
		return errors.New("私鑰長度太短,至少爲36位!")
	}
	// 根據隨機密匙的長度創建私匙
	var curve elliptic.Curve
	if lenth > 521/8+8 {
		curve = elliptic.P521()
	} else if lenth > 384/8+8 {
		curve = elliptic.P384()
	} else if lenth > 256/8+8 {
		curve = elliptic.P256()
	} else if lenth > 224/8+8 {
		curve = elliptic.P224()
	}
	// 生成私匙
	priKey, err := ecdsa.GenerateKey(curve, strings.NewReader(randKey))
	if err != nil {
		return err
	}
	// *****************保存私匙*******************
	// 序列化私匙
	priBytes, err := x509.MarshalECPrivateKey(priKey)
	if err != nil {
		return err
	}
	priBlock := pem.Block{
		Type:  "ECD PRIVATE KEY",
		Bytes: priBytes,
	}
	// 編碼私匙,寫入文件
	if err := pem.Encode(priFile, &priBlock); err != nil {
		return err
	}
	// *****************保存公匙*******************
	// 序列化公匙
	pubBytes, err := x509.MarshalPKIXPublicKey(&priKey.PublicKey)
	if err != nil {
		return err
	}
	pubBlock := pem.Block{
		Type:  "ECD PUBLIC KEY",
		Bytes: pubBytes,
	}
	// 編碼公匙,寫入文件
	if err := pem.Encode(pubFile, &pubBlock); err != nil {
		return err
	}
	return nil
}

// 加載私匙公匙
func loadKey() error {
	// 讀取密匙
	pri, _ := ioutil.ReadFile("ec-pri.pem")
	pub, _ := ioutil.ReadFile("ec-pub.pem")
	// 解碼私匙
	block, _ := pem.Decode(pri)
	var err error
	// 反序列化私匙
	PriKey, err = x509.ParseECPrivateKey(block.Bytes)
	if err != nil {
		return err
	}
	// 解碼公匙
	block, _ = pem.Decode(pub)
	// 反序列化公匙
	var i interface{}
	i, err = x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		return err
	}
	// PubKey = (*ecdsa.PublicKey)(i)
	var ok bool
	PubKey, ok = i.(*ecdsa.PublicKey)
	if !ok {
		return errors.New("the public conversion error")
	}
	return nil
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章