Go语言做对称加密怎么做

【导读】什么是对称加密?go 语言做对称加密怎么做?本文作者从加密原理到代码实现带你上车。
对称加密中,加密和解密使用相同的密钥,因此必须向解密者配送密钥,即密钥配送问题。而非对称加密中,由于加密和解密分别使用公钥和私钥,而公钥是公开的,因此可以规避密钥配送问题。非对称加密算法,也称公钥加密算法。
1977 年,ron rivest、adi shamir、leonard adleman 三人在美国公布了一种公钥加密算法,即 rsa 公钥加密算法。rsa 是目前最有影响力和最常用的公钥加密算法,可以说是公钥加密算法的事实标准。
一、rsa 加密原理
使用 m 和 c 分别表示明文和密文,则 rsa 加密、解密过程如下:
img
其中 e、n 的组合 (e, n) 即为公钥,d、n 的组合 (d, n) 即为私钥。当然 e、d、n 并非任意取值,需要符合一定条件,如下即为 e、d、n 的求解过程。
生成密钥对
e、d、n 的求解过程,也即生成密钥对的过程。涉及如下步骤:1、取两个大质数(也称素数)p、q,n = pq。2、取正整数 e、d,使得 ed mod (p-1)(q-1) = 1,也即:ed ≡ 1 mod (p-1)(q-1)。e 和 d 是模 (p-1)(q-1) 的乘法逆元,仅当 e 与 (p-1)(q-1) 互质时,存在 d。举例验证:1、取 p、q 分别为 13、17,n = pq = 221。2、而 (p-1)(q-1) = 12x16 = 192,取 e、d 分别为 13、133,有 13x133 mod 192 = 1取明文 m = 60,公钥加密、私钥解密,
rsa 加密原理证明过程
手动求解密钥对中的 d
ed mod (p-1)(q-1) = 1,已知 e 和 (p-1)(q-1) 求 d,即求 e 对模 (p-1)(q-1) 的乘法逆元。如上面例子中,p、q 为 13、17,(p-1)(q-1)=192,取 e=13,求 13d mod 192 = 1 中的 d。13d ≡ 1 (mod 192),在右侧添加 192 的倍数,使计算结果可以被 13 整除。13d ≡ 1 + 192x9 ≡ 13x133 (mod 192),因此 d = 133其他计算方法有:费马小定律、扩展欧几里得算法、欧拉定理。
rsa 安全性
由于公钥公开,即 e、n 公开。因此破解 rsa 私钥,即为已知 e、n 情况下求 d。因 ed mod (p-1)(q-1) = 1,且 n=pq,因此该问题演变为:对 n 质因数分解求 p、q。目前已被证明,已知 e、n 求 d 和对 n 质因数分解求 p、q 两者是等价的。实际中 n 长度为 2048 位以上,而当 n》200 位时分解 n 是非常困难的,因此 rsa 算法目前仍被认为是安全实用的。
rsa 计时***和防范
rsa 解密的本质是模幂运算
img
其中 c 为密文,(d,n) 为私钥,均为超过 1024 位的大数运算,直接计算并不可行,因此最经典的算法为蒙哥马利算法。而这种计算是比较是耗时的,因此者可以观察不同的输入对应的解密时间,通过分析推断私钥,称为计时。而防范 rsa 计时的办法,即在解密时加入随机因素,使得***者无法准确获取解密时间。
二、go rsa 加密解密
1、rsa 加解密,必然会去查 crypto/ras 这个包
package rsa implements rsa encryption as specified in pkcs#1.
这是该包的说明:实现 rsa 加密技术,基于 pkcs#1 规范。
对于什么是 pkcs#1,可以查阅相关资料。pkcs(公钥密码标准),而#1 就是 rsa 的标准。可以查看:pkcs 系列简介
从该包中函数的名称,可以看到有两对加解密的函数。
encryptoaep 和 decryptoaepencryptpkcs1v15 和 decryptpkcs1v15
这称作加密方案,详细可以查看,pkcs #1 v2.1 rsa 算法标准
可见,当与其他语言交互时,需要确定好使用哪种方案。
publickey 和 privatekey 两个类型分别代表公钥和私钥,关于这两个类型中成员该怎么设置,这涉及到 rsa 加密算法,本文中,这两个类型的实例通过解析文章开头生成的密钥得到。
2、解析密钥得到 publickey 和 privatekey 的实例
这个过程,我也是花了好些时间(主要对各种加密的各种东东不熟):怎么将 openssl 生成的密钥文件解析到公钥和私钥实例呢?
在 encoding/pem 包中,看到了—–begin type—–这样的字样,这正好和 openssl 生成的密钥形式差不多,那就试试。
在该包中,一个 block 代表的是 pem 编码的结构,关于 pem,请查阅相关资料。我们要解析密钥,当然用 decode 方法:
func decode(data []byte) (p *block, rest []byte)
这样便得到了一个 block 的实例(指针)。
解析来看 crypto/x509。为什么是 x509 呢?这又涉及到一堆概念。先不管这些,我也是看 encoding 和 crypto 这两个包的子包摸索出来的。在 x509 包中,有一个函数:
func parsepkixpublickey(derbytes []byte) (pub interface{}, err error)
从该函数的说明:parsepkixpublickey parses a der encoded public key. these values are typically found in pem blocks with “begin public key”。可见这就是解析 publickey 的。另外,这里说到了 pem,可以上面的 encoding/pem 对了。(pkix 是啥东东,查看这里 )
而解析私钥的,有好几个方法,从上面的介绍,我们知道,rsa 是 pkcs#1,刚好有一个方法:
func parsepkcs1privatekey(der []byte) (key *rsa.privatekey, err error)
返回的就是 rsa.privatekey。
代码实现:
package main
import (
“crypto/rsa”
“crypto/rand”
“crypto/x509”
“encoding/pem”
“os”
“fmt”

func rsagenkey(bits int) error {
/*
生成私钥
*/
//1、使用 rsa 中的 generatekey 方法生成私钥
privatekey, err := rsa.generatekey(rand.reader, bits)
if err != nil {
return err
}
//2、通过 x509 标准将得到的 ras 私钥序列化为:asn.1 的 der 编码字符串
privatestream := x509.marshalpkcs1privatekey(privatekey)
//3、将私钥字符串设置到 pem 格式块中
block1 := pem.block{
type: “private key”,
bytes: privatestream,
}
//4、通过 pem 将设置的数据进行编码,并写入磁盘文件
fprivate, err := os.create(“privatekey.pem”)
if err != nil {
return err
}
defer fprivate.close()
err = pem.encode(fprivate, &block1)
if err != nil {
return err
}
/*
生成公钥
*/
publickey:=privatekey.publickey
publicstream,err:=x509.marshalpkixpublickey(&publickey)
//publicstream:=x509.marshalpkcs1publickey(&publickey)
block2:=pem.block{
type:“public key”,
bytes:publicstream,
}
fpublic,err:=os.create(“publickey.pem”)
if err!=nil {
return err
}
defer fpublic.close()
pem.encode(fpublic,&block2)
return nil
}
//对数据进行加密操作
func encyptogrsa(src []byte,path string) (res []byte,err error) {
//1. 获取秘钥(从本地磁盘读取)
f,err:=os.open(path)
if err!=nil {
return
}
defer f.close()
fileinfo,_:=f.stat()
b:=make([]byte,fileinfo.size())
f.read(b)
// 2、将得到的字符串解码
block,_:=pem.decode(b)
// 使用 x509 将解码之后的数据 解析出来
//x509.marshalpkcs1publickey(block): 解析之后无法用,所以采用以下方法:parsepkixpublickey
keyinit,err:=x509.parsepkixpublickey(block.bytes) //对应于生成秘钥的 x509.marshalpkixpublickey(&publickey)
//keyinit1,err:=x509.parsepkcs1publickey(block.bytes)
if err!=nil {
return
}
//4. 使用公钥加密数据
pubkey:=keyinit.(*rsa.publickey)
res,err=rsa.encryptpkcs1v15(rand.reader,pubkey,src)
return
}
//对数据进行解密操作
func decrptogrsa(src []byte,path string)(res []byte,err error) {
//1. 获取秘钥(从本地磁盘读取)
f,err:=os.open(path)
if err!=nil {
return
}
defer f.close()
fileinfo,_:=f.stat()
b:=make([]byte,fileinfo.size())
f.read(b)
block,_:=pem.decode(b)//解码
privatekey,err:=x509.parsepkcs1privatekey(block.bytes)//还原数据
res,err=rsa.decryptpkcs1v15(rand.reader,privatekey,src)
return
}
func main() {
//rsa.generatekey()
err:=rsagenkey(4096)
if err!=nil {
fmt.println(err)
return
}
fmt.println(“秘钥生成成功!”)
str:=“山重水复疑无路,柳暗花明又一村!”
fmt.println(“加密之前的数据为:”,string(str))
data,err:=encyptogrsa([]byte(str),“publickey.pem”)
data,err=decrptogrsa(data,“privatekey.pem”)
fmt.println(“加密之后的数据为:”,string(data))
}


虎口夺食,京东方 OLED 新款面板抢苹果订单
可调直流电源的设计原理
续航神机小米Max 2拆解,原来内部这么简单
单刀双掷电路图讲解
国产工业机器人的机会究竟在哪里
Go语言做对称加密怎么做
通过红外激光探测人类独特的心脏特征,200 米外不露脸认出你是谁!
TMS320C32与PC机串行通信的软件实现方法
如何选择适合企业的网络设备
国际电子展上有哪些值得关注的新技术会影响您2019年的产品设计呢?
NLP技术对BI而言有那么重要吗?
又见骚红!魅族PRO6Plus红色版本曝光 极为魅惑!
特斯拉2023年Q4交付量达484,507辆
PCB板内地线布局的主要形式和要求阐述
FPGA厂商安路科技拟首次公开发行股票并在境内证券交易所上市
什么是中断和中断系统?单片机中断响应时间的计算
关于全新48V轻度混合动力系统的性能分析和应用介绍
量子计算机的优点_量子计算机的应用_量子计算机的未来应用
SDH和WDM光通信技术如何应用在分布式雷达系统中
我国MEMS传感器打破依赖进口这一困局的三板斧