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

