techniki zaciemniania wrażliwych ciągów w C ++


87

Muszę przechowywać poufne informacje (symetryczny klucz szyfrowania, który chcę zachować dla siebie) w mojej aplikacji C ++. Prostym podejściem jest zrobienie tego:

std::string myKey = "mysupersupersecretpasswordthatyouwillneverguess";

Jednak uruchomienie aplikacji przez stringsproces (lub inny, który wyodrębnia ciągi z aplikacji binarnej) ujawni powyższy ciąg.

Jakie techniki należy zastosować, aby ukryć takie wrażliwe dane?

Edytować:

OK, więc prawie wszyscy powiedzieliście: „Twój plik wykonywalny może zostać poddany inżynierii wstecznej” - oczywiście! To moje zwierzę domowe irytu, więc mam zamiar trochę narzekać tutaj:

Dlaczego na 99% (OK, więc może trochę przesadzam) wszystkich pytań związanych z bezpieczeństwem na tej stronie odpowiada torrent „nie ma możliwości stworzenia całkowicie bezpiecznego programu” - to nie jest pomocne odpowiedź! Bezpieczeństwo to przesuwająca się skala pomiędzy doskonałą użytecznością i brakiem bezpieczeństwa z jednej strony, a doskonałym bezpieczeństwem, ale brakiem użyteczności z drugiej.

Chodzi o to, że wybierasz swoją pozycję na tej ruchomej skali w zależności od tego, co próbujesz zrobić i środowiska, w którym będzie działać Twoje oprogramowanie. Nie piszę aplikacji do instalacji wojskowej, piszę aplikację na domowy komputer . Muszę zaszyfrować dane w niezaufanej sieci za pomocą wcześniej znanego klucza szyfrowania. W takich przypadkach „bezpieczeństwo przez zaciemnienie” jest prawdopodobnie wystarczające! Jasne, ktoś z wystarczającą ilością czasu, energii i umiejętności mógłby odtworzyć plik binarny i znaleźć hasło, ale wiecie co? Nie obchodzi mnie:

Czas potrzebny na wdrożenie bezpiecznego systemu na najwyższym poziomie jest droższy niż utrata sprzedaży z powodu pękniętych wersji (nie to, że faktycznie to sprzedaję, ale rozumiesz, o co mi chodzi). Ten modny trend w programowaniu wśród nowych programistów „pozwala robić to w najlepszy możliwy sposób” jest co najmniej głupi.

Dziękuję za poświęcenie czasu na odpowiedź na to pytanie - okazały się one bardzo pomocne. Niestety mogę zaakceptować tylko jedną odpowiedź, ale przegłosowałem wszystkie przydatne odpowiedzi.


2
Być może, jeśli opiszesz, co próbujesz osiągnąć za pomocą klucza szyfrowania, możemy zaoferować porady, jak tego uniknąć.
joshperry


4
@Kirill: trudno nazwać to pytanie dokładnie tak samo, jak to, o którym wspomniałeś. Rzeczywiście, idea jest taka sama. To nie jest kwestia.
xtofl

1
@xtofl, możesz nie głosować. Dla mnie wygląda to na dwa identyczne pytania.
Kirill V. Lyadvinsky

2
(Nie ma związku z rantem) Sama definicja „klucza prywatnego” to połowa pary kluczy publiczny / prywatny, której nie podajesz. W tym przypadku klucz prywatny jest tym, który przechowujesz na serwerze; ten w aplikacji klienta jest publiczny.
MSalters

Odpowiedzi:


42

Zasadniczo, każdy z dostępem do swojego programu i debugger może i będzie znaleźć klucz w aplikacji, jeśli chcą.

Ale jeśli chcesz się tylko upewnić, że klucz nie pojawia się podczas uruchamiania stringsna twoim pliku binarnym, możesz na przykład upewnić się, że klucz nie znajduje się w zakresie drukowalnym.

Ukryty klucz z XOR

Na przykład możesz użyć XOR do podzielenia klucza na dwie tablice bajtowe:

key = key1 XOR key2

Jeśli utworzysz klucz1 o tej samej długości bajtów, keyjaką możesz użyć (całkowicie) losowych wartości bajtów, a następnie obliczysz key2:

key1[n] = crypto_grade_random_number(0..255)
key2[n] = key[n] XOR key1[n]

Można to zrobić w środowisku kompilacji, a następnie przechowywać tylko key1i key2w aplikacji.

Ochrona twojego pliku binarnego

Innym podejściem jest użycie narzędzia do ochrony pliku binarnego. Na przykład istnieje kilka narzędzi bezpieczeństwa, które mogą upewnić się, że plik binarny jest zaciemniony i uruchamia maszynę wirtualną, na której działa. Utrudnia to debugowanie, a także jest konwencjonalnym sposobem ochrony wielu bezpiecznych aplikacji klasy komercyjnej (również, niestety, złośliwego oprogramowania).

Jednym z najlepszych narzędzi jest Themida , która świetnie chroni Twoje pliki binarne. Jest często używany przez dobrze znane programy, takie jak Spotify, do ochrony przed inżynierią wsteczną. Posiada funkcje zapobiegające debugowaniu w programach takich jak OllyDbg i Ida Pro.

Istnieje również większa lista, być może nieco przestarzała, narzędzi do ochrony Twojego pliku binarnego .
Niektóre z nich są bezpłatne.

Dopasowanie hasła

Ktoś tutaj omówił haszowanie hasła + sól.

Jeśli chcesz zapisać klucz, aby dopasować go do jakiegoś hasła przesłanego przez użytkownika, powinieneś użyć jednokierunkowej funkcji mieszającej, najlepiej łącząc nazwę użytkownika, hasło i sól. Problem z tym polega jednak na tym, że twoja aplikacja musi znać sól, aby móc wykonać jednokierunkowe i porównać wynikowe hashe. Dlatego nadal musisz przechowywać sól gdzieś w aplikacji. Jednak, jak @Edward wskazuje w komentarzach poniżej, będzie to skutecznie chronić przed atakiem słownikowym przy użyciu np. Tęczowych tabel.

Wreszcie możesz użyć kombinacji wszystkich powyższych technik.


Jeśli jest to hasło, które użytkownik musi wprowadzić, zapisz skrót + sól hasła. Zobacz odpowiedź poniżej.

1
@hapalibashi: Jak bezpiecznie przechowywać sól w swojej aplikacji? Nie sądzę, by OP potrzebował jednokierunkowego systemu dopasowywania haseł, tylko uogólniony sposób przechowywania kluczy statycznych.
csl

2
Kiedy patrzyłem na zdemontowane programy, zwykle nie ma zbyt wielu XORów, więc jeśli masz nadzieję użyć XOR do zasłonięcia czegoś, pamiętaj, że zwracają uwagę na siebie.
kb.

2
@kb - to interesujący punkt. Sądzę, że zobaczysz bitowe ands i ors zdarzające się znacznie częściej niż xor. a ^ b == (a & ~ b) || (~ a & b)
Jeremy Powell

4
Znajomość wartości soli zwykle nie daje przeciwnikowi przewagi - celem solenia jest uniknięcie „ataku słownikowego”, w którym atakujący wstępnie obliczył skróty dla wielu prawdopodobnych danych wejściowych. Użycie soli zmusza ich do wstępnego obliczenia swojego słownika z nowym, opartym na soli. Jeśli każda sól zostanie użyta tylko raz, atak słownikowy stanie się całkowicie bezużyteczny.
Edward Dixon,

8

Przede wszystkim zdaj sobie sprawę, że nie możesz zrobić nic, co powstrzymałoby wystarczająco zdeterminowanego hakera, a takich wokół jest mnóstwo. Ochrona w każdej grze i konsoli w pobliżu jest w końcu pęknięta, więc jest to tylko tymczasowa poprawka.

Są 4 rzeczy, które możesz zrobić, aby zwiększyć swoje szanse na pozostanie w ukryciu.

1) Ukryj w jakiś sposób elementy łańcucha - coś tak oczywistego, jak xoring (operator ^), łańcuch z innym łańcuchem będzie wystarczająco dobry, aby łańcuch nie był możliwy do wyszukania.

2) Podziel ciąg na części - podziel ciąg i rozbijaj jego fragmenty na dziwnie nazwane metody w dziwnych modułach. Nie ułatwiaj przeszukiwania i znajdowania metody zawierającej ciąg. Oczywiście jakaś metoda będzie musiała wywołać wszystkie te bity, ale nadal będzie to trochę trudniejsze.

3) Nigdy nie buduj łańcucha w pamięci - większość hakerów używa narzędzi, które pozwalają im zobaczyć łańcuch w pamięci po zakodowaniu go. Jeśli to możliwe, unikaj tego. Jeśli na przykład wysyłasz klucz do serwera, wysyłaj go znak po znaku, aby nigdy nie było całego ciągu. Oczywiście, jeśli używasz go z czegoś takiego jak kodowanie RSA, jest to trudniejsze.

4) Wykonaj algorytm ad-hoc - do tego wszystkiego dodaj unikalny zwrot akcji lub dwa. Może po prostu dodaj 1 do wszystkiego, co wyprodukujesz, lub wykonaj szyfrowanie dwa razy lub dodaj cukier. To tylko utrudnia hakerowi, który już wie, czego szukać, gdy ktoś używa na przykład waniliowego haszowania md5 lub szyfrowania RSA.

Przede wszystkim upewnij się, że nie jest zbyt ważne, kiedy (i będzie, gdy aplikacja stanie się wystarczająco popularna) zostanie odkryty Twój klucz!


5

Strategia, której używałem w przeszłości, polega na tworzeniu tablicy pozornie przypadkowych znaków. Początkowo wstawiasz, a następnie lokalizujesz określone znaki za pomocą procesu algebraicznego, w którym każdy krok od 0 do N daje numer <rozmiar tablicy, która zawiera następny znak w zaciemnionym ciągu. (Ta odpowiedź wydaje się teraz zaciemniona!)

Przykład:

Biorąc pod uwagę tablicę znaków (liczby i myślniki służą wyłącznie jako odniesienie)

0123456789
----------
ALFHNFELKD
LKFKFLEHGT
FLKRKLFRFK
FJFJJFJ!JL

I równanie, którego pierwszych sześć wyników to: 3, 6, 7, 10, 21, 47

Dałoby słowo „HELLO!” z tablicy powyżej.


Dobry pomysł - myślę, że można go jeszcze bardziej ulepszyć, używając niedrukowalnych znaków w tablicy ...
Thomi

4

Zgadzam się z @Checkers, twój plik wykonywalny może zostać odtworzony.

Nieco lepszym sposobem jest tworzenie go dynamicznie, na przykład:

std::string myKey = part1() + part2() + ... + partN();

To prawda, że ​​pozwala to uniknąć ujawnienia ciągu podczas przeszukiwania pliku binarnego. Jednak twój ciąg jest nadal rezydujący w pamięci. Twoje rozwiązanie jest jednak prawdopodobnie wystarczająco dobre do tego, co robię.
Thomi

@Thomi, oczywiście możesz go zniszczyć , gdy tylko z nim skończysz. Jednak nadal nie jest to najlepszy sposób obsługi wrażliwych ciągów znaków.
Nick Dandoulakis

... ponieważ jej zniszczenie nie gwarantuje, że pamięć zostanie od razu ponownie wykorzystana.
Thomi

4

Oczywiście przechowywanie prywatnych danych w oprogramowaniu wysyłanym do użytkownika jest zawsze ryzykowne. Każdy wystarczająco wykształcony (i oddany) inżynier może odtworzyć dane.

Biorąc to pod uwagę, często można zapewnić wystarczające bezpieczeństwo, podnosząc barierę, którą ludzie muszą pokonać, aby ujawnić swoje prywatne dane. To zwykle dobry kompromis.

W twoim przypadku możesz zaśmiecać swoje ciągi danymi niedrukowalnymi, a następnie zdekodować je w czasie wykonywania za pomocą prostej funkcji pomocniczej, takiej jak ta:

void unscramble( char *s )
{
    for ( char *str = s + 1; *str != 0; str += 2 ) {
        *s++ = *str;
    }
    *s = '\0';
}

void f()
{
    char privateStr[] = "\001H\002e\003l\004l\005o";
    unscramble( privateStr ); // privateStr is 'Hello' now.

    string s = privateStr;
    // ...
}

4

Stworzyłem proste narzędzie do szyfrowania ciągów, które może automatycznie generować zaszyfrowane ciągi i ma kilka dodatkowych opcji, aby to zrobić, kilka przykładów:

Ciąg jako zmienna globalna:

// myKey = "mysupersupersecretpasswordthatyouwillneverguess";
unsigned char myKey[48] = { 0xCF, 0x34, 0xF8, 0x5F, 0x5C, 0x3D, 0x22, 0x13, 0xB4, 0xF3, 0x63, 0x7E, 0x6B, 0x34, 0x01, 0xB7, 0xDB, 0x89, 0x9A, 0xB5, 0x1B, 0x22, 0xD4, 0x29, 0xE6, 0x7C, 0x43, 0x0B, 0x27, 0x00, 0x91, 0x5F, 0x14, 0x39, 0xED, 0x74, 0x7D, 0x4B, 0x22, 0x04, 0x48, 0x49, 0xF1, 0x88, 0xBE, 0x29, 0x1F, 0x27 };

myKey[30] -= 0x18;
myKey[39] -= 0x8E;
myKey[3] += 0x16;
myKey[1] += 0x45;
myKey[0] ^= 0xA2;
myKey[24] += 0x8C;
myKey[44] ^= 0xDB;
myKey[15] ^= 0xC5;
myKey[7] += 0x60;
myKey[27] ^= 0x63;
myKey[37] += 0x23;
myKey[2] ^= 0x8B;
myKey[25] ^= 0x18;
myKey[12] ^= 0x18;
myKey[14] ^= 0x62;
myKey[11] ^= 0x0C;
myKey[13] += 0x31;
myKey[6] -= 0xB0;
myKey[22] ^= 0xA3;
myKey[43] += 0xED;
myKey[29] -= 0x8C;
myKey[38] ^= 0x47;
myKey[19] -= 0x54;
myKey[33] -= 0xC2;
myKey[40] += 0x1D;
myKey[20] -= 0xA8;
myKey[34] ^= 0x84;
myKey[8] += 0xC1;
myKey[28] -= 0xC6;
myKey[18] -= 0x2A;
myKey[17] -= 0x15;
myKey[4] ^= 0x2C;
myKey[9] -= 0x83;
myKey[26] += 0x31;
myKey[10] ^= 0x06;
myKey[16] += 0x8A;
myKey[42] += 0x76;
myKey[5] ^= 0x58;
myKey[23] ^= 0x46;
myKey[32] += 0x61;
myKey[41] ^= 0x3B;
myKey[31] ^= 0x30;
myKey[46] ^= 0x6C;
myKey[35] -= 0x08;
myKey[36] ^= 0x11;
myKey[45] -= 0xB6;
myKey[21] += 0x51;
myKey[47] += 0xD9;

Jako ciąg znaków Unicode z pętlą deszyfrującą:

// myKey = "mysupersupersecretpasswordthatyouwillneverguess";
wchar_t myKey[48];

myKey[21] = 0x00A6;
myKey[10] = 0x00B0;
myKey[29] = 0x00A1;
myKey[22] = 0x00A2;
myKey[19] = 0x00B4;
myKey[33] = 0x00A2;
myKey[0] = 0x00B8;
myKey[32] = 0x00A0;
myKey[16] = 0x00B0;
myKey[40] = 0x00B0;
myKey[4] = 0x00A5;
myKey[26] = 0x00A1;
myKey[18] = 0x00A5;
myKey[17] = 0x00A1;
myKey[8] = 0x00A0;
myKey[36] = 0x00B9;
myKey[34] = 0x00BC;
myKey[44] = 0x00B0;
myKey[30] = 0x00AC;
myKey[23] = 0x00BA;
myKey[35] = 0x00B9;
myKey[25] = 0x00B1;
myKey[6] = 0x00A7;
myKey[27] = 0x00BD;
myKey[45] = 0x00A6;
myKey[3] = 0x00A0;
myKey[28] = 0x00B4;
myKey[14] = 0x00B6;
myKey[7] = 0x00A6;
myKey[11] = 0x00A7;
myKey[13] = 0x00B0;
myKey[39] = 0x00A3;
myKey[9] = 0x00A5;
myKey[2] = 0x00A6;
myKey[24] = 0x00A7;
myKey[46] = 0x00A6;
myKey[43] = 0x00A0;
myKey[37] = 0x00BB;
myKey[41] = 0x00A7;
myKey[15] = 0x00A7;
myKey[31] = 0x00BA;
myKey[1] = 0x00AC;
myKey[47] = 0x00D5;
myKey[20] = 0x00A6;
myKey[5] = 0x00B0;
myKey[38] = 0x00B0;
myKey[42] = 0x00B2;
myKey[12] = 0x00A6;

for (unsigned int fngdouk = 0; fngdouk < 48; fngdouk++) myKey[fngdouk] ^= 0x00D5;

Ciąg jako zmienna globalna:

// myKey = "mysupersupersecretpasswordthatyouwillneverguess";
unsigned char myKey[48] = { 0xAF, 0xBB, 0xB5, 0xB7, 0xB2, 0xA7, 0xB4, 0xB5, 0xB7, 0xB2, 0xA7, 0xB4, 0xB5, 0xA7, 0xA5, 0xB4, 0xA7, 0xB6, 0xB2, 0xA3, 0xB5, 0xB5, 0xB9, 0xB1, 0xB4, 0xA6, 0xB6, 0xAA, 0xA3, 0xB6, 0xBB, 0xB1, 0xB7, 0xB9, 0xAB, 0xAE, 0xAE, 0xB0, 0xA7, 0xB8, 0xA7, 0xB4, 0xA9, 0xB7, 0xA7, 0xB5, 0xB5, 0x42 };

for (unsigned int dzxykdo = 0; dzxykdo < 48; dzxykdo++) myKey[dzxykdo] -= 0x42;

Nie, do pracy wykorzystałem stronę stringencrypt.com . Zawiera przykłady C / C ++ stringencrypt.com/c-cpp-encryption, które możesz rozważyć, aby zautomatyzować proste szyfrowanie ciągów.
Bartosz Wójcik

2

W pewnym stopniu zależy od tego, co próbujesz chronić, jak wskazuje Joshperry. Z doświadczenia powiedziałbym, że jeśli jest to część jakiegoś schematu licencjonowania w celu ochrony oprogramowania, nie przejmuj się. W końcu dokonają inżynierii wstecznej. Po prostu użyj prostego szyfru, takiego jak ROT-13, aby zabezpieczyć go przed prostymi atakami (ciągami znaków na nim). Jeśli ma zabezpieczyć wrażliwe dane użytkowników, zastanawiałbym się, czy ochrona tych danych za pomocą klucza prywatnego przechowywanego lokalnie jest mądrym posunięciem. Znowu wszystko sprowadza się do tego, co próbujesz chronić.

EDYCJA: Jeśli masz zamiar to zrobić, połączenie technik, które wskazuje Chris, będzie o wiele lepsze niż rot13.


2

Jak zostało powiedziane wcześniej, nie ma sposobu, aby całkowicie chronić swój ciąg. Ale są sposoby, aby go chronić, zapewniając rozsądne bezpieczeństwo.

Kiedy musiałem to zrobić, umieściłem w kodzie jakiś niewinnie wyglądający ciąg znaków (na przykład informacja o prawach autorskich, fałszywy monit użytkownika lub cokolwiek innego, co nie zostanie zmienione przez kogoś, kto naprawi niepowiązany kod), zaszyfrował to używając samego siebie jako klucz, zaszyfrowałem to (dodając trochę soli) i wykorzystałem wynik jako klucz do zaszyfrowania tego, co faktycznie chciałem zaszyfrować.

Oczywiście można to zhakować, ale zrobienie tego wymaga zdeterminowanego hakera.


Dobry pomysł - inną formą niejasności jest użycie łańcucha, który jest nadal dość mocny (długi, interpunkcyjny i cały ten jazz), ale oczywiście nie wygląda jak hasło.
Thomi

1

Jeśli korzystasz z interfejsu DPAPI użytkownika systemu Windows, http://msdn.microsoft.com/en-us/library/ms995355.aspx

Jak powiedział poprzedni post, jeśli korzystasz z komputera Mac, użyj pęku kluczy.

Zasadniczo wszystkie te urocze pomysły dotyczące przechowywania klucza prywatnego w pliku binarnym są na tyle słabe z punktu widzenia bezpieczeństwa, że ​​nie powinieneś ich robić. Każdy, kto otrzyma Twój klucz prywatny, to wielka sprawa, nie trzymaj go w swoim programie. W zależności od tego, jak zaimportujesz aplikację, możesz przechowywać klucze prywatne na karcie inteligentnej, na zdalnym komputerze, z którym komunikuje się Twój kod lub możesz robić to, co robi większość ludzi i przechowywać je w bardzo bezpiecznym miejscu na komputerze lokalnym (klucz store ”, który jest czymś w rodzaju dziwnego bezpiecznego rejestru), który jest chroniony przez uprawnienia i całą moc systemu operacyjnego.

To jest rozwiązany problem, a odpowiedzią nie jest przechowywanie klucza w programie :)


1

Spróbuj tego . Kod źródłowy wyjaśnia, jak szyfrować i odszyfrowywać w locie wszystkie ciągi w danym projekcie C ++ programu Visual Studio.


1

Ostatnio wypróbowałem jedną z metod:

  1. Weź skrót (SHA256) prywatnych danych i wypełnij go w kodzie jako part1
  2. Weź XOR prywatnych danych i ich hash i wypełnij je w kodzie jako part2
  3. Wypełniaj dane: nie przechowuj ich jako ciąg znaków [], ale wypełniaj je w czasie wykonywania za pomocą instrukcji przypisania (jak pokazano w makrze poniżej)
  4. Teraz wygeneruj prywatne dane w czasie wykonywania, biorąc XOR part1ipart2
  5. Dodatkowy krok : Oblicz hash wygenerowanych danych i porównaj je z part1. Sprawdzi integralność prywatnych danych.

MAKRO do wypełniania danych:

Załóżmy, że dane prywatne mają 4 bajty. Definiujemy dla niego makro, które zapisuje dane z instrukcjami przypisania w losowej kolejności.

#define POPULATE_DATA(str, i0, i1, i2, i3)\
{\
    char *p = str;\
    p[3] = i3;\
    p[2] = i2;\
    p[0] = i0;\
    p[1] = i1;\
}

Teraz użyj tego makra w kodzie, w którym musisz zapisać part1i part2w następujący sposób:

char part1[4] = {0};
char part2[4] = {0};
POPULATE_DATA(part1, 1, 2, 3, 4); 
POPULATE_DATA(part2, 5, 6, 7, 8);

1

Istnieje (bardzo lekki) zaciemniony projekt zawierający tylko nagłówek, stworzony przez adamyaxley, który działa doskonale. Opiera się na funkcjach lambda i makrach i szyfruje łańcuchy tekstowe za pomocą szyfru XOR w czasie kompilacji. W razie potrzeby możemy zmienić ziarno dla każdego sznurka.

Poniższy kod nie zachowa ciągu „hello world” w skompilowanym pliku binarnym.

#include "obfuscate.h"

int main()
{
  std::cout << AY_OBFUSCATE("Hello World") << std::endl;
  return 0;
}

Testowałem z C ++ 17 i Visual Studio 2019 i sprawdzam przez IDA i potwierdzam, że ciąg jest ukryty. Jedną cenną zaletą w porównaniu do ADVobfuscator jest to, że można go konwertować na std :: string (będąc nadal ukrytym w skompilowanym pliku binarnym):

std::string var = AY_OBFUSCATE("string");

0

Zamiast przechowywać klucz prywatny w swoim pliku wykonywalnym, możesz zażądać go od użytkownika i zapisać go za pomocą zewnętrznego menedżera haseł , czegoś podobnego do Dostępu do pęku kluczy w systemie Mac OS X.


no tak i nie ... normalnie zgodziłbym się z tobą, ale w tym przypadku staram się to ukryć przed użytkownikiem oprogramowania, więc przechowywanie go w systemie zewnętrznym nie jest dobrym pomysłem (wiele systemów pęku kluczy może ujawniać hasła jako zwykły tekst użytkownikom posiadającym odpowiednie uprawnienia). Oprogramowanie pęku kluczy doskonale nadaje się do haseł użytkowników, ale nie jest tak dobre do kluczy szyfrowania aplikacji.
Thomi

jeśli czujesz się niepewnie (choć biorąc pod uwagę twoje wyjaśnienia, może to jest wystarczające), możesz połączyć brelok z czymś zakodowanym na stałe :)

0

Zależne od kontekstu, ale możesz po prostu przechowywać skrót klucza i sól (stały ciąg, łatwy do zaciemnienia).

Następnie, gdy (jeśli) użytkownik wprowadzi klucz, dodajesz sól , obliczasz hash i porównujesz.

Sól jest prawdopodobnie niepotrzebne w tym przypadku, to zatrzymuje atak brute-force słownika jeśli hash można wydzielić (a wyszukiwarka Google została również wiedzieć, aby pracy).

Haker nadal musi tylko gdzieś wstawić instrukcję jmp, aby ominąć całość, ale jest to raczej bardziej skomplikowane niż proste wyszukiwanie tekstu.


To jest klucz szyfrowania, a nie skrót hasła. Potrzebuję aktualnego klucza do kodowania i dekodowania danych. Użytkownik nigdy nie widzi klucza, nigdy nie jest on przechowywany poza plikiem binarnym.
Thomi
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.