GO实现ECC椭圆曲线加密算法
椭圆曲线加密算法,即:Elliptic Curve Cryptography,简称ECC,是基于椭圆曲线数学理论实现的一种非对称加密算法。相比RSA,ECC优势是可以使用更短的密钥,来实现与RSA相当或更高的安全。
ECC的主要优势是在某些情况下它比其他的方法使用更小的密钥——比如RSA加密算法——提供相当的或更高等级的安全。
ECC 164位的密钥产生的一个安全级相当于RSA 1024位密钥提供的保密强度,而且计算量较小,处理速度更快,存储空间和传输带宽占用较少。
ECC 164位的密钥产生的一个安全级相当于RSA 1024位密钥提供的保密强度,而且计算量较小,处理速度更快,存储空间和传输带宽占用较少。
目前我国居民二代身份证正在使用 256 位的椭圆曲线密码,比特币也选择ECC作为加密算法。
使用GO实现生成私钥公钥
package main import ( "crypto/ecdsa" "crypto/elliptic" "crypto/rand" "crypto/x509" "encoding/pem" "fmt" "os" ) const EccPrivateKeyFile = "./keystudy/EccPrivateKey.pem" const EccPublicKeyFile = "./keystudy/EccPublicKey.pem" //错误函数封装 func checkErr(mess string,err error) { if err != nil{ fmt.Printf(mess + ":%s\n",err) } } //椭圆曲线加密算法的实现 //生成私钥公钥 func generateEccKeypair() { //- 选择一个椭圆曲线(在elliptic包) //type Curve //func P224() Curve //func P256() Curve //func P384() Curve //func P521() Curve curve := elliptic.P256() //- 使用ecdsa包,创建私钥 //ecdsa椭圆曲线数字签名 privateKey,err := ecdsa.GenerateKey(curve,rand.Reader) checkErr("生成私钥失败",err) //使用x509编码 //MarshalECPrivateKey将ecdsa私钥序列化为ASN.1 DER编码。 derText,err := x509.MarshalECPrivateKey(privateKey) checkErr("x509编码出错",err) //写入pemblock block1 := pem.Block{ Type: "ECC PRIVATE KEY", Headers: nil, Bytes: derText, } //pem encode fp,err := os.Create(EccPrivateKeyFile) checkErr("文件创建失败",err) defer fp.Close() err = pem.Encode(fp,&block1) checkErr("pem encode失败",err) fmt.Printf("++++++++++++++++++++++\n") //获取公钥 publicKey := privateKey.PublicKey //x509编码 derText2,err := x509.MarshalPKIXPublicKey(&publicKey) checkErr("x509编码失败",err) //- 写入pem.Block中 block2 := pem.Block{ Type: "ECC PUBLIC", Headers: nil, Bytes: derText2, } //pem encode fp2,err := os.Create(EccPublicKeyFile) checkErr("FP2创建失败",err) defer fp2.Close() pem.Encode(fp2,&block2) } func main() { generateEccKeypair() }
使用GO实现私钥签名,公钥验证
package main import ( "crypto/ecdsa" "crypto/rand" "crypto/sha256" "crypto/x509" "encoding/pem" "errors" "fmt" "io/ioutil" "math/big" ) //ecc公钥认证 const EccPrivateKeyFile2 = "./keystudy/EccPrivateKey.pem" const EccPublicKeyFile2 = "./keystudy/EccPublicKey.pem" type Signature struct { r *big.Int s *big.Int } //使用私钥签名 func eccSignData(filename string,src []byte) (Signature,error){ //读取私钥解码 fp,err := ioutil.ReadFile(filename) if err != nil{ return Signature{},err } //pem decode block,_ := pem.Decode(fp) //解码der得到私钥 derText := block.Bytes privateKey,err := x509.ParseECPrivateKey(derText) if err != nil{ return Signature{},err } //对原文生成哈希 hash := sha256.Sum256(src) //使用私钥签名 //使用私钥对任意长度的hash值(必须是较大信息的hash结果)进行签名,返回签名结果(一对大整数)。私钥的安全性取决于密码读取器 //func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) r,s,err := ecdsa.Sign(rand.Reader,privateKey,hash[:]) if err != nil{ return Signature{},err } sig := Signature{r,s} return sig,nil } //使用公钥校验 func eccVerifySig(filename string,src []byte,Sign Signature) error{ //读取公钥解码 fp,err := ioutil.ReadFile(EccPublicKeyFile2) if err != nil{ return err } //pem decode block,_ := pem.Decode(fp) //解码der得到私钥 derText := block.Bytes publicKeyInterface,err := x509.ParsePKIXPublicKey(derText) if err != nil{ return err } publicKey, ok := publicKeyInterface.(*ecdsa.PublicKey) if !ok { return errors.New("断言失败,非ecds公钥!\n") } //对原文生成哈希 hash := sha256.Sum256(src) //使用公钥验证 isok := ecdsa.Verify(publicKey,hash[:],Sign.r,Sign.s) if !isok{ return errors.New("校验失败") } return nil } func main() { src := []byte("hello") //私钥签名 Signature,err := eccSignData(EccPrivateKeyFile2,src) if err != nil{ fmt.Println(err) } //src2 := []byte("hello2") //校验 err = eccVerifySig(EccPublicKeyFile2,src,Signature) if err != nil{ fmt.Println(err) return } fmt.Println("校验成功") }
类型断言讲解
https://www.zhihu.com/zvideo/1277562272471314432