返回
Featured image of post RSA加密算法的使用

RSA加密算法的使用

RSA加密算法的使用

  • 生成公私钥
  • 保存文件或者保存在内存中
  • 设置时间有效期,长期有效或者超时重创建公私钥

代码如下

    package zcj_rsa
    
    import (
    	"crypto/rand"
    	"crypto/rsa"
    	"crypto/x509"
    	"encoding/base64"
    	"encoding/pem"
    	"fmt"
    	"os"
    	"path"
    	"time"
    )
    
    const (
    	BITS  = 2048        // 证书大小
    	SAVEKEYPATH = "./"  // 默认保存公私钥的路径
    )
    
    type signData struct {
    	publicKey  		string    // 公钥
    	privateKey 		string    // 私钥
    	generateTime    time.Time // 生成时间
    	isCreate        bool      // 是否创建公私钥
    	Timeout         int       // 证书超时时间 单位时间为分钟 <= 0 表示永久有效
    	SaveMode        bool      // true 保存为文件,False保存在内存中
    	PublicKeyPath   string    // 保存公钥的路径
    	PrivateKeyPath  string    // 保存私钥的路径
    }
    
    // 创建公私钥对
    func (s *signData)creatKey() error {
    	if s.isEffectiveKey(){
    		return fmt.Errorf("公私钥已存在")
    	}
    	// 创建私钥
    	prvKey, err := rsa.GenerateKey(rand.Reader, BITS)
    	if err != nil {
    		return err
    	}
    	//通过x509标准将得到的ras私钥序列化为ASN.1 的 DER编码字符串
    	x509PrivateKey := x509.MarshalPKCS1PrivateKey(prvKey)
    	privateKeyBlock := &pem.Block{
    		Type:"RSA Private key",
    		Bytes: x509PrivateKey,
    	}
    	//处理公钥,公钥包含在私钥中
    	pubKey := prvKey.PublicKey
    	//通过x509标准将得到的ras公钥序列化为ASN.1 的 DER编码字符串
    	x509PublicKey, err := x509.MarshalPKIXPublicKey(&pubKey)
    	if err != nil {
    		return err
    	}
    	publicKeyBlock := &pem.Block{
    		Type:"RSA Public key",
    		Bytes: x509PublicKey,
    	}
    	if s.SaveMode{
    		publicFile, err := os.Create(path.Join(s.PublicKeyPath, "public.pem"))
    		if err!=nil{
    			return err
    		}
    		privateKeyFile, err := os.Create(path.Join(s.PrivateKeyPath, "privateKey.pem"))
    		if err!=nil{
    			return err
    		}
    		defer publicFile.Close()
    		defer privateKeyFile.Close()
    		//保存到文件
    		err = pem.Encode(privateKeyFile,privateKeyBlock)
    		if err!=nil{
    			return err
    		}
    		err = pem.Encode(publicFile,publicKeyBlock)
    		if err!=nil{
    			return err
    		}
    	}else{
    		s.publicKey = string(pem.EncodeToMemory(publicKeyBlock))
    		s.privateKey = string(pem.EncodeToMemory(privateKeyBlock))
    	}
    	s.generateTime = time.Now()
    	s.isCreate = true
    	return nil
    }
    
    // 判断公私钥是否有效
    func (s *signData)isEffectiveKey()bool{
    	if s.isCreate{
    		if s.Timeout <= 0{
    			//log.Info("公私钥创建,且永久有效")
    			return true
    		}
    		duration := time.Now().Sub(s.generateTime).Minutes()
    		if int(duration) <= s.Timeout{
    			//log.Info("公私钥创建,且在有效期")
    			return true
    		}
    	}
    	return false
    }
    
    // 使用私钥进行解密
    func (s *signData)RSADecryption(cipherText string)(string, error){
    	// 保存在内存中进行判断
    	if !s.SaveMode && !s.isEffectiveKey(){
    		return "", fmt.Errorf("公私钥未创建")
    	}
    	cipherBuf, err := base64.StdEncoding.DecodeString(cipherText)
    	if err != nil {
    		return "", err
    	}
    	var buf []byte
    	if s.SaveMode{
    		file,err:=os.Open(path.Join(s.PrivateKeyPath, "privateKey.pem"))
    		if err!=nil{
    			panic(err)
    		}
    		defer file.Close()
    		//读取文件的内容
    		info, _ := file.Stat()
    		buf =make([]byte,info.Size())
    		file.Read(buf)
    	}else{
    		buf = []byte(s.privateKey)
    	}
    	block, _ := pem.Decode(buf)
    	if block == nil{
    		return "", fmt.Errorf("pem decode fild")
    	}
    	privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
    	if err != nil {
    		return "", err
    	}
    	plainText, err := rsa.DecryptPKCS1v15(rand.Reader, privateKey, cipherBuf)
    	if err != nil {
    		return "", err
    	}
    	return string(plainText), err
    }
    
    // 使用公钥加密
    func (s *signData)RSAEncryption(plainText string)(string, error){
    	// 保存在内存中进行判断
    	if !s.SaveMode && !s.isEffectiveKey(){
    		return "", fmt.Errorf("公私钥未创建")
    	}
    	var buf []byte
    	if s.SaveMode{
    		file,err:=os.Open(path.Join(s.PrivateKeyPath, "public.pem"))
    		if err!=nil{
    			panic(err)
    		}
    		defer file.Close()
    		//读取文件的内容
    		info, _ := file.Stat()
    		buf =make([]byte,info.Size())
    		file.Read(buf)
    	}else{
    		buf = []byte(s.publicKey)
    	}
    	block, _ := pem.Decode(buf)
    	if block == nil{
    		return "", fmt.Errorf("pem decode fild")
    	}
    	//x509解码
    	publicKeyInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
    	if err!=nil{
    		return "", nil
    	}
    	//类型断言
    	publicKey:=publicKeyInterface.(*rsa.PublicKey)
    	//对明文进行加密
    	cipherText, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey, []byte(plainText))
    	if err!=nil{
    		return "", nil
    	}
    	strCipher := base64.StdEncoding.EncodeToString(cipherText)
    	return strCipher, nil
    
    }
    
    func RsaInit(saveMode bool, timeOut int, publicKeyPath, privateKeyPath string) *signData {
    	if publicKeyPath == ""{
    		publicKeyPath = SAVEKEYPATH
    	}
    	if privateKeyPath == ""{
    		privateKeyPath = SAVEKEYPATH
    	}
    	return &signData{
    		isCreate:		false,
    		Timeout:        timeOut,
    		SaveMode:       saveMode,
    		PublicKeyPath:  publicKeyPath,
    		PrivateKeyPath: privateKeyPath,
    	}
    }

测试如下

    package zcj_rsa
    
    import (
    	"fmt"
    	"testing"
    )
    
    // 创建rsa保存在文件
    func TestRsaFile(t *testing.T) {
    	rsa := RsaInit(true, 1, "./", "./")
    	err := rsa.creatKey()
    	if err != nil {
    		t.Errorf("公私钥创建失败: %v", err)
    	}
    	// 加密
    	cipherText, err := rsa.RSAEncryption("zcj")
    	if err != nil {
    		t.Errorf("加密失败:%v", err)
    	}
    	// 解密
    	planinText, err := rsa.RSADecryption(cipherText)
    	if err != nil {
    		t.Errorf("解密失败:%v", err)
    	}
    	fmt.Printf("密文:%v \n", cipherText)
    	fmt.Printf("原码:%v \n", planinText)
    }
    
    // 保存rsa在内存
    func TestRsa(t *testing.T) {
    	rsa := RsaInit(false, 1, "", "")
    	err := rsa.creatKey()
    	if err != nil {
    		t.Errorf("公私钥创建失败: %v", err)
    	}
    	// 加密
    	cipherText, err := rsa.RSAEncryption("zcj")
    	if err != nil {
    		t.Errorf("加密失败:%v", err)
    	}
    	// 解密
    	planinText, err := rsa.RSADecryption(cipherText)
    	if err != nil {
    		t.Errorf("解密失败:%v", err)
    	}
    	fmt.Printf("密文:%v \n", cipherText)
    	fmt.Printf("原码:%v \n", planinText)
    }

源码仓库

Licensed under CC BY-NC-SA 4.0
Built with Hugo
Theme Stack designed by Jimmy