2014-09-06 114 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

此異常,當您試圖將數據與私有密鑰加密和公共密鑰解密時,你需要扭轉這種,或者你必須使用一個密鑰來加密和解密數據。這將解決這個例外。