RSA的加密与签名的区别(附Go代码方案)

一.RSA是一种非对称加密,通过一对私钥公钥进行加密解密或者签名与验签,能够确保信息的安全性。

第一种场景,B给A发消息

RSA的加密解密过程如下

(1)A生成一对公钥私钥,私钥自己留着,公钥对外是公开的,谁都可以用

(2)B拿到A的公钥加密一条信息,然后密文发给A

(3)A受到密文用私钥进行解密就看到了B发给他的消息原文

第二种场景,A给B发消息,判断这个消息是否有被篡改

RSA签名以及验证签名过程:

(1)A生成公钥私钥,私钥自己留着,公钥都可以用

(2)A拿着私钥对消息进行签名生成签名,然后消息和签名一起传给B

(3)B收到消息后,用公钥对签名进行验签,如果验出来的和本身消息一致,那说明这个消息没有被改或者劫持


总结起来记住,八个字,公钥加密,私钥签名


import (

"os"

"encoding/pem"

"crypto/x509"

"crypto/rsa"

"crypto/sha256"

"crypto/rand"

"crypto"

"fmt"

)

//生成RSA私钥和公钥,保存到文件中

func GenerateRSAKey(bits int){

//GenerateKey函数使用随机数据生成器random生成一对具有指定字位数的RSA密钥

//Reader是一个全局、共享的密码用强随机数生成器

privateKey, err := rsa.GenerateKey(rand.Reader, bits)

if err!=nil{

panic(err)

}

//保存私钥

//通过x509标准将得到的ras私钥序列化为ASN.1 的 DER编码字符串

X509PrivateKey := x509.MarshalPKCS1PrivateKey(privateKey)

//使用pem格式对x509输出的内容进行编码

//创建文件保存私钥

privateFile, err := os.Create("private.pem")

if err!=nil{

panic(err)

}

defer privateFile.Close()

//构建一个pem.Block结构体对象

privateBlock:= pem.Block{Type: "RSA Private Key",Bytes:X509PrivateKey}

//将数据保存到文件

pem.Encode(privateFile,&privateBlock)

//保存公钥

//获取公钥的数据

publicKey:=privateKey.PublicKey

//X509对公钥编码

X509PublicKey,err:=x509.MarshalPKIXPublicKey(&publicKey)

if err!=nil{

panic(err)

}

//pem格式编码

//创建用于保存公钥的文件

publicFile, err := os.Create("public.pem")

if err!=nil{

panic(err)

}

defer publicFile.Close()

//创建一个pem.Block结构体对象

publicBlock:= pem.Block{Type: "RSA Public Key",Bytes:X509PublicKey}

//保存到文件

pem.Encode(publicFile,&publicBlock)

}

//读取RSA私钥

func GetRSAPrivateKey(path string)*rsa.PrivateKey{

//读取文件内容

file, err := os.Open(path)

if err!=nil{

panic(err)

}

defer file.Close()

info, _ := file.Stat()

buf:=make([]byte,info.Size())

file.Read(buf)

//pem解码

block, _ := pem.Decode(buf)

//X509解码

privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)

return privateKey

}

//读取RSA公钥

func GetRSAPublicKey(path string)*rsa.PublicKey{

//读取公钥内容

file, err := os.Open(path)

if err!=nil{

panic(err)

}

defer file.Close()

info, _ := file.Stat()

buf:=make([]byte,info.Size())

file.Read(buf)

//pem解码

block, _ := pem.Decode(buf)

//x509解码

publicKeyInterface, err := x509.ParsePKIXPublicKey(block.Bytes)

if err!=nil{

panic(err)

}

publicKey := publicKeyInterface.(*rsa.PublicKey)

return publicKey

}

//对消息的散列值进行数字签名

func GetSign(msg []byte,path string)[]byte{

//取得私钥

privateKey:=GetRSAPrivateKey(path)

//计算散列值

hash := sha256.New()

hash.Write(msg)

bytes := hash.Sum(nil)

//SignPKCS1v15使用RSA PKCS#1 v1.5规定的RSASSA-PKCS1-V1_5-SIGN签名方案计算签名

sign, err := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, bytes)

if err!=nil{

panic(sign)

}

return sign

}

//验证数字签名

func VerifySign(msg []byte,sign []byte,path string)bool{

//取得公钥

publicKey:=GetRSAPublicKey(path)

//计算消息散列值

hash := sha256.New()

hash.Write(msg)

bytes := hash.Sum(nil)

//验证数字签名

err:=rsa.VerifyPKCS1v15(publicKey, crypto.SHA256, bytes, sign)

return err==nil

}

//测试RSA数字签名

func main(){

//生成密钥文件

GenerateRSAKey1(2048)

//模拟发送方

//要发送的消息

msg:=[]byte("hello world")

//生成签名

sign:=GetSign(msg,"private.pem")

//模拟接收方

//接受到的消息

acceptmsg:=[]byte("hello world")

//接受到的签名

acceptsign:=sign

//验证签名

result:=VerifySign(acceptmsg,acceptsign,"public.pem")

fmt.Println("验证结果:",result)

}


一起学习,一起进步

推荐阅读更多精彩内容

  • “寂寞也挥发着馀香,原来情动正是这样”顾家明已经爱上了方艳梅,但他还是很爱林子颖。同时爱着两个女人,这是多么可...
    Monica_jw阅读 142评论 0 0
  • 语文老师今天给我们讲了天地人你我他,金木水火土,还有二三,数学老师,给我们讲了多少,轻重,薄厚,新老师还教我们下了...
    刘晓柔阅读 21评论 0 0
  • 今天咱们就掰扯一件事。 说说中国人学英语这事,尤其对于初学者,到底用不用背单词? 为啥要弄明白这个问题? 就是因为...
    虐单词阅读 818评论 2 8
  • 我的家乡没有春秋,只有冬夏。北方人就是如此豪爽,要什么过度,该来的要来,何必磨磨唧唧,热完后,我们勇敢的接受寒冷。...
    沈水之南阅读 21评论 0 0