Go语言 如何实现RSA加密解密

RSA是一种非对称加密算法,它的名字是由它的三位开发者,即RonRivest、AdiShamir和LeonardAdleman 的姓氏的首字母组成的(Rivest-Shamir-Adleman ),可用于数据加密和数字签名。

用于数据加密时,消息发送方利用对方的公钥进行加密,消息接受方收到密文时使用自己的私钥进行解密。

实现代码如下:

import (
	"crypto/rsa"
	"crypto/rand"
	"crypto/x509"
	"os"
	"encoding/pem"
	"fmt"
)
//生成RSA私钥和公钥,保存到文件中
func GenerateRSAKey(bits int){
	//GenerateKey函数使用随机数据生成器random生成一对具有指定字位数的RSA密钥
	//Reader是一个全局、共享的密码用强随机数生成器
	privateKey, err := rsa.GenerateKey(rand.Reader, bits)
	if err!=nil{
		panic(err)
	}
	//保存私钥
	//通过x509标准将得到的ras私钥序列化为ASN.1 的 DER编码字符串
	X509PrivateKey := x509.MarshalPKCS1PrivateKey(privateKey)
	//使用pem格式对x509输出的内容进行编码
	//创建文件保存私钥
	privateFile, err := os.Create("private.pem")
	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)
	}
	//pem格式编码
	//创建用于保存公钥的文件
	publicFile, err := os.Create("public.pem")
	if err!=nil{
		panic(err)
	}
	defer publicFile.Close()
	//创建一个pem.Block结构体对象
	publicBlock:= pem.Block{Type: "RSA Public Key",Bytes:X509PublicKey}
	//保存到文件
	pem.Encode(publicFile,&publicBlock)
}
//RSA加密
func RSA_Encrypt(plainText []byte,path string)[]byte{
	//打开文件
	file,err:=os.Open(path)
	if err!=nil{
		panic(err)
	}
	defer file.Close()
	//读取文件的内容
	info, _ := file.Stat()
	buf:=make([]byte,info.Size())
	file.Read(buf)
	//pem解码
	block, _ := pem.Decode(buf)
	//x509解码
	publicKeyInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err!=nil{
		panic(err)
	}
	//类型断言
	publicKey:=publicKeyInterface.(*rsa.PublicKey)
	//对明文进行加密
	cipherText, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey, plainText)
	if err!=nil{
		panic(err)
	}
	//返回密文
	return cipherText
}
//RSA解密
func RSA_Decrypt(cipherText []byte,path string) []byte{
	//打开文件
	file,err:=os.Open(path)
	if err!=nil{
		panic(err)
	}
	defer file.Close()
	//获取文件内容
	info, _ := file.Stat()
	buf:=make([]byte,info.Size())
	file.Read(buf)
	//pem解码
	block, _ := pem.Decode(buf)
	//X509解码
	privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
	if err!=nil{
		panic(err)
	}
	//对密文进行解密
	plainText,_:=rsa.DecryptPKCS1v15(rand.Reader,privateKey,cipherText)
	//返回明文
	return plainText
}

测试代码如下:

func main(){
 //生成密钥对,保存到文件
 GenerateRSAKey(2048)
 message:=[]byte("hello world")
 //加密
 cipherText:=RSA_Encrypt(message,"public.pem")
 fmt.Println("加密后为:",string(cipherText))
 //解密
 plainText := RSA_Decrypt(cipherText, "private.pem")
 fmt.Println("解密后为:",string(plainText))
}

测试结果如下:

补充:golang中关于RSA加密、解密、签名、验签的总结

golang中关于RSA的加密、解密、签名、验签的使用主要在于使用x509及rsa package下相关的方法。

gocrypt是本人对一般常用的加/解密、签名/验签、hash的封装库,欢迎大家使用。

以下总结相关的各种变化类型:

1.秘钥、加密/签名字符串加密的格式

目前主要见到有hex及base64

(1)hex

针对hex的加解密

hex.DecodeString(s string)//解密
hex.EncodeToString(src []byte) string//加密

(2)base64

base64.StdEncoding.DecodeString(s string) ([]byte, error)//解密
base64.StdEncoding.EncodeToString(src []byte) string//加密

2.私钥的格式

解析私钥的方式如下:

(1)PKCS1

x509.ParsePKCS1PrivateKey(der []byte) (key interface{}, err error)

(2)PKCS8

x509.ParsePKCS8PrivateKey(der []byte) (key interface{}, err error)

3.采用的数字签名算法SHA

以下为RSA sign的不同说明:

(1)SHA1

    hash := sha1.New()
 hash.Write([]byte(originalData))
 encryptedData, err := rsa.SignPKCS1v15(rand.Reader, prvKey, crypto.SHA1, hash.Sum(nil))

(2)SHA256

    hash := sha256.New()
 hash.Write([]byte(originalData))
 encryptedData, err := rsa.SignPKCS1v15(rand.Reader, prvKey, crypto.SHA256, hash.Sum(nil))

4.RSA使用类型

主要有加密/解密、签名/验签4种方式,且加密/解密与签名/验签均是一个相反的过程。两对是根据对公钥及私钥的使用划分的。

加密/解密是采用公钥加密,私钥解密。

签名/验签是采用私钥签名,公钥验签。

(1)加密

rsa.EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) ([]byte, error)

(2)解密

rsa.DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) ([]byte, error)

(3)签名

rsa.SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte) ([]byte, error)

(4)验签

rsa.VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte) error

5.具体的使用示例

(1)加密:采用sha1算法加密后转base64格式
func RsaEncryptWithSha1Base64(originalData,publicKey string)(string,error){
   key, _ := base64.StdEncoding.DecodeString(publicKey)
   pubKey, _ := x509.ParsePKIXPublicKey(key)
   encryptedData,err:=rsa.EncryptPKCS1v15(rand.Reader, pubKey.(*rsa.PublicKey), []byte(originalData))
   return base64.StdEncoding.EncodeToString(encryptedData),err
}
(2)解密:对采用sha1算法加密后转base64格式的数据进行解密(私钥PKCS1格式)
func RsaDecryptWithSha1Base64(encryptedData,privateKey string)(string,error){
   encryptedDecodeBytes,err:=base64.StdEncoding.DecodeString(encryptedData)
   if err!=nil {
      return "",err
   }
   key,_:=base64.StdEncoding.DecodeString(privateKey)
   prvKey,_:=x509.ParsePKCS1PrivateKey(key)
   originalData,err:=rsa.DecryptPKCS1v15(rand.Reader,prvKey,encryptedDecodeBytes)
   return string(originalData),err
}
(3)签名:采用sha1算法进行签名并输出为hex格式(私钥PKCS8格式)
func RsaSignWithSha1Hex(data string, prvKey string) (string, error) {
   keyByts, err := hex.DecodeString(prvKey)
   if err != nil {
      fmt.Println(err)
      return "", err
   }
   privateKey, err := x509.ParsePKCS8PrivateKey(keyByts)
   if err != nil {
      fmt.Println("ParsePKCS8PrivateKey err", err)
      return "", err
   }
   h := sha1.New()
   h.Write([]byte([]byte(data)))
   hash := h.Sum(nil)
   signature, err := rsa.SignPKCS1v15(rand.Reader, privateKey.(*rsa.PrivateKey), crypto.SHA1, hash[:])
   if err != nil {
      fmt.Printf("Error from signing: %s\n", err)
      return "", err
   }
   out := hex.EncodeToString(signature)
   return out, nil
}
(4)验签:对采用sha1算法进行签名后转base64格式的数据进行验签
func RsaVerySignWithSha1Base64(originalData, signData, pubKey string) error{
   sign, err := base64.StdEncoding.DecodeString(signData)
   if err != nil {
      return err
   }
   public, _ := base64.StdEncoding.DecodeString(pubKey)
   pub, err := x509.ParsePKIXPublicKey(public)
   if err != nil {
      return err
   }
   hash := sha1.New()
   hash.Write([]byte(originalData))
   return rsa.VerifyPKCS1v15(pub.(*rsa.PublicKey), crypto.SHA1, hash.Sum(nil), sign)
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。如有错误或未考虑完全的地方,望不吝赐教。

(0)

相关推荐

  • Golang实现http文件上传小功能的案例

    看代码吧~ package main import ( "fmt" "io" "net/http" "os" ) func main() { http.HandleFunc("/", index) http.HandleFunc("/upload", upload) http.ListenAndServe(":1789", nil) } func upload(w h

  • golang 如何实现HTTP代理和反向代理

    代理的核心功能可以用一句话概括:接受客户端的请求,转发到后端服务器,获得应答之后返回给客户端. 代理的功能有很多,事实上整个互联网到处都充斥着代理服务器.如果所有的 HTTP 访问都是客户端和服务器端直接进行的话,我们的网络不仅会变得缓慢,而且性能会大打折扣. 代理服务器根据不同的配置和使用,可能会有不同的功能,这些功能主要包括: 内容过滤:代理可以根据一定的规则限制某些请求的连接.比如有些公司会设置内部网络无法访问某些购物.游戏网站,或者学校的网络不让学生访问色情暴力的网站等 节省成本:代理服

  • Go语言获取文件的名称、前缀、后缀

    示例代码: package main import ( "fmt" "path" ) func main() { filename := "device/sdk/CMakeLists.txt" filenameall := path.Base(filename) filesuffix := path.Ext(filename) fileprefix := filenameall[0:len(filenameall) - len(filesuffi

  • go mod 安装依赖 unkown revision问题的解决方案

    背景 公司一个golang的项目,使用到了公司的私有仓库,去执行go mod tidy(下载依赖)的时候,到download公司私有库的时候就报错,报错信息也不明显,只是提示找不到影响版本unkown revision 小知识 go mod golang用来管理用来的,类似java的maven(但肯定没有maven这么好用) go mod tidy ,下载更新依赖 go install这种下载依赖的方式其实是通过go get的方式去下载的 go insall -x 加上-x命令,可以查看更多的错

  • Goland使用Go Modules创建/管理项目的操作

    创建项目 Location:新项目文件夹GOROOT:go 安装根目录Proxy:https://goproxy.io,direct 重要:https://goproxy.io是下载go包的代理地址,设置后可在国内正常下载go仓库/github的包. 创建一个go文件 创建了一个test.go 下载安装需要的包 这里演示安装mysql driver包:github.com/go-sql-driver/mysql 直接import显示找不到包,使用左下方命令行工具,安装mysql driver 使

  • 解决golang 关于全局变量的坑

    学习golang不久,在定义全局变量的时候遇见了坑.写个小例子,增强记忆. 错误版本 var p int func main() { p, err := test(4) if err != nil { log.Fatal(err) } } func test(i int) (int, error) { return i + 1, nil } 编译一直不通过,p declared and not used.后来查了查资料,看见这种其实是在main里边又重新定义了p,所以一直提示p定义了但是没有使用

  • Go语言 如何实现RSA加密解密

    RSA是一种非对称加密算法,它的名字是由它的三位开发者,即RonRivest.AdiShamir和LeonardAdleman 的姓氏的首字母组成的(Rivest-Shamir-Adleman ),可用于数据加密和数字签名. 用于数据加密时,消息发送方利用对方的公钥进行加密,消息接受方收到密文时使用自己的私钥进行解密. 实现代码如下: import ( "crypto/rsa" "crypto/rand" "crypto/x509" "

  • Java RSA加密解密实现方法分析【附BASE64 jar包下载】

    本文实例讲述了Java RSA加密解密实现方法.分享给大家供大家参考,具体如下: 该工具类中用到了BASE64,需要借助第三方类库:javabase64-1.3.1.jar javabase64-1.3.1.jar 本站下载地址. 注意: RSA加密明文最大长度117字节,解密要求密文最大长度为128字节,所以在加密和解密的过程中需要分块进行. RSA加密对明文的长度是有限制的,如果加密数据过大会抛出如下异常: Exception in thread "main" javax.cryp

  • python实现RSA加密(解密)算法

    RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准. 今天只有短的RSA钥匙才可能被强力方式解破.到2008年为止,世界上还没有任何可靠的攻击RSA算法的方式.只要其密钥的长度足够长,用RSA加密的信息实际上是不能被解破的.但在分布式计算和量子计算机理论日趋成熟的今天,RSA加密安全性受到了挑战. RSA算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥.

  • python rsa 加密解密

    最近有需求,需要研究一下RSA加密解密安全:在网上百度了一下例子文章,很少有文章介绍怎么保存.传输.打印加密后的文本信息,都是千篇一律的.直接在一个脚本,加密后的文本信息赋于变量,然后立马调用解密.仔细想了一下RSA加密解密的过程,确定有二端,一端为:加密端,一端为解密端,一般不在同一台机器.在这里,我只模拟了保存在文件,然后再读出来:关于怎以通过网络传输,也是大同小异. 用RSA加密后的密文,是无法直接用文本显示,因为存在一些无法用文本信息编码显示的二进制数据.对于保存,网络传输,打印不乱码,

  • Python下实现的RSA加密/解密及签名/验证功能示例

    本文实例讲述了Python下实现的RSA加密/解密及签名/验证功能.分享给大家供大家参考,具体如下: 原文是py2环境,而我的环境是py3,所以对原代码做了修改:decode(), encode() import rsa # 生成密钥 (pubkey, privkey) = rsa.newkeys(1024) # 保存密钥 with open('public.pem','w+') as f: f.write(pubkey.save_pkcs1().decode()) with open('pri

  • C#自定义RSA加密解密及RSA签名和验证类实例

    本文实例讲述了C#自定义RSA加密解密及RSA签名和验证类.分享给大家供大家参考.具体分析如下: 这个C#类自定义RSA加密解密及RSA签名和验证,包含了RSA加密.解密及签名所需的相关函数,带有详细的注释说明. using System; using System.Text; using System.Security.Cryptography; namespace DotNet.Utilities { /// <summary> /// RSA加密解密及RSA签名和验证 /// </

  • php基于openssl的rsa加密解密示例

    本文实例讲述了php基于openssl的rsa加密解密.分享给大家供大家参考,具体如下: <?php $config = array( //"config" =>"D:/phpserver/Lighttpd/openssl.cnf", //'config' =>'D:/phpStudy/Lighttpd/OpenSSL.cnf', 'private_key_bits' => 1024, // Size of Key. 'private_key

  • 同时兼容JS和C#的RSA加密解密算法详解(对web提交的数据加密传输)

    前言 我们在Web应用中往往涉及到敏感的数据,由于HTTP协议以明文的形式与服务器进行交互,因此可以通过截获请求的数据包进行分析来盗取有用的信息.虽然https可以对传输的数据进行加密,但是必须要申请证书(一般都是收费的),成本较高.那么问题来了,如果对web提交的敏感数据进行加密呢?web应用中,前端的数据处理和交互基本上都是靠javascript来完成,后台的逻辑处理可以C#(java)等进行处理. 微软的C#中虽然有RSA算法,但是格式和OpenSSL生成的公钥/私钥文件格式并不兼容.这个

  • Java中RSA加密解密的实现方法分析

    本文实例讲述了Java中RSA加密解密的实现方法.分享给大家供大家参考,具体如下: public static void main(String[] args) throws Exception { // TODO Auto-generated method stub HashMap<String, Object> map = RSAUtils.getKeys(); //生成公钥和私钥 RSAPublicKey publicKey = (RSAPublicKey) map.get("

  • Java实现的RSA加密解密算法示例

    本文实例讲述了Java实现的RSA加密解密算法.分享给大家供大家参考,具体如下: import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.Image; import java.awt.RenderingHints; import java.awt.image.BufferedImage; import java.

随机推荐