数字签名如何工作
- 数字签名由两部分组成:
- 使用私钥从消息创建签名的算法;
- 允许任何人验证签名的算法;
数字签名应该满足的要求
- 签名不可伪造性
- 签名不可抵赖性
- 签名可信任,签名的识别应用相对容易,任何人都可以验证签名的有效性
- 签名不可复制、签名与原文是不可分割的整体;
- 签名消息不可篡改,因为任意比特数据被篡改,其签名便被随之改变,那么任何人可以验证而拒绝接受此签名。
RSA数字签名的核心步骤
1.RSA数字签名的核心步骤
- 选择hash算法,对需要签名的数据进行hash 运算
- 读取私钥文件,解析出私钥对象
- 1.1读取私钥文件,获取私钥字节
- 1.2对私钥文件进行解码,生成加密快对象
- 1.3解析DER编码的私钥,生成私钥对象 - RSA数字签名,生成base64编码的签名字符串
2.RSA验证数字签名的核心步骤
- 对base64编码的签名内容进行解码,返回签名字节
- 选择hash算法,对需要签名的数据进行hash运算
- 读取公钥文件,解析出公钥对象
- 读取公钥文件,获取公钥字节
- 解码公钥字节,生成加密快对象
- 解析DER编码的公钥,生成公钥接口
- 公钥接口转型成公钥对象 - RSA验证数字签名
GO 实现RSA数字签名代码
package main
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"errors"
"fmt"
"io/ioutil"
)
func main() {
str := "will be best"
base64Sig,_ := RSASign([]byte(str),"./files/private.pem")
fmt.Println("签名后信息",base64Sig)
err := RSAVerify([]byte(str),base64Sig,"./files/public.pem")
if err == nil {
fmt.Println("验证签名ok!")
} else {
fmt.Println("验证失败!")
}
}
func RSASign(data []byte,filename string) (string,error) {
//1.选择hash算法,对需要签名的数据进行hash运算
myhash := crypto.SHA256
hashInstance := myhash.New()
hashInstance.Write(data)
hashed := hashInstance.Sum(nil)
//2.读取私钥文件,解析出私钥对象
privateKey,err :=ReadParsePrivateKey(filename)
if err != nil {
return "",err
}
//3.RSA数字签名
bytes,err := rsa.SignPKCS1v15(rand.Reader,privateKey,myhash,hashed)
if err != nil {
return "",err
}
return base64.StdEncoding.EncodeToString(bytes),nil
}
//公钥验证数据签名是否正确
func RSAVerify(data []byte,base64Sig,filename string) error {
//- 对base64编码的签名内容进行解码,返回签名字节
bytes,err := base64.StdEncoding.DecodeString((base64Sig))
if err != nil {
return err
}
//- 选择hash算法,对需要签名的数据进行hash运算
myhash := crypto.SHA256
hashInstance := myhash.New()
hashInstance.Write(data)
hashed := hashInstance.Sum(nil)
//- 读取公钥文件,解析出公钥对象
publicKey,err := ReadParsePublicKey(filename)
if err != nil {
return err
}
//- RSA验证数字签名
return rsa.VerifyPKCS1v15(publicKey,myhash,hashed,bytes)
}
//读取公钥文件,解析出公钥对象
func ReadParsePublicKey(filename string) (*rsa.PublicKey,error) {
//--1.读取公钥文件,获取公钥字节
publicKeyBytes,err := ioutil.ReadFile(filename)
if err != nil {
return nil,err
}
//--2.解码公钥字节,生成加密对象
block,_ := pem.Decode(publicKeyBytes)
if block == nil {
return nil,errors.New("公钥信息错误")
}
//--3.解析DER编码的公钥,生成公钥接口
publicKeyInterface,err :=x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return nil,err
}
//--4.公钥接口转型成公钥对象
publicKey := publicKeyInterface.(*rsa.PublicKey)
return publicKey,nil
}
//读取私钥文件,解析出私钥对象
func ReadParsePrivateKey(filename string) (*rsa.PrivateKey,error) {
//--1.读取私钥文件,获取私钥字节
privateKeyBytes,_ := ioutil.ReadFile(filename)
//--2.对私钥文件进行编码,生成加密对象
block,_ := pem.Decode(privateKeyBytes)
if block == nil {
return nil,errors.New("私钥信息错误")
}
//3.解析DER编码的私钥,生成私钥对象
privateKey,err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return nil,err
}
return privateKey,err
}