Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2015-03

Saving and reading TBlowfish crypted text

6 messages · 3 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Antonio Sanguigni

Hi all,

I need to encrypt TMemo.Lines and to write it to a file. Then, of course, I need the contrary operation I mean reading encrypted text on file, decrypt it to put into TMemo.Lines.

Reading the Net I found lots of example code.

Now, I'm able to to crypt and decrypt from stream, I'm able to write and read TMemo plain text on a text file. My real difficult is to read from crypted (I hope it is right) file to decrypt into a TMemo. I got a TReadError on de.ReadAnsiString.

Here is my example code (please, nevermind about memory lacks and dirty code, it is just a test).

Thanks in advance for any help.

Antonio

//------------ Crypt and write -----------
procedure TForm1.Button1Click(Sender: TObject);
var fs: TFileStream;
  tfOut: TextFile;
begin
  fs := TFileStream.Create('textfile.txt', fmCreate);
  fs.Seek(0,soBeginning);
  { 1 }
   key := 'testkey';
   { 2 }
   s1 := TStringStream.Create('');
   en := TBlowFishEncryptStream.Create(key,s1);
   { 3 }
   en.WriteAnsiString(Memo1.Lines.Text);
   fs.WriteBuffer(Pointer(s1.DataString)^, length(s1.DataString));
   en.Free;
  fs.Free;
end;
//----------------Read and decrypt ------------------
procedure TForm1.Button2Click(Sender: TObject);
var
tr : string;
fs : TFileStream;
tfOut: TextFile;
Begin
   Fs := TFileStream.Create('textfile.txt', fmOpenRead or fmShareDenyNone);
   SetLength(tr, Fs.Size);
   Fs.ReadBuffer(tr[1], Fs.Size);
   key := 'testkey';
   s2 := TStringStream.Create(tr);
//   s1.Free;
   de := TBlowFishDeCryptStream.Create(key,s2);
  { 6 }
  temp := de.ReadAnsiString; // TEReadError exception
  WriteLn('decrypted: ' + temp);
  Memo1.Lines.Text := temp;
  de.Free;
  s2.Free;
end;
Antonio Sanguigni alias slapshot ---------------------------------------------------------------------- Servizi informatici Windows e GNU/Linux- http://www.pieroni.biz GioveLUG (Linux User Group) - http://www.giovelug.org
Graeme Geldenhuys
to Antonio Sanguigni
Antonio Sanguigni wrote
en.WriteAnsiString(Memo1.Lines.Text); fs.WriteBuffer(Pointer(s1.DataString)^, length(s1.DataString)); en.Free;

Maybe you decryption isn't working because the encrypted text you created isn't complete.

Normally you need to call Flush to write the remaining bytes before you free the TBlowFishEncryptStream instance.

I normally use the Read() and Write() methods too. I've never used Blowfish WriteAnsiString() before.

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/
Antonio Sanguigni
to Graeme Geldenhuys

2015-03-17 10:50 GMT+01:00 Graeme Geldenhuys :

Show quoted text 5 lines
Maybe you decryption isn't working because the encrypted text you created isn't complete. Normally you need to call Flush to write the remaining bytes before you free the TBlowFishEncryptStream instance.

That was the trick, Graeme. Thank you so much !!

Antonio

Antonio Sanguigni alias slapshot ---------------------------------------------------------------------- Servizi informatici Windows e GNU/Linux- http://www.pieroni.biz GioveLUG (Linux User Group) - http://www.giovelug.org
Ewald
to Graeme Geldenhuys: Maybe you decryption isn't working because the encrypted text you created isn't complete.…
Graeme Geldenhuys wrote 10 lines
On 2015-03-16 20:05, Antonio Sanguigni wrote: > en.WriteAnsiString(Memo1.Lines.Text); > fs.WriteBuffer(Pointer(s1.DataString)^, length(s1.DataString)); > en.Free; Maybe you decryption isn't working because the encrypted text you created isn't complete. Normally you need to call Flush to write the remaining bytes before you free the TBlowFishEncryptStream instance.

The docs state that it is called automatically upon destruction: "Flush is called automatically when the stream is destroyed, so there is no need to call it after all data was written and the stream is no longer needed." -- http://www.freepascal.org/docs-html/fcl/blowfish/tblowfishencryptstream.flush.html

A question related to this thread: what mode-of-operation do the TBlowFishStream descendants use? e.g. EBC, CBC, STR, OFB, ... (abbreviations taken from http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation)

It is not documented at http://www.freepascal.org/docs-html/fcl/blowfish/tblowfishencryptstream.html I think.

Ewald
Graeme Geldenhuys
to Ewald
Ewald wrote
The docs state that it is called automatically upon destruction:

Correct, and I knew that. But I was explicitly looking at the code Antonio supplied. As I also mentioned, I normally use Read() and Write(), where he uses different methods.

So looking at his code.

1)   en.WriteAnsiString(Memo1.Lines.Text);
2)   fs.WriteBuffer(Pointer(s1.DataString)^, length(s1.DataString));
3)   en.Free;

1 - Clear text is sent to the encryption object. Internally I presume the Read() and Write() methods are used.

2 - The data (bytes) already encrypted are written to the file on the hard drive.

3 - The encryption object is freed, which internally calls Flush(), at which point the remaining bytes are processed. But, as far as I can see the encrypted data was already written the hard drive (in step 2), so that last few bytes Flush() processed are missed.

So my suggestion is to call Flush() between steps 1 and 2.

This is my interpretation of what is going on with the code I have seen (I haven't actually tried to compiler and run that code). If I am wrong, feel free to correct me.

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/
Ewald
to Graeme Geldenhuys
Graeme Geldenhuys wrote 9 lines
On 2015-03-17 18:49, Ewald wrote: > The docs state that it is called automatically upon destruction: Correct, and I knew that. But I was explicitly looking at the code Antonio supplied. [...] This is my interpretation of what is going on with the code I have seen (I haven't actually tried to compiler and run that code). If I am wrong, feel free to correct me.

No, you are quite correct. I should've looked more closely to the code supplied (the 2-letter variable names must have confused me I suppose). Sorry for the noise.

Ewald