ClientDatSet.LoadFromFile(DeCryptFile(XMLFile))?

517 Views Asked by At

I have a Delphi 10.4 program with a clientdataset, loading XML files users choose with OpenFile dialog. It works just fine and depending on the contents of the XML, the fielddef structure is set automatically.

Now I want to be able to read Decrypted files and with ClientDataSet.SaveToFile, save Encrypted files.

Currently I'm using Lockbox 3.7 to Decrypt the chosen file, creating a temp file, which is then read by loadfromfile. Likewise Savetofile writes data back to a temp file, which is then encrypted and given it's chosen name. It works very well, but leaves the temp file on disk. And even if I delete the temp file in code, it's relatively easy to recover it, if you know how. So the security with Encryption like this, is not so high after all.

I would want to be able to perform the decryption directly in LoadFromFile (and similar encryption at SaveToFile) as a fileEn(or De)Crypt function, as suggested by the subject, without the use of temp files, but haven't been able to find any useful functions.

Do anybody know of such function ? If so, please point me in the right direction. The last couple of days I've been using google to search for something useful, but it has left me more confused and lost, than I feel I was before.

An alternative solution where the temp files created by the LockBox EnCryptFile (and DeCryptFile) are completely destroyed, to a point where no recovery is possible, would do as a temporary solution, so pointers to ways to destroy a file completely, would also be welcome.

Thanks in advance for any help I can get.

2

There are 2 best solutions below

3
On BEST ANSWER

Use ClientDataSet.LoadFromStream instead of LoadFromFile. I'm sure LockBox has a function to decrypt into a TStream. Use a TMemoryStream to avoid storing decrypted data to disk.

Likewise, write the client dataset to a stream (SaveToStream), use a TMemoryStream and it will stay in memory. Then encrypt it and save the result to disk.

0
On

piette: Thanks for your input. I have accepted your answer.

And after messing around for a little while, I've come up with the following solution. Please do not comment on missing error check (try-Except) or housekeeping (try-Final) as it is only a test. In the final code, all checks will be in place and users be notified in case of errors encountered. I will also change it to a function, returning true or false, depending on success or not.

And just a few words to clarify: On the form I have a TCryptographicLibrary and TCodec from Lockbox 3.7. The Codec ChainMode and Cipher has been chosen by the user before selecting a file to load, and the user also provides a password used as key. The file is selected with OpenDialog. Also on the form is a TClientDataSet, a TDataSource, a TDBGrid and a TDBNavigator.

I messed around for a while getting "Missing Data Provider or Data Packet" at the time of ClientDataSet.LoadFromStream and the reason turned out to be a missing Seek on the stream. Hence the line: XMLSt.Seek(0, soBeginning); just before loading the stream.

This code is working, giving me a filled-in DBGrid, with Fields and Defs and Data according to the XML file selected.

Procedure TForm1.LoadFile(FileName : String; PassWord : string);
var XMLSt : TMemoryStream;
    DecSt : TMemoryStream;
begin
  DecSt := TMemoryStream.Create;
  DecSt.LoadFromFile(FileName);

  XMLSt := TMemoryStream.Create;

  Codec1.Password    := PassWord;
  Codec1.DeCryptStream(XMLSt,DecSt);

  XMLSt.Seek(0, soBeginning);
  ClientDataSet1.LoadFromStream(XMLSt);

  XmlSt.Free;
  DecSt.Free;

  ClientDataSet1.Active  := true;
end;

And reversing the operation, using ClientDataSet.SaveToStream, Codec1.EnCryptStream and TMemoryStream.SaveToStream in stead, will save the ClientDataSet contents as an encrypted XML file.

NB! This test is with a form, allowing the user to select a decrypted XML file, edit the contents and (once the corresponding SaveFile is in place), be able to save the contents again as an encrypted XML file. It is relatively easy to remove the visual components and create them at runtime, allowing this to be a general function, transporting EnCrypted data from an XML file to a ClientDataSet and back.

Again, Thanks for your input !