Go使用Rsa加解密

一次使用rsa的经历

最近项目中要提供一个接口供客户端查询信息。逻辑简单主要考虑安全性问题,信息保密要求不高但是要保证是服务端返回的,也就是要防止数据被篡改和替换。

因为只有一个这样的接口,而且申请证书比较麻烦就不考虑https了。客户端的安全性不是很可靠,如果用AES这样的对称加密,密钥放客户端会有较大风险。考虑用rsa加密来达到目的。

初步想法是服务端保存rsa私钥,用来加密数据,客户端保存公钥,解密服务端返回的数据,这样客户端只能解服务端返回的数据,而且是密文传输。想法很简单,实现起来就遇到了问题。Go语言的rsa包提供的解密方法只能使用公钥加密。

函数原型
func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, label []byte) (out []byte, err error)

试验半天还是不知道如何使用私钥加密。Go论坛上有个使用私钥加密的讨论https://groups.google.com/d/msg/golang-nuts/SkOBSsqLsrE/5rLo02hutbwJ,大概的意思是公钥大家都能拿到,用私钥加密的信息并没有起到保密的作用,一般私钥只用来签名。虽然理论上私钥加密是可以的,但在这里只好换一个思路。

在这个场景中,签名可以达到要求,用私钥对关键信息签名,客户端用公钥校验,可以保证接受正确的服务端信息,唯一不太好的是明文传输的,需要引入一个对称加密对消息加密。

要引入对称加密,可以由客户端随机生成key,用这个key对称加密带校验信息的数据,然后用公钥加密key,这样只有服务端能解出key。然后服务端把客户端带上来的校验信息和数据打包,使用这个key进行对称加密再返回,客户端用自己生成的key解密并校验数据。这样一个流程能保证接受正确的服务端信息,同时是密文传输。

公钥是放在客户端的,假如被其他人拿到,破解了查询协议,最多只能查到数据。要伪造数据去欺骗其他客户端,必须同时知道其他客户端生成的key和校验信息,才能用伪造的请求的结果去欺骗这个客户端。若是AES的key泄漏,不但能查到数据,还能构造其他客户端的查询结果。

rsa使用笔记

在跟客户端对接的过程中由于对rsa不是很熟悉,遇到了一些问题。

  1. padding模式
    rsa遵循公钥加密标准(Public Key Cryptography Standards, PKCS),老的是1.x,一般用1.5,新的是2。对应的padding模式有三种:PKCS1V15对应v1.5,OAEP对应v2,Nopadding。Go的rsa库有前面两种,推荐使用OAEP。

  2. hash算法
    Go的rsa库提供hash函数的参数,可以自己设置hash函数,推荐使用sha256。不同hash值的长度会影响OAEP模式下最大消息长度,下面会讲到。加解密的hash函数要设置成一样的,客户端使用的比较旧的openssl使用的sha1,跟我设置的不一样,因为这个调试了很久。对比了一下sha256和md5,md5要快一点。

  3. 消息长度
    每次加解密的消息长度有限制。对于v1.5,最大长度为keyBytes-11keyBytes是私钥字节数,比如2048位的私钥就是256字节。对于v2,最大长度为keyBytes-(hashSize*2+2),根据hash函数不同长度不同,比如sha1计算结果20字节,对于2048位的key最大长度256-(20*2+2)
    如果原文超过了这个一般就分块进行加密。

rsa简介

  1. 选择质数pq,计算n=p*q,欧拉函数φ(n)=(p-1)*(q-1)

  2. 随机选择一个整数e,条件是1< e < φ(n),且eφ(n)互质,计算模反元素d,即(e*d)mod(φ(n))=1

  3. 经过上面两步得到p、q、n、e、d五个数,把n、e作为公钥,n、d作为私钥进行加解密。

    • 加密:消息mm<n,计算(pow(m,e))mod(n)=cc就是m的密文
    • 解密:密文c,计算(pow(c,d)mod(n))=m
    • 对于m>=n,可以分块加密或者使用对称加密m然后公钥加密对称加密密钥

    算法的安全性保证在于很难从ne推断出d,计算d需要知道φ(n),而当n值很大的时候,直接计算φ(n)很困难,分解n得到p、q也很困难。

    rsa原理的介绍推荐阮一峰老师的文章

Go语言rsa简单封装

为了方便使用做了个简单封装,放在Github上。

安装方法
go get github.com/RivenZoo/goutil/dencrypt

打赏
  • 版权声明: 本博客所有文章除特别声明外,均采用 Apache License 2.0 许可协议。转载请注明出处!
  • © 2015-2024 RivenZoo
  • Powered by Hexo Theme Ayer
  • PV: UV:

请我喝杯咖啡吧~

支付宝
微信