Muszę zaimplementować 256-bitowe szyfrowanie AES, ale wszystkie przykłady, które znalazłem w Internecie, wykorzystują „KeyGenerator” do wygenerowania 256-bitowego klucza, ale chciałbym użyć własnego klucza dostępu. Jak mogę stworzyć własny klucz? Próbowałem uzupełnić go do 256 bitów, ale potem pojawia się błąd informujący, że klucz jest za długi. Mam zainstalowaną łatkę do nieograniczonej jurysdykcji, więc to nie problem :)
To znaczy. KeyGenerator wygląda tak ...
// Get the KeyGenerator
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128); // 192 and 256 bits may not be available
// Generate the secret key specs.
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
EDYTOWAĆ
Właściwie uzupełniałem hasło do 256 bajtów, a nie bitów, co jest zbyt długie. Poniżej znajduje się kod, którego używam teraz, gdy mam z tym więcej doświadczenia.
byte[] key = null; // TODO
byte[] input = null; // TODO
byte[] output = null;
SecretKeySpec keySpec = null;
keySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
output = cipher.doFinal(input)
Bity „TODO”, które musisz zrobić sam :-)
java
encryption
cryptography
passwords
aes
Nippysaurus
źródło
źródło
Odpowiedzi:
Udostępnij
password
(achar[]
) isalt
(-byte[]
8 bajtów wybranych przezSecureRandom
markę stanowi dobrą sól - co nie musi być utrzymywane w tajemnicy) odbiorcy spoza pasma. Następnie, aby uzyskać dobry klucz z tych informacji:Liczby magiczne (które można gdzieś zdefiniować jako stałe) 65536 i 256 to odpowiednio liczba iteracji pochodnych kluczy i rozmiar klucza.
Funkcja wyprowadzania klucza jest iterowana, co wymaga znacznego wysiłku obliczeniowego, co uniemożliwia atakującym szybkie wypróbowanie wielu różnych haseł. Liczbę iteracji można zmienić w zależności od dostępnych zasobów obliczeniowych.
Rozmiar klucza można zmniejszyć do 128 bitów, co nadal jest uważane za „silne” szyfrowanie, ale nie zapewnia większego marginesu bezpieczeństwa, jeśli zostaną wykryte ataki osłabiające AES.
W tym samym kluczu pochodnym, używanym z odpowiednim trybem łączenia bloków, można szyfrować wiele wiadomości. W łańcuchu bloków szyfrów (CBC) dla każdej wiadomości generowany jest losowy wektor inicjalizacji (IV), co daje inny tekst szyfru, nawet jeśli zwykły tekst jest identyczny. CBC może nie być najbezpieczniejszym dostępnym trybem (patrz AEAD poniżej); istnieje wiele innych trybów o różnych właściwościach bezpieczeństwa, ale wszystkie wykorzystują podobne losowe dane wejściowe. W każdym przypadku wyjściami każdej operacji szyfrowania są tekst zaszyfrowany i wektor inicjalizacji:
Przechowuj
ciphertext
iiv
. Podczas deszyfrowania plikSecretKey
jest regenerowany dokładnie w ten sam sposób, przy użyciu hasła o tych samych parametrach soli i iteracji. Zainicjuj szyfr za pomocą tego klucza i wektora inicjalizacji zapisanego z komunikatem:Java 7 zawiera obsługę API dla trybów szyfrowania AEAD , a dostawca „SunJCE” dołączony do dystrybucji OpenJDK i Oracle implementuje je począwszy od Java 8. Jeden z tych trybów jest zdecydowanie zalecany zamiast CBC; zapewni ochronę integralności danych, a także ich prywatności.
A
java.security.InvalidKeyException
z komunikatem „Nielegalny rozmiar klucza lub parametry domyślne” oznacza, że siła kryptografii jest ograniczona; pliki zasad jurysdykcji o nieograniczonej sile nie znajdują się we właściwej lokalizacji. W JDK należy je umieścić pod${jdk}/jre/lib/security
Na podstawie opisu problemu wygląda na to, że pliki zasad nie są poprawnie zainstalowane. Systemy mogą łatwo mieć wiele środowisk wykonawczych Java; sprawdź dwukrotnie, aby upewnić się, że używana jest poprawna lokalizacja.
źródło
PBEwith<prf>and<encryption>
algorytmów; na przykład SunJCE nie zapewnia i PBE dla AES. Po drugie, włączenie jasypt nie jest celem. Pakiet, który ma zapewniać bezpieczeństwo bez konieczności rozumienia podstawowych zasad, wydaje się niebezpieczny prima facie.tmp.getEncoded()
jako skrót. Powinieneś także przechowywaćsalt
i iteracje (65536 w tym przykładzie), abyś mógł ponownie obliczyć skrót, gdy ktoś próbuje się uwierzytelnić. W takim przypadku wygeneruj sól za pomocą kryptograficznego generatora liczb losowych przy każdej zmianie hasła.Rozważ użycie modułu szyfrującego Spring Security
Zapewnia prostą abstrakcję do szyfrowania i wydaje się pasować do wymaganych tutaj,
Spojrzenie na elementy wewnętrzne ujawnia strukturę podobną do odpowiedzi Ericksona .
Jak wspomniano w pytaniu, wymaga to również zasad jurysdykcji nieograniczonej siły Java Cryptography Extension (JCE) (w przeciwnym razie napotkasz
InvalidKeyException: Illegal Key Size
). Jest do pobrania dla Java 6 , Java 7 i Java 8 .Przykładowe użycie
I próbka wyjściowa,
źródło
NULL_IV_GENERATOR
Wykorzystywane przez narzędzie sprężyna nie jest bezpieczna. Jeśli aplikacja nie zapewnia IV, pozwól dostawcy wybrać go i zapytaj go po inicjalizacji.Po przeczytaniu sugestii Ericksona i zebraniu, co mogłem z kilku innych postów i tego przykładu tutaj , próbowałem zaktualizować kod Douga zalecanymi zmianami. Edytuj, aby poprawić.
Kilka uwag: Używa 128-bitowego klucza szyfrowania - Java najwyraźniej nie wykona 256-bitowego szyfrowania od razu po wyjęciu z pudełka. Implementacja 256 wymaga zainstalowania dodatkowych plików w katalogu instalacyjnym Java.
Poza tym nie jestem osobą kryptograficzną. Uważajcie.
źródło
printStackTrace()
CipherInputStream
iCipherOutputStream
nie stanowi większego problemu. Problemem jest tasowanie wszystkich wyjątków pod stołem. Problem polega na tym, że sól nagle stała się polem i że wymagane jest podanie IV. Problem polega na tym, że nie jest zgodny z konwencjami kodowania Java. Problemem jest fakt, że działa to tylko na plikach, o które nie zapytano. To, że reszta kodu jest w zasadzie kopią, również nie pomaga. Ale może poprawię to, aby było lepiej, jak sugerowano ...Generowanie własnego klucza z tablicy bajtów jest łatwe:
Ale utworzenie 256-bitowego klucza nie wystarczy. Jeśli generator kluczy nie może wygenerować 256-bitowych kluczy,
Cipher
klasa prawdopodobnie nie obsługuje również 256-bitowego AES. Mówisz, że masz zainstalowaną nielimitowaną łatkę jurysdykcyjną, więc szyfr AES-256 powinien być obsługiwany (ale wtedy klucze 256-bitowe też powinny być, więc może to być problem z konfiguracją).Obejściem braku obsługi AES-256 jest wzięcie darmowej implementacji AES-256 i wykorzystanie jej jako niestandardowego dostawcy. Wymaga to stworzenia własnej
Provider
podklasy i korzystania z niejCipher.getInstance(String, Provider)
. Ale może to być proces zaangażowany.źródło
Cipher
, a nie samego dostawcy. Możesz używać AES-256 w Javie 8 i niższych, ale musisz użyć zastrzeżonego API. Lub środowisko wykonawcze, które nie stwarza ograniczeń co do wielkości klucza.W przeszłości robiłem haszowanie klucza za pomocą czegoś takiego jak SHA256, a następnie wyodrębnianie bajtów z hasza do bajtu klucza [].
Po utworzeniu bajtu [] możesz po prostu zrobić:
źródło
Cipher aes256 = Cipher.getInstance("AES/OFB/NoPadding"); MessageDigest keyDigest = MessageDigest.getInstance("SHA-256"); byte[] keyHash = keyDigest.digest(secret.getBytes("UTF-8")); SecretKeySpec key = new SecretKeySpec(keyHash, "AES"); aes256.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(initializationVector));
Robię to samo, co zasugerowałem w Twojej odpowiedzi, ale nadal mam do czynienia z java.security.InvalidKeyException: Nielegalny rozmiar klucza Czy pobieranie pliku zasad JCE jest obowiązkowe?Dodając do edycji @ Wufoo, następująca wersja używa InputStreams zamiast plików, aby ułatwić pracę z różnymi plikami. Przechowuje również IV i sól na początku pliku, dzięki czemu tylko hasło musi być śledzone. Ponieważ IV i Sól nie muszą być tajne, to ułatwia życie.
źródło
(Może pomocny dla innych osób o podobnych wymaganiach)
Miałem podobny wymóg używania
AES-256-CBC
szyfrowania i deszyfrowania w Javie.Aby osiągnąć (lub określić) 256-bajtowe szyfrowanie / deszyfrowanie,
Java Cryptography Extension (JCE)
zasady powinny być ustawione na"Unlimited"
Można go ustawić w
java.security
pliku w$JAVA_HOME/jre/lib/security
(dla JDK) lub$JAVA_HOME/lib/security
(dla JRE)crypto.policy=unlimited
Lub w kodzie jako
Java 9 i nowsze wersje mają tę opcję domyślnie włączoną.
źródło
Rozważ użycie Encryptor4j, którego jestem autorem.
Najpierw upewnij się, że masz zainstalowane pliki zasad nieograniczonej jurysdykcji , aby móc używać 256-bitowych kluczy AES.
Następnie wykonaj następujące czynności:
Możesz teraz użyć szyfratora do zaszyfrowania wiadomości. Możesz również wykonać szyfrowanie strumieniowe, jeśli chcesz. Dla Twojej wygody automatycznie generuje i przygotowuje bezpieczny IV.
Jeśli jest to plik, który chcesz skompresować, zapoznaj się z tą odpowiedzią Szyfrowanie dużego pliku za pomocą AES za pomocą JAVA dla jeszcze prostszego podejścia.
źródło
Użyj tej klasy do szyfrowania. To działa.
A to są ivBytes i losowy klucz;
źródło