我必须在服务器上解密帧。加密的帧通过套接字上的GPRS通过客户端设备来自加密。加密使用 TripleDes 和给定的 key 完成。我在服务器端使用相同的算法和 key 。框架是十六进制和Ascii字符串的组合。现在的问题是:当我用零填充字节数组时,出现以下异常。
javax.crypto.BadPaddingException: Given final block not properly padded
以下是我的代码:
byte[] key = new byte[]{31, 30, 31, 36, 32, 11, 11, 11, 22, 26,
30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30};
myKeySpec = new DESedeKeySpec(key);
mySecretKeyFactory = SecretKeyFactory.getInstance("TripleDES");
de = mySecretKeyFactory.generateSecret(myKeySpec);
Cipher c = Cipher.getInstance("TripleDES");
c.init(Cipher.DECRYPT_MODE, key);
int l = completeHexStr.length();
if (l%8==1){
completeHexStr = completeHexStr + "0000000";
}else if (l%8==7){
completeHexStr = completeHexStr + "0";
}
byte decordedValue[] =completeHexString.getBytes();
byte[] decValue = c.doFinal(decordedValue);
String decryptedValue = new String(decValue);
System.out.println("decryptedValue= " + decryptedValue);
这是我在代码内部使用的功能:
public String stringToHex(String base) {
StringBuffer buffer = new StringBuffer();
int intValue = 0;
for (int x = 0; x < base.length(); x++) {
intValue = base.charAt(x);
String hex = Integer.toHexString(intValue);
if (hex.length() == 1) {
buffer.append("0" + hex + "");
} else {
buffer.append(hex + "");
}
}
return buffer.toString();
}
public String byteToAscii(byte[] b, int length) {
String returnString = "";
for (int i = 0; i < length; i++) {
returnString += (char) (b[i] & 0xff);
}
return returnString;
}
这是c中用于客户端加密的代码。
#include <svc_sec.h>
const unsigned char fixed_key[] = { 0x31, 0x30, 0x31, 0x36, 0x32, 0x11, 0x11, 0x11, 0x22, 0x26, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30};
int Comm_Encrypt_Data(unsigned char *Test_Input_Data, int Len_Input_Data)
{
int Count_Input_Data, Counter_Input_Data;
unsigned long Timer_1;
unsigned char Init_Vector[8];
int Counter_Init_Vector, Temp_Byte_Count;
unsigned char *Temp_Dst_Ptr, *Temp_Src_Ptr;
unsigned char Temp_Input_Frame[9], Temp_Output_Frame[9];
unsigned char Test_Output_Data[500];
unsigned char Test_Key_Arr[9];
memset(&Init_Vector[0], '\0', sizeof(Init_Vector));
memset(Test_Key_Arr, '0', sizeof(Test_Key_Arr));
memcpy(Test_Key_Arr, &fixed_key[0], 8);
Test_Key_Arr[sizeof(Test_Key_Arr)-1] = '\0';
Display_Data("KEY: ", Test_Key_Arr, sizeof(Test_Key_Arr)-1);
memset(Test_Output_Data, '\0', sizeof(Test_Output_Data));
memcpy(Test_Output_Data, Test_Input_Data, 48);
Count_Input_Data = Len_Input_Data -48 -3; //minus Data before payload, 3 bytes of '|' and CRC
Counter_Input_Data = 0;
while(Counter_Input_Data < Count_Input_Data)
{
Temp_Byte_Count = Count_Input_Data- Counter_Input_Data;
if(Temp_Byte_Count > 8)
Temp_Byte_Count = 8;
memcpy(Temp_Input_Frame, &Test_Input_Data[48+Counter_Input_Data], Temp_Byte_Count);
//succeeding bytes to be 0
if(Temp_Byte_Count < 8)
{
memset(&Temp_Input_Frame[Temp_Byte_Count], '0', (8-Temp_Byte_Count));
}
Display_Data("InPut Data Before Init",Temp_Input_Frame, Temp_Byte_Count);
//============Initialize the data
Temp_Dst_Ptr = (unsigned char *)Temp_Input_Frame;
Temp_Src_Ptr = (unsigned char *)&Init_Vector[0];
for(Counter_Init_Vector =0;Counter_Init_Vector < 8; Counter_Init_Vector++)
*Temp_Dst_Ptr++ ^= *Temp_Src_Ptr++;
//============Initializing data ends
DES(DESE, (unsigned char *)&Test_Key_Arr[0],
(unsigned char *)&Temp_Input_Frame[0], (unsigned char *)&Temp_Output_Frame[0]);
//DES(TDES3KE, (unsigned char *)&Test_Key_Arr[0],
// (unsigned char *)&Temp_Input_Frame[0], (unsigned char *)&Temp_Output_Frame[0]);
Display_Data("AFTER DES::::", Temp_Output_Frame, Temp_Byte_Count);
memcpy(&Test_Output_Data[48+Counter_Input_Data], Temp_Output_Frame, Temp_Byte_Count);
Counter_Input_Data += Temp_Byte_Count;
if(Counter_Input_Data < Count_Input_Data)
{
memcpy(Init_Vector, Temp_Output_Frame, 8);
}
}
{
memset(Test_Input_Data, '\0', Len_Input_Data);
memcpy(&Test_Input_Data[0], &Test_Output_Data[48], Counter_Input_Data); //1 Separator + 2 CRCs
}
Display_Data("Final Output Frame", Test_Input_Data, Counter_Input_Data);
return Counter_Input_Data;
}
我是java
Cryptography
的新手。请告诉我该怎么做?任何人都可以发布可以正常解密我的框架的代码。提前致谢。 最佳答案
代码的主要问题是您使用默认的PKCS5Padding进行解密。 "TripleDES"
将在内部产生"TripleDES/ECB/PKCS5Padding"
。这与Sun JCE提供程序中实现的一样。其他大多数提供程序都复制此默认设置。
看来您期望的是零填充,这意味着您应该改用"DESede/ECB/NoPadding"
。之后,您可以使用外部函数来计算纯文本的大小(如果不小心,删除零填充可能会在最后删除零值的纯文本)。
其他问题:
"0"
的字符值,这可能是错误的我已指示
"ECB"
,因为我不知道所使用的实际模式。如果可以找出答案,可以使用正确的模式和填充算法来修改您的问题。如果ECB不起作用,您可能还想尝试CBC模式。请注意,除非常特殊的情况外,ECB模式不安全使用。将CBC与随机IV一起使用是最低要求。