Szyfrowanie pliku Xorowaniem. Znak nowej linii - problem

0

Jak odbywa się szyfrowanie pliku XoRem? Ja to robię tak:

  1. Zamieniam literke na kod ASCII
  2. Xoruje
  3. wynik zmieniam na znak ASCII
    Problem jest wtedy gdy wynik Xorowania to 243 - czyli kod nowej lini.
    Po zapisaniu do pliku txt i odkodowaniu wiadomość jest urwana :(
    Jak temu zaradzić? Jak ominąć nieszczęsne 243.

Aby uniknąć błędów wyczytałem że kod znaku ASCII dobrze zamienić na HEX.

Kod znaku ASCII np 45 podstawiony pod inttohex() daje mi 2D.

Jak zamienić 2D na znak? (raczej sie nie da), więc do pliku tekstowego zapisywać np. #2D#10...
Jak potem to odczytywac i zamieniać na prawidłową literę.
Testowałem kilka opcji i cały czas mam jakieś błędy.
Gdy owe 2D chce przypisać do Sringa wywala błąd "Char and String".

2

traktuj plik jako binarny a nie tekstowy

0

Tak to dla pliku tekstowego było by dobre rozwiązanie. Ale chciałem sobie troche ułatwić i LOGINY i HASLA przechowuję w pliku INI.
i korzystając z INI.ReadString otrzymuję stringa ale do znaku nowej lini. Ktos na 4p podawał że jest to dobre rozwiązanie bo szyfruje tylko hasła.
Niestety nie podał jak sobie poradził z tymi problemami jakie ja mam. niby ASCII -> HEX ale to tworzy nowe problemy :/

[Delphi] Kodowanie pliku *.INI autor flabra

4
maxiu1989 napisał(a):

Tak to dla pliku tekstowego było by dobre rozwiązanie. Ale chciałem sobie troche ułatwić i LOGINY i HASLA przechowuję w pliku INI.
i korzystając z INI.ReadString otrzymuję stringa ale do znaku nowej lini. Ktos na 4p podawał że jest to dobre rozwiązanie bo szyfruje tylko hasła.
Niestety nie podał jak sobie poradził z tymi problemami jakie ja mam. niby ASCII -> HEX ale to tworzy nowe problemy :/

Nie za bardzo zrozumiałem, ale spróbuję wyjaśnić:
Skoro to hasełko to go nie szyfruj jakimś słabym XORem tylko pobierz sobie chociażby bibliotekę do MD5 albo SHA i je hashuj. I zapisuj tak: XXYYZZ gdzie kolejne dwa znaki to bajt zapisany szesnastokowo (Inttohex(c,2)). A oryginalny możesz odzyskać forem z StrToInt('$'+s).

1

Popieram 123, dodatkowo dane o podwyższonych wymogach bezpieczeństwa (tu hasła) w Windows powinny być przechowywane
albo:
a) w rejestrze w gałęzi HKEY_CURRENT_USER: http://pcsupport.about.com/od/termshm/g/hkey_current_user.htm
albo w katalogu użytkownika:
b) CSIDL_LOCAL_APPDATA: http://delphi.about.com/od/kbwinshell/a/SHGetFolderPath.htm
albo
c) jeśli hasła mają być dostępne dla wszystkich użytkowników - to gdziekolwiek, tylko wtedy to mizerne security - jeśli każdy może ten plik podejrzeć.

Co do MD5 to koniecznie zastosuj solenie: http://skfox.com/2007/12/18/md5-hashes-and-salt/
Bez tego można odgadnąć hasło - patrz:

W uproszczeniu sól w MD5 to (najlepiej) losowy ciąg znaków którego zastosowanie powoduje, że wartość MD5 dla dwóch różnych przypadków (użytkowników, komputerów, sesji) będzie różna nawet wtedy, gdy zastosujesz tą samą treść na wejściu (to samo hasło).

0

Bardzo Dziękuję za sporo konkretnej wiedzy i wskazówek :) Xorowanie już mi sie udało (i zapis HEX). Po prostu Przy dekodowaniu nie odczytywałem 2 kolejnych liter.
A teraz Xor spróbuję zamienić na coś lepszego. :)

0

Przede wszystkim, według mojej wiedzy, koniec linii to znaki 13 i 10, w hex odpowiednio 0D i 0A, a nie 243.

Jeżeli w pliku są tylko standardowe znaki tekstowe, to możesz posłużyć się alfabetem składającym się z 64 znaków (np. taki, jaki wykorzystuje Base64) lub 128 znaków (wszystkie znaki o kodach ASCII od 32 do 128 plus 32 dodatkowych znaków tekstowych).

Przy szyfrowaniu przetwarzasz tylko znaki należące do alfabetu, a pozostałe przepisujesz.

Ponieważ każdy znak ma swój numer niezależny od ASCII nie będzie ryzyka, że wypadnie jakiś znak specjalny. Wtedy na każdy znak przypada 6 lub 7 bitów.

Innymi słowy: Pobierasz znak z pliku, uzyskujesz numer tego znaku w alfabecie, na tym numerze robisz XOR i otrzymujesz nowy numer znaku, który wstawiasz do pliku.

0
maxiu1989 napisał(a):

A teraz Xor spróbuję zamienić na coś lepszego. :)

Nie wiem, w jakiej technologii piszesz program. Wiem, że Java i .NET oferują gotowe rozwiązania. Jak chodzi o zaszyfrowanie danych, to pomyśl o AES 128bit a jak chodzi o hash to MD5. W obu wymienionych technologiach jest jedno i drugie.

0

MD5 to cienki pomysł, bo jest krótki i ma sporo kolizji. Ja polecę SHA256 i wyżej.

0

Algorytm haszujący musi być dobry, ale dodatkowo bardzo ważne jest abyś hashe solił.

1
winerfresh napisał(a):

MD5 to cienki pomysł, bo jest krótki i ma sporo kolizji. Ja polecę SHA256 i wyżej.

adf88 napisał(a):

Algorytm haszujący musi być dobry, ale dodatkowo bardzo ważne jest abyś hashe solił.

Co z tego że hashowanie będzie bardziej skomplikowane niż aplikacja, liczy się to że nikt nie złamie hasła!!! A to że może zmienić "je" na "jne" to mniejsza.

Nie przesadzacie trochę z tym nie wiadomo jak wymyślnym hashowaniem?

0
-123oho napisał(a):
winerfresh napisał(a):

MD5 to cienki pomysł, bo jest krótki i ma sporo kolizji. Ja polecę SHA256 i wyżej.

adf88 napisał(a):

Algorytm haszujący musi być dobry, ale dodatkowo bardzo ważne jest abyś hashe solił.

Co z tego że hashowanie będzie bardziej skomplikowane niż aplikacja, liczy się to że nikt nie złamie hasła!!! A to że może zmienić "je" na "jne" to mniejsza.

Nie przesadzacie trochę z tym nie wiadomo jak wymyślnym hashowaniem?

Dodanie soli to żadne wymyślne hashowanie tylko KONIECZNOŚĆ.
A zmiana MD5 na SHA-x to żaden problem - przecież i tak nie będzie tego sam implementował (nie powinien)...

0
vpiotr napisał(a):

Dodanie soli to żadne wymyślne hashowanie tylko KONIECZNOŚĆ.
A zmiana MD5 na SHA-x to żaden problem - przecież i tak nie będzie tego sam implementował (nie powinien)...

Nie zgodzę się, solenie powinno się stosować jeżeli chodzi o coś co ma mieć większą siłę kryptograficzną, typowy program nie potrzebuje takich funkcji.
O ile MD5 może się okazać złym wyjściem bez soli, o tyle SHA już nie powinna być tragiczna.
Nie trzeba armaty do zabicia muchy. Natomiast warto też wiedzieć o poważniejszych zabezpieczeniach gdy bezpieczeństwo będzie istotniejsze.

0

Obejrzyj filmik który podałem wcześniej

Też mam cracker MD5 na CUDA no i co. Ale będę chakierować czyjeś programy w których sam będę sobie konto robić!!! mhmhm. I na co mi to że złamię hasło do programu do którego mam fizyczny dostęp i mogę po prostu zmienić mu kod?
To i tak jest wyłamywanie otwartych drzwi. Gdy gra jest warta świeczki to nawet solone Sha512 ciebie nie uratuje.

Trzeba być debilem żeby zamiast zmienić hash na swój łamać oryginalny pass. Jeszcze łatwiej można skasować konto i do nowego wkleić ustawienia. Już o zmianie jednego bajtu w kodzie nie wspomnę. Litości.

0
-123oho napisał(a):

Obejrzyj filmik który podałem wcześniej

Też mam cracker MD5 na CUDA no i co. Ale będę chakierować czyjeś programy w których sam będę sobie konto robić!!! mhmhm. I na co mi to że złamię hasło do programu do którego mam fizyczny dostęp i mogę po prostu zmienić mu kod?
To i tak jest wyłamywanie otwartych drzwi. Gdy gra jest warta świeczki to nawet solone Sha512 ciebie nie uratuje.

A na ile szacujesz czas znalezienia hasła dla SHA-2 (512 bitów)?

Bo ja znalazłem wyliczenie 3,17 * 10^64 lat - może masz jakieś lepsze?

http://stackoverflow.com/questions/6776050/how-long-to-brute-force-a-salted-sha-512-hash-salt-provided

-123oho napisał(a):

Trzeba być debilem żeby zamiast zmienić hash na swój łamać oryginalny pass. Jeszcze łatwiej można skasować konto i do nowego wkleić ustawienia. Już o zmianie jednego bajtu w kodzie nie wspomnę. Litości.

No właśnie na tym polega solenie - nie wiesz co możesz wkleić.

0

A na ile szacujesz czas znalezienia hasła dla SHA-2 (512 bitów)?

Bo ja znalazłem wyliczenie 3,17 * 10^64 lat - może masz jakieś lepsze?

Czyli sądzisz że czas jest stały niezależnie od maszyny ani od ich ilości? Ciekawe.
Jest jeszcze jeden sposób: Porwać ciebie i wymusić na tobie hasło, oejku :> .

No właśnie na tym polega solenie - nie wiesz co możesz wkleić.

To zapobiega tylko podmianie hashu. I tak jestem pewien że analizując program albo przyglądając się wynikom zależnie od danych w INI można odgadnąć o co chodzi. Celem solenia nie jest zapobieganie podmianie hashy tylko niemożność użycia rainbow tables (więc nie dają NIC przy łamaniu jednego hasła).

0

@-123oho ty chyba nie rozumiesz. Nie chodzi o zabezpieczenie twojej aplikacji jakimś tam hasełkiem. @maxiu1989 pisał, że przechowuje LOGINY i HASLA. Jeśli ktoś te dane mu wykradnie, to może przejmować konta mailowe/bankowe/społecznościowe ... (tak, ludzie używają tych samych haseł do różnych serwisów). Wprowadzając system rejestracji spoczywa na tobie spora odpowiedzialność.

0

Jeśli ktoś te dane mu wykradnie, to może przejmować konta mailowe/bankowe/społecznościowe

Z tego co rozumiem to ta aplikacja siedzi grzecznie na dysku, więc jakim cudem ktoś ma wykraść te dane?

Wprowadzając system rejestracji spoczywa na tobie spora odpowiedzialność.

Rejestrując się spoczywa na tobie spora odpowiedzialność. I tak jeżeli używasz tych samych haseł to któryś genialny serwis wuwuwu albo ci wyśle hasło plaintextem na meila, albo w ogóle przechowuje plaintextem. Więc nie wiem czemu zakładacie że tak należy tego chronić skoro szansa że ktoś ci ukradnie te dane jest mniejsza niż atak na jakiś super serwis który być może ma jeszcze gorsze zabezpieczenia. Paranoja jakaś.

0
-123oho napisał(a):

Jeśli ktoś te dane mu wykradnie, to może przejmować konta mailowe/bankowe/społecznościowe

Z tego co rozumiem to ta aplikacja siedzi grzecznie na dysku, więc jakim cudem ktoś ma wykraść te dane?

Rozumiem, że myślisz, że komputer lokalny podłączony do intrnetu może przeglądać jego zasoby, ale działa to tylko w jedną stronę?

0
winerfresh napisał(a):
-123oho napisał(a):

Jeśli ktoś te dane mu wykradnie, to może przejmować konta mailowe/bankowe/społecznościowe

Z tego co rozumiem to ta aplikacja siedzi grzecznie na dysku, więc jakim cudem ktoś ma wykraść te dane?

Rozumiem, że myślisz, że komputer lokalny podłączony do intrnetu może przeglądać jego zasoby, ale działa to tylko w jedną stronę?

Jeżeli nie dbasz o bezpieczeństwo swojego komputera to ktoś ci walnie keyloggera i na bardzo wiele zda się solony hash.

Szukacie dziury w i tak najsilniejszym elemencie, bo jeżeli ktoś jest w stanie odczytać hash to jest też w stanie znaleźć milion innych sposobów na przechwycenie hasła.

0
-123oho napisał(a):

...bo jeżeli ktoś jest w stanie odczytać hash to jest też w stanie znaleźć milion innych sposobów na przechwycenie hasła...
A całej bazy haseł? To jest najbardziej łakomy kąsek. Chodzi o masowość. A co się dzieje później z takimi bazami? Użyjcie wyobraźni.

W przypadku jakiegoś mało popularnego serwisu z niewielką ilością użytkowników to faktycznie zbyt wysoki poziom zabezpieczeń może być przesadą. Ale IMO nie należy lekceważyć tego tematu. Ja bym się skłaniał jednak do solenia nawet w przypadku małych serwisów. A na pewno warto o nim wspomnieć na forum programistycznym.

-123oho napisał(a):

Jeżeli nie dbasz o bezpieczeństwo swojego komputera...
Przeciętny użytkownik komputera jest informatycznie ułomny. Tyle na temat indywidualnej dbałości.

0

A całej bazy haseł? To jest najbardziej łakomy kąsek. Chodzi o masowość. A co się dzieje później z takimi bazami? Użyjcie wyobraźni.

W przypadku jakiegoś mało popularnego serwisu z niewielką ilością użytkowników to faktycznie zbyt wysoki poziom zabezpieczeń może być przesadą. Ale IMO nie należy lekceważyć tego tematu. Ja bym się skłaniał jednak do solenia nawet w przypadku małych serwisów. A na pewno warto o nim wspomnieć na forum programistycznym.

Ale przecież my nie mówimy o żadnym serwisie tylko programie na dysku który nigdzie się nie łączy cholera. Bo jak chodzi o serwis to oczywiście że jestem nawet nie za soleniem ale użyciem czegoś porządniejszego.

Przeciętny użytkownik komputera jest informatycznie ułomny. Tyle na temat indywidualnej dbałości.

No to skoro mogę się dobrać do dysku to na pewno będzie mi najbardziej zależeć na hashu... I jeżeli będzie saltowane to wezmę też salt i będzie taka sama złożoność...

0

"mówimy o ... programie na dysku który nigdzie się nie łączy" skąd wiesz, że nigdzie się nie łączy? Nikt nic nie mówił na ten temat. A serwisy też są "programami na dysku".

0
adf88 napisał(a):

"mówimy o ... programie na dysku który nigdzie się nie łączy" skąd wiesz, że nigdzie się nie łączy? Nikt nic nie mówił na ten temat. A serwisy też są "programami na dysku".

Jakie serwisy są programami na dysku? O_o
Domyślam się że nie łączy się nigdzie w celach autoryzacji etc. etc.

Zresztą, autor nie wygląda na zainteresowanego naszymi rozważaniami nad bezpieczeństwem D:

0

Skoro oftop jest o soleniu to się dopiszę, choć nie wczytywałem się w temat:

Solenie jest pomocne wtedy, gdy haker dostał się do całej naszej bazy, wraz ze wszystkimi hasłami i solami. Solenie poprawia bezpieczeństwo haseł na co najmniej dwa sposoby:

  1. Solenie może długo trwać, wielokrotnie dłużej niż samo haszowanie, wobec czego łamanie się wydłuża.
    2a. Jeżeli hasła nie są posolone to od razu widać, kto ma takie same hasła, wobec czego ludzie używający popularnych haseł są bardziej narażeni.
    2b. Jeżeli hasła nie są posolone to jest możliwe łamanie wszystkich haseł naraz. Standardowa procedura łamania wygląda tak, że generuje się wszystkie kombinacje bitów do jakiejś tam długości i pewnej charakterystyce i haszuje, a następnie porównuje z podanym haszem. Gdyby hasła były solone to trzeba taką procedurę, wraz z soleniem każdej wygenerowanej kombinacji, powtórzyć dla każdego hasła. Natomiast jeżeli hasła nie są solone, to przy każdym wygenerowaniu kombinacji haszujemy ją tylko jednokrotnie (a nie tyle razy ile jest haseł), a potem obliczony hasz szukamy w zbiorze haszy z bazy, co może zajmować czas stały zakładając haszmapę haszy.

Ale tutaj chyba zbyt mocno odbiegam od tematu.

0

Ale tutaj chyba zbyt mocno odbiegam od tematu.

@Wibowit - zawsze jakieś solidniejsze wytłumaczenie jest mile widziane;

Chłopaki, może zamiast rozwijać dyskusję o znaczeniu solenia zastanowicie się nad tym, czy autor w ogóle chce wykorzystać jakiekolwiek popularne algorytmy szyfrujące...? Bo jak na razie to nie zauważyłem ani jednego posta od niego, który na to by wskazywał; Chyba tą dyskusją odstraszyliście go i teraz pewnie już nic nie napisze :-P

Mi się wydaje, że on po prostu chce wykorzystać swój własny algorytm; Oczywiście na 99.99% będzie to nędzne "Crack Me", ale zawsze swoje; Poczekajcie na jego opinię zanim rozpocznie się kolejny OffTopic na tematy odległe od poruszanego;

Skupcie się, pytania brzmią: "Jak odbywa się szyfrowanie pliku XoRem?", "Jak temu zaradzić? Jak ominąć nieszczęsne 243." oraz "Jak zamienić 2D na znak?";

0

Odpowiedz na moje pytania i wątpliwości na temat XOR'a już się pojawiły. Trochę namieszałem, ze względu na to że z szyfrowaniem zetknąłem się pierwszy raz.

Jeśli chodzi o program:
LOGINY i HASŁA przechowuję zaszyfrowane w pliku INI. I póki przy szyfrowaniu XOrem nie wypadnie wartość 13 to jest ok.
Aby nie przechowywać w pliku INI znaku nowej lini, zamieniłem numer znaku ASCII na HEX i taki przechowuję.

Aplikacja nie łączy się z internetem a szyfrowane dane są potrzebne jedynie do kont użytkowników (uprawnienia).
Szyfrowanie ma spełnić taka funkcję że ktoś jak wejdzie w plik INI i zobaczy dziwne dane to go wyłączy.
Oczywiście można by użyć czegoś mocniejszego, ale w tym wypadku myślę, że starczy.

Cieszę się że pojawiły się takie konkretne i profesjonalne odpowiedzi, natomiast nie jestem w stanie tego wszystkeigo sprawdzić i przetestować. Minie troche czasu zanim sam będę mógł dyskutować ta takim poziomie. Dyskusji nie przerywam proszę kontynuować ja tu często zaglądam :)

0
maxiu1989 napisał(a)

Jeśli chodzi o program:
LOGINY i HASŁA przechowuję zaszyfrowane w pliku INI.

Nie rób tego, takie rzeczy chowa się jak najgłebiej, żeby dociekliwy użytkownik nie mógł w prosty sposób ich odczytać; Szyfruj je i zapisuj do pliku choćby amorficznego - nie jest to oczywiście jako takie zabezpieczenie bo każdy nawet największy matoł potrafi znaleźć w sieci i pobrać jakiś Hex-edytor, ale zablokujesz możliwość otworzenia takiego pliku w edytorach tekstowych;

maxiu1989 napisał(a)

Aby nie przechowywać w pliku INI znaku nowej lini, zamieniłem numer znaku ASCII na HEX i taki przechowuję.

To jest błąd... Błedem jest w ogóle wykorzystywanie plików tekstowych do przechowywania informacji tak wielkiej wagi; Już wytłumaczę - mechanizm odczytywania zawartości danego klucza skonstruowany jest tak, że czyta linię do znaku końca linii LF (Line Feed) lub CR (Carrige Return); Więc jeśli bajtem wynikowym z operacji szyfrowania okaże się któryś z wyżej wymienionych to metoda obiektu nie da rady odczytać części poza tym znakiem, stąd łańcuch będzie urwany; Musiałbyś napisać swój parser żeby uniknąć takiego zachowania;

Można to sprawdzić np. takim kodem:

program Foo;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  INIFIles;

const
  INI_FILE_NAME = 'C:\Foo.ini';
begin
  if FileExists(INI_FILE_NAME) then
    DeleteFile(INI_FILE_NAME);

  with TINIFile.Create(INI_FILE_NAME) do
    try
      WriteString('MAIN', 'Line', 'Line 1'#13'Line 2');
    finally
      Free();
    end;

  with TINIFile.Create(INI_FILE_NAME) do
    try
      Write('Value: "', ReadString('MAIN', 'Line', ''), '"');
    finally
      Free;
    end;

  ReadLn;
end.

Teoretycznie na ekranie konsoli powinien zostać wyświetlony łańcuch Value: "Line 1‭‭‮‬‭‭‮‬Line2" (trochę to głupie...), ale dzięki znakowi o kodzie #13 lub #10 druga część łańcucha zostanie utracona, stąd na wyjściu dostaniesz Value: "Line 1";

Właśnie dlatego odradzam przechowywania szyfrowanych danych w plikach tekstowych, bo prawdopodobieństwo otrzymania któregoś z ww. znaków jako wyniku szyfrowania jest dość spore;

0

Właśnie dlatego odradzam przechowywania szyfrowanych danych w plikach tekstowych, bo prawdopodobieństwo otrzymania któregoś z ww. znaków jako wyniku szyfrowania jest dość spore;

Aby nie przechowywać w pliku INI znaku nowej lini, zamieniłem numer znaku ASCII na HEX i taki przechowuję.

Ty w ogóle patrzysz co piszą inni Furious? Już dawno mu mówiłem o używaniu HEXa i on to robi.

Nie rób tego, takie rzeczy chowa się jak najgłebiej, żeby dociekliwy użytkownik nie mógł w prosty sposób ich odczytać; Szyfruj je i zapisuj do pliku choćby amorficznego - nie jest to oczywiście jako takie zabezpieczenie bo każdy nawet największy matoł potrafi znaleźć w sieci i pobrać jakiś Hex-edytor, ale zablokujesz możliwość otworzenia takiego pliku w edytorach tekstowych;

"Twoje lamerskie zabezpieczenie nie jest bezpieczne, ale moje lamerskie zabezpieczenie jest". Już lepiej użyć jakiś hash, będzie trochę bardziej życiowo (chociaż jeszcze nie na tyle bezpiecznie aby niemożliwe było odzyskanie hasła).

2
furious programming napisał(a):

Właśnie dlatego odradzam przechowywania szyfrowanych danych w plikach tekstowych, bo prawdopodobieństwo otrzymania któregoś z ww. znaków jako wyniku szyfrowania jest dość spore;
Ale jakie prawdopodobieństwo znowu? Trzeba tylko prawidłowo przetworzyć dane.

Podam przepis ogólny.

Mamy przykładowy zestaw dozwolonych znaków wejściowych:

PlainSet := '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()_=+`~[]{};"\:|,./<>?'

oraz wyjściowych

CipherSet := '0123456789ABCDEFabcdef'

Znaków wejściowych jest 92 czyli potrzeba nam 6,52 bita na każdy.
Znaków wyjściowych jest 22 czyli 4,46 bita na każdy.
Tak więc jedna porcja danych wejściowych daje się zapisać przy pomocy 6,52 bita. Jako, że będziemy XOR'ować te dane użyjemy pełnych 7-miu bitów. Każde 7 bitów można zapisać w 2 porcjach danych wyjściowych (7 <= 2 * 4,46).
W celu zmniejszenia redundancji można przyjąć inny stosunek i 2 porcje danych wejściowych kodować na 3 porcjach danych wyściowych. 2 porcje danych wejściowych to 2 * 6,52 = 13,04 bita. Jako, że będziemy XOR'ować użyjemy pełnych 14 bitów. Każde 14 bitów można zapisać w 3 porcjach danych wyjściowych (14 <= 3 * 4,46).

PlainSetLen := Length(PlainSet);
CipherSetLen := Length(CipherSet);
PlainPortionLen := 2;
CipherPortionLen := 3;
PortionBits := 14;

Przejdźmy do liczenia. Niech zdefiniowane będą funkcje:

{ zamienia znak na reprezentację bitową czyli indeks tego znaku w tablicy zestawu znaków }
function CharDecode(Data: Char, DataSet: String): Integer; begin Result := Pos(Data, DataSet); end;
{ odwrotność CharDecode }
function CharCode(Data: Integer; DataSet: String): Char; begin Result := DataSet[Data]; end;
{ zwraca 'count' kolejnych znaków wejściowych }
function ReadInputPortion(count: integer): String;
{ zapisuje znaki na wyjście }
function WriteOutputPortion(portion: String);
{ zwraca kolejne 'NumBits' bitów klucza szyfrującego (cyklicznie) }
function NextKeyPortion(NumBits: Integer): Integer;
{ resetuje 'NextKeyPortion' tak aby zaczęła zwracać bity od początku klucza }
procedure ResetKey();

I teraz transkodujemy informację:

procedure Transcode(
  InSet: String; InSetLen, InPortionLen: Integer; 
  OutSet: String; OutSetLen, OutPortionLen: Integer;
  PortionBits: Integer);
var
  InPortion, OutPortion: String;
  RawPortion: Integer;
  i: Integer;
begin
  ResetKey();
  SetLength(OutPortion, OutPortionLen);

  while True do
  begin
    { pobieramy porcję informacji }
    InPortion := ReadInputPortion(InPortionLen);
    if Length(InPortion) = 0 then break;

    { zamieniamy na informację bitową }
    RawPortion := 0;
    for i := 1 to InPortionLen do
    begin
      RawPortion := RawPortion * InSetLen;
      RawPortion := RawPortion + CharDecode(InPortion[i], InSet);
    end;

    { Szyfrujemy. Tutaj użyłem XOR'owania ale algorytm może być dowolny.
      Ważne jest aby porcja zaszyfrowana mieściła się w zakładanym 'PortionBits' }
    RawPortion := RawPortion xor NextKeyPortion(PortionBits);

    { zamieniamy na format wyjściowy }
    for i := 1 to OutPortionLen do
    begin
      OutPortion[i] := CharCode(RawPortion mod OutSetLen);
      RawPortion := RawPortion div OutSetLen;
    end;

    { zapisujemy wynik na wyjście }
    WriteOutputPortion(OutPortion);
  end;
end;

procedure PlainToCipher();
begin
  Transcode(
     PlainSet, PlainSetLen, PlainPortionLen,
     CipherSet, CipherSetLen, CipherPortionLen,
     PortionBits);
end;

procedure CipherToPlain();
begin
  Transcode(
     CipherSet, CipherSetLen, CipherPortionLen,
     PlainSet, PlainSetLen, PlainPortionLen,
     PortionBits);
end;

Przepis jest ogólny ale sporo może się uprościć np. dobierając tak zestawy znaków, aby dało się kodować 1 do 1.

Jeszcze jest kwestia z końcówką danych wejściowych, co zrobić jeśli ilość znaków wejściowych nie jest podzielna przez wielkość porcji wejściowej? Można sobie z tym radzić na różne sposoby. Np. dopełnić zerami (jeśli kodujemy tylko w jedną stronę) albo kodować redundantywnie po jednym znaku, albo dobrać zestawy znaków aby nie było "części ułamkowych" itp.

1 użytkowników online, w tym zalogowanych: 0, gości: 1