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
}