2012-05-03 22 views
14

Tengo que descifrar un marco en mi servidor. El marco encriptado proviene del dispositivo del cliente a través de GPRS en el socket. La encriptación se realiza con TripleDes y con una clave determinada. Utilizo el mismo algoritmo y clave en el lado del servidor. Frame es una combinación de Hex y Ascii String. Ahora el problema es: cuando relleno mi matriz de bytes con ceros, obtengo la siguiente excepción.javax.crypto.BadPaddingException: Dado que el bloque final no está correctamente ajustado

javax.crypto.BadPaddingException: Given final block not properly padded 

que sigue es mi código:

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); 

Estas son las funciones que estoy usando en el código:

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; 
     } 

El código en C se utiliza para el cifrado en el lado del cliente .

#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; 
} 

Soy nuevo en java Cryptography. ¿Por favor, dime cómo hacerlo? ¿Alguien puede publicar el código que puede funcionar correctamente para descifrar mi fotograma? Gracias por adelantado.

Respuesta

6

(3) DES cifra/descifra bloques de 8 bytes. Como no todos los textos tienen exactamente 8 bytes, el último bloque debe contener bytes que no son originales del texto plano.

El truco consiste en averiguar cuál es el último carácter del texto sin formato. En ocasiones, la longitud del texto sin formato se conoce de antemano; luego, los caracteres del relleno pueden ser cualquier cosa en realidad.

Si no se conoce la longitud del texto sin formato, se debe utilizar un algoritmo de relleno determinista, p. PKCS5Padding. PKCS5Padding siempre realiza el relleno, incluso si el texto sin formato es N * tamaño de bloque en bytes. La razón de esto es simple: de lo contrario, no se sabe si el último byte es texto sin formato o relleno.

Trataré de venir con un código de trabajo más tarde ... tengo que probarlo. Mientras tanto, intenta usar los algoritmos de relleno.

+0

thanks.i he trabajado ya con PKCS5Padding pero no he visto ninguna diferencia en mi caso. – java2485

3

He echado un vistazo a su método stringToHex y parece ser incorrecto. Pruebe este en su lugar:

 StringBuilder rep = new StringBuilder(); 
     for (byte b : base.getBytes) { 
      rep.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1)); 
     } 
     System.out.println(rep); 

También encontré este TripleDes with Padding ejemplo; podrías probar con el algoritmo y la transformación que usa el ejemplo.

4

Si la documentación no indica qué relleno se está utilizando en el texto cifrado entrante, descifre con "NoPadding", que aceptará cualquier tipo de relleno en el último bloque. Luego, eche un vistazo al hexágono de su último bloque. Eso le dirá qué relleno se está utilizando en el extremo de encriptación. Enmiende su código para esperar el tipo correcto de relleno. Los diferentes tipos de relleno están cubiertos here.

10

El principal problema con su código es que está descifrando usando un valor predeterminado de PKCS5Padding. "TripleDES" dará como resultado "TripleDES/ECB/PKCS5Padding" internamente. Esto es como se implementa en el proveedor Sun JCE; la mayoría de los otros proveedores copian este valor predeterminado.

Parece que espera cero relleno, lo que significa que debe usar "DESede/ECB/NoPadding" en su lugar. Después de eso, puede usar una función externa para calcular el tamaño del texto sin formato (eliminar el relleno cero puede eliminar el texto sin formato de valor cero al final si no tiene cuidado).

Otras cuestiones:

  • que tratan de datos PAD antes de descifrado (que debiera datos UNPAD después descifrado)
  • codificación y codificación de caracteres cuestiones, como tratando de almohadilla con el valor del carácter de "0", que probablemente sea incorrecto

He indicado "ECB" porque no sé la verdadera modo utilizado. Puede enmendar su pregunta con el modo correcto y el algoritmo de relleno si puede averiguarlo. Es posible que desee probar el modo CBC si ECB no funciona.

Tenga en cuenta que el modo ECB no es seguro de usar, excepto en circunstancias muy específicas. El uso de CBC con un IV aleatorizado es un requisito mínimo.

+1

muchas gracias. Funcionó. ahora le dije al cliente que envíe un cuadro encriptado con relleno. y utilicé DES/CBC/NoPadding y descifré bien. – java2485

+0

Me alegro de que funcionó, espero haber ayudado a resolver el problema ... –

Cuestiones relacionadas