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:
Posta un commento