![](/img/trans.png)
[英]RSA encryption causing IllegalBlockSizeException in Java
[英]RSA Encryption in Java: IllegalBlockSizeException
我正在尝试在我的 Java 项目中设置 RSA 加密。 我在终端中使用以下命令生成了一个非对称密钥:
keytool -genkey -keyalg RSA -alias mykey -keystore mykey.jks -storepass mykeypass -keypass mykeypass
现在我使用以下方法加载密钥库:
public void loadKeyStore() throws KeyStoreException, CertificateException, IOException,
NoSuchAlgorithmException {
keyStore = KeyStore.getInstance(KEY_TYPE);
char[] storePwdArray = STORE_PASS.toCharArray();
FileInputStream fis = new FileInputStream(KEY_STORE_PATH);
keyStore.load(fis, storePwdArray);
}
现在,我有两种方法,一种用于加密,一种用于解密:
public String encrypt(String data) throws CertificateException, KeyStoreException, IOException, NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
if (keyStore == null) {
loadKeyStore();
}
Certificate cert = keyStore.getCertificate(ALIAS);
Cipher rsa = Cipher.getInstance("RSA/ECB/PKCS1Padding");
rsa.init(Cipher.ENCRYPT_MODE, cert.getPublicKey());
byte[] encryptedBytes = rsa.doFinal(data.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(encryptedBytes);
}
public String decrypt(String encryptedData) throws UnrecoverableKeyException, CertificateException, KeyStoreException, IOException, NoSuchAlgorithmException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, NoSuchPaddingException {
if (keyStore == null) {
loadKeyStore();
}
Cipher rsa = Cipher.getInstance("RSA/ECB/PKCS1Padding");
char[] keyPwdArray = KEY_PASS.toCharArray();
Key key = keyStore.getKey(ALIAS, keyPwdArray);
rsa.init(Cipher.DECRYPT_MODE, key);
byte[] decryptedBytes = rsa.doFinal(encryptedData.getBytes());
return new String(decryptedBytes, StandardCharsets.UTF_8);
}
在主要方法中,我尝试加密和解密字符串并打印它,如下所示:
public static void main(String[] args) throws UnrecoverableKeyException, NoSuchPaddingException, IllegalBlockSizeException, CertificateException, KeyStoreException, IOException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
RSAEncryptionService encryptionService = new RSAEncryptionService();
String secretMessage = "Hello World!";
String encryptedMessage = encryptionService.encrypt(secretMessage);
System.out.println(encryptedMessage);
String decryptedMessage = encryptionService.decrypt(encryptedMessage);
System.out.println(decryptedMessage);
}
The encryption works fine and returns something like that: B61g7zzXDNW9AO/Idc/OBZOCDOJpQTwgchD9uJisEBgxy8HV1XPYZZaLEnxkJHed2sBAQXEIyCDcIAHWk5rxn40tVd4NwlIUya1rB6WNvRFLrrN30G7VjMU6NNUdwJ55n7is2Ylfu0SkwNpy/o4e9LaZyzCyr4lJsTbFEXJQJKqLsOC+ysHYdhzx61Y8UJw6mUhleju7h11OcdDBdGEtAtBcKx9WDt2cgHrdtYUgUkwmEy3vTuuyUwVVpjA4QwUsjXnN+i19FQBZt67sMYIpUT4x4yJ8egqN4mJ2N8aNLwF7m/FS7EZphXdna4KN0srKBbPquB1ER5be6RnoyMFDsg==
但是当涉及到解密时,我得到以下异常:
Exception in thread "main" javax.crypto.IllegalBlockSizeException: Data must not be longer than 256 bytes
at java.base/com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:349)
at java.base/com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:406)
at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2205)
我尝试了什么:
我在 StackOverflow 上的某个地方读到我需要增加密钥的大小。 但是,这也会产生更长的加密字符串,然后异常只是指出“数据不得长于 512/1024/... 字节”。
我尝试使用代码中生成的密钥对,如下所示。 那行得通,但我不知道如何将该 KeyPair 放入我的密钥库。
public void initKeyStore() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, KeyStoreException, IOException, CertificateException {
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
generator.initialize(2048);
KeyPair pair = generator.generateKeyPair();
Cipher encryptCipher = Cipher.getInstance("RSA");
encryptCipher.init(Cipher.ENCRYPT_MODE, pair.getPublic());
byte[] secretMessageBytes = "secretMessage".getBytes(StandardCharsets.UTF_8);
byte[] encryptedMessageBytes = encryptCipher.doFinal(secretMessageBytes);
String encodedMessage = Base64.getEncoder().encodeToString(encryptedMessageBytes);
System.out.println(encodedMessage);
Cipher decryptCipher = Cipher.getInstance("RSA");
decryptCipher.init(Cipher.DECRYPT_MODE, pair.getPrivate());
byte[] decryptedMessageBytes = decryptCipher.doFinal(encryptedMessageBytes);
String decryptedMessage = new String(decryptedMessageBytes, StandardCharsets.UTF_8);
System.out.println(decryptedMessage);
}
原因很简单。 您正在使用 2048 位证书。 它不能加密任何大于 256 字节的数据,因为它需要小于 RSA 模数。
在 RSA 加密中,您通常需要使用信封来支持任意数据大小的加密。 简而言之,这意味着您需要使用随机对称密钥和对称算法(如 AES)加密数据,然后使用 RSA 加密其密钥并将两者发送到另一端。 对方先解密对称密钥,然后用它解密原始数据。 所以它会是这样的:
Encryption side
-----------------
1- Generate random AES key
2- Encrypt data with AES and generated key
3- Encrypt Key with RSA public key
4- Send 2 encrypted data to the other side
Decryption side
-----------------
1- Split received data to encrypted key and encrypted data
1- Decrypt AES Key with RSA private key
2- Decrypt data with AES and decrypted AES key
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.