Willino Blog

Sono un ingegnere informatico, appassionato di fotografia, chitarra acustica, micologia e Tennis Tavolo. In questo blog cercherò di raccontare eventi ed esperienze che in qualche modo potrebbero risultare utili a tutti.

giovedì 8 ottobre 2009

TripleDES bug in LockBox

Da qualche tempo mi sono imbattuto con un seccante problema di incongruenza di risultati legati alla crittografia di un flusso di byte tramite le funzioni TripleDes di LockBox per Delphi.
In seguito ad alcune analisi del codice sorgente della suite Lockbox, ho scoperto l'arcano.
Quando vengono criptati solamente 8 byte, le funzioni di crittografia aggiungono erroneamente altri 8 byte vuoti in coda al flusso da criptare; esattamente come se stessimo criptando un flusso di byte NON multiplo di 8 byte.
L'errore di fondo, nel codice, consiste nell'aggiungere un blocco di 8 byte senza verificare se il flusso sia già multiplo di 8 byte.

Di seguito la riga di codice principale responsabile dell'errore nella funzione TripleDESEncryptStream della unit LbProc di LockBox.
• Esempio SQL/WSQL
  1.  If Encrypt Then
2. Inc(BlockCount);
Codice incriminato


Ho risolto il problema riscrivendo la funzione in toto (considerato il fatto che non mi piace come è stata concepita).
L'unica vera differenza nella funzione scritta da me è legata al fatto che la utilizzo esclusivamente con SmartCard e, pertanto, trovo comodo che i parametri siano di tipo Array di Byte, piuttosto che Stream.

Ecco di seguito il codice sorgente.
• Esempio SQL/WSQL
  1.Procedure TripleDes(const Source: Array Of Byte; 
2. const Key: TKey128;
3. var Dest: TAnyArray;
4. Encrypt: Boolean);
5.
6. Function CheckBlockSize(fBlock : TDESBlock) : Byte;
7. Var
8. Last : Byte;
9. Begin
10. Last:=1;
11. While (Last<=SizeOf(fBlock)) And (fBlock[Last-1]<>0) Do
12. Inc(Last);
13. Result:=Last-1;
14. End;
15.
16.Var
17. I : LongInt;
18. Block : TDESBlock;
19. Context : TTripleDESContext;
20. BlockMod,
21. BlockCount : LongInt;
22.
23. InStream : TMemoryStream;
24. OutStream : TMemoryStream;
25.Begin
26. InStream := TMemoryStream.Create;
27. OutStream := TMemoryStream.Create;
28. Try
29. InStream.Write(Source[0], Length(Source));
30. InStream.Position := 0;
31.
32. InitEncryptTripleDES(Key, Context, Encrypt);
33.
34. BlockMod:=(InStream.Size Mod SizeOf(Block));
35. BlockCount := (InStream.Size Div SizeOf(Block));
36.
37. For I := 1 To BlockCount Do
38. Begin
39. InStream.Read(Block, SizeOf(Block));
40. EncryptTripleDES(Context, Block);
41. // scrittura ultimo blocco in decrypt
42. If Not Encrypt And (I=BlockCount) Then
43. OutStream.Write(Block, CheckBlockSize(Block))
44. Else
45. OutStream.Write(Block, SizeOf(Block));
46. End;
47.
48. // scrittura ultimo blocco in encrypt
49. If Encrypt And (BlockMod<>0) Then
50. Begin
51. FillChar(Block,SizeOf(Block),0);
52. InStream.Read(Block, BlockMod);
53. EncryptTripleDES(Context, Block);
54. OutStream.Write(Block, SizeOf(Block));
55. End;
56.
57. OutStream.Position := 0;
58. SetLength(Dest, OutStream.Size);
59. OutStream.Read(Dest[0], OutStream.Size);
60. Finally
61. InStream.Free;
62. OutStream.Free;
63. End;
64.End;
Soluzione


E' possibile estrarre la funzione dalle Unit LockBox e scriverla in una propria aggiungendo alla lista delle uses le seguenti:
• Esempio SQL/WSQL
  1.Uses
2. LbCipher,
3. lbProc,
4. LbString;
Unit da aggiungere

Nessun commento:

ANSA.it - Top News