【Golang】基于RSA算法的数据通信和数字签名

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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值