Go-ecc加密解密详解与代码

Go-ecc加密解密详解与代码,第1张

目录

Ecc概述

历史

密钥对生成

加密算法

解密算法

小结

Ecc的Go实现

crypto/ecdsa 包

crypto/elliptic 包

crypto/rand 包

crypto/x509包

代码

生成密钥对

加密

解密

测试代码

截图

补:ECC和RSA对比

参考


Ecc概述

ECC的主要优势是在某些情况下它比其他的算法(比如RSA加密算法)使用更小的密钥并提供相当的或更高等级的安全。ECC的另一个优势是可以定义群之间的双线性映射,基于Weil对或是Tate对;双线性映射已经在密码学中发现了大量的应用,例如基于身份的加密。
不过一个缺点是加密和解密 *** 作的实现比其他机制花费的时间长。

比特币也是用的这个。

历史 椭圆曲线在代数学和几何学上已广泛研究了150多年之久,有丰富而深厚的理论积累。1985年,Koblitz和Miller提出椭圆曲线密码体制(EllipticCurve Cryptosystem,简称ECC)椭圆曲线并不是椭圆,之所以称为椭圆曲线是因为它们是用三次方程来表示的,它的一般形式:,其中a,b,c,d和e是满足某些条件的实数。大多数的椭圆曲线密码系统是在模p或F2下运算。椭圆曲线密码已经逐渐被采用,已成为公钥密码的一个重要发展方向。 密钥对生成  选择一个椭圆曲线E:,构造一个椭圆群Ep(a,b)。 在Ep(a,b)中挑选生成元点G=(x1,y1),G应使得满足nG=O最小的n是一个非常大的素数。 选择一个小于n的整数作为其私钥,然后产生其公钥PA=G。

注:公开的信息(E,G,n,PA)

IEpI表示椭圆群Ep(a,b)的元素个数,n是IEpI的素因子。满足:

加密算法 将m编码成一个数m在保持同等安全的条件下所需的密钥长度(单位为比特)

RSA102420483072768015360
ECC160224256384512
Ecc的Go实现 crypto/ecdsa

func GenerateKey(c elliptic.Curve, rand io.Reader) (priv *PrivateKey, err error)

公钥/私钥。因为

type PrivateKey struct {
     PublicKey     
     D   *big.Int 
}

公钥在私钥的结构体里面

crypto/elliptic 包

func P256() Curve

返回一个实现了P-256的曲线。

crypto/rand

func Read(b []byte) (n int, err error)

本函数是一个使用io.ReadFull调用Reader.Read的辅助性函数。当且仅当err == nil时,返回值n == len(b)。

crypto/x509包

func MarshalECPrivateKey(key *ecdsa.PrivateKey) ([]byte, error)

MarshalECPrivateKey将ecdsa私钥序列化为ASN.1 DER编码。 

x509等其他包在https://blog.csdn.net/lady_killer9/article/details/118026802 中有提到。

代码 生成密钥对 使用ecdsa.GenerateKey生成私钥使用x509.MarshalECPrivateKey对生成的私钥序列化使用pem.Block转为块,使用pem.Encode编码保存私钥到文件公钥从私钥结构体中取出,其他类似,x509序列化使用MarshalECPrivateKey函数即可
// 生成ECC私钥对
// keySize 密钥大小, 224 256 384 521
// dirPath 密钥文件生成后保存的目录
// 返回 错误
func GenerateECCKey(keySize int,dirPath string) error {
	// generate private key
	var priKey *ecdsa.PrivateKey
	var err error
	switch keySize{
	case 224:priKey,err = ecdsa.GenerateKey(elliptic.P224(),rand.Reader)
	case 256:priKey,err = ecdsa.GenerateKey(elliptic.P256(),rand.Reader)
	case 384:priKey,err = ecdsa.GenerateKey(elliptic.P256(),rand.Reader)
	case 521:priKey,err = ecdsa.GenerateKey(elliptic.P521(),rand.Reader)
	default:priKey,err = nil,nil
	}
	if priKey == nil{
		_, file, line, _ := runtime.Caller(0)
		return util.Error(file,line+1,errors.EcckeyError)
	}
	if err != nil{
		_, file, line, _ := runtime.Caller(0)
		return util.Error(file,line+1,err.Error())
	}
	// x509
	derText,err := x509.MarshalECPrivateKey(priKey)
	if err != nil{
		_, file, line, _ := runtime.Caller(0)
		return util.Error(file,line+1,err.Error())
	}
	// pem block
	block := &pem.Block{
		Type:"ecdsa private key",
		Bytes:derText,
	}
	file,err := os.Create(dirPath+"eccPrivate.pem")
	if err != nil{
		_, file, line, _ := runtime.Caller(0)
		return util.Error(file,line+1,err.Error())
	}
	err = pem.Encode(file,block)
	if err != nil{
		_, file, line, _ := runtime.Caller(0)
		return util.Error(file,line+1,err.Error())
	}
	file.Close()
	// public key
	pubKey := priKey.PublicKey
	derText, err = x509.MarshalPKIXPublicKey(&pubKey)
	block = &pem.Block{
		Type:"ecdsa public key",
		Bytes:derText,
	}
	file, err = os.Create(dirPath+"eccPublic.pem")
	if err != nil{
		_, file, line, _ := runtime.Caller(0)
		return util.Error(file,line+1,err.Error())
	}
	err = pem.Encode(file,block)
	if err != nil{
		_, file, line, _ := runtime.Caller(0)
		return util.Error(file,line+1,err.Error())
	}
	file.Close()
	return nil
}
加密

go包没有ecc的加密,这里采用的github上的一个项目的ecies包

获取block块使用x509.ParsePKIXPublicKey解析为公钥断言后转为ecies包的Public类型(转换函数附在后面)使用ecies.Encrypt加密
// Ecc 加密
// plainText 明文
// filePath 公钥文件路径
// 返回 密文 错误
func EccEncrypt(plainText []byte,filePath string)  ([]byte, error) {
	// get pem.Block
	block,err := util.GetKey(filePath)
	if err != nil{
		_, file, line, _ := runtime.Caller(0)
		return nil,util.Error(file,line+1,err.Error())
	}
	// X509
	publicInterface,err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil{
		_, file, line, _ := runtime.Caller(0)
		return nil,util.Error(file,line+1,err.Error())
	}
	publicKey,flag := publicInterface.(*ecdsa.PublicKey)
	if flag == false{
		_, file, line, _ := runtime.Caller(0)
		return nil,util.Error(file,line+1,errors.RsatransError)
	}
	cipherText,err := ecies.Encrypt(rand.Reader,util.PubEcdsaToEcies(publicKey),plainText,nil,nil)
	if err != nil{
		_, file, line, _ := runtime.Caller(0)
		return nil,util.Error(file,line+1,err.Error())
	}
	return cipherText,err
}
解密 获取block块使用x509.ParseECPrivateKey解析为私钥转为ecies的私钥格式(转换函数附在后面)使用ecies.Decrypt解密
// ECC 解密
// cipherText 密文
// filePath 私钥文件路径
// 返回 明文 错误
func EccDecrypt(cipherText []byte,filePath string) (plainText []byte,err error)  {
	// get pem.Block
	block,err := util.GetKey(filePath)
	if err != nil{
		_, file, line, _ := runtime.Caller(0)
		return nil,util.Error(file,line+1,err.Error())
	}
	// get privateKey
	privateKey, _ := x509.ParseECPrivateKey(block.Bytes)
	priKey := util.PriEcdsaToEcies(privateKey)
	plainText,err = priKey.Decrypt(cipherText,nil,nil)
	if err != nil{
		_, file, line, _ := runtime.Caller(0)
		return nil,util.Error(file,line+1,err.Error())
	}
	return plainText,nil
}

附:ecdsa包的公钥私钥转为ecies对应的密钥的转换代码,全部代码看后面gitee链接 

// ecdsa public key to ecies public key
func PubEcdsaToEcies(pub *ecdsa.PublicKey) *ecies.PublicKey {
	return &ecies.PublicKey{
		X:      pub.X,
		Y:      pub.Y,
		Curve:  pub.Curve,
		Params: ecies.ParamsFromCurve(pub.Curve),
	}
}
// ecdsa private key to ecies private key
func PriEcdsaToEcies(prv *ecdsa.PrivateKey) *ecies.PrivateKey {
	pub := PubEcdsaToEcies(&prv.PublicKey)
	return &ecies.PrivateKey{*pub, prv.D}
}
测试代码
	plainText := []byte("hi, I'm lady_killer9")
	cipherText,err := EccEncrypt(plainText,"./eccPublic.pem")
	if err!=nil{
		fmt.Println(err)
	}
	fmt.Printf("加密后:%s\n",cipherText)
	plainText,err = EccDecrypt(cipherText,"./eccPrivate.pem")
	if err!=nil{
		fmt.Println(err)
	}
	fmt.Printf("解密后:%s\n",plainText)
截图

全部源码代码放在:https://gitee.com/frankyu365/gocrypto

补:ECC和RSA对比

数论基础

RSA:欧拉定理

ECC:离散对数

安全性基础

RSA:整数分解问题的困难性

ECC:椭圆曲线,离散对数问题的难解性

当前安全密钥长度

RSA:1024位

ECC:160位

消耗

RSA:CPU、内存消耗大

ECC:CPU、内存消耗小

安全等级与密钥长度

RSA:增长较快

ECC:成线性

参考

《现代密码学教程 谷利泽,杨义先等》

Go标准库-crypto/ecdsa

Go标准库-crypto/elliptic

Go标准库-crypto/rand

Go标准库-crypto/hex

Go标准库-crypto/sha256

Github-以太坊​​​​​​​

更多Go相关内容:Go-Golang学习总结笔记

有问题请下方评论,转载请注明出处,并附有原文链接,谢谢!如有侵权,请及时联系。如果您感觉有所收获,自愿打赏,可选择支付宝18833895206(小于),您的支持是我不断更新的动力。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/994397.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存