Forum > Beginners

<solved>Easy encryption of text files... Code added 16052024

<< < (8/8)

Sprek Skik:

--- Quote from: Dzandaa on May 17, 2024, 09:56:47 am ---Hi
@Sprek Skik

Thank you too.

B->

--- End quote ---

In another program I used your code with compress. This also works perfect! Thanks for your help with encryption.
I don't know very much of Lazarus so I am very happy with the result. It's difficult to find specific code when something doesn't work. I also make use of Google's Gemini but this AI program has some troubles with Lazarus.

grtz Sprek

Dzandaa:
Hi

@Sprek Skik

I'm glad my code was helpful.

This forum is very dynamic and there is almost always someone to find a solution :)

I've programmed in a lot of languages, unfortunately,
I've only known Lazarus for two years,
I naively thought that Pascal was just a teaching language.

But no, it's a solid, cross-platform windowed language.

The documentation is a bit lacking, but the forum is very responsive.

To try it is to adopt it:)

Have a nice day.

B->

Thaddy:
I have expanded my previous replies somewhat with a simple class where you can override the encryption algorithm to taste.
it works with any stream. About the simplest I could achieve with binary compatibility between platforms Win and Lin:
--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---unit cryptstreams;{ A simple encryption/decryption stream based on a pseudo random   number generator, PRNG for short.  We use a Linear Congruential Generator, LCG for short.   This makes use of the deterministic nature of PRNG's, meaning that,  given a known seed, the sequence is always the same, while   approaching equi-distribution in its outcome. The possibility to  use cycles, strongly improves the crypt quality: i.e, five cycles is  mathematically almost unbreakable without knowledge of:  - Key, which is the random seed in the range of a Cardinal.  - Cycles, how many times the crypt is run over the same data.  - The algorithm used to crypt/decrypt.    Here I have used a very simple and fast PRNG, but the encryption  function can be overriden with your algorithm of choice without   affecting the functionality of the the class.    Encryption is limited to memory size, but you can also implement this  using a class derived from TFileStream instead without many changes.  The most important part is just the WriteByte function and that works  with any stream.    There is some more explanation in the sourcecode below.    Enjoy,    Thaddy de Koning.    NO license, use as you like.  (C)1998-2024 Thaddy de Koning  (I used the idea first in 1998, not as a class,    but as a function )}      {$mode objfpc}{$H+}interfaceuses   classes; type{$if not declared(Tbytes)}  TBytes = array of byte;{$ifend}   TSimpleStreamCrypter = class(TMemoryStream)  strict private     FKey,    FCycles:Cardinal;    FInStream:TStream;    FLoaded:Boolean;    function GetBytes:TBytes;inline;  strict protected    { Writes a byte, encrypts immediately on write.      You can override this with a different encryption algorithm }    procedure WriteByte(aByte:Byte);virtual;    procedure LoadFromStream(Stream:TStream);  public    constructor Create(InStream:TStream;Key:Cardinal;Cycles:cardinal = 5);virtual;overload;    property Bytes:TBytes read GetBytes;  end; implementation   constructor TSimpleStreamCrypter.Create(InStream:TStream;Key:Cardinal;Cycles:cardinal);  begin    inherited create;    FLoaded := False;    FInStream := InStream;    FKey := Key;    FCycles := Cycles;    Size:=InStream.Size;    LoadFromStream(InStream);  end;    function TSimpleStreamCrypter.GetBytes:TBytes;  begin     Result := [];     SetLength(Result,Size);     move(PByte(memory)[0],Result[0],Size);     end;   { If you distrust the LCG, you can override this with    another PRNG, but since we use 5 cycles as default,    the resulting encryption is very, very strong.     If you test with chi squared (.5) you will find almost    perfect equi-distribution over 5 cycles and 1000 probes     with different keys. That means it is pretty much unbreakable    without the knowledge of key, cycles and prng. }   procedure TSimpleStreamCrypter.WriteByte(aByte:Byte);  begin    { This is an LCG, actually the same as Delphi's Random }    FKey := FKey * 134775813 { is prime, do not change }  + 1;    inherited WriteByte(aByte xor (FKey * 256 shr 32));  end;    procedure TSimpleStreamCrypter.LoadFromStream(Stream:TStream);  var    i,j:integer;    b:Byte;  begin    { freshen up first }    clear;    { We only need to read the first cycle from the instream       Our stream is then already encrypted for one cycle }    if not Floaded then    begin      Stream.Seek(0,0);      for j:= 0 to Stream.Size -1 do      { encryption is byte wise and in-place }        WriteByte(Stream.ReadByte);      { flag the first encryption round }      FLoaded := True;      { Keep track of the cycles }      Dec(FCycles);    end;    { After that, we can cycle over our own data }        for i:= 0 to FCycles-1 do    begin      Seek(0,0);      for j:= 0 to Size -1 do      begin        b:= ReadByte;        { Go back to where we were, because ReadByte advanced           the stream by one }        Seek(-1,soFromCurrent);        { Overwrite with new value }        WriteByte(b);      end;    end;  end; end. Small example:
--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---program testcryptstreams;{$mode objfpc}{$H+}{$codepage utf8}uses   sysutils, classes, cryptstreams,CryptRandom;var  Crypt:TSimpleStreamCrypter;  Instream:TStream;  S:UnicodeString = 'This is thè téxt to êncrypt/decrypt Ä.';begin  { Encrypt a stream. With strings, the encoding is important    to allow cross-platform crypt and binary compatibility. }  InStream := TStringStream.Create(S, Tencoding.Unicode);  try    Crypt:=TSimpleStreamCrypter.Create(InStream,12345);    try      S:=Crypt.Bytes;      writeln(S);    finally      Crypt.Free;    end;  finally    InStream.Free;  end;  { Decrypt the stream: same code }  InStream := TStringStream.Create(S,Tencoding.Unicode);  try    Crypt:=TSimpleStreamCrypter.Create(InStream,12345);    try      S:=Crypt.Bytes;      writeln(S);    finally      Crypt.Free;    end;  finally    InStream.Free;  end;  Readln;end.needed operators for the example, as well as the original function:
--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---{   This unit implements strong and very fast encryption/decrytion,  It is based on a pseudo random number generator (PRNG) where the  random seed is used as the key/pass. PRNG's produce repeatable   sequences given the same random seed. The values are equidistributed  over the domain, though.( tested chi squared )   To successfully attack this method of encryption you will need three things:  - knowledge of the key  - knowledge of the prng  - knowledge of the number of cycles  Any weakness is in the prng used, but offset by the number of cycles.  Encryption is symmetric: the same crypt routine encrypts and decrypts.  The encryption becomes stronger when the number of cycles is increased.    Completely rewritten using modern object pascal features.   Prng is still the same.    (c) 1998 - 2024, Thaddy de Koning. Use as you like, not licensed.}unit cryptrandom;{$mode objfpc}{$modeswitch advancedrecords}interfaceuses   {$ifdef unix}cwstring,{$endif}sysutils;    function Crypt(const Data:TBytes;Key:Cardinal;Cycles:Cardinal=1):TBytes;inline;   { convenience operators for string types to TBytes and back }  operator := (const a:ShortString):TBytes;inline;  operator := (const a:AnsiString):TBytes;inline;  operator := (const a:UTF8String):TBytes;inline;  operator := (const a:WideString):Tbytes;  operator := (const a:UnicodeString):Tbytes;   operator := (const a:TBytes):ShortString;inline;  operator := (const a:TBytes):AnsiString;inline;  operator := (const a:TBytes):UTF8String;inline;  operator := (const a:Tbytes):WideString;inline;  operator := (const a:TBytes):UnicodeString;inline; implementation   function Crypt(const Data:TBytes;Key:Cardinal;Cycles:Cardinal=1):TBytes;inline;  var    i,j:integer;   begin    Result := [];    Setlength(Result, Length(Data));    For i:= 0 to Pred(Cycles) do      for j:= 0 to high(Data) do      begin        { this is the lcg type prng }        Key := Key * 134775813  + 1;        Result[j] := Data[j] xor (Key * 256 shr 32);      end;  end;      operator := (const a:ShortString):TBytes;inline;  var    T:UTF8String;  begin    T:= a;    Result:=BytesOf(T);  end;   operator := (const a:AnsiString):TBytes;inline;  begin    Result := BytesOf(a);  end;    operator := (const a:UTF8String):TBytes;inline;  begin    Result := BytesOf(a);  end;    operator := (const a:WideString):Tbytes;inline;  begin    Result := WideBytesOf(a);  end;       operator := (const a:UnicodeString):TBytes;inline;  begin    Result := WideBytesOf(a);  end;   operator := (const a:TBytes):ShortString;inline;  begin    SetString(Result,PAnsiChar(a),Length(a));  end;   operator := (const a:TBytes):AnsiString;inline;  begin    SetString(Result,PAnsiChar(a),length(a));  end;    operator := (const a:TBytes):UTF8String;inline;  begin    SetString(Result,PAnsiChar(a),length(a));  end;    operator := (const a:Tbytes):WideString;  begin    Result := WideStringOf(a);  end;     operator := (const a:TBytes):UnicodeString;inline;  begin    Result := WideStringOf(a)  end; {$ifndef unix}initialization{   This is for binary compatibility of shortstring and ansistring  between Windows and Linux.  NOT for display purposes, that depends on your console/terminal. }   SetMultiByteConversionCodePage(CP_UTF8);finalization   SetMultiByteConversionCodePage(CP_ACP);{$endif}end.
Remarks:
- This encryption is very fast
- Using cycles, it is stronger than any suggested (at the cost of some speed, of course )
- Firmly founded in theory.
- You can override the encryption scheme.

I hope this code is understandable even for beginners.
(plz note my windows console is configured as utf8. does not affect binary level)




Thaddy:
my previous post is about streams, but the core function is of course just this;
--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---  function Crypt(const Data:TBytes;Key:Cardinal;Cycles:Cardinal=1):TBytes;inline;  var    i,j:integer;   begin    Result := [];    Setlength(Result, Length(Data));    For i:= 0 to Pred(Cycles) do      for j:= 0 to high(Data) do      begin        { this is the lcg type prng }        Key := Key * 134775813  + 1;        Result[j] := Data[j] xor (Key * 256 shr 32);      end;  end;
i recommend to use streaming, though.

Navigation

[0] Message Index

[*] Previous page

Go to full version