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

本函数是一个使用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


网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

加入社区》https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0

pto/ecdsa]( )

Go标准库-crypto/elliptic

Go标准库-crypto/rand

Go标准库-crypto/hex

[外链图片转存中...(img-c30guas5-1725654869860)]

[外链图片转存中...(img-y1ZNRKwR-1725654869861)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

加入社区》https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0

相关推荐
有梦想的咸鱼_1 小时前
go实现并发安全hashtable 拉链法
开发语言·golang·哈希算法
杜杜的man6 小时前
【go从零单排】go中的结构体struct和method
开发语言·后端·golang
幼儿园老大*6 小时前
走进 Go 语言基础语法
开发语言·后端·学习·golang·go
半桶水专家6 小时前
go语言中package详解
开发语言·golang·xcode
llllinuuu6 小时前
Go语言结构体、方法与接口
开发语言·后端·golang
cookies_s_s6 小时前
Golang--协程和管道
开发语言·后端·golang
王大锤43916 小时前
golang通用后台管理系统07(后台与若依前端对接)
开发语言·前端·golang
产幻少年6 小时前
golang函数
golang
为什么这亚子6 小时前
九、Go语言快速入门之map
运维·开发语言·后端·算法·云原生·golang·云计算
半桶水专家6 小时前
用go实现创建WebSocket服务器
服务器·websocket·golang