分享几个 Go 语言中使用 RSA 算法对字符串的加密解密的代码片段

2023-12-19 09:29:42 浏览数 (2)

一 生成公钥和私钥

使用随机数据生成器random生成一对具有指定字位数的RSA密钥,生成 RSA 的公钥和私钥,并保存至 key 目录中,入参为加密的位数。

代码语言:javascript复制
// GenerateRSAKey 函数使用随机数据生成器random生成一对具有指定字位数的RSA密钥,生成 RSA 的公钥和私钥,并保存至 key 目录中,入参为加密的位数。
func GenerateRSAKeys(bits int) {
	if createDir("keys") {
		fmt.Println("keys目录已成功新建,本次生成的公钥和私钥将存放于该目录,请谨慎保存!")
	} else {
		fmt.Println("keys目录已存在,本次生成的公钥和私钥将存放于该目录,请谨慎保存!")
	}
	//Reader是一个全局、共享的密码用强随机数生成器
	privateKey, err := rsa.GenerateKey(rand.Reader, bits)
	if err != nil {
		panic(err)
	}
	//通过x509标准将得到的ras私钥序列化为ASN.1 的 DER编码字符串,使用pem格式对x509输出的内容进行编码。
	X509PrivateKey := x509.MarshalPKCS1PrivateKey(privateKey)
	//创建文件保存私钥
	privateFile, err := os.Create("keys/private.key")
	if err != nil {
		panic(err)
	}
	defer privateFile.Close()
	//构建一个pem.Block结构体对象
	privateBlock := pem.Block{Type: "RSA PRIVATE KEY", Bytes: X509PrivateKey}
	//将数据保存到文件
	pem.Encode(privateFile, &privateBlock)
	//获取公钥的数据
	publicKey := privateKey.PublicKey
	//X509对公钥编码
	X509PublicKey, err := x509.MarshalPKIXPublicKey(&publicKey)
	if err != nil {
		panic(err)
	}
	//创建用于保存公钥的文件
	publicFile, err := os.Create("keys/public.key")
	if err != nil {
		panic(err)
	}
	defer publicFile.Close()
	//创建一个pem.Block结构体对象
	publicBlock := pem.Block{Type: "PUBLIC KEY", Bytes: X509PublicKey}
	pem.Encode(publicFile, &publicBlock)
}

二 从私钥推导出公钥

传入字符串类型的私钥,返回其对应的公钥。并将对应的公钥和私钥存放到相应的目录。

代码语言:javascript复制
func GetPublicKeyFromPrivateKey(privateKeyString string) string {
	privateKeyBytes := []byte(privateKeyString)
	privateKeyBlock, _ := pem.Decode(privateKeyBytes)
	if privateKeyBlock == nil || privateKeyBlock.Type != "RSA PRIVATE KEY" {
		panic(errors.New("解码包含公钥的PEM块失败"))
	}
	publicKey, err := x509.ParsePKCS1PrivateKey(privateKeyBlock.Bytes)
	if err != nil {
		panic(err)
	}
	publicKeyDer, _ := x509.MarshalPKIXPublicKey(&publicKey.PublicKey)
	publicKeyBlock := pem.Block{Type: "PUBLIC KEY", Bytes: publicKeyDer}
	return string(pem.EncodeToMemory(&publicKeyBlock))
}
// createDir 创建存放公钥和私钥的目录,如已经存在则不创建.
func createDir(name string) bool {
	_, err := os.Stat(name)
	if !os.IsExist(err) {
		e := os.Mkdir("keys", os.ModePerm)
		if e != nil {
			return false
		}
	} else {
		return false
	}
	return true
}

三 使用公钥对字符串进行加密

公钥加密方法,第一个参数为需要加密的字符串,第二个参数为 RSA 公钥字符串。加密后返回一个 Base64 编码的字符串及错误。

代码语言:javascript复制
func PublicKeyEncrypt(text string, publicKey string) (string, error) {
	var publicKeyBytes []byte = []byte(publicKey)
	block, _ := pem.Decode(publicKeyBytes)
	publicKeyInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		panic(err)
	}
	// 类型断言
	pubKey := publicKeyInterface.(*rsa.PublicKey)

	// 对明文进行加密
	encryptText, err := rsa.EncryptPKCS1v15(rand.Reader, pubKey, []byte(text))
	if err != nil {
		panic(err)
	}
	// 返回base64编码字符串
	return base64.StdEncoding.EncodeToString(encryptText), nil
}

四 使用私钥对已加密的字符串进行解密

私钥解密方法,第一个参数为base64编码的加密字符串,第二个参数为 RSA 私钥字符串。解密后返回原始字符串。

代码语言:javascript复制
func PrivateKeyDecrypt(encryptText string, privateKey string) (string, error) {
	decryptTextBytes, err := base64.StdEncoding.DecodeString(encryptText)
	if err != nil {
		panic(err)
	}
	block, _ := pem.Decode([]byte(privateKey))
	//X509解码
	priKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
	if err != nil {
		panic(err)
	}
	//对密文进行解密
	decryptText, _ := rsa.DecryptPKCS1v15(rand.Reader, priKey, decryptTextBytes)
	//返回明文
	return string(decryptText), nil
}

以上内容仅供参考。

0 人点赞