Mega Code Archive

 
Categories / Delphi / String
 

Secure Compression for TStringList

Title: Secure Compression for TStringList Question: This was discussed in http://www.delphi3000.com/articles/article_3648.asp but no source code provided. There was also another one at http://www.delphi3000.com/articles/article_2964.asp but you needed the Addaim components for that. Answer: I combined routines from two open source projects to produce a simple way of saving a stringlist to disk in a compressed and very securely encrypted fashion (using the AES algorithm). The two components are LockBox from Turbopower - available at http://sourceforge.net/projects/tplockbox/ and UCL Compression Library API for Borland Delphi from http://www.zeitungsjunge.de/delphi/ucl/index.htm The unit EncCompress is listed below. It defines a simple class TCompEnc which lets you load a text file into the stringlist. To save a plain text string list, first compress it using the UCLCompressStream, then feed this into the lockbox encryption component and save that to disk. Loading the encrypted file back in is just a matter of reversing the process, load the file, decrypt it then decompress it. I've provided a simple test program - just drop a couple of buttons onto a form and hook up the click event to these routines. Make sure that the text for the key is the same in both!! You'll need a test file 'test.txt', and after clicking both buttons you should find that the 'test2.txt' that is output is identical to the original. I appreciate I've done two things which aren't very good- one use an internal member directly (enc.flist) and used a tMemoryStream to save and load files from disk instead of a TFileStream (before anyone points these out!) Note: the AES (Rijndael) is symmetric so the same key encrypts and decrypts. // Sample event handler code procedure TForm1.Button1Click(Sender: TObject); var enc : TCompEnc; list : tstringlist; begin Enc := TCompEnc.Create; list := tstringlist.create; list.LoadFromFile('test.txt'); enc.flist.Text := list.text; enc.KeyText := 'hgjhgkjghkjh654328878'; enc.SaveToFile('test.dat'); enc.free; list.free; end; procedure TForm1.Button2Click(Sender: TObject); var enc : TCompEnc; begin Enc := TCompEnc.Create; Enc.KeyText := 'hgjhgkjghkjh654328878'; Enc.LoadFromfile('test.dat'); Enc.Flist.SaveToFile('test2.txt'); Enc.free; end; // The unit unit EncCompress; interface uses Windows, SysUtils, Classes, diuclstreams,LbCipher, LbClass; type TCompEnc = class FList : TStringList; FKeyText : string; private function GetList: TStringlist; procedure SetKeyText(const Value: string); public Constructor Create; Destructor Destroy;override; procedure LoadFromFile(Filename : string); procedure SaveToFile(Filename : string); property List : TStringlist read GetList; property KeyText : string write SetKeyText; end; implementation uses math; const COMPRESSION_LEVEL = 3; BUFFER_SIZE = $4000; { TCompEnc } constructor TCompEnc.Create; begin inherited; Flist := TStringList.Create; end; destructor TCompEnc.Destroy; begin FList.Free; inherited; end; function TCompEnc.GetList: TStringlist; begin Result := Flist; end; // Step 1 Compress Flist Strings into stream // Compress stream // Save stream to file. procedure TCompEnc.SaveToFile(Filename: string); var Str : TStringStream; CompStream : TMemoryStream; FileStream : TMemoryStream; MyCipher : TLbRijndael; begin MyCipher := TLbRijnDael.Create(nil); MyCipher.GenerateKey( FKeyText ); Str := tStringStream.Create( Flist.Text ); Str.Position := 0; CompStream := TMemoryStream.create; UclCompressStream( Str,CompStream,3,BUFFER_SIZE); Str.Free; CompStream.Position := 0; try // Prepare key... Filestream := tmemoryStream.Create; MyCipher.EncryptStream(CompStream, FileStream); FileStream.Position := 0; FileStream.SaveToFile( Filename ); FileStream.Free; finally CompStream.Free; end; end; // Loads File. // 1st step, decrypt from AES to just Compressed // 2nd step, Decompress into flist procedure TCompEnc.LoadFromFile(Filename: string); var Source, Dest : TMemoryStream; MyCipher : TLbRijnDael; begin // Decryption Source := TMemoryStream.Create; Source.LoadFromFile(Filename); Source.Position := 0; Dest := TMemoryStream.Create; MyCipher := TLbRijnDael.Create(nil); MyCipher.GenerateKey( FKeyText ); try MyCipher.DecryptStream(Source, Dest); MyCipher.Free; Dest.Position := 0; Source.Position := 0; if UclDecompressStream(Dest,Source,BUFFER_SIZE) then begin Flist.Clear; Source.Position := 0; Flist.LoadFromStream( Source ); end; finally Dest.Free; end; Source.Free; end; procedure TCompEnc.SetKeyText(const Value: string); begin FKeyText := Value; end; end.