提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
提示:以下是本篇文章正文内容,下面案例可供参考
一、RSA是什么?
RSA是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的 [1] 。
RSA公开密钥密码体制是一种使用不同的加密密钥与解密密钥,“由已知加密密钥推导出解密密钥在计算上是不可行的”密码体制 [2] 。
在公开密钥密码体制中,加密密钥(即公开密钥)PK是公开信息,而解密密钥(即秘密密钥)SK是需要保密的。加密算法E和解密算法D也都是公开的。虽然解密密钥SK是由公开密钥PK决定的,但却不能根据PK计算出SK [2] 。
正是基于这种理论,1978年出现了著名的RSA算法,它通常是先生成一对RSA密钥,其中之一是保密密钥,由用户保存;另一个为公开密钥,可对外公开,甚至可在网络服务器中注册。为提高保密强度,RSA密钥至少为500位长,一般推荐使用1024位。这就使加密的计算量很大。为减少计算量,在传送信息时,常采用传统加密方法与公开密钥加密方法相结合的方式,即信息采用改进的DES或IDEA对话密钥加密,然后使用RSA密钥加密对话密钥和信息摘要。对方收到信息后,用不同的密钥解密并可核对信息摘要 [2] 。
RSA是被研究得最广泛的公钥算法,从提出到现在已近三十年,经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一。1983年麻省理工学院在美国为RSA算法申请了专利 [3] 。
RSA允许你选择公钥的大小。512位的密钥被视为不安全的;768位的密钥不用担心受到除了国家安全管理(NSA)外的其他事物的危害;1024位的密钥几乎是安全的。RSA在一些主要产品内部都有嵌入,像 Windows、网景 Navigator、 Quicken和 Lotus Notes [3] 。
二、go语言实现
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/hex"
"encoding/pem"
"fmt"
"os"
)
func RsaGenKey(bits int) error {
//GenerateKey函数使用随机数生成器生成一对指定长度的公钥和私钥
//rand.Reader是一个全局,共享的密码随机生成器
privKey, err := rsa.GenerateKey(rand.Reader, bits)
if err != nil {
panic(err)
}
//x509是通用的整数格式:序列号 签名算法 颁发者 有效时间 持有者 公钥
//PKCS:RSA实验室与其他安全系统开发商为促进公钥密码的发展而指定的一系列标准
priStream := x509.MarshalPKCS1PrivateKey(privKey)
//将私钥字符串设置pem格式的块中
/*
pem是一种整数或私钥的格式:
---------------BEGIN RSA Private Key---------------
--------------END RSA Private Key-------------------
*/
block := pem.Block{
Type:"RSA Private Key",
Bytes:priStream,
}
privFile, err := os.Create("private.pem")
if err != nil {
panic(err)
}
defer privFile.Close()
//将块编码到文件
err = pem.Encode(privFile, &block)
if err != nil {
panic(err)
}
//从私钥中获取公钥
pubKey := privKey.PublicKey
//将公钥序列化
pubStream := x509.MarshalPKCS1PublicKey(&pubKey)
//将公钥设置到pem块中
block = pem.Block{
Type:"RSA Public Key",
Bytes:pubStream,
}
pubFile, err := os.Create("publiv.pem")
defer pubFile.Close()
if err != nil {
panic(err)
}
err = pem.Encode(pubFile, &block)
if err != nil {
panic(err)
}
return nil
}
//公钥加密
func RsaPublicEncrypt(src, pathName []byte) ([]byte, error) {
file, err := os.Open(string(pathName))
msg := []byte("")
if err != nil {
return msg, err
}
defer file.Close()
info, err := file.Stat()
if err != nil {
return msg, err
}
//创建切片,用于存储公钥
recvBuf := make([]byte, info.Size())
//读取公钥
file.Read(recvBuf)
//将得到的公钥反序列化
//参数一:存储公钥的切片, 参数二:剩余未解密的数据
block, _ := pem.Decode(recvBuf)
//使用x509将编码之后的公钥解析出来
pubKey, err := x509.ParsePKCS1PublicKey(block.Bytes)
if err != nil {
return msg, err
}
msg , err = rsa.EncryptPKCS1v15(rand.Reader, pubKey, src)
if err != nil {
return msg, err
}
return msg, nil
}
//使用私钥解密
func RsaPrivateDecrypt(src []byte, pathName string) ([]byte, error) {
msg := []byte("")
file, err := os.Open(pathName)
if err != nil {
return msg, err
}
info, err := file.Stat()
if err != nil {
return msg, err
}
//创建切片,用于存储私钥钥
recvBuf := make([]byte, info.Size())
//读取私钥钥
file.Read(recvBuf)
block, _ := pem.Decode(recvBuf)
privKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return msg, err
}
msg, err = rsa.DecryptPKCS1v15(rand.Reader, privKey, src)
if err != nil {
panic(err)
}
return msg,nil
}
func main() {
//err := RsaGenKey(1024)
//if err != nil {
// fmt.Println("秘钥对生成失败!")
//}else {
// fmt.Println("秘钥对生成成功!")
//}
src := []byte("wei!")
encrypt_msg, _ := RsaPublicEncrypt(src, []byte("publiv.pem"))
fmt.Println("encrypt_msg = ", hex.EncodeToString(encrypt_msg))
decrypt_msg, _ := RsaPrivateDecrypt(encrypt_msg, "private.pem")
fmt.Println("decrypt_msg = ", string(decrypt_msg))
}