Italian community of Lazarus and Free Pascal

Programmazione => Generale => Topic aperto da: slapshot - Marzo 16, 2015, 10:02:58 am

Titolo: Criptare TMemo su file
Inserito da: slapshot - Marzo 16, 2015, 10:02:58 am
Ciao a tutti,

ho la necessità di criptare il contenuto di un TMemo (o un componente più evoluto se me lo consigliate). Sbirciando sul web ho trovato molto codice che fa uso della unit blowfish ed è questo algoritmo di criptazione che vorrei usare.
Riesco a criptare e decriptare senza problemi, così come riesco a scrivere il contenuto della proprietà Lines di tipo TStrings su file e a rileggerne il contenuto facendo uso della proprietà Lines.Text che mi restituisce un'intera stringa da riassegnare sempre alla Linex.Text usando TFileStream.

Ciò che mi sta dando delle difficoltà  è salvare il contenuto criptato su file, rileggerlo e decriptarlo. Nella scrittura sembra non ci siano problemi, il contenuto viene criptato. Ma nella lettura ho idea che ci sia qualcosa che non quadra. L'errore restituito è Exception class External SIGSEGV

Di seguito un codice demo (ignorate il fatto che non ci siano try-finally, try-except ecc.. è solo codice di test):

Grazie per ogni eventuale aiuto/suggerimento

Codice: [Seleziona]
// Salvo criptato
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;

//  Memo1.Lines.SaveToStream(fs);
  fs.Free;
end;                 

Codice: [Seleziona]
 Leggo criptato
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, Fs.Size);

  s2 := TStringStream.Create(tr); //l'errore viene dato qui dal debugger ma probabilmente è la stringa tr ad avere dei problemi.
  s1.Free;

  de := TBlowFishDeCryptStream.Create(key,s2);

  temp := de.ReadAnsiString;
  WriteLn('decrypted: ' + temp);
  Memo1.Lines.Text := temp;

  de.Free;
  s2.Free;

end;               
Titolo: Re:Criptare TMemo su file
Inserito da: nomorelogic - Marzo 16, 2015, 11:14:13 am
ciao
hai dato un'occhiata a questa guida?

http://www.lazaruspascal.it/index.php?page=135 (http://www.lazaruspascal.it/index.php?page=135)
Titolo: Re:Criptare TMemo su file
Inserito da: slapshot - Marzo 16, 2015, 11:22:58 am
Sì, avevo scorso la guida. A parte il metodo copyfrom che non conosco mi sembra pressoché simile alle altre trovate sulla rete. Come dicevo nel primo post non ho problemi a criptare e decriptare al volo i dati nel TMemo, così come non ho problemi a scrivere su file e poi a leggere in chiaro lo stesso contenuto. Il mio problema è criptare -> scrivere su file il testo criptato (e fino qui sembra tutto regolare) -> leggere dal file -> decriptare -> depositare di nuovo il contenuto in TMemo. E' questa seconda parte che mi dà problemi, ovvero leggere dal file di testo il contenuto criptato e poi decriptarlo.

Grazie
Titolo: Re:Criptare TMemo su file
Inserito da: nomorelogic - Marzo 16, 2015, 12:26:06 pm
prova a mettere un breakpoint su questa riga:

Codice: [Seleziona]
s2 := TStringStream.Create(tr); //l'errore viene dato qui dal debugger ma probabilmente è la stringa tr ad avere dei problemi.

quando l'esecuzione si interrompe, vedi cosa c'è nella stringa

Edit:
prova a cambiare la readbuffer immediatamente sopra come segue
Codice: [Seleziona]
Fs.ReadBuffer(tr[1], Fs.Size);
Titolo: Re:Criptare TMemo su file
Inserito da: slapshot - Marzo 16, 2015, 05:17:30 pm
Grazie per la risposta. Ho modificato la ReadBuffer come mi hai detto e il software va avanti. Ottengo un'eccezione EReadError with message Stream Read Error con  esattamente qui:

Codice: [Seleziona]
 temp := de.ReadAnsiString;

la s2.datastring mi sembra restituire una stringa criptata o meglio non è intellegibile. Tuttavia, quando tento di usare la ReadAnsistring dell'oggetto de lo stream va in errore :O

Titolo: Re:Criptare TMemo su file
Inserito da: slapshot - Marzo 16, 2015, 05:20:28 pm
Mi viene il dubbio che dopo la criptazione il file venga convertito in binario e che nel rileggerlo ci sia qualche problema ad usare ReadAnsistring ...
Titolo: Re:Criptare TMemo su file
Inserito da: slapshot - Marzo 17, 2015, 11:32:46 am
Le mie supposizioni erano errate !! Ho scritto alla lista fpc-pascal e il solito Graeme Geldenhuys mi ha dato un bel suggerimento. Dopo la criptazione occorre usare il metodo flush per fare in modo che si consolidi la criptazione e venga poi effettivamente scritta su disco. ora funziona perfettamente !!

Riporto il codice di seguito se a qualcuno può essere utile !

Codice: [Seleziona]
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);
   en.Flush; // l'invocazione di questo metodo ha risolto il problema !!
   fs.WriteBuffer(Pointer(s1.DataString)^, length(s1.DataString));
   en.Free;
   fs.Free;                   
Titolo: Re:Criptare TMemo su file
Inserito da: nomorelogic - Marzo 17, 2015, 03:15:42 pm
grazie per la condivisione ;)
Titolo: Re:Criptare TMemo su file
Inserito da: slapshot - Marzo 18, 2015, 09:52:49 am
Codice: [Seleziona]
en.WriteAnsiString(Memo1.Lines.Text);
   en.Flush; // l'invocazione di questo metodo ha risolto il problema !!
   fs.WriteBuffer(Pointer(s1.DataString)^, length(s1.DataString));
   en.Free;

da ulteriori approfondimenti sembra che il metodo Flush venga chiamato implicitamente al free. Nel mio codice, però, il distruttore dell'oggetto en viene chiamato dopo il WriteAnsistring e quindi si rende necessario esplicitamente invocare il metodo Flush. Spostare en.Free una riga più sopra avrebbe evitato l'invocazione diretta del metodo flush. Non ho ancora provato ma credo sia così.