1

我有一个带有客户端数据集的 Delphi 10.4 程序,加载用户使用 OpenFile 对话框选择的 XML 文件。它工作得很好,并且根据 XML 的内容,fielddef 结构会自动设置。

现在我希望能够读取解密文件并使用 ClientDataSet.SaveToFile 保存加密文件。

目前我正在使用 Lockbox 3.7 解密所选文件,创建一个临时文件,然后由 loadfromfile 读取。同样,Savetofile 将数据写回临时文件,然后对其进行加密并为其指定名称。它工作得很好,但将临时文件留在磁盘上。即使我在代码中删除了临时文件,如果你知道如何恢复它也相对容易。所以像这样加密的安全性毕竟不是那么高。

正如主题所建议的那样,我希望能够直接在 LoadFromFile 中(以及 SaveToFile 中的类似加密)作为 fileEn(或 De)Crypt 函数执行解密,而不使用临时文件,但无法找到任何有用的功能。

有人知道这样的功能吗?如果是这样,请指出我正确的方向。最近几天我一直在使用谷歌搜索有用的东西,但它让我比以前更加困惑和迷失。

由 LockBox EnCryptFile(和 DeCryptFile)创建的临时文件被完全破坏到无法恢复的程度的替代解决方案将作为临时解决方案,因此也欢迎提供完全破坏文件的方法的指针.

提前感谢我能得到的任何帮助。

4

2 回答 2

1

使用ClientDataSet.LoadFromStream而不是LoadFromFile. 我确定 LockBox 具有解密成 TStream 的功能。使用 aTMemoryStream避免将解密的数据存储到磁盘。

同样,将客户端数据集写入流 ( SaveToStream),使用 a TMemoryStream,它将保留在内存中。然后对其进行加密并将结果保存到磁盘。

于 2020-12-10T14:17:53.443 回答
1

皮耶特:感谢您的意见。我已经接受了你的回答。

在搞砸了一段时间后,我想出了以下解决方案。请不要评论缺少错误检查(try-Except)或内务处理(try-Final),因为它只是一个测试。在最终代码中,所有检查都将到位,并在遇到错误时通知用户。我也会把它改成一个函数,返回真假,取决于成功与否。

只需要澄清几句话:在表单上,​​我有一个来自 Lockbox 3.7 的 TCryptographicLibrary 和 TCodec。Codec ChainMode 和 Cipher 已由用户在选择要加载的文件之前选择,并且用户还提供了用作密钥的密码。使用 OpenDialog 选择文件。表格上还有一个 TClientDataSet、一个 TDataSource、一个 TDBGrid 和一个 TDBNavigator。

在 ClientDataSet.LoadFromStream 时,我搞砸了一段时间,得到“缺少数据提供程序或数据包”,原因是流中缺少 Seek。因此这一行: XMLSt.Seek(0, soBeginning); 就在加载流之前。

这段代码正在工作,给我一个填充的 DBGrid,根据选择的 XML 文件,带有字段和定义以及数据。

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;

反之,使用 ClientDataSet.SaveToStream、Codec1.EnCryptStream 和 TMemoryStream.SaveToStream 将 ClientDataSet 内容保存为加密的 XML 文件。

注意!该测试使用一个表单,允许用户选择一个解密的 XML 文件,编辑内容,并且(一旦相应的 SaveFile 到位),能够再次将内容保存为加密的 XML 文件。移除可视组件并在运行时创建它们相对容易,允许这是一个通用功能,将加密数据从 XML 文件传输到 ClientDataSet 并返回。

再次感谢您的意见!

于 2020-12-11T10:18:45.807 回答