【问题标题】:Understanding encrypting a file, using LockBox 3 and Delphi XE2了解加密文件,使用 LockBox 3 和 Delphi XE2
【发布时间】:2013-02-04 22:26:55
【问题描述】:

因此,我当前的任务涉及获取给定的文本字符串(例如:ABC123)并使用 LockBox3 的 EncryptString(source, target) 函数对其进行加密。我可以成功加密字符串并将输出保存到 .txt 文件中。

此过程的下一步是使用 LockBox3 的 EncryptFile(source, target) 函数获取包含我已经加密的字符串的 .txt 并使用 AES-128 加密所述文件(与字符串加密相同,但密码不同)

基本上,我可以让字符串正确加密并输出到 .txt 文件。然后我请求用户获取 .txt,并将其带入我的程序。然后程序会尝试获取该文件并进一步加密它。当我这样做时,我得到一个要输出的文件。但是当我去解密所述文件时,生成的 .txt 不包含原始文本..或任何与此相关的文本。我基本上对应该如何加密 .txt 文件感到困惑。有什么建议么?如果这个问题/代码不够具体,我深表歉意。请让我知道还有什么,如果我需要澄清一下情况,以便更好地帮助你们了解我正在努力解决的问题!谢谢!

编辑1:

好的,谢谢大家的建议。澄清:

我在解密过程中拥有的流将在以后使用,以便在我解密文件后,我可以从中读取并解密剩余的加密(从第一步开始)字符串。

进一步澄清:

用于加密字符串的编解码器 (Codec1) 使用带有 CBC 的 AES-128,标签为“0”,AsymetricKeySize 为 1024(我很确定这与这种类型的加密无关,正确吗?)我的编解码器用于加密文件(上面的 Codec2)具有相同的设置,但是 Codec1 和 Codec2 的密码不同。基本上,我使用 Codec1 加密字符串并将其写入 .txt,然后使用 Codec2 加密所述文件..最终解密它并使用 Stream 从所述文件中读取并再次使用 Codec1 解密该字符串。

我的文件加密/解密代码:

字符串加密:

procedure TForm1.Button1Click(Sender: TObject);
begin
  codec1.Password := WORD_1;
  //Begin encryption
  sPlainText := Serial_number.Number;         //Store Serial Number of machine 
  codec1.EncryptString(sPlainText,CipherText);   //Encrypt (base64)
  listbox2.Clear;
  listbox2.AddItem(Ciphertext, AnsiCipher);
  end;

将加密字符串写入文件并保存:

saveDialog := TSaveDialog.Create(self);
  saveDialog.Title := 'Choose location to save Authentication Code';
  saveDialog.InitialDir := 'C:\';
  saveDialog.DefaultExt := '';
  saveDialog.FilterIndex := 1;
  saveDialog.Execute();
  glb_fileName1 := saveDialog.FileName;
 //open stream and write cipher to a .txt of chosen location
  try
    Stream := TFileStream.Create(saveDialog.GetNamePath + saveDialog.FileName + '.txt', fmOpenReadWrite);
  except
    Stream := TFileStream.Create(saveDialog.GetNamePath + saveDialog.FileName + '.txt', fmCreate);
  end;
    for k := 1 to (Length(CipherText)) do
        buff[k] := byte(CipherText[k]);
    ptr := @buff[1];
    Stream.WriteBuffer(ptr^, Length(CipherText));
  Stream.Free;
  saveDialog.Free;

获取 .txt 的位置以进行文件加密:

procedure TForm1.Button4Click(Sender: TObject);
var
  fileName : string;
  holder_obj : TSerial_number;
begin
  holder_obj := Tserial_number.Create;
  listbox4.Clear;

if OpenTextFileDialog1.Execute() then
   fileName := OpenTextFileDialog1.FileName;     
   listbox4.AddItem(filename, holder_obj);
end;

文件加密:

  Codec2.Password := WORD_2;
  sCrypt := glb_fileName1 + '_enc.txt';
  Codec2.EncryptFile(glb_fileName1+'.txt', sCrypt);

抓取加密文件进行解密:

procedure TForm1.Button3Click(Sender: TObject);
var
  holder_obj : TSerial_number;
begin
  holder_obj := Tserial_number.Create;
  listbox3.Clear;
if OpenTextFileDialog1.Execute() then
   glb_fileName2 := OpenTextFileDialog1.FileName;
   listbox3.AddItem(glb_filename2, holder_obj);
end;

文件解密(打开一个流从解密文件中读取,以便我可以解密它包含的加密字符串):

procedure TForm1.Button5Click(Sender: TObject);
var
  saveDialog : TSaveDialog;
begin
  saveDialog := TSaveDialog.Create(self);
  saveDialog.Title := 'Choose location to save Decrypted Authentication Code';
  saveDialog.InitialDir := 'C:\';
  saveDialog.DefaultExt := '';
  saveDialog.Execute();
  glb_fileName1:= saveDialog.FileName;
 //open stream and write cipher to a .txt of chosen location
  try
    Stream := TFileStream.Create(saveDialog.GetNamePath + saveDialog.FileName + '.txt', fmOpenReadWrite);
  except
    Stream := TFileStream.Create(saveDialog.GetNamePath + saveDialog.FileName + '.txt', fmCreate);
  end;
  Stream.Free;

  Codec2.Password := WORD_2;
  Codec2.DecryptFile(glb_fileName2, saveDialog.FileName + '.txt');
  saveDialog.Free;
end;

【问题讨论】:

  • 您正在创建或打开流,然后立即释放它。您永远不会使用它从任何地方读取任何内容,因此您可以完全删除整个 try..except..end;StreamFree; 块。除了无缘无故地浪费 CPU 周期和碎片内存之外,它什么也不做。 (您也可以丢弃 Stream 变量声明本身,如果它没有在该块中的任何地方使用。(注释说“打开并将密码写入文本文件,但代码没有这样的事情。)有一堆在解密部分中对您的问题没有意义的代码,可以删除以清楚起见。
  • 如果您描述Codec2 是什么(具体的LockBox 类是什么)也会有所帮助。
  • 您描述了加密文件两次但只解密一次。您需要颠倒加密步骤的顺序来解密它。
  • 我的编解码器 (Codec1) 用于加密字符串(此处未显示)正在使用带有 CBC 的 AES-128,标签为“0”,AsymetricKeySize 为 1024(我很确定与这种类型的加密无关,对吗?)我用于加密文件的编解码器(上面的 Codec2)具有相同的设置,但是 Codec1 和 Codec2 的密码不同。基本上,我使用 Codec1 加密字符串并将其写入 .txt,然后使用 Codec2 加密所述文件..最终解密它并使用 Stream 从所述文件中读取并再次使用 Codec1 解密该字符串。
  • 你确定你得到了正确的文件。在您的解密块 (Button5Click) 中,如果文件不存在,您将创建该文件。甚至没有任何理由在该方法中拥有文件流对象。我也质疑 DecryptFile 调用中参数的顺序。我没有查看库,但我希望它们首先具有输入文件,然后是输出文件。

标签: file encryption delphi-xe2 lockbox-3


【解决方案1】:

您提供的代码很复杂,无法尝试查看问题所在。如果你只是想看看编码/解码是否有效,你应该只需要像下面的代码这样的简单代码。只需将测试文件放在驱动器上并硬编码名称即可。如果 InputFile.txt 和 Un-EncryptedFile.text 相同,这将使您知道编码/解码有效。

一旦你开始工作,你就可以开始建立你的完整例程。您发布的代码确实与在按钮单击之间使用的全局变量以及刚刚命名为 1、2 等的全局变量混淆了。您创建的流什么都不做,只会使问题更加混乱。将事情回归基础并首先使其发挥作用。

procedure TestEncodeDecode();
begin
  Codec2.Password := WORD_2;
  Codec2.EncryptFile('c:\InputFile.txt', 'c:\EncryptedFile.txt');
  Codec2.DecryptFile('c:\EncryptedFile.txt', 'c:\Un-EncryptedFile.txt');
end;

【讨论】:

    【解决方案2】:

    我也对你的问题感到困惑。冒着误解您的问题的风险,我假设您正在尝试:

    1. 加密字符串;
    2. 将加密字符串存储在文件中
    3. 加密文件(双重加密)
    4. 逆向重建原始字符串。

    selftest() 方法证明这是可行的。

    如果此解释正确,请考虑以下解决方案。 (在 Delphi 2010 中测试。未在 XE2 中测试)

    unit uDoubleEncrypt;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, uTPLb_CryptographicLibrary, uTPLb_BaseNonVisualComponent,
      uTPLb_Codec;
    
    type
      TmfmDoubleEncrypt = class(TForm)
        Codec1: TCodec;
        Codec2: TCodec;
        CryptographicLibrary1: TCryptographicLibrary;
        btnGo: TButton;
        memoLog: TMemo;
        dlgSave1: TSaveDialog;
        dlgOpen1: TOpenDialog;
        procedure btnGoClick(Sender: TObject);
    
      private
        FFileName_Plain, FFileName_Cipher: string;
        sSerial: string;
        function  EncryptStringWithCodec1( const sPlaintext: string): ansistring;
        function  GetFileName( dlgOpenX: TOpenDialog; var sFN: string): boolean;
        procedure SaveAnsiStringToFile( const sFN: string; const sSerialCipherText: AnsiString);
        function  ReconstructSerial: string;
    
      public
        procedure Put( const LineFmt: string; const Args: array of const);
        procedure Button1Click;
        procedure Button4Click;
        function  SelfTest: boolean;
      end;
    
    var
      mfmDoubleEncrypt: TmfmDoubleEncrypt;
    
    implementation
    
    {$R *.dfm}
    
    procedure TmfmDoubleEncrypt.btnGoClick( Sender: TObject);
    var
      WORD_1, WORD_2: string;
    begin
    WORD_1 := 'red';
    WORD_2 := 'blue';
    sSerial := '123'; // Serial_number.Number; // Store Serial Number of machine
    Codec1.Password := WORD_1;
    Codec2.Password := WORD_2;
    
    // Run the self test.
    SelfTest;
    
    // Clean up.
    Codec1.Burn;
    Codec2.Burn
    // You may also want to delete temporary files here.
    end;
    
    function TmfmDoubleEncrypt.EncryptStringWithCodec1(
      const sPlaintext: string): ansistring;
    begin
    // Assume Codec1 properties already set-up:
    //  1. Password
    //  2. CryptoLibrary
    //  3. Cipher (at design-time)
    //  4. Chain-mode
    Codec1.Reset; // Normally not necessary. A defence agains the codec being left in a corrupt state.
    Codec1.EncryptString( sPlaintext, result)
    end;
    
    
    function TmfmDoubleEncrypt.GetFileName(
      dlgOpenX: TOpenDialog; var sFN: string): boolean;
    begin
    result := dlgOpenX.Execute;
    if result then
      sFN := dlgOpenX.FileName
    end;
    
    procedure TmfmDoubleEncrypt.Put(
      const LineFmt: string; const Args: array of const);
    begin
    memoLog.Lines.Add( Format( LineFmt, Args))
    end;
    
    procedure TmfmDoubleEncrypt.SaveAnsiStringToFile(
      const sFN: string; const sSerialCipherText: AnsiString);
    const
      Modes: array[boolean] of word = (fmCreate, fmOpenReadWrite);
    var
      SaveStream: TStream;
    begin
    SaveStream := TFileStream.Create( sFN, Modes[ FileExists( sFN)]);
    try
      SaveStream.Size := 0;
      if sSerialCipherText <> '' then
        SaveStream.WriteBuffer( sSerialCipherText[1], Length( sSerialCipherText))
    finally
      SaveStream.Free
      end
    end;
    
    procedure TmfmDoubleEncrypt.Button1Click;
    // This method is equivalent to gEdit101's Button1Click()
    var
      sPlainText: string;
      sSerialCipherText: AnsiString;
      sFN: string;
    begin
    sPlainText := sSerial;
    sSerialCipherText := EncryptStringWithCodec1( sPlainText);
    Put( 'Encrypted serial number is %s', [sSerialCipherText]);
    if GetFileName( dlgOpen1, sFN) then
      begin
      SaveAnsiStringToFile( sFN, sSerialCipherText);
      FFileName_Plain := sFN; // Store for Button4Click()
      Put('encrypted serial number save to file "%s".',[sFN])
      end;
    end;
    
    procedure TmfmDoubleEncrypt.Button4Click;
    // This method is equivalent to gEdit101's Button4Click()
    var
      sPlainText: string;
      sSerialCipherText: AnsiString;
      sFN: string;
    begin
    Codec2.Reset;
    FFileName_Cipher := FFileName_Plain + '_enc.dat'; // Not a text file. + '_enc.txt' would be wrong.
    Codec2.EncryptFile( FFileName_Plain, FFileName_Cipher);
    Put( 'Double Encrypted serial number is now stored in file "%s"', [FFileName_Cipher]);
    end;
    
    
    function TmfmDoubleEncrypt.ReconstructSerial: string;
    var
      CipherStream, PlainStream: TStream;
      sEncryptedSerial: AnsiString;
    begin
    CipherStream := TFileStream.Create( FFileName_Cipher, fmOpenRead);
    PlainStream  := TMemoryStream.Create;
    try
      Codec2.Reset;
      Codec2.DecryptStream( PlainStream, CipherStream);
      PlainStream.Position := 0;
      SetLength( sEncryptedSerial, PlainStream.Size);
      if Length( sEncryptedSerial) > 0 then
        PlainStream.ReadBuffer( sEncryptedSerial[1], Length( sEncryptedSerial));
      Codec1.Reset;
      Codec1.DecryptString( result, sEncryptedSerial)
    finally
      CipherStream.Free;
      PlainStream.Free
      end
    end;
    
    function TmfmDoubleEncrypt.SelfTest: boolean;
    var
      sRecon: string;
    begin
    Put('Commencing self test...',[]);
    try
      Button1Click;  // 1st encryption
      Button4Click;  // 2nd encryption
      sRecon := ReconstructSerial; // Reconstruction
      result := sSerial = sRecon
    finally
      Put('Finished self test. Result = %s',[BoolToStr( result, True)]);
      end;
    end;
    
    end.
    

    这个单位的 dfm 是 ...

    object mfmDoubleEncrypt: TmfmDoubleEncrypt
      Left = 0
      Top = 0
      Caption = 'Double Encrypt'
      ClientHeight = 304
      ClientWidth = 643
      Color = clBtnFace
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clWindowText
      Font.Height = -11
      Font.Name = 'Tahoma'
      Font.Style = []
      OldCreateOrder = False
      DesignSize = (
        643
        304)
      PixelsPerInch = 96
      TextHeight = 13
      object btnGo: TButton
        Left = 8
        Top = 8
        Width = 75
        Height = 25
        Caption = 'Go'
        TabOrder = 0
        OnClick = btnGoClick
      end
      object memoLog: TMemo
        Left = 8
        Top = 39
        Width = 627
        Height = 257
        Anchors = [akLeft, akTop, akRight, akBottom]
        Color = clInfoBk
        ReadOnly = True
        ScrollBars = ssVertical
        TabOrder = 1
      end
      object Codec1: TCodec
        AsymetricKeySizeInBits = 1024
        AdvancedOptions2 = []
        CryptoLibrary = CryptographicLibrary1
        Left = 440
        Top = 112
        StreamCipherId = 'native.StreamToBlock'
        BlockCipherId = 'native.AES-128'
        ChainId = 'native.CBC'
      end
      object Codec2: TCodec
        AsymetricKeySizeInBits = 1024
        AdvancedOptions2 = []
        CryptoLibrary = CryptographicLibrary1
        Left = 536
        Top = 112
        StreamCipherId = 'native.StreamToBlock'
        BlockCipherId = 'native.AES-128'
        ChainId = 'native.CBC'
      end
      object CryptographicLibrary1: TCryptographicLibrary
        Left = 480
        Top = 48
      end
      object dlgSave1: TSaveDialog
        InitialDir = 'C:\Temp'
        Title = 'Choose location to save Authentication Code'
        Left = 440
        Top = 176
      end
      object dlgOpen1: TOpenDialog
        InitialDir = 'C:\'
        Left = 536
        Top = 176
      end
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-22
      • 2013-02-12
      • 1970-01-01
      相关资源
      最近更新 更多