前端时间学习了RSA加密解密,但是加密的字节数据长一点就会出现以下异常。
Exception in thread "main" javax.crypto.IllegalBlockSizeException: Data must not be longer than 117 bytes
at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:346)
at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:391)
at javax.crypto.Cipher.doFinal(Cipher.java:2087)
总的来说这是由于这个加密方式所决定的。它跟密钥的强度有关 keyPairGenerator.initialize(1024);
例如我这边密钥强度为1024bit
-->对应字节就是128byte
-->可加密的密文长度最大则是128-11 = 117。
-->所以当我明文字节超过117byte就会提示以上错误。当然小于117byte的话是没有事的。
另外:
加密后的密文长度也是和密钥长度有关的,以(1024来算)
-->密文长度刚好为128byte
基于以上
即可实现长字节分段加密和分段解密,也就不会出现我遇到的异常。
网上的实现例子不少,不过还是自己亲自敲来的更好。
//这边生成密钥和私钥
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(1024);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
//公钥和私钥
RSAPublicKey aPublic = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey aPrivate = (RSAPrivateKey) keyPair.getPrivate();
//加密明文
String ming = "012345678901234567890123456789012345678901234567890123456789" +
"0123456789012345678901234567890123456789012345678901234567890123456789" +
"0123456789012345678901234567890123456789012345678901234567890123456789" +
"0123456789012345678901234567890123456789012345678901234567890123456789";
System.out.println("明文加密字节长度"+ming.getBytes().length);
StringBuffer miwen = new StringBuffer();
//分段加密开始
{
Cipher rsa = Cipher.getInstance("RSA");
rsa.init(Cipher.ENCRYPT_MODE,aPublic);
int offset = 0;
byte[] data = ming.getBytes();
while (offset < data.length){
byte[] bytes = rsa.doFinal(Arrays.copyOfRange(data,offset,Math.min(offset+117,data.length)));
miwen.append(new BASE64Encoder().encode(bytes));
offset += 117;
}
System.out.println("加密后的密文为(BASE64编码)-->");
System.out.println(miwen.toString());
}
//分段解密
{
Cipher rsa = Cipher.getInstance("RSA");
rsa.init(Cipher.DECRYPT_MODE,aPrivate);
//获得密文字节
byte[] data = new BASE64Decoder().decodeBuffer(miwen.toString());
int offset = 0;
StringBuffer getMing = new StringBuffer();
while (offset < data.length){
byte[] bytes = rsa.doFinal(Arrays.copyOfRange(data, offset, Math.min(offset + 128,data.length)));
getMing.append(new String(bytes));
offset += 128;
}
System.out.println("解密后的明文-->");
System.out.println(getMing.toString());
}
以上控制台输出结果
明文加密字节长度270
加密后的密文为(BASE64编码)-->
DkQb2eklfSPTf1YG4w8h/NkWzcbKMruX/zsoeY6VA8Wdvgg7A0IhiKj5aoRLfshdHkAelW23aVPz
awX8TGbz70V9u1QGbXT91/1llTiPdgqSS5nFzYDdzq9D/L9XNVDPXtVvOxSvkhLqpwINaW0X99kY
TcMICRuygCaQ5gdvUKk=JkH1+00yRNl+vAp2gsFubQCTIW5og3jfTBhIHBBO0cItx8XHRDS8KkIORe+PlwaCCnlRJfdZtZzl
mWyQWt1Rzl+R5JKbEi9tBCYhXy5Ztkd4qY+xONnBfrWINbet6Qk7N21ZhJNZXhhhfquqGBtw12tF
3oFT/+SlsQZY0AehpC8=T90DA2eWl0HW6HtnRVNxqZMDOYanMf1oJmdTmPbMlgxP1YZ5PU0Yzafsg5+TD0wt7z2dJ7lM3XQr
sLMI2Z42afYZ1msciX4CpQ0stSnV1orbEMpATBKbeaVPYS90/TKhVEQzWdwEhViUmpDlkzLdhhH/
RJUGmABjd0H9oXcfLtY=
解密后的明文-->
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789