我正在使用rsa密鑰來加密一個長字符串,我將發送給我的服務器(將使用服務器的公鑰和我的私鑰對其進行加密)但是,拋出一個異常,如javax.crypto.IllegalBlockSizeException: Data must not be longer than 256 bytes
我覺得直到現在我還沒有正確理解rsa的工作(使用內置庫是造成這種情況的原因)。
有人可以解釋爲什麼拋出這個異常。發送長字符串是否完全不可能加密?獲取IllegalBlockSizeException:使用rsa時數據長度不能超過256字節
回答
RSA算法只能加密具有在比特RSA密鑰長度的最大字節長度 與八個減去11填充 字節劃分,即最大字節數=密鑰長度以位/ 8位數據 - 11 。
所以基本上你用8 -11(如果你有填充)分割密鑰長度。例如,如果您有2048位密鑰,則可以加密2048/8 = 256個字節(如果您有填充,則爲 - 11個字節)。因此,要麼使用更大的密鑰,要麼使用對稱密鑰加密數據,並使用rsa加密該密鑰(這是推薦的方法)。
這將要求您:
- 生成對稱密鑰
- 加密與對稱密鑰
- 對數據進行加密與RSA對稱密鑰
- 發送加密密鑰和數據
- 使用rsa解密加密的對稱密鑰
- 使用對稱密鑰解密數據
- done :)
爲什麼會有這樣的限制,只能將數據加密到一定的長度? – Ashwin 2012-04-07 01:17:12
只有在使用'PKCS1Padding'時,'bits/8 - 11'中的密鑰長度纔有效。例如,'NoPadding'限制將是'密鑰長度,位數/ 8'。 – divanov 2013-11-18 21:38:57
PKCS#1v1.5填充和無填充都不安全。使用OAEP填充(將塊大小減少11個字節以上) – CodesInChaos 2014-08-13 10:22:12
您不應該直接在您的機密數據上使用RSA。您應該只使用上的RSA僞隨機或完全隨機的數據,如會話密鑰或消息認證碼。
你已經在256字節的問題 - 這是因爲你可能使用2048位密鑰。密鑰能夠將0
到2^2048 - 1
範圍內的任何整數加密到相同的範圍內,這意味着您的數據必須是256個字節或更小。
如果您打算加密的比這更多,請使用一個RSA加密爲對稱算法的會話密鑰加密,並使用對加密您的數據。
爲什麼會有這樣的限制,只能將數據加密到一定的長度? – Ashwin 2012-04-07 01:17:40
由於RSA是在_finite [ring](http://en.wikipedia.org/wiki/Ring_(mathematics))_上執行的,因此唯一存在的數字是範圍爲[[0,2^2048- 1]',包括在內。任何長度超過2048位的消息都表示超出此範圍的數字,並且必須以兩個數據塊編碼或 - 如果您需要安全性 - 整個消息應在會話密鑰中加密。實際部署的RSA必須防止[多重攻擊](http://en.wikipedia.org/wiki/RSA_(算法)#Attacks_against_plain_RSA),並且從不處理「原始」明文是安全使用RSA的一個重要部分。 – sarnold 2012-04-08 22:50:04
要繼續從上面的John Snow的回答中,我創建了一個簡單的隨機對稱密碼庫,您可以使用它來簡單地使用私鑰加密任何長度的數據。
你可以找到GitHub - random-symmetric-crypto
final RandomSymmetricCipher cipher = new RandomSymmetricCipher();
// Encrypt the data and the random symmetric key.
final CryptoPacket cryptoPacket = cipher.encrypt(inputData, PRIVATE_KEY_BASE64);
// Convert the CryptoPacket into a Base64 String that can be readily reconstituted at the other end.
final CryptoPacketConverter cryptoPacketConverter = new CryptoPacketConverter();
final String base64EncryptedData = cryptoPacketConverter.convert(cryptoPacket);
System.out.println("Base64EncryptedData=" + base64EncryptedData);
// Decrypt the Base64 encoded (and encrypted) String.
final byte[] outputData = cipher.decrypt(base64EncryptedData, PUBLIC_KEY_BASE64);
我無法找到您指定要使用哪種填充模式的位置。您應該明確指定OAEP填充,因爲其他常見填充(如PKCS#1v1.5或根本不填充)是不安全的。 – CodesInChaos 2014-08-13 10:27:09
樂意接受拉請求。你有沒有填充不安全的URL? – William 2014-08-13 12:19:47
Boneh寫了一篇關於[攻擊RSA]的好概述(http://crypto.stanford.edu/~dabo/papers/RSA-survey.pdf)。 Crypto.se也有許多關於RSA的問題(http://crypto.stackexchange.com/search?q=textbook+rsa)。我在代碼的對稱部分找不到MAC。這意味着你很容易受到主動攻擊,比如填充神諭。舊的仍然流行的PKCS#1v1.5填充容易受到主動攻擊(除非你仔細研究弱點*),即Bleichenbacher的攻擊。 – CodesInChaos 2014-08-13 12:34:13
你需要的公鑰
int keyLength = publicKey.getModulus().bitLength()/16;
String[] datas = splitString(data, keyLength - 11);
String mi = ""//the data after encrypted;
for (String s : datas) {
mi += bcd2Str(cipher.doFinal(s.getBytes()));
}
return mi;
public static String bcd2Str(byte[] bytes) {
char temp[] = new char[bytes.length * 2], val;
for (int i = 0; i < bytes.length; i++) {
val = (char) (((bytes[i] & 0xf0) >> 4) & 0x0f);
temp[i * 2] = (char) (val > 9 ? val + 'A' - 10 : val + '0');
val = (char) (bytes[i] & 0x0f);
temp[i * 2 + 1] = (char) (val > 9 ? val + 'A' - 10 : val + '0');
}
return new String(temp);
}
基於@約翰雪回答您的數據拆分圖書館,我做了一個例子
生成對稱密鑰(AES,128位)
01使用AESString plainText = "Please encrypt me urgently..." Cipher aesCipher = Cipher.getInstance("AES"); aesCipher.init(Cipher.ENCRYPT_MODE, secKey); byte[] byteCipherText = aesCipher.doFinal(plainText.getBytes());
加密使用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(byteCipherText);
發送加密的數據(byteCipherText)鍵+加密AES密鑰(encryptedKey)
KeyGenerator generator = KeyGenerator.getInstance("AES"); generator.init(128); // The AES key size in number of bits SecretKey secKey = generator.generateKey();
加密純文本
在客戶端,使用RSA私鑰解密對稱密鑰
cipher.init(Cipher.PRIVATE_KEY, prKey); byte[] decryptedKey = cipher.doFinal(encryptedKey);
解密密使用解密的對稱密鑰
//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);`
- 1. RSA解密錯誤 - IllegalBlockSizeException:數據不得超過128字節
- 2. 通過推送通知發送超過256字節的數據
- 3. DER長度超過4個字節?
- 4. 長度使用AES-256-CBC
- 5. Android 8.0:IllegalBlocksizeException當使用RSA/ECB/OAEPWithSHA-512AndMGF1Padding
- 6. 獲取字符串的字節長度
- 7. 當使用aes/ecb/pkcs5padding解密字節數組時,IllegalBlockSizeException
- 8. 用於啓動進程的環境塊的長度不能超過65535字節
- 9. 如何使數據庫大小超過256字節[鏈接器文件 - MPLAB]
- 10. PE:inputNumber最大長度不能超過13
- 11. 如何在android中通過BLE發送超過256字節的數據?
- 12. Bash:獲取長度爲offset的字節
- 13. Android TTS文字長度超過4k字符不能播放
- 14. 從數據流api中保存數據存儲區中長度超過1500字節的字符串時出錯
- 15. 當讀取小字節長度時使用DataInputStream緩慢讀取性能
- 16. 當返回的數據超過4150個字節時,WaitForSingleObject超時
- 17. Android cropper不能超越256?
- 18. 如何使用RSA加密AES密鑰而不會遇到「javax.crypto.IllegalBlockSizeException:數據不得超過117個字節」
- 19. 當在HANA中插入CLOB時(長度超過7FFFFF),獲取最大字符串長度時出現錯誤
- 20. 要解密的數據超過128字節模數的最大值。 RSA DECRYPTION c#
- 21. 長度爲密鑰長度的數據的簽名RSA
- 22. 如何在IRIX中輸入長度超過256個字符的命令
- 23. NHibernate圖像存儲 - 字節[]值的長度超過配置的長度
- 24. Java - SHA-256散列:無效的AES密鑰長度:64字節
- 25. 在java客戶端獲取負字節數組長度或大量字節數組長度
- 26. 長度捕獲的數據包超過MTU
- 27. 將數字添加到長號碼(長度超過13位數)
- 28. Apache Commons Crypto - 獲取IllegalBlockSizeException
- 29. 如何獲得使用LINQ to Entities的字節數組長度?
- 30. 使用命令行從過濾器獲取數據包字節
只需使用HTTPS和加密將被透明地進行。 – zaph 2016-07-19 04:50:20