1. 生成公钥和私钥
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"fmt"
"os"
)
type Rsa struct {
}
/*
* 生成RSA公钥和私钥并保存在对应的目录文件下
* 参数bits: 指定生成的秘钥的长度, 单位: bit
*/
func (r *Rsa) RsaGenKey(bits int, privatePath, pubulicPath string) error {
// 1. 生成私钥文件
// GenerateKey函数使用随机数据生成器random生成一对具有指定字位数的RSA密钥
privateKey, err := rsa.GenerateKey(rand.Reader, bits)
if err != nil {
return err
}
// 2. MarshalPKCS1PrivateKey将rsa私钥序列化为ASN.1 PKCS#1 DER编码
derPrivateStream := x509.MarshalPKCS1PrivateKey(privateKey)
// 3. Block代表PEM编码的结构, 对其进行设置
block := pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: derPrivateStream,
}
// 4. 创建文件
privateFile, err := os.Create(privatePath)
defer privateFile.Close()
if err != nil {
return err
}
// 5. 使用pem编码, 并将数据写入文件中
err = pem.Encode(privateFile, &block)
if err != nil {
return err
}
// 1. 生成公钥文件
publicKey := privateKey.PublicKey
derPublicStream, err := x509.MarshalPKIXPublicKey(&publicKey)
if err != nil {
return err
}
block = pem.Block{
Type: "RSA PUBLIC KEY",
Bytes: derPublicStream,
}
publicFile, err := os.Create(pubulicPath)
defer publicFile.Close()
if err != nil {
return err
}
// 2. 编码公钥, 写入文件
err = pem.Encode(publicFile, &block)
if err != nil {
panic(err)
return err
}
return nil
}
func (r *Rsa) testGenRSA() {
r.RsaGenKey(2048, "privateKey.pem","publicKey.pem")
}
func main() {
r := &Rsa{}
r.testGenRSA()
fmt.Println("成功生成公钥和私钥")
}
2. 数据通信
公钥加密, 私钥解密
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"fmt"
"os"
)
type Rsa struct {
}
/*
* RSA公钥加密
*/
func (r *Rsa) RSAEncrypt(src []byte, filename string) ([]byte, error) {
// 根据文件名读出文件内容
file, err := os.Open(filename)
if err != nil {
return nil, err
}
defer file.Close()
info, _ := file.Stat()
buf := make([]byte, info.Size())
file.Read(buf)
// 从数据中找出pem格式的块
block, _ := pem.Decode(buf)
if block == nil {
return nil, err
}
// 解析一个der编码的公钥
pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
fmt.Println(err)
return nil, err
}
publicKey := pubInterface.(*rsa.PublicKey)
// 公钥加密
result, _ := rsa.EncryptPKCS1v15(rand.Reader, publicKey, src)
return result, nil
}
/*
* RSA私钥解密
*/
func (r *Rsa) RSADecrypt(src []byte, filename string) ([]byte, error) {
// 根据文件名读出内容
file, err := os.Open(filename)
if err != nil {
return nil,err
}
defer file.Close()
info, _ := file.Stat()
buf := make([]byte, info.Size())
file.Read(buf)
// 从数据中解析出pem块
block, _ := pem.Decode(buf)
if block == nil {
return nil,err
}
// 解析出一个der编码的私钥
privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
// 私钥解密
result, err := rsa.DecryptPKCS1v15(rand.Reader, privateKey, src)
if err != nil {
return nil,err
}
return result,nil
}
func (r *Rsa) testRSA() {
msg := "This is a girl."
cipherText, _:= r.RSAEncrypt([]byte(msg), "publicKey.pem")
fmt.Println("加密后的字符串:", string(cipherText))
plainText, _:= r.RSADecrypt(cipherText, "privateKey.pem")
fmt.Println("解密后的字符串:", string(plainText))
}
func main() {
r := &Rsa{}
r.testRSA()
}
3. 数字签名
私钥加密, 公钥解密
package main
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha512"
"crypto/x509"
"encoding/pem"
"fmt"
"os"
)
func main() {
src := []byte("在消息认证码中,需要发送者和接收者之间共享密钥,而这个密钥不能被主动攻击者Mallory获取。如果这个密钥落入Mallory手中,则Mallory也可以计算出MAC值,从而就能够自由地进行篡改和伪装攻击,这样一来消息认证码就无法发挥作用了。")
sigText := SignatureRSA(src, "privateKey.pem")
bl := VerifyRSA(src, sigText, "publicKey.pem")
fmt.Println("数字签名验证结果:", bl)
}
// RSA签名 - 私钥
func SignatureRSA(plainText []byte, fileName string) []byte{
//1. 打开磁盘的私钥文件
file, err := os.Open(fileName)
if err != nil {
panic(err)
}
//2. 将私钥文件中的内容读出
info, err := file.Stat()
if err != nil {
panic(err)
}
buf := make([]byte, info.Size())
file.Read(buf)
file.Close()
//3. 使用pem对数据解码, 得到了pem.Block结构体变量
block, _ := pem.Decode(buf)
//4. x509将数据解析成私钥结构体 -> 得到了私钥
privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
panic(err)
}
//5. 创建一个哈希对象 -> md5/sha1 -> sha512
// sha512.Sum512()
myhash := sha512.New()
//6. 给哈希对象添加数据
myhash.Write(plainText)
//7. 计算哈希值
hashText := myhash.Sum(nil)
//8. 使用rsa中的函数对散列值签名
sigText, err := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA512, hashText)
if err != nil {
panic(err)
}
return sigText
}
// RSA签名验证
func VerifyRSA(plainText, sigText []byte, pubFileName string) bool {
//1. 打开公钥文件, 将文件内容读出 - []byte
file, err := os.Open(pubFileName)
if err != nil {
panic(err)
}
info, err := file.Stat()
if err != nil {
panic(err)
}
buf := make([]byte, info.Size())
file.Read(buf)
file.Close()
//2. 使用pem解码 -> 得到pem.Block结构体变量
block, _ := pem.Decode(buf)
//3. 使用x509对pem.Block中的Bytes变量中的数据进行解析 -> 得到一接口
pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
panic(err)
}
//4. 进行类型断言 -> 得到了公钥结构体
publicKey := pubInterface.(*rsa.PublicKey)
//5. 对原始消息进行哈希运算(和签名使用的哈希算法一致) -> 散列值
hashText := sha512.Sum512(plainText)
//6. 签名认证 - rsa中的函数
err = rsa.VerifyPKCS1v15(publicKey, crypto.SHA512, hashText[:], sigText)
if err == nil {
return true
}
return false
}
4. 参考教程
[1] https://blog.csdn.net/boss2967/article/details/83018039
[2] https://www.jianshu.com/p/60fe90594583