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
}