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

相关推荐
Thomas_YXQ42 分钟前
Unity3D iOS闪退问题解决方案
ios
风无雨2 小时前
GO启动一个视频下载接口 前端可以边下边放
前端·golang·音视频
Daniel_Coder3 小时前
iOS Widget 开发-7:TimelineProvider 机制全解析:构建未来时间线
ios·swift·widget
Daniel_Coder4 小时前
iOS Widget 开发-3:Widget 的种类与尺寸(主屏、锁屏、灵动岛)
ios·swift·widget
Engandend20 小时前
Flutter与iOS混合开发交互
flutter·ios·程序员
LuckyLay21 小时前
使用 Docker 搭建 Go Web 应用开发环境——AI教你学Docker
前端·docker·golang
山水域1 天前
GoogleAdsOnDeviceConversion 库的作用与用法
ios
Lucifer晓1 天前
记录一次Flutter项目上传App Store Connect出现“Validation failed”错误的问题
flutter·ios
阿里超级工程师1 天前
经验分享-没有xcode也可以上传App Store Connect
xcode·上传ipa
扶我起来还能学_1 天前
uniapp Android&iOS 定位权限检查
android·javascript·ios·前端框架·uni-app