2013-08-14 17 views
41

Jaki jest zalecany sposób generowania bezpiecznego, losowego klucza AES w Javie, przy użyciu standardowego JDK?Jak utworzyć bezpieczny losowy klucz AES w Javie?

w innych postach, znalazłem to, ale przy użyciu SecretKeyFactory może być lepszy pomysł:

KeyGenerator keyGen = KeyGenerator.getInstance("AES"); 
SecureRandom random = new SecureRandom(); // cryptograph. secure random 
keyGen.init(random); 
SecretKey secretKey = keyGen.generateKey(); 

Byłoby wspaniale, gdyby odpowiedź zawiera wyjaśnienie, dlaczego jest to dobry sposób generowania losowy klucz. Dzięki!

+0

To pomoże mighth http://stackoverflow.com/questions/10252449/is-aes-key-random – Tala

+0

@Tala Tam znalazłem [cytowany kod] (http://stackoverflow.com/a/10252662/1005481). Ale z tego posta nie mogłem ustalić konsensusu co do tego, jak stworzyć losowy klucz i dlaczego to był bezpieczny sposób. –

Odpowiedz

53

użyłbym sugerowaną kodu, ale z lekkim uproszczeniem:

KeyGenerator keyGen = KeyGenerator.getInstance("AES"); 
keyGen.init(256); // for example 
SecretKey secretKey = keyGen.generateKey(); 

Niech dostawca wybrać sposób planuje uzyskać przypadkowość - nie zdefiniować coś, co może nie być tak dobre jak to, co dostawcy już wybrał.

Ten przykładowy kod zakłada (as Maarten points out below), że skonfigurowałeś plik java.security, aby dołączyć preferowanego dostawcę u góry listy. Jeśli chcesz ręcznie określić dostawcę, po prostu zadzwoń pod numer KeyGenerator.getInstance("AES", "providerName");.

Aby uzyskać naprawdę bezpieczny klucz, należy użyć narzędzia hardware security module (HSM) do wygenerowania i ochrony klucza. Producenci HSM zwykle dostarczają dostawcę JCE, który wykona dla ciebie wszystkie kluczowe generacje, używając powyższego kodu.

+1

Normalnie również pomijam nazwę dostawcy. Skonfiguruj platformę (np. Używając pliku 'java.security' lub konfigurując' Provider' programowo używając 'Security.addProvider()' i podobnie). W przeciwnym razie kod będzie mniej przenośny i nie pozwoli użytkownikowi na zmianę np. HSM bez zmiany kodu aplikacji. –

+0

Dlaczego muszę określić dostawcę? Domyślnym zachowaniem jest użycie dostawcy o najwyższym priorytecie, który obsługuje algorytm, co wydaje mi się wystarczające. –

+2

Nie wszystkie metody generowania kluczy są sobie równe i możesz chcieć jawnie wybrać np. metoda generowania kluczy przez dostawcę. Jest to szczególnie przydatne dla dostawców dla tokenów bezpieczeństwa. Jednak w przypadku AES generator liczb losowych może mieć większe znaczenie - możesz na przykład użyć wolniejszego, bezpieczniejszego generatora liczb losowych z certyfikatem FIPS zamiast domyślnego. –

19

Stosowanie metody KeyGenerator jest preferowaną metodą. Jak wskazywał Duncan, na pewno dałbym klucz wielkości podczas inicjalizacji. KeyFactory to metoda, która powinna być używana dla wcześniej istniejących kluczy.

OK, więc przejdźmy do nitty-piaszczysty tego. Zasadniczo klucze AES mogą mieć dowolną wartość. Nie ma "słabych kluczy" jak w (3) DES. Nie ma też bitów, które mają konkretne znaczenie jak w (3) bitach parzystości DES. Zatem generowanie klucza może być tak proste, jak generowanie tablicy bajtów z losowymi wartościami i tworzenie wokół niej SecretKeySpec.

Ale nadal istnieją zalety metody, której używasz: KeyGenerator jest specjalnie stworzony do generowania kluczy. Oznacza to, że kod może być zoptymalizowany dla tej generacji. Ten może ma korzyści wydajności i bezpieczeństwa. Może być zaprogramowany tak, aby uniknąć ataków na boczny kanał czasu, które mogłyby na przykład odsłonić klucz. Zauważ, że dobrym pomysłem może być wyczyszczenie wszystkich byte[], które przechowują kluczowe informacje, ponieważ mogą zostać ujawnione w pliku wymiany (i tak może być i tak).

Ponadto, jak wspomniano, nie wszystkie algorytmy używają całkowicie losowych kluczy. Tak więc używanie KeyGenerator ułatwiłoby przełączanie się na inne algorytmy. Bardziej nowoczesne szyfry będą akceptować tylko w pełni losowe klucze; jest to postrzegane jako główna korzyść w stosunku do np. DES.

Wreszcie, w moim przypadku najważniejszy powód, dla którego metoda KeyGenerator jest jedynym prawidłowym sposobem obsługi kluczy AES w bezpiecznym tokenie (karta inteligentna, moduł TPM, token USB lub HSM). Jeśli utworzysz byte[] z SecretKeySpec, klucz musi pochodzić z pamięci. Oznacza to, że klucz można umieścić w bezpiecznym tokenie, ale klucz jest odsłonięty w pamięci niezależnie. Zwykle bezpieczne tokeny działają tylko z kluczami, które są generowane w bezpiecznym tokenie lub są wstrzykiwane przez np. karta inteligentna lub ceremonia kluczowa. A KeyGenerator może być dostarczony z dostawcą, dzięki czemu klucz jest generowany bezpośrednio w bezpiecznym tokenie.

Jak wskazano w Duncan's answer: należy zawsze wyraźnie określić rozmiar klucza (i wszelkie inne parametry). Nie należy polegać na domyślnych ustawieniach dostawcy, ponieważ to spowoduje, że nie będzie jasne, co robi aplikacja, a każdy dostawca może mieć własne ustawienia domyślne.

+0

Dzięki za te doskonałe informacje podstawowe! –

+0

Im więcej, tym weselej. Doskonała odpowiedź jak zwykle :-) –

2

Wiele dobrych wskazówek w innych postach. To co mam użyć:

Key key; 
SecureRandom rand = new SecureRandom(); 
KeyGenerator generator = KeyGenerator.getInstance("AES"); 
generator.init(256, rand); 
key = generator.generateKey(); 

Jeśli potrzebujesz innego dostawcy losowość, którą kiedyś zrobić dla celów testowych, po prostu zastąpić rand z

MySecureRandom rand = new MySecureRandom(); 
+0

Po raz pierwszy określam generator losowy, po raz drugi długość klucza AES do użycia (256). Są to oddzielne metody init. – Andy

Powiązane problemy