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

相关推荐
Pandaconda23 分钟前
【Golang 面试题】每日 3 题(三十九)
开发语言·经验分享·笔记·后端·面试·golang·go
加油,旭杏27 分钟前
【go语言】变量和常量
服务器·开发语言·golang
行路见知27 分钟前
3.3 Go 返回值详解
开发语言·golang
编程小筑1 小时前
R语言的编程范式
开发语言·后端·golang
技术的探险家1 小时前
Elixir语言的文件操作
开发语言·后端·golang
Ai 编码助手1 小时前
Golang 中强大的重试机制,解决瞬态错误
开发语言·后端·golang
齐雅彤2 小时前
Lisp语言的区块链
开发语言·后端·golang
齐雅彤2 小时前
Lisp语言的循环实现
开发语言·后端·golang
梁雨珈2 小时前
Lisp语言的物联网
开发语言·后端·golang
邓熙榆3 小时前
Logo语言的网络编程
开发语言·后端·golang