Go实现RSA数字签名算法(附代码)

数字签名如何工作
  • 数字签名由两部分组成:
    • 使用私钥从消息创建签名的算法;
    • 允许任何人验证签名的算法;
数字签名应该满足的要求
  • 签名不可伪造性
  • 签名不可抵赖性
  • 签名可信任,签名的识别应用相对容易,任何人都可以验证签名的有效性
  • 签名不可复制、签名与原文是不可分割的整体;
  • 签名消息不可篡改,因为任意比特数据被篡改,其签名便被随之改变,那么任何人可以验证而拒绝接受此签名。
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
}

在这里插入图片描述

发布了19 篇原创文章 · 获赞 85 · 访问量 1333

猜你喜欢

转载自blog.csdn.net/qq_45828877/article/details/103965407