2012-05-03 5 views
14

Devo decrypt un frame sul mio server. Il frame crittografato proviene dal dispositivo client tramite GPRS sul socket. La crittografia viene eseguita con TripleDes e con una determinata chiave. Uso lo stesso algoritmo e la chiave sul lato server. Frame è una combinazione di Hex e Ascii String. Ora il problema è: quando solco il mio array di byte con zero ottengo la seguente eccezione.javax.crypto.BadPaddingException: Dato blocco finale non adeguatamente riempito

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

seguito è il mio codice:

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

Qui ci sono le funzioni che sto usando all'interno del codice:

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

Questo è il codice in C utilizzato per la crittografia a lato client .

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

Sono nuovo in Java Cryptography. Per favore dimmi come si fa? Qualcuno può pubblicare il codice che può funzionare correttamente per decrittografare il mio frame. Grazie in anticipo.

risposta

6

(3) DES crittografa/decodifica blocchi di 8 byte. Poiché non tutti i testi sono precisamente 8 byte, l'ultimo blocco deve contenere byte che non sono originali del testo normale.

trucco è quello di scoprire quale è l'ultimo carattere del testo in chiaro. A volte la lunghezza del testo normale è nota in anticipo - quindi i caratteri di riempimento possono essere qualsiasi cosa realmente.

Se la lunghezza del testo normale non è nota, è necessario utilizzare un algoritmo di riempimento deterministico, ad es. PKCS5Padding. PKCS5Padding esegue sempre il riempimento, anche se il testo in chiaro è N * Blocksize in byte. La ragione di ciò è semplice: altrimenti non sa se l'ultimo byte è testo o padding.

cercherò di venire con un codice di lavoro più tardi ... deve provarlo. Nel frattempo prova a utilizzare gli algoritmi di riempimento.

+0

grazie. Ho già lavorato con PKCS5Padding ma nessuna differenza ho visto nel mio caso. – java2485

3

Ho dato un'occhiata al tuo metodo stringToHex e sembra non essere corretto. Provate questo invece:

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

Inoltre ho trovato questo TripleDes with Padding esempio; potresti provare con l'algoritmo e la trasformazione che usa l'esempio.

4

Se la documentazione non indica quale padding viene utilizzato sul testo cifrato in arrivo, quindi decodificare con "NoPadding", che accetta qualsiasi tipo di riempimento nell'ultimo blocco. Quindi dai un'occhiata all'esagono del tuo ultimo blocco. Questo ti dirà quale padding viene usato alla fine della crittografia. Modificare il codice per aspettarsi il tipo corretto di padding. I diversi tipi di imbottitura sono coperti here.

10

Il problema principale con il codice è che si sta decifrando utilizzando un valore predefinito di PKCS5Padding. "TripleDES" si tradurrà in "TripleDES/ECB/PKCS5Padding" internamente. Questo è come è implementato nel provider Sun JCE; la maggior parte degli altri provider copia questo valore predefinito.

Sembra che ti aspetti lo zero padding, il che significa che dovresti usare "DESede/ECB/NoPadding". Dopo di che è possibile utilizzare una funzione esterna per calcolare le dimensioni del testo normale (rimuovendo lo zero padding si può rimuovere il testo normale con valore zero alla fine se non si presta attenzione).

Altre questioni:

  • cercano di dati di rilievo prima di decrittazione (si dovrebbe unpad dati dopo decrittazione)
  • codifica e codifica dei caratteri questioni, come ad esempio cercando di pad con il valore del carattere di "0", che è probabilmente errato

Ho indicato "ECB" perché non conosco l'effettivo modalità utilizzata. Se riesci a scoprirlo, potresti modificare la tua domanda con la giusta modalità e l'algoritmo di riempimento. Potresti voler provare anche la modalità CBC se la BCE non funziona.

Si noti che la modalità ECB non è sicura da usare tranne che per circostanze molto specifiche. L'utilizzo di CBC con una IV randomizzata è un requisito minimo.

+1

grazie mille ha funzionato. ora ho detto al ragazzo del cliente di inviare una cornice cifrata con imbottitura. e ho usato DES/CBC/NoPadding e decodificato bene. – java2485

+0

Felice che abbia funzionato, spero di aver contribuito a risolvere il problema ... –