首页 > 其他分享 >rsa加解密的内容超长的问题解决

rsa加解密的内容超长的问题解决

时间:2023-06-08 17:56:31浏览次数:31  
标签:加密 加解密 RSA rsa padding 超长 密钥 对称 长度

一. 现象:      有一段老代码用来加密的,但是在使用key A的时候,抛出了异常: javax.crypto.IllegalBlockSizeException: Data must not be longer than 117 bytes。 老代码已经做了分段的加密,应该是已经考虑了加密长度的问题才对。换了另一个线上代码中的key B,正常加密没有异常。
二. 解决:      老代码如下: private static String  encryptByPublicKey(String plainText , String publicKey)  throws Exception {
  int MAX_ENCRYPT_BLOCK =  128 ;
  byte[] data = plainText.getBytes( "utf-8") ;
  Key e = RSASignature. getPublicKey(publicKey) ;
  //  对数据加密
  Cipher cipher = Cipher. getInstance( "RSA") ;
  cipher.init(Cipher. ENCRYPT_MODE , e) ;
  int inputLen = data. length ;
  ByteArrayOutputStream out =  new ByteArrayOutputStream() ;
  int offSet =  0 ;
  byte[] cache ;
  int i =  0 ;
  //  对数据分段加密
  while (inputLen - offSet >  0) {
    if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
      cache = cipher.doFinal(data , offSet , MAX_ENCRYPT_BLOCK) ;
    }  else {
      cache = cipher.doFinal(data , offSet , inputLen - offSet) ;
    }
    out.write(cache ,  0 , cache. length) ;
    i++ ;
    offSet = i * MAX_ENCRYPT_BLOCK ;
  }
  byte[] encryptedData = out.toByteArray() ;
  out.close() ;
  return Base64. encodeBase64String(encryptedData) ; }      将 MAX_ENCRYPT_BLOCK值换为64就解决了问题。按报错提示的改为117也可以,不过为了凑整,选择了64。
三. 原因:      实际使用RSA加解密算法通常有两种不同的方式,一种是使用对称密钥(比如 AES/ DES等加解密方法)加密数据,然后使用非对称密钥(RSA加解密密钥)加密对称密钥;另一种是直接使用非对称密钥加密数据。第一种方式安全性高,复杂度也高,不存在加密数据长度限制问题,第二种方式安全性差一些,复杂度低,但是存在加密数据限制问题(即使用非对称密钥加密数据时,一次加密的数据长度是(密钥长度/8-11))。      目前双方约定的方式为第二种方式,而对应于本次抛错的密钥,key长度为1024位,1024/8 - 11 = 117,所以一次加密内容不能超过117bytes。另一个密钥没有问题,因为key的长度为2048位, 2048 /8 - 11 = 245, 一次加密内容不能超过 245 bytes。而分段加密代码中用128为单位分段,从而使得一个密钥报错,另一个不报错。
四.扩展:

  1. 为什么一次加密的数据长度为 (密钥长度/8-11) ? 网上有说明文长度小于等于密钥长度(Bytes)-11,这说法本身不太准确,会给人感觉RSA 1024只能加密117字节长度明文。实际上,RSA算法本身要求加密内容也就是明文长度m必须0<m<n,也就是说内容这个大整数不能超过n,否则就出错。那么如果m=0是什么结果?普遍RSA加密器会直接返回全0结果。如果m>n,由于 m e  ≡ c (mod n) ,c为密文,m为明文,e和n组成公钥,显然当m>n时,m与m-n得出的密文一样,无法解密,运算就会出错。 所以,RSA 1024 实际可加密的明文长度最大也是1024bits,但问题就来了:

    如果小于这个长度怎么办?就需要进行padding,因为如果没有padding,用户无法确分解密后内容的真实长度,字符串之类的内容问题还不大,以0作为结束符,但对二进制数据就很难理解,因为不确定后面的0是内容还是内容结束符。

    只要用到padding,那么就要占用实际的明文长度,于是才有117字节的说法。我们一般使用的padding标准有NoPPadding、OAEPPadding、PKCS1Padding等,其中PKCS#1建议的padding就占用了11个字节。

    如果大于这个长度怎么办?很多算法的padding往往是在后边的,但PKCS的padding则是在前面的,此为有意设计,有意的把第一个字节置0以确保m的值小于n。

    这样,128字节(1024bits)-减去11字节正好是117字节,但对于RSA加密来讲,padding也是参与加密的,所以,依然按照1024bits去理解,但实际的明文只有117字节了。

    关于PKCS#1 padding规范可参考:RFC2313 chapter 8.1,我们在把明文送给RSA加密器前,要确认这个值是不是大于n,也就是如果接近n位长,那么需要先padding再分段加密。除非我们是“定长定量自己可控可理解”的加密不需要padding。
  2. 为什么有不同长度的key? 看一下密钥的生成过程: 第一步,随机选择两个不相等的质数p和q。
    第二步,计算p和q的乘积n。n即密钥长度。
    第三步,计算n的欧拉函数φ(n)。
    第四步,随机选择一个整数e,条件是1< e < φ(n),且e与φ(n) 互质。
    第五步,计算e对于φ(n)的模反元素d。
    第六步,将n和e封装成公钥,n和d封装成私钥。 加密(c为密文,m为明文):   m e  ≡ c (mod n) 解密 (c为密文,m为明文) :   c d  ≡ m (mod n) 对极大整数做因数分解(由n,e推出d)的难度决定了RSA算法的可靠性。换言之,对一极大整数做因数分解愈困难,RSA算法愈可靠。假如有人找到一种快速因数分解的算法,那么RSA的可靠性就会极度下降。但找到这样的算法的可能性是非常小的。今天只有短的RSA密钥才可能被暴力破解。只要密钥长度足够长,用RSA加密的信息实际上是不能被解破的。目前一般为1024 bit以上的密钥,推荐2048 bit以上。
  3. 对称加密vs分对称加密? 对称加密是最快速、最简单的一种加密方式,加密(encryption)与解密(decryption)用的是同样的密钥(secret key)。对称加密有很多种算法,由于它效率很高,所以被广泛使用在很多加密协议的核心当中。对称加密通常使用的是相对较小的密钥,一般小于256 bit。因为密钥越大,加密越强,但加密与解密的过程越慢。密钥的大小既要照顾到安全性,也要照顾到效率,是一个trade-off。对称加密的一大缺点是密钥的管理与分配。 非对称加密为数据的加密与解密提供了一个非常安全的方法,它使用了一对密钥,公钥(public key)和私钥(private key)。私钥只能由一方安全保管,不能外泄,而公钥则可以发给任何请求它的人。非对称加密使用这对密钥中的一个进行加密,而解密则需要另一个密钥。虽然非对称加密很安全,但是和对称加密比起来,它非常的慢。 将两者结合起来,将对称加密的密钥使用非对称加密的公钥进行加密,然后发送出去,接收方使用私钥进行解密得到对称加密的密钥,然后双方可以使用对称加密来进行沟通。

五.结论:      优先选择方案:使用对称密钥(比如 AES/ DES等加解密方法)加密数据,然后使用非对称密钥(RSA加解密密钥)加密对称密钥。原问题中由于双方约定了非对称加密的方式,所以用分段加密来解决了问题,但是可以知道这样是比较低效的。

标签:加密,加解密,RSA,rsa,padding,超长,密钥,对称,长度
From: https://www.cnblogs.com/lidabo/p/17467264.html

相关文章

  • 一个RSA的C++封装
    使用RSA的难点:公钥和私钥的保存与加载。在很多的场合下,密钥是以文件的形式分开保存的,对程序员使用者来说,需要解决公钥和私钥的生成、保存、加载问题。加解密过程中的分组问题。RSA加解密的开销很大,比DES和AES高2个数量级,一般情况下不适合用来对较长的数据进行加解密。但是,RSA......
  • RsaUtils
    importorg.apache.commons.codec.binary.Base64;importjavax.crypto.Cipher;importjava.io.ByteArrayOutputStream;importjava.security.*;importjava.security.interfaces.RSAPrivateKey;importjava.security.interfaces.RSAPublicKey;importjava.security.spec......
  • Laravel Api接口数据进行加解密
    Laravel利用中间件处理API接口数据加解密;在某些时候,为了接口数据的安全和保密性,需要对来回的数据进行加密处理。如果是Laravel框架,中间件绝对是个好东西。Laravel中间件包含一个完整的工作流,即请求前中间件(request)和请求后中间件(response)。在我们这次的场景中,刚好很好的用到了......
  • yum源导入KEY值----warning: rpmts_HdrFromFdno: Header V3 RSA/SHA1 Signature, key
    Totalsize:42MDownloadingPackages:warning:rpmts_HdrFromFdno:HeaderV3RSA/SHA1Signature,keyIDc105b9de:NOKEYRetrievingkeyfromfile:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5GPGkeyretrievalfailed:[Errno14]Couldnotopen/readfile:///......
  • RSA之拒绝套路(2)
    前言话不多说,接着前一期RSA之拒绝套路(1) ,继续探讨RSA的相关问题,上一期,我们讨论了,如果泄露了(n,e,dp,c)可以导致密文被解密的危害。这一次,我们探讨如果泄露(dp,dq,q,p,c)会带来什么严重影响?题干dp=904944869732431047562983111757050028871554401210259466642757905486949557996614......
  • Bouncy Castle SM2加解密
    配置过程下载相关包。我参考了连接:https://blog.csdn.net/weixin_42221688/article/details/90475014修改配置文件$JAVA_HOME$\jre\lib\security\java.security,在末尾添加security.provider.11=org.bouncycastle.jce.provider.BouncyCastleProvider;测试:代码运行sm2_demo......
  • RSA密钥证书的生成
    @@rsa密钥生成 首先需要下载OpenSSL软件,一直点击下一步就好,链接:链接:https://pan.baidu.com/s/1uHNpKGF9j9c1bQ6QAwtpOA提取码:myit(百度网盘分享无须官网下载,如若不好使请私信或者评论) 启动位置是在你软件安装的位置下,找到bin目录,然后在上方文件位置直接输入cmd,或者打开dos......
  • LangChain入门(三)-对超长文本进行总结
    GitHub-liaokongVFX/LangChain-Chinese-Getting-Started-Guide:LangChain的中文入门教程LangChain的中文入门教程.ContributetoliaokongVFX/LangChain-Chinese-Getting-Started-GuidedevelopmentbycreatinganaccountonGitHub.https://github.com/liaokongVFX/LangCh......
  • java 实现AES加解密后,与在线工具测试结果不一致
    最近有个项目,因为参数里面带有sql可能是客户网关对参数做了防侵入,用简单的base64加密后居然还是不行,决定用AES加密。代码如下。/***参数加密私钥*/staticfinalStringparamPrivateKey="3dae12897b044f96";声明密钥/***加密*@paramsSrc......
  • 强化学习基础篇[2]:SARSA、Q-learning算法简介、应用举例、优缺点分析
    强化学习基础篇[2]:SARSA、Q-learning算法简介、应用举例、优缺点分析1.SARSASARSA(State-Action-Reward-State-Action)是一个学习马尔可夫决策过程策略的算法,通常应用于机器学习和强化学习学习领域中。它由Rummery和Niranjan在技术论文“ModifiedConnectionistQ-Learning(MCQL)......