Go语言使用椭圆曲线进行数字签名

2019-11-24  本文已影响0人  realguan
package main

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

func main() {
    GenerateEccKey()
    src := []byte("椭圆曲线进行数字签名")
    rText,sText := EccSignature(src,"eccPrivate.pem")
    bl := EccVerify(src,rText,sText,"eccPublic.pem")
    fmt.Println(bl)
}

// 生成密钥对
func GenerateEccKey() {
    // --------私钥写入磁盘--------
    // 1 使用ecdsa生成密钥对
    privateKey,err := ecdsa.GenerateKey(elliptic.P521(),rand.Reader)
    if err != nil {
        panic(err)
    }
    // 2 使用x509将私钥进行序列化
    derText,err := x509.MarshalECPrivateKey(privateKey)
    if err != nil {
        panic(err)
    }
    // 3 将序列化后的字符串放入pem.Block结构体中
    block := pem.Block{
        Type:"ecdsa private key",
        Bytes:derText,
    }
    // 4 使用pem编码
    file,err := os.Create("eccPrivate.pem")
    if err != nil {
        panic(err)
    }
    pem.Encode(file,&block)
    file.Close()

    // --------公钥写入磁盘--------
    // 1 从私钥中获取公钥
    publicKey := privateKey.PublicKey
    // 2 x509序列化公钥
    derText,err = x509.MarshalPKIXPublicKey(&publicKey)
    if err != nil {
        panic(err)
    }
    // 3 将序列化后的字符串放入pem.Block 中
    block = pem.Block{
        Type:"ecdsa public key",
        Bytes:derText,
    }
    // 4 使用pem编码
    file,err = os.Create("eccPublic.pem")
    if err != nil {
        panic(err)
    }
    pem.Encode(file,&block)
    file.Close()
}

// ecdsa 签名
func EccSignature(plainText []byte,privName string) (rText,sText []byte) {
    // 1 打开私钥将内容读取出来
    file,err := os.Open(privName)
    if err != nil {
        panic(err)
    }
    fileInfo,err := file.Stat()
    if err != nil {
        panic(err)
    }
    buf := make([]byte,fileInfo.Size())
    file.Read(buf)
    file.Close()
    // 2 pem解码
    block,_ := pem.Decode(buf)
    // 3 x509解析
    privateKey,err := x509.ParseECPrivateKey(block.Bytes)
    if err != nil {
        panic(err)
    }
    // 4 对原始数据进行hash运算得到散列值
    hashText := sha1.Sum(plainText)
    // 5 进行数据签名
    r,s,err := ecdsa.Sign(rand.Reader,privateKey,hashText[:])
    if err != nil {
        panic(err)
    }
    // 6 对r,s内存中的数据进行格式化
    rText,err = r.MarshalText()
    if err != nil {
        panic(err)
    }
    sText,err = s.MarshalText()
    if err != nil {
        panic(err)
    }
    return
}

// ecdsa签名认证
func EccVerify(plainText,rText,sText []byte,pubFile string) bool {
    // 1 打开公钥文件,将内容读取出来
    file,err := os.Open(pubFile)
    if err != nil {
        panic(err)
    }
    fileInfo,err := file.Stat()
    if err != nil {
        panic(err)
    }
    buf := make([]byte,fileInfo.Size())
    file.Read(buf)
    file.Close()
    // 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 对原始数据进行hash运算得到散列值
    hashText := sha1.Sum(plainText)
    // 6 签名认证
    // 将rText,sText 转换成 int
    var r,s big.Int
    r.UnmarshalText(rText)
    s.UnmarshalText(sText)
    bl := ecdsa.Verify(publicKey,hashText[:],&r,&s)
    return bl
}
上一篇下一篇

猜你喜欢

热点阅读