获取IllegalBlockSizeException:使用rsa时,数据不得超过256个字节

Ash*_*win 41 java encryption rsa

我使用rsa密钥加密一个长字符串,我将发送到我的服务器(将使用服务器的公钥和我的私钥加密它)但它抛出一个异常,就像javax.crypto.IllegalBlockSizeException: Data must not be longer than 256 bytes 我觉得我还没有理解rsa的工作到现在为止(使用内置库是导致此问题的原因).
有人可以解释为什么抛出这个异常.是不是可以发送长字符串加密?

Joh*_*now 66

RSA算法只能加密具有RSA密钥长度的最大字节长度的数据,其中比特除以8减去11个填充字节,即最大字节数=密钥长度(位/ 8-11).

所以基本上你将密钥长度除以8 -11(如果你有填充).例如,如果你有一个2048位密钥,你可以加密2048/8 = 256字节(如果你有填充,则为11字节).因此,要么使用更大的密钥,要么使用对称密钥加密数据,并使用rsa加密该密钥(这是推荐的方法).

这将要求你:

  1. 生成对称密钥
  2. 使用对称密钥加密数据
  3. 使用rsa加密对称密钥
  4. 发送加密密钥和数据
  5. 用rsa解密加密的对称密钥
  6. 使用对称密钥解密数据
  7. 完了:)

  • PKCS#1v1.5填充和无填充都是不安全的.使用OAEP填充(将块大小减少超过11个字节) (4认同)
  • 限制`密钥长度(位/ 8 - 11`)仅在使用"PKCS1Padding"时有效.例如,使用`NoPadding`限制将是`密钥长度(位/ 8). (2认同)
  • 优秀。这个答案帮助我加密了大量数据。[示例](/sf/answers/3277990131/) (2认同)

Wal*_*eed 31

根据@John Snow的回答,我做了一个例子

  1. 生成对称密钥(128位AES)

    KeyGenerator generator = KeyGenerator.getInstance("AES");
    generator.init(128); // The AES key size in number of bits
    SecretKey secKey = generator.generateKey();
    
    Run Code Online (Sandbox Code Playgroud)
  2. 使用AES加密纯文本

    String plainText = "Please encrypt me urgently..."
    Cipher aesCipher = Cipher.getInstance("AES");
    aesCipher.init(Cipher.ENCRYPT_MODE, secKey);
    byte[] byteCipherText = aesCipher.doFinal(plainText.getBytes());
    
    Run Code Online (Sandbox Code Playgroud)
  3. 使用RSA公钥加密密钥

    KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
    kpg.initialize(2048);
    KeyPair keyPair = kpg.generateKeyPair();
    
    PublicKey puKey = keyPair.getPublic();
    PrivateKey prKey = keyPair.getPrivate();
    
    Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
    cipher.init(Cipher.PUBLIC_KEY, puKey);
    byte[] encryptedKey = cipher.doFinal(secKey.getEncoded()/*Seceret Key From Step 1*/);
    
    Run Code Online (Sandbox Code Playgroud)
  4. 发送加密数据(byteCipherText)+加密AES密钥(encryptedKey)

  5. 在客户端,使用RSA私钥解密对称密钥

    cipher.init(Cipher.PRIVATE_KEY, prKey);
    byte[] decryptedKey = cipher.doFinal(encryptedKey);
    
    Run Code Online (Sandbox Code Playgroud)
  6. 使用解密的对称密钥解密密码

    //Convert bytes to AES SecertKey
    SecretKey originalKey = new SecretKeySpec(decryptedKey , 0, decryptedKey .length, "AES");
    Cipher aesCipher = Cipher.getInstance("AES");
    aesCipher.init(Cipher.DECRYPT_MODE, originalKey);
    byte[] bytePlainText = aesCipher.doFinal(byteCipherText);
    String plainText = new String(bytePlainText);`
    
    Run Code Online (Sandbox Code Playgroud)

  • 在第3步中有错误吗?我没有看到"secKey"被加密intead Cipher初始化,因为RSA正在加密加密数据. (3认同)

sar*_*old 11

您不应直接在您的秘密数据上使用RSA.您应该只在伪随机完全随机数据上使用RSA ,例如会话密钥或消息验证代码.

你得到了256字节的问题 - 这是因为你可能正在使用2048位密钥.键是能够任意整数的范围内进行加密0,以2^2048 - 1在同一范围内,这意味着你的数据必须是256个字节或更小.

如果您打算加密更多,请使用一个RSA加密来加密对称算法的会话密钥,并使用来加密您的数据.

  • 因为RSA是在_finite [ring](http://en.wikipedia.org/wiki/Ring_(数学))_上执行的,所以唯一存在的数字是`[0,2 ^ 2048-1]范围内的整数]`,包容性.任何超过2048位的消息都表示超出此范围的数字,并且必须以两个块进行编码,或者 - 如果您需要安全性 - 整个消息应在会话密钥中加密.真实部署的RSA必须防止[多次攻击](http://en.wikipedia.org/wiki/RSA_(算法)#Attacks_against_plain_RSA),从不处理"原始"明文是安全使用RSA的一个重要部分. (4认同)