服务端加密数据,客户端解密数据,但总是报出错误:e.getMessage()Input length (with padding) not multiple of 16 bytes

时间:2021-03-12 18:30:03
服务端对一些数据进行加密,客户端对数据进行解密
客户端部分程序如下: while(true){
try{
byte[] buf=new byte[256];
in.read(buf);
String str=new String(buf);
ta.append("服务器说:"+str);

try{
                                         /解密
}catch(Exception e){
System.out.println("e.getMessage()"+e.getMessage());
}
ta.append("\n");
}catch(IOException e){}

总是报出错误:e.getMessage()Input length (with padding) not multiple of 16 bytes
想问一下,该怎么弄才能正常?

14 个解决方案

#1


怎么没人回答的呢?到现在也没办法解决
大家帮着看看,好吗

#2


这叫人怎么帮你呢,原码又不贴,谁知道你的解密部分作了什么操作会抛出异常。

#3


while(true){
try{
byte[] buf=new byte[1024];
in.read(buf);
String str=new String(buf);
ta.append("服务器说:"+str);
//解密
try{
AESTool aes = AESTool.getInstance();

//密钥-测试
String sByteKey ="137DBFE262DFEDF83D124F5F5348927C"; 
//设置密钥
aes.setKey(Util.hex2byte(sByteKey));
String plainTxt = aes.toDecrypt(str);
System.out.println("decryptedTxt ="+plainTxt);
ta.append("服务器解密后说:"+plainTxt);
}catch(Exception e){
System.out.println("e.getMessage()"+e.getMessage());
}
ta.append("\n");
}catch(IOException e){}
}

public String toEncrypt(String plainText) throws Exception {
//使用密钥,设置为加密模式
cipher.init(Cipher.ENCRYPT_MODE, key);

byte[] cipherText = cipher.doFinal(plainText.getBytes());
String b64str = new BASE64Encoder().encode(cipherText);
return b64str;
}

/**
 * 解密
 * @param cipherText:密文(含BASE64编码)
 * @return :plainText,明文
 * @throws Exception
 */
public String toDecrypt(String cipherText) throws Exception {
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] bPlainText = cipher.doFinal(new BASE64Decoder().decodeBuffer(cipherText));
String plainText = new String(bPlainText);
return plainText;
}

#4


检查长度

#5


楼主用printStackTrace方法看看哪里抛出了异常

#6


我是发觉长度有问题,那么当长度可能会很长,无法确定时,我该怎么做?代码怎么写?
我写数据端先设定读到的长度,
ta.append("加密后:"+signedTxt_BASE64);
String len=String.valueOf(signedTxt_BASE64.length());
signedTxt_BASE64=len+signedTxt_BASE64;
byte[] buf2=signedTxt_BASE64.getBytes();
out.write(buf2);
我读数据端
byte[] lenthBuffer = new byte[4] ;

byte[] bBuffer = new byte[1024] ;
ByteBuffer buffer ;
int readLenPos =0 ;

int messageLength = 0 ;
try{
while (true)
{
int readLen = in.read(lenthBuffer,readLenPos,lenthBuffer.length - readLenPos);
if (readLen < lenthBuffer.length - readLenPos)
{
readLenPos += readLen ; 
continue ;
}

messageLength = (lenthBuffer[0] & 0xFF) << 24 +  (lenthBuffer[1] & 0xFF) << 16
    + (lenthBuffer[2] & 0xFF) << 8 +  (lenthBuffer[3] & 0xFF);
break ;
}
buffer = ByteBuffer.allocate(messageLength);

while (buffer.hasRemaining())
{
int readlen = in.read(bBuffer,0, Math.min(bBuffer.length, buffer.remaining()));
if (readlen<=0)
{
System.out.println("已经断开");
break ;
}
buffer.put(bBuffer,0,readlen);
}

String str=new String(buffer.array());
ta.append("客户机说:"+str);
但是什么都没读到。为什么呢?

#7


大家帮我看看啊,我验证过传过去的数据在解密前没又缺少和增加任何字节。但还是报出这样的错误。在我原先的不传输的application中就完全正常。想问一下这是为什么。?

#8


String len=String.valueOf(signedTxt_BASE64.length());
signedTxt_BASE64=len+signedTxt_BASE64;
byte[] buf2=signedTxt_BASE64.getBytes();
out.write(buf2);
楼主这样写有问题,传递的不是len不是一个长度而是len的是字符,如果len是32,那接受到的长度的时候就是3332。而且读取长度也只有2个字节并不是4个字节的int。
建议out的时候先out.writeInt(len),或者把len转换为字节数组再发送出去。
至于解码出错可以肯定你接收的内容和你发送的内容不相符。最简单的是把发送的内容和接收的内容都转换为16进制的字符对比一下

#9


len是32,那接受到的长度的时候就是3332。这是为什么?
我将传送的长度送过去,让对方读,然后设置长度,连续读,否则读不完。就出现Input length (with padding) not multiple of 16 bytes。
但是现在过去,都正确,就是会缺头四个字符,为什么?
补上后,还是报出相同错误。愿闻其祥?

#10


因为你out.write的时候是写字符串,并不是写int。写的时候会用getBytes转为字节数组来传送,例如len=32的时候,字符串转为字节数组之后就是{32,33}(3和2的ascii码,长度只有2)。而你接收之后是用messageLength = (lenthBuffer[0] & 0xFF) << 24 +  (lenthBuffer[1] & 0xFF) << 16 + (lenthBuffer[2] & 0xFF) << 8 +  (lenthBuffer[3] & 0xFF);把字节数组转为int,而不是用Integer.parstInt来转换,得到的长度会有问题。你可以试试把字符32用getBytes之后可不可以代入你的转换里转换成int,这里肯定会出错。
再有你客户端读头四个字节并不是length,例如上面说的长度是32,那只有头两个字节是长度,后两个字节就是内容了。
在传递流的时候要注意传递要求是int的时候是不可以直接转换成字符来传递,要把int转为4个字节的byte数组来传递,或者转为DataOuputSteam之后outInt来实现。

#11


还有一个问题就是你(lenthBuffer[0] & 0xFF) << 24 +  (lenthBuffer[1] & 0xFF) << 16 + (lenthBuffer[2] & 0xFF) << 8 +  (lenthBuffer[3] & 0xFF);把一个4个字节的byte数组转为int有问题,我记得好像应该用或
(lenthBuffer[0] & 0xFF) << 24 | (lenthBuffer[1] & 0xFF) << 16 | (lenthBuffer[2] & 0xFF) << 8 | (lenthBuffer[3] & 0xFF);
你可以试试用一个byte数组测试一下,我试过用你那个,总是得到0。你可以把{0x00, 0x00, 0x00, 0x01}代入看看能不能得到1

#12


想问一下RSA在application 中加解密正常,但是在经过socket传递后,总是报出:
too much data for RSA block?
这是为什么?

#13


这个应该是接收到的包和发送的包不相同,把发送的内容和接收的内容对比一下,特别是解析处的加密内容部分

#14


问个题外话, (n & 0xFF) 和 n 有什么区别吗?我怎么感觉是一样的(如果n是java中的byte,或者是c中的unsigned char)

#1


怎么没人回答的呢?到现在也没办法解决
大家帮着看看,好吗

#2


这叫人怎么帮你呢,原码又不贴,谁知道你的解密部分作了什么操作会抛出异常。

#3


while(true){
try{
byte[] buf=new byte[1024];
in.read(buf);
String str=new String(buf);
ta.append("服务器说:"+str);
//解密
try{
AESTool aes = AESTool.getInstance();

//密钥-测试
String sByteKey ="137DBFE262DFEDF83D124F5F5348927C"; 
//设置密钥
aes.setKey(Util.hex2byte(sByteKey));
String plainTxt = aes.toDecrypt(str);
System.out.println("decryptedTxt ="+plainTxt);
ta.append("服务器解密后说:"+plainTxt);
}catch(Exception e){
System.out.println("e.getMessage()"+e.getMessage());
}
ta.append("\n");
}catch(IOException e){}
}

public String toEncrypt(String plainText) throws Exception {
//使用密钥,设置为加密模式
cipher.init(Cipher.ENCRYPT_MODE, key);

byte[] cipherText = cipher.doFinal(plainText.getBytes());
String b64str = new BASE64Encoder().encode(cipherText);
return b64str;
}

/**
 * 解密
 * @param cipherText:密文(含BASE64编码)
 * @return :plainText,明文
 * @throws Exception
 */
public String toDecrypt(String cipherText) throws Exception {
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] bPlainText = cipher.doFinal(new BASE64Decoder().decodeBuffer(cipherText));
String plainText = new String(bPlainText);
return plainText;
}

#4


检查长度

#5


楼主用printStackTrace方法看看哪里抛出了异常

#6


我是发觉长度有问题,那么当长度可能会很长,无法确定时,我该怎么做?代码怎么写?
我写数据端先设定读到的长度,
ta.append("加密后:"+signedTxt_BASE64);
String len=String.valueOf(signedTxt_BASE64.length());
signedTxt_BASE64=len+signedTxt_BASE64;
byte[] buf2=signedTxt_BASE64.getBytes();
out.write(buf2);
我读数据端
byte[] lenthBuffer = new byte[4] ;

byte[] bBuffer = new byte[1024] ;
ByteBuffer buffer ;
int readLenPos =0 ;

int messageLength = 0 ;
try{
while (true)
{
int readLen = in.read(lenthBuffer,readLenPos,lenthBuffer.length - readLenPos);
if (readLen < lenthBuffer.length - readLenPos)
{
readLenPos += readLen ; 
continue ;
}

messageLength = (lenthBuffer[0] & 0xFF) << 24 +  (lenthBuffer[1] & 0xFF) << 16
    + (lenthBuffer[2] & 0xFF) << 8 +  (lenthBuffer[3] & 0xFF);
break ;
}
buffer = ByteBuffer.allocate(messageLength);

while (buffer.hasRemaining())
{
int readlen = in.read(bBuffer,0, Math.min(bBuffer.length, buffer.remaining()));
if (readlen<=0)
{
System.out.println("已经断开");
break ;
}
buffer.put(bBuffer,0,readlen);
}

String str=new String(buffer.array());
ta.append("客户机说:"+str);
但是什么都没读到。为什么呢?

#7


大家帮我看看啊,我验证过传过去的数据在解密前没又缺少和增加任何字节。但还是报出这样的错误。在我原先的不传输的application中就完全正常。想问一下这是为什么。?

#8


String len=String.valueOf(signedTxt_BASE64.length());
signedTxt_BASE64=len+signedTxt_BASE64;
byte[] buf2=signedTxt_BASE64.getBytes();
out.write(buf2);
楼主这样写有问题,传递的不是len不是一个长度而是len的是字符,如果len是32,那接受到的长度的时候就是3332。而且读取长度也只有2个字节并不是4个字节的int。
建议out的时候先out.writeInt(len),或者把len转换为字节数组再发送出去。
至于解码出错可以肯定你接收的内容和你发送的内容不相符。最简单的是把发送的内容和接收的内容都转换为16进制的字符对比一下

#9


len是32,那接受到的长度的时候就是3332。这是为什么?
我将传送的长度送过去,让对方读,然后设置长度,连续读,否则读不完。就出现Input length (with padding) not multiple of 16 bytes。
但是现在过去,都正确,就是会缺头四个字符,为什么?
补上后,还是报出相同错误。愿闻其祥?

#10


因为你out.write的时候是写字符串,并不是写int。写的时候会用getBytes转为字节数组来传送,例如len=32的时候,字符串转为字节数组之后就是{32,33}(3和2的ascii码,长度只有2)。而你接收之后是用messageLength = (lenthBuffer[0] & 0xFF) << 24 +  (lenthBuffer[1] & 0xFF) << 16 + (lenthBuffer[2] & 0xFF) << 8 +  (lenthBuffer[3] & 0xFF);把字节数组转为int,而不是用Integer.parstInt来转换,得到的长度会有问题。你可以试试把字符32用getBytes之后可不可以代入你的转换里转换成int,这里肯定会出错。
再有你客户端读头四个字节并不是length,例如上面说的长度是32,那只有头两个字节是长度,后两个字节就是内容了。
在传递流的时候要注意传递要求是int的时候是不可以直接转换成字符来传递,要把int转为4个字节的byte数组来传递,或者转为DataOuputSteam之后outInt来实现。

#11


还有一个问题就是你(lenthBuffer[0] & 0xFF) << 24 +  (lenthBuffer[1] & 0xFF) << 16 + (lenthBuffer[2] & 0xFF) << 8 +  (lenthBuffer[3] & 0xFF);把一个4个字节的byte数组转为int有问题,我记得好像应该用或
(lenthBuffer[0] & 0xFF) << 24 | (lenthBuffer[1] & 0xFF) << 16 | (lenthBuffer[2] & 0xFF) << 8 | (lenthBuffer[3] & 0xFF);
你可以试试用一个byte数组测试一下,我试过用你那个,总是得到0。你可以把{0x00, 0x00, 0x00, 0x01}代入看看能不能得到1

#12


想问一下RSA在application 中加解密正常,但是在经过socket传递后,总是报出:
too much data for RSA block?
这是为什么?

#13


这个应该是接收到的包和发送的包不相同,把发送的内容和接收的内容对比一下,特别是解析处的加密内容部分

#14


问个题外话, (n & 0xFF) 和 n 有什么区别吗?我怎么感觉是一样的(如果n是java中的byte,或者是c中的unsigned char)