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

相关推荐
Rex_Code1 小时前
iOS Google登录
ios
Chandler242 小时前
Go:反射
开发语言·后端·golang
盒子69103 小时前
go for 闭环问题【踩坑记录】
开发语言·后端·golang
kph_Hajash3 小时前
Xcode16 调整 Provisioning Profiles 目录导致证书查不到
ios·cronet·provisioning·profiles
WDeLiang3 小时前
optool为macho文件增加动态库
学习·ios
帅次4 小时前
Flutter Expanded 与 Flexible 详解
android·flutter·ios·小程序·webview
techdashen5 小时前
性能比拼: Rust vs Zig vs Go
开发语言·golang·rust
ii_best7 小时前
选择 iOS 按键精灵无根有根越狱辅助工具的理由
ios
墨雪遗痕7 小时前
使用 inobounce 解决 iOS 皮筋效果导致的无法下拉刷新
ios
依旧风轻7 小时前
iOS 冷启动时间监控:启动起点有哪些选择?
macos·ios·cocoa·sqi·coldstart