2014-09-06 91 views
0

我有解密的问题(也许错了加密,太)与RSA在Java中的数据。 我想在字符串一些更多的信息加密的公钥,然后解密此公钥和与它加密的东西(我用的2048 RSA):错误RSA数据爪哇解密:javax.crypto.BadPaddingException:解密错误

加密:

public void saveExportToFile(String fileName, BigInteger mod, BigInteger exp, String info, PublicKey puk) throws IOException { 
    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    ObjectOutputStream oout = new ObjectOutputStream(new BufferedOutputStream(baos)); 
    try { 
     oout.writeObject(mod); 
     oout.writeObject(exp); 
     oout.writeChars(info); 
     oout.close(); 
     baos.close(); 
     Cipher cipher = Cipher.getInstance("RSA"); 
     cipher.init(Cipher.ENCRYPT_MODE, puk); 

     FileOutputStream fos = new FileOutputStream(new File(fileName)); 
     BufferedOutputStream bos = new BufferedOutputStream(fos); 

     byte[] data = baos.toByteArray(); 

     int i = 0; 
     byte[] buffer = new byte[128]; 
     byte[] cipherData = null; 
     while (i < data.length) { 
      if (i+128 >= data.length) { 
       buffer = new byte[data.length - i]; 
       System.arraycopy(data, i, buffer, 0, data.length - i); 
       cipherData = cipher.doFinal(buffer); 
       bos.write(cipherData); 
      } else { 
       System.arraycopy(data, i, buffer, 0, 128); 
       cipherData = cipher.doFinal(buffer); 
       bos.write(cipherData); 
      } 
      i += 128; 
     } 

     bos.close(); 
    } catch (Exception e) { 
     throw new IOException("Unexpected error", e); 
    } 
} 

解密:

public void getDataFromRSA(String sendname, PrivateKey privateKey) { 
    try { 
     BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File(sendname))); 

     Cipher cipher = Cipher.getInstance("RSA"); 
     cipher.init(Cipher.DECRYPT_MODE, privateKey); 

     int length = 0; 
     int allLength = 0; 
     byte[] buffer = new byte[128]; 
     byte[] bufferAC = null; 
     byte[] outData = null; 
     byte[] allData = null; 
     byte[] tmpData = null; 
     while ((length = bis.read(buffer)) != -1) { 
      if (length < 128) { 
       bufferAC = new byte[length]; 
       System.arraycopy(buffer, 0, bufferAC, 0, length); 
       outData = cipher.doFinal(bufferAC); 
      } else { 
       outData = cipher.doFinal(buffer); // HERE IS THE ERROR 
      } 
      allLength += outData.length; 
      tmpData = allData; 
      allData = new byte[allLength]; 
      System.arraycopy(tmpData, 0, allData, 0, tmpData.length); 
      System.arraycopy(outData, 0, allData, tmpData.length, outData.length); 
     } 
    } catch (IOException | NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | ClassNotFoundException | InvalidKeySpecException e) { 
     e.printStackTrace(); 
    } 
} 

编辑 OK,看来我不知道密码,因为我以为多。我只想使用RSA(如果可能的话),因为我不需要多次传输信息(信息大小各不相同)。我已经编辑加密这样的:

int i = 0; 
byte[] buffer = new byte[245]; 
byte[] cipherData = null; 
while (i < data.length) { 
    if (i+245 >= data.length) { 
     buffer = new byte[data.length - i]; 
     System.arraycopy(data, i, buffer, 0, data.length - i); 
    } else { 
     System.arraycopy(data, i, buffer, 0, 245); 
    } 
    cipherData = cipher.update(buffer); 
    bos.write(cipherData); 
    i += 245; 
} 
bos.write(cipher.doFinal()); // HERE IS THE ERROR 
bos.close(); 

现在我得到javax.crypto.IllegalBlockSizeException: Data must not be longer than 245 bytes(缓冲区大小尝试了较低的值)。是否因为数据长度不是块大小的倍数?这可以解决吗?感谢您的回答。

+0

您不应该使用RSA作为分组密码。在你的方案中,攻击者可以简单地将先前的块插入密码中的任何位置,而无需在解密期间发现它。混合加密/解密并不难,你为什么不努力做正确的事情? – 2014-09-06 16:46:41

+0

对于你当前的问题:RSA有填充开销,你应该把最多245个字节和每256个字节解密(11字节开销)。如果必须的话,在带有245字节加密缓冲区和256字节解密*输入*缓冲区的循环中使用doFinal。请注意,这不会解决您的协议,只是您当前的实施。 – 2014-09-06 16:50:07

+0

谢谢,我现在使用混合加密技术现在没有问题 – d3im 2014-09-07 19:26:55

回答

3

首先,你应该用混合加密,即,使用对称密码第一加密数据,然后与一个RSA密钥加密随机秘密 - 同时发送到接收器。

其次,你应该从来没有在一个循环中执行doFinal单条信息。改为使用update和单个doFinal

第三,2048位为256个字节。只要你一直试图解密128个字节而不是256个,你会得到这个异常。通常我使用2048/Byte.SIZE代替它,它使代码更具可读性并避免错误。

+0

你是绝对正确的。谢谢,现在我在Java密码学中学到了一些新东西。我只有一个问题 - 在普通Java中保存了哪些算法(之前我使用过BouncyCastle)?我想要一些通用的东西。现在我使用SHA-512,RSA 2048和AES 128(首先我尝试了与BouncyCastle一起使用的AES/ECB/PKCS5Padding,但它在解密时给了我错误) – d3im 2014-09-07 19:25:54

+0

这是一组奇怪的参数。如果您希望具有一致的安全级别,则应该至少使用RSA的较大密钥大小。请参阅keylength.com。切勿使用ECB。如果可用,请尝试使用GCM。 OAEP对于RSA来说是个好主意。 – 2014-09-07 22:04:30

0

此异常,当您试图将数据与私有密钥加密和公共密钥解密时,你需要扭转这种,或者你必须使用一个密钥来加密和解密数据。这将解决这个例外。