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
// 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;
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;
prova a mettere un breakpoint su questa riga:
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
Fs.ReadBuffer(tr[1], Fs.Size);
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:
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
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 !
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;
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ì.