Tworzę aplikację, która będzie przechowywać hasła, które użytkownik może odzyskać i zobaczyć. Hasła dotyczą urządzenia sprzętowego, więc nie ma mowy o sprawdzaniu ich pod kątem skrótów.
Muszę wiedzieć:
Jak zaszyfrować i odszyfrować hasło w PHP?
Jaki jest najbezpieczniejszy algorytm szyfrowania haseł?
Gdzie mogę przechowywać klucz prywatny?
Czy zamiast przechowywać klucz prywatny, warto wymagać od użytkowników wprowadzenia klucza prywatnego za każdym razem, gdy potrzebują odszyfrowania hasła? (Można zaufać użytkownikom tej aplikacji)
W jaki sposób można ukraść i odszyfrować hasło? Czego muszę być świadomy?
php
security
encryption
passwords
HajdarA
źródło
źródło
Odpowiedzi:
Osobiście użyłbym tak,
mcrypt
jak inni opublikowali. Ale jest o wiele więcej wartych uwagi ...Jak zaszyfrować i odszyfrować hasło w PHP?
Poniżej znajdziesz silną klasę, która zajmie się wszystkim za Ciebie:
Jaki jest najbezpieczniejszy algorytm szyfrowania haseł?
najbezpieczniejszy ? ktokolwiek z nich. Najbezpieczniejszą metodą, jeśli zamierzasz szyfrować, jest ochrona przed lukami w ujawnianiu informacji (XSS, zdalne włączanie itp.). Jeśli się wydostanie, atakujący może w końcu złamać szyfrowanie (żadne szyfrowanie nie jest w 100% nieodwracalne bez klucza - jak zauważa @NullUserException, nie jest to do końca prawdą. Istnieją pewne schematy szyfrowania, których nie można złamać, takie jak OneTimePad ) .
Gdzie mogę przechowywać klucz prywatny?
Chciałbym użyć 3 kluczy. Jeden jest dostarczany przez użytkownika, jeden jest specyficzny dla aplikacji, a drugi dla użytkownika (jak sól). Klucz aplikacji może być przechowywany w dowolnym miejscu (w pliku konfiguracyjnym poza katalogiem głównym, w zmiennej środowiskowej itp.). Specyficzne dla użytkownika będzie przechowywane w kolumnie w bazie danych obok zaszyfrowanego hasła. Podany przez użytkownika nie byłby przechowywany. Następnie zrobiłbyś coś takiego:
Zaletą jest to, że dowolne 2 klucze mogą zostać naruszone bez narażania danych. W przypadku ataku typu SQL Injection mogą zdobyć
$userKey
drugie 2. Jeśli istnieje exploit na serwerze lokalnym, mogą zdobyć$userKey
i$serverKey
, ale nie trzeci$userSuppliedKey
. Jeśli pobiją użytkownika kluczem, mogą dostać$userSuppliedKey
, ale pozostałe 2 nie (ale z drugiej strony, jeśli użytkownik zostanie pobity kluczem, i tak spóźnisz się).Czy zamiast przechowywać klucz prywatny, warto wymagać od użytkowników wprowadzenia klucza prywatnego za każdym razem, gdy potrzebują odszyfrowania hasła? (Można zaufać użytkownikom tej aplikacji)
Absolutnie. Właściwie to jedyny sposób, w jaki bym to zrobił. W przeciwnym razie musisz przechowywać niezaszyfrowaną wersję w trwałym formacie pamięci (pamięć współdzielona, taka jak APC lub memcached, lub w pliku sesji). To narażanie się na dodatkowe kompromisy. Nigdy nie przechowuj niezaszyfrowanej wersji hasła w niczym z wyjątkiem zmiennej lokalnej.
W jaki sposób można ukraść i odszyfrować hasło? Czego muszę być świadomy?
Każda forma naruszenia bezpieczeństwa Twoich systemów umożliwi im przeglądanie zaszyfrowanych danych. Jeśli mogą wstrzyknąć kod lub dostać się do systemu plików, mogą przeglądać odszyfrowane dane (ponieważ mogą edytować pliki, które odszyfrowują dane). Każda forma ataku typu Replay lub MITM zapewni im również pełny dostęp do odpowiednich kluczy. Sniffowanie nieprzetworzonego ruchu HTTP również da im klucze.
Używaj SSL dla całego ruchu. I upewnij się, że nic na serwerze nie ma jakichkolwiek luk w zabezpieczeniach (CSRF, XSS, SQL Injection, Eskalacja uprawnień, zdalne wykonanie kodu itp.).
Edycja: Oto implementacja klasy PHP silnej metody szyfrowania:
Należy pamiętać, że używam funkcji dodana w PHP 5.6:
hash_equals
. Jeśli masz mniej niż 5,6, możesz użyć tej zastępczej funkcji, która implementuje funkcję porównywania z bezpiecznym czasem, używając podwójnej weryfikacji HMAC :Stosowanie:
Następnie, aby odszyfrować:
Zwróć uwagę, że użyłem
$e2
drugiego razu, aby pokazać, że różne instancje nadal będą poprawnie odszyfrowywać dane.Teraz, jak to działa / dlaczego używać go zamiast innego rozwiązania:
Klucze
Klucze nie są używane bezpośrednio. Zamiast tego klucz jest rozciągany przez standardowe wyprowadzenie PBKDF2.
Klucz używany do szyfrowania jest unikalny dla każdego zaszyfrowanego bloku tekstu. Dlatego dostarczony klucz staje się „kluczem głównym”. Dlatego ta klasa zapewnia rotację kluczy dla kluczy szyfrujących i uwierzytelniających.
WAŻNA UWAGA ,
$rounds
parametr jest skonfigurowany dla prawdziwych losowych kluczy o wystarczającej sile (co najmniej 128 bitów losowych kluczy Cryptographically Secure). Jeśli zamierzasz używać hasła lub nielosowego klucza (lub mniej losowego niż 128 bitów CS losowo), musisz zwiększyć ten parametr. Sugerowałbym minimum 10000 haseł (im więcej cię stać, tym lepiej, ale doda to do środowiska uruchomieniowego) ...Integralność danych
Szyfrowanie:
MCRYPT_BLOWFISH
lubMCRYPT_RIJNDAEL_128
szyfrów iMCRYPT_MODE_CBC
dla trybu. Jest wystarczająco silny i nadal dość szybki (cykl szyfrowania i deszyfrowania zajmuje około 1/2 sekundy na moim komputerze).Teraz, jeśli chodzi o punkt 3 z pierwszej listy, to dałoby ci taką funkcję:
Możesz go rozciągnąć w
makeKey()
funkcji, ale ponieważ zostanie rozciągnięty później, nie ma to większego sensu.Jeśli chodzi o wielkość magazynu, zależy to od zwykłego tekstu. Blowfish używa 8-bajtowego rozmiaru bloku, więc będziesz mieć:
W przypadku 16-znakowego źródła danych do zaszyfrowania będzie 16 znaków. Oznacza to, że rzeczywisty rozmiar zaszyfrowanych danych wynosi 16 bajtów ze względu na wypełnienie. Następnie dodaj 16 bajtów na sól i 64 bajty na hmac, a całkowity przechowywany rozmiar wynosi 96 bajtów. Więc co najwyżej jest 80 znaków, aw najgorszym 87 znaków ...
Mam nadzieję że to pomogło...
Uwaga: 12/11/12: Właśnie zaktualizowałem tę klasę o DUŻO lepszą metodę szyfrowania, używając lepiej wyprowadzonych kluczy i naprawiając generowanie MAC ...
źródło
-64
s na-128
pomogły (więc dostajesz$enc = substr($data, 128, -128)
i$mac = substr($data, -128);
Jak zaszyfrować i odszyfrować hasło w PHP? Wdrażając jeden z wielu algorytmów szyfrowania. (lub używając jednej z wielu bibliotek)
Jaki jest najbezpieczniejszy algorytm szyfrowania haseł? Istnieje mnóstwo różnych algorytmów, z których żaden nie jest w 100% bezpieczny. Ale wiele z nich jest wystarczająco bezpiecznych dla celów handlowych, a nawet wojskowych
Gdzie mogę przechowywać klucz prywatny? Jeśli zdecydowałeś się zaimplementować klucz publiczny - algorytm kryptograficzny (np. RSA), nie przechowujesz klucza prywatnego. użytkownik ma klucz prywatny. Twój system ma klucz publiczny, który można przechowywać w dowolnym miejscu.
Czy zamiast przechowywać klucz prywatny, warto wymagać od użytkowników wprowadzania klucza prywatnego za każdym razem, gdy potrzebują odszyfrowania hasła? (Użytkownicy tej aplikacji mogą być zaufani) Cóż, jeśli twój użytkownik pamięta absurdalnie długie liczby pierwsze - tak, czemu nie. Ale generalnie musisz wymyślić system, który pozwoli użytkownikowi gdzieś przechowywać klucz.
W jaki sposób można ukraść i odszyfrować hasło? Czego muszę być świadomy? Zależy to od zastosowanego algorytmu. Jednak zawsze upewnij się, że nie wysyłasz niezaszyfrowanego hasła do lub od użytkownika. Zaszyfruj / odszyfruj go po stronie klienta lub użyj protokołu https (lub użyj innych środków kryptograficznych, aby zabezpieczyć połączenie między serwerem a klientem).
Jeśli jednak wszystko, czego potrzebujesz, to przechowywanie haseł w sposób zaszyfrowany, sugerowałbym użycie prostego szyfru XOR. Główny problem z tym algorytmem polega na tym, że można go łatwo złamać za pomocą analizy częstotliwości. Jednak ponieważ generalnie hasła nie są tworzone z długich akapitów tekstu w języku angielskim, nie sądzę, abyś się tym przejmował. Drugi problem z XOR Cipher polega na tym, że jeśli masz wiadomość zarówno w postaci zaszyfrowanej, jak i odszyfrowanej, możesz łatwo znaleźć hasło, za pomocą którego została zaszyfrowana. Ponownie, nie jest to duży problem w twoim przypadku, ponieważ dotyczy tylko użytkownika, który został już naruszony w inny sposób.
źródło
Przykład z instrukcji jest nieznacznie zredagowany na potrzeby tego przykładu):
Do odszyfrowania hasła użyłbyś mcrypt_decrypt .
Najlepszy algorytm jest raczej subiektywny - zapytaj 5 osób, uzyskaj 5 odpowiedzi. Osobiście, jeśli domyślny (Blowfish) nie jest dla Ciebie wystarczająco dobry, prawdopodobnie masz większe problemy!
Biorąc pod uwagę, że PHP potrzebuje go do szyfrowania - nie jestem pewien, czy możesz go gdziekolwiek ukryć - mile widziane komentarze na ten temat. Oczywiście obowiązują standardowe najlepsze praktyki kodowania PHP!
Biorąc pod uwagę, że klucz szyfrowania i tak będzie w Twoim kodzie, nie jesteś pewien, co zyskasz, pod warunkiem, że reszta aplikacji będzie bezpieczna.
Oczywiście, jeśli zaszyfrowane hasło i klucz szyfrowania zostaną skradzione, gra się kończy.
Postawiłbym jeźdźca na mojej odpowiedzi - nie jestem ekspertem od kryptografii PHP, ale myślę, że to, na co odpowiedziałem, jest standardową praktyką - mile widziane są komentarze innych.
źródło
$pass = $text
. Myślę, że zmienił to, aby odpowiedzieć na pytanie, i nie zauważył drugiego wystąpienia.MCRYPT_MODE_ECB
nie używa IV. Po drugie, gdyby tak było, musiałbyś przechowywać IV, ponieważ bez niego nie można odszyfrować danych ...Wielu użytkowników sugerowało używanie mcrypt ... co jest poprawne, ale lubię pójść o krok dalej, aby ułatwić jego przechowywanie i przesyłanie (ponieważ czasami zaszyfrowane wartości mogą utrudniać ich wysyłanie przy użyciu innych technologii, takich jak curl lub json) .
Po pomyślnym zaszyfrowaniu przy użyciu mcrypt, uruchom go przez base64_encode, a następnie przekonwertuj na kod szesnastkowy. Raz w kodzie szesnastkowym można łatwo przenieść na różne sposoby.
A po drugiej stronie:
źródło
Zasugerowałbym szyfrowanie za pomocą klucza publicznego tylko wtedy, gdy chcesz mieć możliwość ustawienia hasła użytkownika bez jego interakcji (może to być przydatne w przypadku resetowania i udostępniania haseł).
Klucz publiczny
openssl_public_encrypt
iopenssl_private_decrypt
Symetryczny
Obie
4
. Tak - użytkownicy musieliby za każdym razem wprowadzać hasło aplikacji, ale przechowywanie go w sesji spowodowałoby inne problemy5
.źródło
openssl_private_decrypt()
.Próbowałem czegoś takiego, ale pamiętaj, że nie jestem kryptografem ani nie posiadam dogłębnej wiedzy na temat
php
żadnego języka programowania. To tylko pomysł. Mój pomysł polega na zapisaniukey
w jakimś pliku lubdatabase
(lub wpisaniu ręcznie), którego (lokalizacji) nie da się łatwo przewidzieć (i oczywiście wszystko zostanie kiedyś odszyfrowane, koncepcja polega na wydłużeniu czasu deszyfrowania) i zaszyfrowanie poufnych informacji.Należy pamiętać, że to tylko koncepcja. Wszelkie ulepszenia tego kodu byłyby bardzo odczuwalne.
źródło
Ech? Nie rozumiem. Czy masz na myśli tylko to, że hasło musi być możliwe do odzyskania?
Jak powiedzieli inni, rozszerzenie mcrypt zapewnia dostęp do wielu funkcji kryptograficznych - jednak zachęcasz użytkowników do umieszczenia wszystkich swoich jajek w jednym koszyku - takim, który będzie potencjalnie celem dla atakujących - i jeśli nawet nie wiesz jak zacząć rozwiązywać problem, to wyrządzasz użytkownikom krzywdę. Nie jesteś w stanie zrozumieć, jak chronić dane.
Większość luk w zabezpieczeniach powstaje nie dlatego, że bazowy algorytm jest wadliwy lub niezabezpieczony, ale z powodu problemów ze sposobem wykorzystania algorytmu w kodzie aplikacji.
To powiedziawszy, można zbudować w miarę bezpieczny system.
Szyfrowanie asymetryczne należy rozważać tylko wtedy, gdy wymaga się, aby użytkownik utworzył bezpieczną wiadomość, którą może odczytać inny (określony) użytkownik. Powodem jest to, że jest kosztowny obliczeniowo. Jeśli chcesz tylko zapewnić repozytorium, w którym użytkownicy będą mogli wprowadzać i pobierać własne dane, wystarczające jest szyfrowanie symetryczne.
Jeśli jednak przechowujesz klucz do odszyfrowania wiadomości w tym samym miejscu, w którym znajduje się zaszyfrowana wiadomość (lub gdzie jest przechowywana zaszyfrowana wiadomość), system nie jest bezpieczny. Użyj tego samego tokena do uwierzytelnienia użytkownika, co w przypadku klucza deszyfrującego (lub w przypadku szyfrowania asymetrycznego użyj tokena jako frazy hasła klucza prywatnego). Ponieważ będziesz musiał przechowywać token na serwerze, na którym odbywa się deszyfrowanie, przynajmniej tymczasowo, możesz rozważyć użycie niemożliwego do przeszukiwania substratu do przechowywania sesji lub przekazanie tokena bezpośrednio do demona powiązanego z sesją, który będzie przechowywał token w pamięci i deszyfrowanie wiadomości na żądanie.
źródło
Użyj password_hash i password_verify
I odszyfrować:
źródło