自己试验了下rsa
https://github.com/xiazemin/rsa
golang 只提供了公钥加密私钥解密的算法
晚上找了下私钥签名(加密),公钥验证(解密)的算法
公钥是公开的,私钥是自己保存的,用私钥对数据进行签名,用公钥验证签名。
RSA_private_encrypt和RSA_public_decrypt
https://www.openssl.org/docs/manmaster/man3/RSA_private_encrypt.html
翻查一下go的文档,存在在类似的函数(crypt/rsa):
func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) ([]byte, error)和func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) ([]byte, error)。但仔细看,这里是使用公钥进行加密,使用私钥进行解密,和描述刚好相反。
压根就是一rsa签名,就用crypt/rsa里面,func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte) ([]byte, error)实现的。
https://github.com/buf1024/golib/blob/master/crypt/rsa.go
这是一个非对称加密算法,一般通过公钥加密,私钥解密。
在加解密过程中,使用openssl生产密钥。执行如下操作:
1)创建私钥:
openssl genrsa -out private.pem 1024 //密钥长度,1024觉得不够安全的话可以用2048,但是代价也相应增大
2)创建公钥:
openssl rsa -in private.pem -pubout -out public.pem
这样便生产了密钥。
一般地,各个语言也会提供API,用于生成密钥。在Go中,可以查看encoding/pem包和crypto/x509包。
二、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和DecryptOAEP
EncryptPKCS1v15和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对了。
而解析私钥的,有好几个方法,从上面的介绍,我们知道,RSA是PKCS#1,刚好有一个方法:
func ParsePKCS1PrivateKey(der []byte) (key *rsa.PrivateKey, err error)
返回的就是rsa.PrivateKey。
IETF的安全领域的公钥基础实施(PKIX)工作组正在为互联网上使用的公钥证书定义一系列的标准。PKIX工作组在1995年10月成立。
PKIX的目的是要开发必须的互联网标准来支持可互操作的PKI。工作组的第一项任务就是要创建一个概要文件,把证书数据结构、扩展域和数据取值限定在一个特定的可选范围内。X.509标准的巨大灵活性使得互操作难以实现,PKIX工作组希望通过限定允许的选项,提高PKI系统间的互操作性。
PKIX工作组定义了公钥证书及CRL的概要文件。在一些情况下,他还定义了其他的证书扩展字段或证书属性,还有这些属性的对象标识。PKIX也正在开发新的协议,以便于PKI生命周期中自始至终对PKI信息的管理。这些协议部分包括证书管理协议(CMP)、安全多用途邮件扩展(S/MIME)和在线证书状态协议(OCSP)。
密码学里目前有两大经典算法,一个是对称加解密,其代表是AES加解密;另一个是非对加解密,其代表是RSA加解密。
AES加密又分为ECB、CBC、CFB、OFB等几种
在加密算法中主要使用较多加密方式分别是对称加密和非对称加密,对称加密中的代表是AES,DES,3DES等,非对称加密中使用比较多的是RSA,ECC等,最近火热的比特币中就使用ECC椭圆曲线算法
在压测 的时候发现 rsa 签名 性能十分低下,网上查资料 有人说 使用 openssl 的速度是 golang 的数倍, 于是我就用cgo (openssl) 和 golang rsa 做了一个对比,发现居然相差五倍,openssl 完胜。
下面是我的实现代码地址,有兴趣的可以下载运行试一下
https://github.com/Bulesxz/rsa_cgo
网上找遍了官方提供的库crypto/rsa中只有公钥加密私钥解密的实现,意味着无法实现私钥加密公钥解密,而要实现双向认证必须要使用私钥加密公钥解密,通过几个小时的寻找其实有很多论坛中也在讨论这个问题,也有童鞋在GITHUB上面提及了一些解决方案
https://github.com/wenzhenxi/gorsa
https://github.com/farmerx/gorsa
对称加密和非对称加密的区别:
对称加密中只有一个钥匙也就是KEY,加解密都依靠这组密钥
非对称加密中有公私钥之分,私钥可以生产公钥(比特币的钱包地址就是公钥),一般加密通过公钥加密私钥解密(也有私钥加密公钥解密)
RSA使用场景:
我们最熟悉的就是HTTPS中就是使用的RSA加密,CA机构给你颁发的就是私钥给到我们进行配置,在请求过程中端用CA内置到系统的公钥加密,请求道服务器由服务器进行解密验证,保障了传输过程中的请求加密
高安全场景(比如金融设备银联交易等)下的双向认证(一机一密钥),每台机器本地都会生成一组公私钥对,并且吧公钥发送给服务器,这个使用发起的请求模型如下:
服务器的公私钥对简称: s_puk,s_pvk
端生成的公私钥对简称: c_puk,c_pvk
服务器存储: s_pvk和c_puk
端存储 :s_puk,c_pvk
端使用c_pvk加密请求 -> 服务器使用c_puk解密(验证端) -> 使用s_pvk加密返回结果返回 -> 端使用s_puk解密获得返回结果(验证服务器)
这个过程中就完成了端认证服务器,服务器认证端称之为双向认证(这里是指简单的表达这个模型,更加安全的模式中会引入加密机进一步保障安全)