To jest pierwsza strona, która pojawia się za pośrednictwem Google, a luki w zabezpieczeniach we wszystkich implementacjach sprawiają, że wzdrygam się, więc publikuję to, aby dodać informacje dotyczące szyfrowania dla innych, ponieważ minęło 7 lat od oryginalnego postu. Mam tytuł magistra inżynierii komputerowej i spędziłem dużo czasu studiując i ucząc się kryptografii, więc rzucam moje dwa centy, aby uczynić internet bezpieczniejszym miejscem.
Zwróć również uwagę, że wiele implementacji może być bezpiecznych w danej sytuacji, ale po co ich używać i potencjalnie przypadkowo popełniać błąd? Używaj najsilniejszych dostępnych narzędzi, chyba że masz konkretny powód, aby tego nie robić. Ogólnie rzecz biorąc, zdecydowanie radzę korzystać z biblioteki i trzymać się z daleka od drobiazgowych szczegółów, jeśli możesz.
UPDATE 05.04.18: I przepisał kilka części, aby były łatwiejsze do zrozumienia i zmienił Zalecana bibliotekę z Jasypt do nowej biblioteki Google Tink , polecam całkowicie usuwając Jasypt z istniejącej instalacji.
Przedmowa
Poniżej opiszę podstawy bezpiecznej kryptografii symetrycznej i wskażę typowe błędy, które widzę w Internecie, gdy ludzie samodzielnie wdrażają kryptografię w standardowej bibliotece Java. Jeśli chcesz po prostu pominąć wszystkie szczegóły, przejdź do nowej biblioteki Google Tink, zaimportuj ją do swojego projektu i użyj trybu AES-GCM do wszystkich swoich szyfrowań, a będziesz bezpieczny.
Teraz, jeśli chcesz poznać podstawowe szczegóły dotyczące szyfrowania w Javie, czytaj dalej :)
Szyfry blokowe
Najpierw musisz wybrać symetryczny klucz szyfrujący blokowy. Szyfr blokowy to funkcja / program komputerowy używany do tworzenia pseudolosowości. Pseudolosowość to fałszywa losowość, której żaden komputer inny niż komputer kwantowy nie byłby w stanie odróżnić go od prawdziwej losowości. Szyfr blokowy jest jak element konstrukcyjny kryptografii, a gdy jest używany z różnymi trybami lub schematami, możemy tworzyć szyfrowanie.
Jeśli chodzi o dostępne dzisiaj algorytmy szyfrowania blokowego, upewnij się, że NIGDY , powtarzam NIGDY nie używam DES , powiedziałbym nawet, że NIGDY nie używaj 3DES . Jedynym szyfrem blokowym, który nawet wydanie Snowdena z NSA było w stanie zweryfikować, że jest naprawdę tak blisko Pseudo-Random, jak to tylko możliwe, to AES 256 . Istnieje również AES 128; różnica polega na tym, że AES 256 działa w 256-bitowych blokach, podczas gdy AES 128 działa w 128 blokach. Podsumowując, AES 128 jest uważany za bezpieczny, chociaż odkryto pewne słabości, ale 256 jest tak solidny, jak to tylko możliwe.
Zabawny fakt DES został złamany przez NSA, kiedy został założony i przez kilka lat trzymany w tajemnicy. Chociaż niektórzy ludzie nadal twierdzą, że 3DES jest bezpieczny, istnieje sporo artykułów naukowych, które odkryły i przeanalizowały słabości 3DES .
Tryby szyfrowania
Szyfrowanie jest tworzone, gdy bierzesz szyfr blokowy i używasz określonego schematu, tak że losowość jest połączona z kluczem do stworzenia czegoś, co jest odwracalne, o ile znasz klucz. Nazywa się to trybem szyfrowania.
Oto przykład trybu szyfrowania i najprostszego trybu znanego jako EBC, abyś mógł wizualnie zrozumieć, co się dzieje:
Tryby szyfrowania, które najczęściej zobaczysz w Internecie, to:
CTR EBC, CBC, GCM
Istnieją inne tryby poza wymienionymi, a naukowcy zawsze pracują nad nowymi, aby poprawić istniejące problemy.
Przejdźmy teraz do implementacji i tego, co jest bezpieczne. NIGDY nie używaj EBC, jest to złe w ukrywaniu powtarzających się danych, jak pokazał słynny pingwin linuksowy .
Podczas implementacji w Javie należy pamiętać, że jeśli używasz następującego kodu, tryb EBC jest ustawiony domyślnie:
Cipher cipher = Cipher.getInstance("AES");
... NIEBEZPIECZEŃSTWO TO JEST WRAŻLIWOŚĆ! i niestety jest to widoczne w całym StackOverflow oraz online w samouczkach i przykładach.
Nonces i IV
W odpowiedzi na problem znaleziony w trybie EBC stworzono rzeczowniki znane również jako IV. Chodzi o to, że generujemy nową zmienną losową i dołączamy ją do każdego szyfrowania, aby po zaszyfrowaniu dwóch takich samych wiadomości wychodziły one różne. Piękno za tym kryje się w tym, że kroplówka lub nonce jest powszechnie znana. Oznacza to, że osoba atakująca może mieć do tego dostęp, ale dopóki nie ma Twojego klucza, nie może nic zrobić z tą wiedzą.
Typowe problemy, które zobaczę, to to, że ludzie ustawią IV jako wartość statyczną, jak w tej samej stałej wartości w swoim kodzie. i tutaj jest pułapka dla IV, gdy powtórzysz jeden, faktycznie naruszysz całe bezpieczeństwo swojego szyfrowania.
Generowanie losu IV
SecureRandom randomSecureRandom = SecureRandom.getInstance("SHA1PRNG");
byte[] iv = new byte[cipher.getBlockSize()];
randomSecureRandom.nextBytes(iv);
IvParameterSpec ivParams = new IvParameterSpec(iv);
Uwaga: SHA1 jest zepsuty, ale nie mogłem znaleźć sposobu prawidłowego zaimplementowania SHA256 w tym przypadku użycia, więc jeśli ktoś chciałby się tym zająć i zaktualizować, byłoby wspaniale! Również ataki SHA1 są nadal niekonwencjonalne, ponieważ złamanie ogromnego klastra może zająć kilka lat. Sprawdź szczegóły tutaj.
Implementacja CTR
W trybie CTR nie jest wymagane dopełnienie.
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
Wdrożenie CBC
Jeśli zdecydujesz się zaimplementować tryb CBC, zrób to z PKCS7Padding w następujący sposób:
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
Luka w zabezpieczeniach CBC i CTR oraz dlaczego warto używać GCM
Chociaż niektóre inne tryby, takie jak CBC i CTR, są bezpieczne, napotykają na problem polegający na tym, że atakujący może odwrócić zaszyfrowane dane, zmieniając ich wartość po odszyfrowaniu. Powiedzmy, że szyfrujesz wyimaginowaną wiadomość bankową „Sprzedaj 100”, zaszyfrowana wiadomość wygląda tak, jakby to „eu23ng” atakujący zmienił się o jeden bit na „eu53ng”, a po odszyfrowaniu wiadomości nagle brzmiała „Sprzedaj 900”.
Aby tego uniknąć, większość internetu korzysta z GCM i za każdym razem, gdy widzisz HTTPS, prawdopodobnie używa GCM. GCM podpisuje zaszyfrowaną wiadomość hashem i sprawdza, czy wiadomość nie została zmieniona przy użyciu tego podpisu.
Unikałbym wdrażania GCM ze względu na jego złożoność. Lepiej jest korzystać z nowej biblioteki Google Tink, ponieważ tutaj ponownie, jeśli przypadkowo powtórzysz IV, narażasz klucz w przypadku GCM, co jest ostateczną luką w zabezpieczeniach. Nowi badacze pracują nad trybami szyfrowania IV odpornymi na powtórzenia, w których nawet jeśli powtórzysz IV, klucz nie jest zagrożony, ale to jeszcze nie weszło do głównego nurtu.
Jeśli chcesz zaimplementować GCM, oto link do ładnej implementacji GCM . Nie mogę jednak zapewnić bezpieczeństwa lub czy jest on prawidłowo zaimplementowany, ale powoduje to uszkodzenie podstaw. Zwróć też uwagę, że w przypadku GCM nie ma dopełnienia.
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
Klucze a hasła
Kolejną bardzo ważną uwagą jest to, że w przypadku kryptografii klucz i hasło to nie to samo. Klucz w kryptografii musi mieć pewną entropię i losowość, aby można go było uznać za bezpieczny. Dlatego musisz upewnić się, że używasz odpowiednich bibliotek kryptograficznych do wygenerowania klucza.
Więc naprawdę masz dwie implementacje, które możesz tutaj zrobić, pierwszą jest użycie kodu znalezionego w tym wątku StackOverflow do generowania losowego klucza . To rozwiązanie wykorzystuje bezpieczny generator liczb losowych do tworzenia od podstaw klucza, którego możesz użyć.
Inną mniej bezpieczną opcją jest użycie danych wejściowych użytkownika, takich jak hasło. Problem, o którym mówiliśmy, polega na tym, że hasło nie ma wystarczającej entropii, więc musielibyśmy użyć PBKDF2 , algorytmu, który pobiera hasło i je wzmacnia. Oto implementacja StackOverflow, która mi się podobała . Jednak biblioteka Google Tink ma to wszystko wbudowane i powinieneś z tego skorzystać.
Programiści Androida
Jedną z ważnych kwestii, na które należy zwrócić uwagę, jest wiedza, że kod Androida można poddać inżynierii wstecznej, aw większości przypadków jest to również kod Java. Oznacza to, że jeśli przechowujesz hasło w postaci zwykłego tekstu w swoim kodzie. Haker może go łatwo odzyskać. Zwykle w przypadku tego typu szyfrowania chcesz użyć kryptografii asymetrycznej i tak dalej. To jest poza zakresem tego postu, więc nie będę się w to zagłębiał.
Ciekawa lektura z 2013 roku : wskazuje, że 88% implementacji Crypto w systemie Android zostało wykonanych nieprawidłowo.
Końcowe przemyślenia
Po raz kolejny sugerowałbym unikanie bezpośredniego wdrażania biblioteki java dla kryptowalut i używanie Google Tink , zaoszczędzi ci to bólu głowy, ponieważ naprawdę wykonali dobrą robotę, poprawnie implementując wszystkie algorytmy. A nawet wtedy upewnij się, że sprawdziłeś problemy poruszane na githubie Tink, tu i tam pojawiają się luki w zabezpieczeniach.
Jeśli masz jakieś pytania lub uwagi, możesz je skomentować! Bezpieczeństwo zawsze się zmienia i musisz zrobić wszystko, aby za nim nadążyć :)