RSA是"非对称加密算法",非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。公钥与私钥是配对的,用公钥加密的数据只有配对的私钥才能解密,反之亦然。因加解密使用两个不同的密钥,所以这种算法叫作非对称加密算法。
使用RSA加密算法流程如下:
1.消息接收方B先把公钥广播,消息发送方A保存B的公钥
2.当A需要向B发送消息时,先用B的公钥将消息进行加密,再将密文发送给A
3.A接受到密文以后,使用自己的私钥进行解密
RSA具有一个离散对数和椭圆曲线加密都没有的特性:
既可以用公钥加密然后私钥解密,也可以用私钥加密然后公钥解密(对称性)。
公钥加密然后私钥解密,可以用于通信中拥有公钥的一方向拥有私钥的另一方传递机密信息,不被第三方窃听。
那么私钥加密然后公钥解密是用在什么场合呢?就是数字签名。
RSA中的每一个公钥都有唯一的私钥与之对应,任一公钥只能解开对应私钥加密的内容。换句话说,其它私钥加密的内容,这个公钥是解不开的。
如果你生成了一对RSA密钥,你把公钥公布出去,并告诉全世界人这个公钥是你的。之后你只要在发送的消息,比如“123456”,后面加上用私钥加密过的密文,其他人拿公钥解密,看解密得到的内容是是“123456”就可以知道这个“123456”是不是你发的。
签名:
1、提取消息摘要,使用发送方私钥对消息摘要加密,生成消息签名。
2、将消息签名和消息一起,使用接收方公钥加密,获得密文。
验签:
1、使用接收方私钥对密文解密,获得消息和消息签名。
2、使用发送方公钥解密消息签名,获得消息摘要。
3、使用相同办法重新提取消息摘要,与上一步中消息摘要对比,如相同则验签成功。
三、Go语言使用RSA算法加解密实例
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/hex"
"encoding/pem"
"fmt"
"os"
)
//生成密钥对(公钥和私钥)
func RsaGenKey(bits int) error{
//通过随机数生成密钥对
priveKey,err := rsa.GenerateKey(rand.Reader,bits)
if err != nil {
return err
}
//x509通用的证书格式:序列号,签名算法,颁发者,有效时间等
//PKCS:由RSA实验室和开发商指定的标准
priStream := x509.MarshalPKCS1PrivateKey(priveKey)
block := pem.Block{
Type:"RSA Private key",
Bytes:priStream,
}
/*
-------------------BEGIN RSA Private Key---------------------
内容
-------------------END RSA Private Key-----------------------
*/
//创建存储私钥文件
priveFile,err := os.Create("private.pem")
defer priveFile.Close()
if err != nil{
return err
}
//将块编码到文件中
err = pem.Encode(priveFile,&block)
if err != nil{
return err
}
//从公钥获取私钥
pubKey := priveKey.PublicKey
//通过x509标准达到rsa公钥序列化后的切片
pubStream,err := x509.MarshalPKIXPublicKey(&pubKey)
if err != nil{
return err
}
//创建公钥块
block = pem.Block{
Type:"RSA Public Key",
Bytes:pubStream,
}
pubFile,err := os.Create("public.pem")
defer pubFile.Close()
if err != nil{
return err
}
//将公钥块编码到文件
err = pem.Encode(pubFile,&block)
if err!= nil{
return err
}
return nil
}
//公钥加密函数
//src待加密的数据,pathName公钥路径
func RsaPublicEncrypt(src []byte,pathName string)([]byte,error){
//打开公钥文件
file,err := os.Open(pathName)
defer file.Close()
if err != nil{
return []byte(""),err
}
//获取文件信息
info,err := file.Stat()
if err != nil{
return []byte(""),err
}
//创建切片,用于存储文件中读取到的公钥信息
recvBuf := make([]byte,info.Size())
//读取公钥文件
file.Read(recvBuf)
//将得到的切片解码到块中
block,_ := pem.Decode(recvBuf)
//使用x509包中的ParsePKIXPublicKey解析公钥
pubInter,err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil{
return []byte(""),err
}
//通过断言将接口转换成公钥
pubKey := pubInter.(*rsa.PublicKey)
msg,err := rsa.EncryptPKCS1v15(rand.Reader,pubKey,src)
if err != nil{
return []byte(""),err
}
return msg,err
}
//使用私钥解密信息
//src:待解密的私钥信息 pathName:私钥路径
func RsaPrivateDecrypt(src []byte,pathName string)([]byte,error){
//通过私钥文件路径打开私钥文件
file,err := os.Open(pathName)
defer file.Close()
if err != nil{
return []byte(""),err
}
info,err := file.Stat()
if err != nil {
return []byte(""), err
}
//创建切片用于接受私钥内容
recvBuf := make([]byte,info.Size())
//读取私钥文件
file.Read(recvBuf)
block,_ := pem.Decode(recvBuf)
privateKey,err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil{
return []byte(""),err
}
msg,err := rsa.DecryptPKCS1v15(rand.Reader,privateKey,src)
if err != nil{
return []byte(""),err
}
return msg,nil
}
func main(){
err := RsaGenKey(1024)
if err != nil{
fmt.Println("err=",err)
}
src := []byte("单枪匹马你别怕,一腔孤勇又如何!")
data,err := RsaPublicEncrypt(src,"public.pem")
if err != nil{
fmt.Println("err:",err)
return
}
fmt.Println("加密:",hex.EncodeToString(data))
data,err = RsaPrivateDecrypt(data,"private.pem")
if err != nil{
fmt.Println("Decrypt err:",err)
return
}
fmt.Println("解密:",string(data))
}
package main
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/pem"
"errors"
"fmt"
"os"
)
//生成密钥对(公钥和私钥)
func RsaGenKey(bits int) error{
//通过随机数生成密钥对
priveKey,err := rsa.GenerateKey(rand.Reader,bits)
if err != nil {
return err
}
//x509通用的证书格式:序列号,签名算法,颁发者,有效时间等
//PKCS:由RSA实验室和开发商指定的标准
priStream := x509.MarshalPKCS1PrivateKey(priveKey)
block := pem.Block{
Type:"RSA Private key",
Bytes:priStream,
}
/*
-------------------BEGIN RSA Private Key---------------------
内容
-------------------END RSA Private Key-----------------------
*/
//创建存储私钥文件
priveFile,err := os.Create("private.pem")
defer priveFile.Close()
if err != nil{
return err
}
//将块编码到文件中
err = pem.Encode(priveFile,&block)
if err != nil{
return err
}
//从公钥获取私钥
pubKey := priveKey.PublicKey
//通过x509标准达到rsa公钥序列化后的切片
pubStream,err := x509.MarshalPKIXPublicKey(&pubKey)
if err != nil{
return err
}
//创建公钥块
block = pem.Block{
Type:"RSA Public Key",
Bytes:pubStream,
}
pubFile,err := os.Create("public.pem")
defer pubFile.Close()
if err != nil{
return err
}
//将公钥块编码到文件
err = pem.Encode(pubFile,&block)
if err!= nil{
return err
}
return nil
}
//公钥加密函数
//src待加密的数据,pathName公钥路径
func RsaPublicEncrypt(src []byte,pathName string)([]byte,error){
//打开公钥文件
file,err := os.Open(pathName)
defer file.Close()
if err != nil{
return []byte(""),err
}
//获取文件信息
info,err := file.Stat()
if err != nil{
return []byte(""),err
}
//创建切片,用于存储文件中读取到的公钥信息
recvBuf := make([]byte,info.Size())
//读取公钥文件
file.Read(recvBuf)
//将得到的切片解码到块中
block,_ := pem.Decode(recvBuf)
//使用x509包中的ParsePKIXPublicKey解析公钥
pubInter,err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil{
return []byte(""),err
}
//通过断言将接口转换成公钥
pubKey := pubInter.(*rsa.PublicKey)
msg,err := rsa.EncryptPKCS1v15(rand.Reader,pubKey,src)
if err != nil{
return []byte(""),err
}
return msg,err
}
//使用私钥解密信息
//src:待解密的私钥信息 pathName:私钥路径
func RsaPrivateDecrypt(src []byte,pathName string)([]byte,error){
//通过私钥文件路径打开私钥文件
file,err := os.Open(pathName)
defer file.Close()
if err != nil{
return []byte(""),err
}
info,err := file.Stat()
if err != nil {
return []byte(""), err
}
//创建切片用于接受私钥内容
recvBuf := make([]byte,info.Size())
//读取私钥文件
file.Read(recvBuf)
block,_ := pem.Decode(recvBuf)
privateKey,err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil{
return []byte(""),err
}
msg,err := rsa.DecryptPKCS1v15(rand.Reader,privateKey,src)
if err != nil{
return []byte(""),err
}
return msg,nil
}
//私钥签名
//data:消息内容
//pathName:私钥文件名
func RsaSign(data []byte,pathName string)([]byte,error){
h := sha256.New()
h.Write(data)
hashed := h.Sum(nil)
//获取私钥
file,err := os.Open(pathName)
defer file.Close()
if err != nil{
return []byte(""),err
}
info,err := file.Stat()
if err != nil {
return []byte(""), err
}
//创建切片用于接受私钥内容
recvBuf := make([]byte,info.Size())
//读取私钥文件
file.Read(recvBuf)
block,_ := pem.Decode(recvBuf)
privateKey,err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil{
return []byte(""),err
}
return rsa.SignPKCS1v15(rand.Reader,privateKey,crypto.SHA256,hashed)
}
//公钥验证
func RsaSignVer(data []byte,pathName string,signature []byte)error{
//获取私钥
file,err := os.Open(pathName)
defer file.Close()
if err != nil{
return err
}
info,err := file.Stat()
if err != nil {
return err
}
//创建切片用于接受公钥内容
recvBuf := make([]byte,info.Size())
//读取公钥文件
file.Read(recvBuf)
hashed := sha256.Sum256(data)
block,_ := pem.Decode(recvBuf)
if block == nil{
return errors.New("public key error")
}
// 解析公钥
pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return err
}
// 类型断言
pub := pubInterface.(*rsa.PublicKey)
//验证签名
return rsa.VerifyPKCS1v15(pub, crypto.SHA256, hashed[:], signature)
}
func main(){
err := RsaGenKey(1024)
if err != nil{
fmt.Println("err=",err)
}
msg := []byte("单枪匹马你别怕,一腔孤勇又如何!")
fmt.Println("msg:",string(msg))
sig,err := RsaSign(msg,"private.pem")
if err !=nil{
fmt.Println("RsaSign error:",err)
return
}
fmt.Println("sig:",sig)
if err := RsaSignVer(msg,"public.pem",sig);err != nil{
fmt.Println("RsaSignVer error:",err)
return
}
fmt.Println("签名验证成功")
}