密码技术--椭圆曲线EDCSA数字签名及Go语言应用 - Go语言中文社区

密码技术--椭圆曲线EDCSA数字签名及Go语言应用


1.生成秘钥对并写入磁盘文件

1.使用ecdsa生成秘钥对

2.将私钥写入磁盘

  • 使用x509进行反序列化
  • 将得到的切片字符串放到pem.Block结构体中
  • 使用pem编码

3.将公钥写入磁盘

  • 从私钥中得到公钥
  • 使用x509进行序列化
  • 将得到的切片字符串放入pem.Block结构体中
  • 使用pem编码

2.使用私钥进行数字签名

1.打开私钥文件,将内容读出来

2.使用pem进行数据解码

3.使用x509对数据还原

4.对原始数据进行哈希运算

5.进行数字签名
func Sign(rand io.Reader, priv PrivateKey, hash []byte) (r, s big.Int, err error)
6.返回值为指针,因此需要将该地址指向内存中的数据进行序列话

3.使用公钥验证数字签名

1.打开公钥文件,读出数据

2.使用pem进行解码

3.使用x509进行公钥数据还原
func ParsePKIXPublicKey(derBytes []byte) (pub interface{}, err error)

4.由于上一步返回的是一个接口类型,因此需要进行类型断言,将接口类型转换为公钥

5.对原始数据进行哈希运算

6.验签

4.go中应用

package main

import (
    "crypto/ecdsa"
    "crypto/elliptic"
    "crypto/rand"
    "crypto/x509"
    "encoding/pem"
    "os"
    "crypto/sha256"
    "math/big"
)

func GenerateEcdsaKey () {
    //1.使用ecdsa生成秘钥对
    privateKey, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
    if err != nil {
        panic(err)
    }
    //2.将私钥写入磁盘
    //* 使用x509进行反序列化
    ecPrivateKey, err := x509.MarshalECPrivateKey(privateKey)
    if err != nil {
        panic(err)
    }
    //* 将得到的切片字符串放到pem.Block结构体中
    block := pem.Block{
        Type:    "ecdsa private key",
        Headers: nil,
        Bytes:   ecPrivateKey,
    }
    //* 使用pem编码
    file, err := os.Create("ecPrivate.pem")
    if err != nil {
        panic(err)
    }
    defer file.Close()
    err = pem.Encode(file, &block)
    if err != nil {
        panic(err)
    }
    //3.将公钥写入磁盘
    //* 从私钥中得到公钥
    publicKey := privateKey.PublicKey
    //* 使用x509进行序列化
    ecPublicKey, err := x509.MarshalPKIXPublicKey(&publicKey)
    if err != nil {
        panic(err)
    }
    //* 将得到的切片字符串放入pem.Block结构体中
    block = pem.Block{
        Type:    "ecdsa public key",
        Headers: nil,
        Bytes:   ecPublicKey,
    }
    //* 使用pem编码
    file, err = os.Create("ecPublic.pem")
    if err != nil {
        panic(err)
    }
    defer file.Close()
    pem.Encode(file, &block)
}

//签名
func SignECDSA (plainText []byte, priFileName string) (rText, sText []byte) {
    //1.打开私钥文件,将内容读出来
    file, err := os.Open(priFileName)
    if err != nil {
        panic(err)
    }
    defer file.Close()
    fileInfo, err := file.Stat()
    if err != nil {
        panic(err)
    }
    buf := make([]byte, fileInfo.Size())
    _, err = file.Read(buf)
    if err != nil {
        panic(err)
    }
    //2.使用pem进行数据解码
    block, _ := pem.Decode(buf)
    //3.使用x509对数据还原
    privateKey, err := x509.ParseECPrivateKey(block.Bytes)
    if err != nil {
        panic(err)
    }
    //4.对原始数据进行哈希运算
    hashText := sha256.Sum256(plainText)
    //5.进行数字签名
    var r, s *big.Int //注意这里
    r, s, err = ecdsa.Sign(rand.Reader, privateKey, hashText[:])
    if err != nil {
        panic(err)
    }
    //6.返回值为指针,因此需要将该地址指向内存中的数据进行序列话
    rText, err = r.MarshalText()
    if err != nil {
        panic(err)
    }
    sText, err = s.MarshalText()
    if err != nil {
        panic(err)
    }
    return rText,sText
}

//验签
func VerifyECDSA (plainText, rText, sText []byte, pubFileName string) bool {
    //1.打开公钥文件,读出数据
    file, err := os.Open(pubFileName)
    if err != nil {
        panic(err)
    }
    defer file.Close()
    fileInfo, err := file.Stat()
    if err != nil {
        panic(err)
    }
    buf := make([]byte, fileInfo.Size())
    _, err = file.Read(buf)
    if err != nil {
        panic(err)
    }
    //2.使用pem进行解码
    block, _ := pem.Decode(buf)
    //3.使用x509进行公钥数据还原
    pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
    if err != nil {
        panic(err)
    }
    //4.由于上一步返回的是一个接口类型,因此需要进行类型断言,将接口类型转换为公钥
    publicKey := pubInterface.(*ecdsa.PublicKey)
    //5.对原始数据进行哈希运算
    hashText := sha256.Sum256(plainText)
    //6.验签
    var r, s big.Int
    r.UnmarshalText(rText)
    s.UnmarshalText(sText)
    res := ecdsa.Verify(publicKey, hashText[:], &r, &s)
    return res
}
版权声明:本文来源Segmentfault,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://segmentfault.com/a/1190000040064016
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2021-06-13 12:15:54
  • 阅读 ( 604 )
  • 分类:Go

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢