椭圆曲线加密算法,即:Elliptic Curve Cryptography,简称ECC,是基于椭圆曲线数学理论实现的一种非对称加密算法。相比RSA,ECC优势是可以使用更短的密钥,来实现与RSA相当或更高的安全。
ECC的主要优势是在某些情况下它比其他的方法使用更小的密钥——比如RSA加密算法——提供相当的或更高等级的安全。
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