Jak szyfrować dane żeby zachowały kolejność na liście sortowanej?

0

Witam.
Zastanawiam się nad takim zagadnieniem. Jeszcze nie szukałem, w ten weekend chcę to zrobić, ale jeśli ktoś ma jakieś luźne skojarzenia to polecam się.

Załóżmy, że mamy tablice rekordów (raczej dynamiczna) i nie korzystając z żadnego narzędzia chcę w kodzie zrobić indeksowanie wg poszczególnych danych. Ale dane mają być szyfrowane również w pamięci i odczytywane tuż przy wyjściu/ wyświetleniu. Jak w miarę bezpiecznie (to ważniejsze) i niezbyt wolno je szyfrować.

a) dwie takie same dane występujące po sobie wyglądały inaczej. żeby nie można ich było porównać i skojarzyć.

b) dane posortowane nie szyfrowane i szyfrowane miały by taka samą kolejność.

c) struktura dowolna

Przyjmijmy, że wszystkie dane są stringami (np. liczby będą zamieniane na stringi). Przykład może być oparty na jedno wymiarowej array[0..4] of String. Stringi mają taka samą długość. np. 'aaa','bbb','ccc',ccc','ddd'.

Chyba ze to nie możliwe ale może jednak.

0

Po pierwsze jeśli szyfrujesz/deszyfrujesz dane i zaszywasz klucz w tym samym programie to nie da się zabezpieczyć danych w żaden sposób - dla crackera to tylko kwestia czasu.
Podpunkt a jest możliwy do realizacji jednak trudno będzie uniknąć kolizji
Podpunkt b jest całkowicie bez sensu, zwłaszcza z połączeniem z pkt. a - chcesz, aby równocześnie identyczne wartości dawały możliwie skrajnie różne szyfrogramy i do tego zachować oryginalną kolejność. Najzwyczajniej zostaw wynikowe stringi w takiej samej kolejności w jakiej był oryginał a skup się na podpunkcie a. Jeśli szyfrogramy będą miały dużą entropię to co komu po tym, że zna kolejność bezwartościowych śmieci, których nie może odczytać.

Napisz dlaczego w ogóle chcesz szyfrować dane w pamięci - pewnie uda się zaproponować lepsze rozwiązanie. Najlepiej napisz do czego służy program, czy dane mają być szyfrowane też w plikach, kiedy będzie podawany klucz i na jak długo przechowywany (jednorazowo czy na raz na czas działania programu).

0

Zalezy po co Ci te szyfrowane dane. Jesli planujesz je wyswietlic to posortuj przed wyswietleniem. Jesli klucz po ktorym szyfrujesz nie potrzebuje szyfrowania, a reszta danych tak to sortuj po tym kluczu, a reszte trzymaj zaszyfrowane. Zawsze mozesz np. pierwsze n liter zostawic niezaszyfrowanych i zaszyfrowac reszte. Generalnie nie widze sensu sortowania zaszyfrowanych danych.

0

Tak przypuszczałem, że założenia nie są zbyt ale tak jak wspomnieniem dopiero się do tego zabieram. Wiem że temat jest dość rozległy więc jak coś jest naciągane albo nie efektywne to mnie prostujcie. To z zachowaniem kolejności może faktycznie było przesadzone, więc stawiamy na bezpieczeństwo.

I może zawężę do konkretnego przypadku.

  1. Potrzebne są klasy obsługujące (pytam tylko o mechanizmy szyfrujące):
    a) licencje programu,
    b) profile użytkowników w programie;
    c) klasy były by stałymi elementami dodawanymi do każdego projektu/ programu, więc wskazana różnorodność, żeby nawet w przypadku zdebagowania jednego programu nie oznaczało to poznania algorytmów dla pozostałych programów. Więc domyślam się, że przynajmniej jeden element będzie niepowtarzalny dla każdego programu, jakiś fragment algorytmu. Ale może się mylę i nie ma takiej potrzeby.

  2. Właśnie dobrze by było żeby podejrzenie danych było jak najbardziej utrudnione na każdym etapie i jeśli to możliwe to na wejściu przetwarzaniu i wyjściu. Po nocnych przemyśleniach zastanawiam się nad kluczem prywatnym i publicznym, ale w tej chwili to na razie luźna myśl.

1

Kiedyś napisałem program szyfrujący. Szyfrował tylko tekst.
Tu masz link do ściągnięcia: http://chomikuj.pl/pawel24pl/Programy/koder+pro.exe
Ta wersja koduje na trzy hasła.
Wersję z jednym hasłem przedstawiłem na YT:
Użyłem do tego tablicy ASCII. Przykład:

278!406!445!446!435!204!250!262!266!376!438!420!409!197!305!327!392!430!428!326!

Kodowanie:

 
var
petla, petla2, wartosc, przejscie, wartosc2, przejscie2, wartosc3, przejscie3 : integer;
out1 , haslo1, haslo2, haslo3: string;
begin
memo2.Clear;
For petla := 0 to memo1.Lines.Count -1 do begin
out1 := '';
     przejscie := 1;
     przejscie2 := 1;
     przejscie3 := 1;
     haslo1 := edit1.Text + '1' + ReverseString(edit2.Text) ;
     haslo2 := ReverseString(edit2.Text) + '22' + edit3.Text ;
     haslo3 := edit3.Text + '333'+ ReverseString(edit1.Text) ;

   For petla2 :=1 to length(memo1.Lines[petla]) do begin

     wartosc := ord(haslo1[przejscie]) + ord(haslo2[przejscie2])+ord(haslo3[przejscie3]);
     Inc(przejscie); Inc(przejscie2); Inc(przejscie3);
     If przejscie > length(haslo1) then przejscie := 0;
     If przejscie2 > length(haslo2) then przejscie2 := 0;
     If przejscie3 > length(haslo3) then przejscie3 := 0;

     out1 := out1 + inttostr(ord(memo1.Lines[petla][petla2])+wartosc)+'!';

   end;
   memo2.Lines.Add(out1);
end;

Dekodowanie:

var
petla, petla2,  wartosc, przejscie, wartosc2, przejscie2, wartosc3, przejscie3  : integer;
out1 , haslo1, haslo2, haslo3: string;
lista: Tstrings;
begin
lista := TstringList.Create;
 memo1.Clear;
try

For petla := 0 to memo2.Lines.Count-1 do begin
 lista.clear;
   ExtractStrings(['!'], [], pchar(memo2.Lines[petla]) ,lista);
   out1 := ' ';
     przejscie := 1;
     przejscie2 := 1;
     przejscie3 := 1;
     przejscie3 := 1;
     haslo1 := edit1.Text + '1' + ReverseString(edit2.Text) ;
     haslo2 := ReverseString(edit2.Text) + '22' + edit3.Text ;
     haslo3 := edit3.Text + '333'+ReverseString(edit1.Text) ;
   for petla2 := 0 to lista.Count -1 do begin

     wartosc := ord(haslo1[przejscie]) + ord(haslo2[przejscie2]) + ord(haslo3[przejscie3]);
     Inc(przejscie); Inc(przejscie2); Inc(przejscie3);
     If przejscie > length(haslo1) then przejscie := 0;
     If przejscie2 > length(haslo2) then przejscie2 := 0;
     If przejscie3 > length(haslo3) then przejscie3 := 0;

    out1 := out1 + chr(strtoint(lista[petla2])-wartosc);


    end;
   out1 := trim(out1);
 memo1.Lines.Add(out1);
end;
  except end;

end;
 

Mam nadzieję, że pomogłem.

1

Algorytm szyfrujący nie musi być tajny. Do szyfrowania profili osobiście użyłbym jakiegoś szyfru symetrycznego np. AES'a. Użytkownik wybierając swój profil podaje hasło które służy do rozszyfrowania np. pliku z profilem. Szyfrowanie danych podczas działania programu jest raczej zbędne - problem w tym, że za każdym razem kiedy chciałbyś użyć "tajnych" danych musiałbyś podać klucz, co przy częstym używaniu byłoby uciążliwe dla użytkownika. Z drugiej strony jeśli zapamiętasz klucz na cały czas działania programu to będzie możliwy do wygrzebania gdzieś z pamięci. Żeby atakujący mógł zrobić z tego użytek (czyli sczytać pamięć programu) musiałby mieć i tak już dostęp do maszyny - a tu już może posłużyć się prostym keyloggerem.
Co do sprawdzania licencji to tu już gorzej bo możesz tylko utrudnić napisanie generatora kluczy dla twojego programu przez atakującego. Atakujący nie musi nawet starać się szukać odpowiedniego algorytmu tylko zrobi skok, który ominie sprawdzanie licencji. Zatem przed stworzeniem crack'a się nie zabezpieczysz, możesz tylko to utrudnić. Chyba, że najważniejsza część programu byłaby po stronie serwerowej a program kliencki tylko wysyłał by zlecenia np. przeprowadzenia jakiegoś działania na wybranym pliku. Każdy użytkownik miałby założone konto na serwerze zdalnym - bez opłacenia licencji konta nie założy a na serwerze możesz sobie zliczać np. ilość użyć itp.

0

Dzięki @pawel24pl . Wszelkie przykłady linki mile widziane. Chodzi mi o nowe spojrzenie na szyfrowanie a skoro klasa miała by być "uniwersalna" więc muszę maksymalnie skomplikować sprawę. Czasem najprostsze rzeczy są najlepsze. Podejrzewam, że będzie kilka szyfrowań i wybór dla danej aplikacji na zasadzie losowej uzależniony od "czegoś". Jak to dokładnie ma wyglądać to właśnie badam temat żeby nie narobić "szkolnych błędów" jako że specjalista nie jestem a nie chciałbym żeby to się dało w 5 minut obejść.

@szopenfx wiem, że przed crakami będzie ciężko. Po twojej wypowiedzi dotarło do mnie, że nie obejdzie się bez kilku "odmian". Bo jeszcze trafia się potrzeba, żeby zabezpieczyć program licencją, który niestety nie ma dostępu online. 

Co do serwera to nie myślałem o czymś takim i chyba nie mam takiej możliwości na razie, co najwyżej baza MySQL ale zostawię furtkę na rozbudowę. Tak że jest nad czym myśleć.

2

@Integers Może bardzo późno, ale znalazłem (choćby dla przyszłych pokoleń).
Szyfrowanie enigmą.
Robisz tak przy pierwszym uruchomieniu:

  1. Generujesz podczas instalacji dyski.
  2. Zapisujesz do pliku.
    3 Korzystasz z procedur i funkcji
    Przy kolejnym uruchomieniu:
  3. Otwierasz dyski
    2 Korzystasz z procedur i funkcji

Przy stworzeniu klasy podajesz ścieżkę do dysków, a w następnym, czy utworzyć jeżeli nie istnieją.
Jeżeli dysków nie będzie , uruchomi Ci się bez dysków i będziesz musiał je ręcznie załadować.
Wszystko w załączniku.

PS Enigma jest szyfrem symetrycznym, tzn. zaszyfrowana szyfracja jest odszyfrowana.

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