Forum > Beginners
<solved>Easy encryption of text files... Code added 16052024
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