Algorytm szyfrowania

TeWuX

Chciałem przedstawić wam trochę inny algorytm szyfrowania. Nie będzie polegał na zmianie liter w alfabecie na inne, ani nie jest to XORowanie.
Algorytm ten odczytuje plik do zaszyfrowania po jednym bajcie. Następnie na podstawie jakiegoś szyfru dodaje do każdego kolejnego bajta wartość z jednej litery szyfru.
Nie wiem czy to jasno opisałem więc może przykładzik:

procedure TForm1.Szyfruj(PlikIn, PlikOut: String; kod: String);
var
  F1, F2 : TMemoryStream;
  FSize, i : LongInt;
  X : byte;
  dl, m, j : word;
begin
  dl := Length(kod);
  F1 := TMemoryStream.Create;
  F1.LoadFromFile(Plik);
  F1.Position:=0;
  FSize:= F1.Size;
  F2 := TMemoryStream.Create;
  F2.SetSize(FSize);

  For i to FSize-1 do
  begin
    F1.Read(X,1);
    m := i mod dl;
    For j:=0 to dl-1 do
      If (m=j) then X:=X+Ord(Kod[j]);
    F2.Write(X,1);
  end;
  F2.SaveToFile(PlikOut);
  F1.Free; F2.Free;
end;

Mam nadzieję, że teraz już wszystko jasne.
W pętki For j:=0... wykonuje się szyfrowanie pojedynczego bajtu z piku.
Funkcja Ord wyciąga wartość litery w kodzie ASCII.
Nie należy się martwić przekroczeniem wartości 255 w zmiennej X, ponieważ gdy osiągnie wartość wyższą od 255 zaczyna liczyć od 0. Tak więc gdy X= 200+120=65.
Gdy mamy kod np. 'god' to do
pierwszego bajtu pliku będzie dodana litera 'g',
do drugiego - 'o',
trzeciego - 'd',
czwartego znowu 'g' ,
piątego znowu 'o' itd.
Całej reszty chyba nie trzeba tłumaczyć?
Aha jest jeszcze jedna sprawa: gdy plik jest za długi (tzn. kilka MB) to czasami są błędy z zapisem.
Ja w swoich programie Kryptorator (można go ściągnąć z działu Programy) dodałem jeszcze zmienną TFileStream. Tak więc dane są kopiowane po bajcie z F1 do F2, a następnie w całości do TFileStream.
Dlaczego tak? Odpowiedź: Prędkość.
Gdybym po bajcie kopiował wszystko odrazu do TFileStream (czyli praktycznie odrazu na twardziela, a nie do RAMu) to prędkość przy kilku megabajtowych plikach mocno spada.
Dobra więc jak to zapisać?
Tu macie całą procedurę:

procedure TForm1.Szyfruj(PlikIn, PlikOut: String; kod: String);
var
  F1, F2 : TMemoryStream;
  F3 : TFileStream;
  FSize, i : LongInt;
  X : byte;
  dl, m, j : word;
begin
  dl := Length(kod);
  F1 := TMemoryStream.Create;
  F1.LoadFromFile(Plik);
  F1.Position:=0;
  FSize:= F1.Size;
  F2 := TMemoryStream.Create;
  F2.SetSize(FSize);

  For i to FSize-1 do
  begin
    F1.Read(X,1);
    m := i mod dl;
    For j:=0 to dl-1 do
      If (m=j) then X:=X+Ord(Kod[j]);
    F2.Write(X,1);
  end;
  F1.Position:=0;
  F2.Position:=0;
  F3 := TFileStream.Create(PlikOut,fmCreate);
  F3.CopyFrom(F2,FSize);
  
  F1.Free; F2.Free; F3.Free;
end;

W swoim Kryporatorze mam podobnie tylko przy szyfrowaniu dałem kilka komplikacji, podobnych do tej:

X:=X+Ord(Kod[j-dl]+i*j

No ale jak odszyfrować taki plik?
Dajemy identyczną procedurę tylko zamiast:

X:=X+Ord(Kod[j]);
dajemy: ```delphi X:=X-Ord(Kod[j]); ``` nasza skomplikowana wersja będzie wyglądać tak: ```delphi X:=X-Ord(Kod[j-dl]-i*j ```

No i chyba to już wszystko.

7 komentarzy

Mam 2 Pytania czy zamiast For i to FSize-1 nie powinno być For i:=0 to FSize-1? bo przy samym "i"mi sie nie kompiluje.Odrazu się przyznam,ze nie rozumiem tego kodu stąd moje 2 pytanie : Jak wywołać tą procedurę ?

To może być bezpieczne tylko, jeśli będziemy szyfrowali tekstem (pseudo)losowym, Random z Delphi nie jest generatorem kryptograficznym, więc nie polecam. Poza tym nie możemy użyć jednego strumienia do szyfrowania dwóch różnych plików, jeśli system ma być bezpieczny.

x:=x+?., a może lepiej x:=lo(x+ord(kod[i mod dl])), lo() by program się nie przewrócił (przy włączonej kontroli zakresów).
Czemu służą zmienne ?j? i ?m?? na moje oko niczemu!

Wiem że może za genialne to nie jest. Nie znam się za bardzo na kryptografii. Chodziło o pewien zakład z kolegą...miałem mu zaszyfrować jakiś tekst aby on go potem próbował odszyfrować...no a że nigdy nie robił takich rzeczy wcześniej...to mu się nieudało :-)

lol wynalazles szyfr Vigenera... Na dodatek lekko uproszczona wersje... Jest to klasyczny szyfr polialfabetyczny (ilosc alfabetow okresla dlugosc klucza), na dodatek dosc prosty do zlamania (biorac pod uwage nawet fakt zmiany rozkladu statystycznego tekstu)

No już przeniosłem do Gotowców

Niewielka modyfikacja może dać dużo wydajniejsze (w znaczeniu trudniejsze do złamania) szyfrowanie. Zamiast cyklicznego użycia stałego ciągu znaków (w przykładzie "god") można na podstawie tegoż ciągu wygenerować jakąś liczbę (np. sumę kodów znaków), przypisać ją do RandSeed i każdy kolejny znak ciągu przeznaczonego do szyfrowania sumować z kolejną wartością Random(255). Deszyfrowanie analogiczne. Jeszcze lepsze rezultaty osiągniemy nie ograniczając się do jednego znaku, ale używając całej grupy (np. 4 znaków i liczb typu Integer zamiast Byte jako zakresu Random).