-2

So my current task involves taking a given string of text (Ex: ABC123) and encrypting it using LockBox3's EncryptString(source, target) function. I can successfully encrypt the string and get the output to save to a .txt file.

The next step in this process is to then use LockBox3's EncryptFile(source, target) function to take the .txt containing my already-encrypted string and encrypting said file using AES-128 (same as the string encryption but with diff password)

Basically, I can get the string to encrypt correctly and output to a .txt file. I then request that the user grab the .txt, and bring it into my program. The program then attempts to take that file and encrypt it further. When I do this, I get a file to output.. however when I go to decrypt said file the resulting .txt does not contain the original text.. or any text for that matter. I am basically confused as to how I should be going about encrypting the .txt file. Any suggestions? I apologize if this question/code is not specific enough. Please let me know what else, if anything I need to make clear about the situation in order to better help you guys understand what I'm struggling with! Thanks!

EDIT1:

Alright everyone, thanks for the suggestions. To clarify:

The stream I have in the decryption process is to be used later, so that after I have decrypted the file, I can read from it and decrypt the remaining encrypted (from the first step) string.

To clarify further:

My codec (Codec1) for encrypting the string is using AES-128 with CBC, with a tag of "0" and an AsymetricKeySize of 1024 (which, Im pretty sure is irrelevant for this type of encryption correct?) My codec for encrypting FILES (Codec2 above) has the same settings, however the passwords for Codec1 and Codec2 are different. Basically, I am using Codec1 to encrypt a string and write it to a .txt, and then I am using Codec2 to encrypt said file.. eventually decrypt it and use the Stream to read from said file and decrypt that string using Codec1 again.

my file encryption/decryption code:

String Encryption:

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;

Write encrypted string to a file and save it:

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;

Grab location of .txt for file encryption:

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;

File Encryption:

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

Grab Encrypted File for decryption:

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;

File Decryption (opening a stream to read from the decrypted file once I have it, so that I can decrypt the encrypted string it contains):

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;
gedit101
  • 3
  • 1
  • 3
  • You're creating or opening the stream and then immediately freeing it. You're never reading anything from anywhere using it, so you can remove that entire `try..except..end;StreamFree;` block completely. It does nothing except waste CPU cycles and fragment memory for no reason. (You can also discard the `Stream` variable declaration itself, if it's not used anywhere but in that block. (The comment says `open and write cipher to a text file, but the code does no such thing.) There's a bunch of code that's meaningless to your question in the decryption part that could be removed for clarity. – Ken White Feb 04 '13 at 22:58
  • It would also help if you described what `Codec2` is (what specific LockBox class). – Ken White Feb 04 '13 at 23:08
  • You describe encrypting the file twice but only decrypting it once. You need to reverse the order of the encrypting steps to decrypt it. – Mark Elder Feb 04 '13 at 23:34
  • My codec (Codec1) for encrypting the string (which is not shown here) is using AES-128 with CBC, with a tag of "0" and an AsymetricKeySize of 1024 (which, Im pretty sure is irrelevant for this type of encryption correct?) My codec for encrypting FILES (Codec2 above) has the same settings, however the passwords for Codec1 and Codec2 are different. Basically, I am using Codec1 to encrypt a string and write it to a .txt, and then I am using Codec2 to encrypt said file.. eventually decrypt it and use the Stream to read from said file and decrypt that string using Codec1 again. – gedit101 Feb 05 '13 at 15:11
  • Are you sure you are getting the right file. In your decrption block (Button5Click) you are creating the file if it does not exist. There is not even any reason to have a file stream object in that method. Also I question the order of the params in the DecryptFile call. I did not look at the library but I would have expected them to have the input file first and the output file second. – Mark Elder Feb 05 '13 at 22:23
  • Mark - The way it is set up now I have glb_fileName2 as the source param, and saveDialog.Filename+'.txt' as the destination. The glb_fileName2 is stored in Button3Click.. and then used in Button5Click. The stream is there to create a new plaintext file in which to store the output of the file decryption. I guess this leaves me wondering if I am thinking about file decryption all wrong. Where should the destination for the decryption result be, exactly? – gedit101 Feb 05 '13 at 22:56
  • Your last step (File Decryption) is really confusing and I don't understand what you are attempting to do. YOur caption `File Decryption (opening a stream to read from the decrypted file once I have it, so that I can decrypt the encrypted string it contains)` is self-contradictory. There is no decrypted file at this point. In the previous step you encrypted, not decrypted. – Sean B. Durkin Feb 05 '13 at 23:39
  • Perhaps you are trying to do this: (1) Encrypt string with Codec1 and store in file; (2) Encrypt fiel with Codec2 and store in another file; (3) Reverse step 2; (4) Reverse step 1 to recreate the original string? Is this what you are trying to do? – Sean B. Durkin Feb 05 '13 at 23:45
  • I'm really confused. 24 hours ago I asked you to remove the unnecessary code, and to provide the specific classname that was being used as `Codec2`, and instead of doing either of those you added 100+ lines of *more unnecessary code*, still didn't provide the specific classname you were using, and added dozens of lines of text that really don't say anything more than what you originally asked. So, asking again: Can you please remove all of the extraneous meaningless text and code from your question, and provide the **specific class** you're trying to use from LockBox3? Thanks. – Ken White Feb 06 '13 at 00:03

2 Answers2

2

The code you provided is way to complicated to try and see what is going wrong. If you are just trying to see if the encoding/decoding works you should only need simple code like the code below. Just put a test file on your drive and hardcode the names. That will let you know that the encoding/decoding works if the InputFile.txt and Un-EncryptedFile.text are the same.

Once you have the working then you can start to build up your full routines. The code you have posted is really confusing with the globals being used between the button clicks and just named 1, 2, etc. You have streams created that do nothing and only confuse the issue more. Strip things back to the basics and get that working first.

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;
Mark Elder
  • 3,987
  • 1
  • 31
  • 47
2

I too am confused about what your question is asking. At the risk of misinterpreting your question, I have assumed that you are trying:

  1. Encrypt a string;
  2. Store the encrypted string in a file
  3. Encrypt the file (double encryption)
  4. Reverse the previous steps to reconstruct the original string.

The selftest() method proves that this works.

If this interpretation is correct, please consider something like the following solution. (Tested in Delphi 2010. Not test in 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.

The dfm for this unit is ...

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
Sean B. Durkin
  • 12,659
  • 1
  • 36
  • 65