Java Security: niedozwolony rozmiar klucza lub parametry domyślne?

409

Zadałem pytanie na ten temat wcześniej, ale nie otrzymałem właściwej odpowiedzi i nigdzie nie zaprowadziłem.

Wyjaśniłem więc kilka szczegółów na temat problemu i naprawdę chciałbym usłyszeć wasze pomysły na to, jak mogę to naprawić lub co powinienem spróbować.

Mam Java 1.6.0.12 zainstalowaną na moim serwerze Linux, a poniższy kod działa idealnie.

String key = "av45k1pfb024xa3bl359vsb4esortvks74sksr5oy4s5serondry84jsrryuhsr5ys49y5seri5shrdliheuirdygliurguiy5ru";
try {
    Cipher c = Cipher.getInstance("ARCFOUR");

    SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "ARCFOUR");
    c.init(Cipher.DECRYPT_MODE, secretKeySpec);

    return new String(c.doFinal(Hex.decodeHex(data.toCharArray())), "UTF-8");

} catch (InvalidKeyException e) {
    throw new CryptoException(e);
}

Dzisiaj zainstalowałem Javę 1.6.0.26 na moim serwerze i kiedy próbuję uruchomić aplikację, otrzymuję następujący wyjątek. Domyślam się, że ma to związek z konfiguracją instalacji Java, ponieważ działa w pierwszej, ale nie działa w późniejszej wersji.

Caused by: java.security.InvalidKeyException: Illegal key size or default parameters
    at javax.crypto.Cipher.a(DashoA13*..) ~[na:1.6]
    at javax.crypto.Cipher.a(DashoA13*..) ~[na:1.6]
    at javax.crypto.Cipher.a(DashoA13*..) ~[na:1.6]
    at javax.crypto.Cipher.init(DashoA13*..) ~[na:1.6]
    at javax.crypto.Cipher.init(DashoA13*..) ~[na:1.6]
    at my.package.Something.decode(RC4Decoder.java:25) ~[my.package.jar:na]
    ... 5 common frames omitted

Linia 25 to: c.init(Cipher.DECRYPT_MODE, secretKeySpec);

Uwagi:
* java.security w katalogu java na serwerze 1.6.0.12 jest prawie całkowicie zgodna z plikiem java.security w wersji 1.6.0.26. W pierwszym nie ma żadnych dodatkowych dostawców.
* Poprzednie pytanie jest tutaj .

Rihards
źródło
4
Może to być również zgłaszane jako błąd: Caused by: java.security.InvalidKeyException: Illegal key size(bez „lub parametrów domyślnych”) w Javie 8
hackajar
Wystarczy użyć OpenJDK i będzie działać.
Rodrigo Asensio
@RodrigoAsensio: Używam OpenJDK i nie działa z nim. Musisz zainstalować nieograniczoną liczbę plików jar dotyczących zasad jurysdykcji. A potem to zadziała.
anjanb
5
Zaktualizuj odpowiedź do @AniketThakur. Od wersji Java 9 i Java 8u151 nie ma już potrzeby pobierania i ręcznego instalowania plików zasad jurysdykcji. Aby włączyć nieograniczoną kryptografię, można użyć nowej właściwości crypto.policy Security. Jeśli nowa właściwość Security (crypto.policy) jest ustawiona w pliku java.security lub została ustawiona dynamicznie przy użyciu wywołania Security.setProperty () przed zainicjowaniem frameworka JCE, ustawienie to zostanie zachowane. Domyślnie właściwość będzie niezdefiniowana.
Marcin Kłopotek,

Odpowiedzi:

722

Najprawdopodobniej nie masz teraz zainstalowanego pliku nieograniczonej siły.

Może być konieczne pobranie tego pliku:

Java Cryptography Extension (JCE) Pliki nieograniczonej siły Jurysdykcja 6

Java Cryptography Extension (JCE) Pliki z nieograniczoną siłą Zasady jurysdykcji 7 Pobieranie

Java Cryptography Extension (JCE) Nieograniczona siła Jurysdykcja Pliki zasad 8 Pliki do pobrania (wymagane tylko dla wersji wcześniejszych niż Java 8 u162)

Wyodrębnij pliki jar z zip i zapisz je w ${java.home}/jre/lib/security/.

James Black
źródło
2
@JamesBlack - Tak, i sprawdzić, czy wszystkie zasady zostały pokryte kładę pod słoika za Java/jre/lib/security, Java/jdk/lib/securityi Java/jdk/jre/lib/security. Uruchomienie „java -version” zwraca oczekiwane szczegóły.
aroth
5
W przypadku pakietu SDK IBM (np. WebSphere) pobierz pliki strategii nieograniczonej jurysdykcji ze strony www14.software.ibm.com/webapp/iwm/web/preLogin.do?source=jcesdk
quietmint
4
Od wersji Java 9 i Java 8u151 nie ma już potrzeby pobierania i ręcznego instalowania plików zasad jurysdykcji. Aby włączyć nieograniczoną kryptografię, można użyć nowej właściwości crypto.policy Security. Jeśli nowa właściwość Security (crypto.policy) jest ustawiona w pliku java.security lub została ustawiona dynamicznie przy użyciu wywołania Security.setProperty () przed zainicjowaniem frameworka JCE, ustawienie to zostanie zachowane. Domyślnie właściwość będzie niezdefiniowana.
Marcin Kłopotek,
4
Tak więc ta pozytywna odpowiedź jest teraz nieaktualna i przestarzała. Jak głosujemy lub pomijamy tę odpowiedź, aby stackoverflow.com/a/46857694/2808798 mógł być odpowiedzią „zaakceptowaną”?
Jesse Adelman
3
@JesseAdelman - Niestety ma to prawie 7 lat, niewiele można zrobić. Ktokolwiek poprosiłby, musiałby to zmienić.
James Black
54

Pliki jurysdykcji JRE / JDK / Java 8 można znaleźć tutaj:

Java Cryptography Extension (JCE) Nieograniczona siła Pliki zasad jurysdykcji 8 Pobieranie

Jak James powiedział powyżej:
zainstaluj pliki w ${java.home}/jre/lib/security/.

Saad Malik
źródło
2
Próbowałem za pomocą 6 i 7, ale nie działały. Musiałem zainstalować 8. Dzięki.
Jason Kim
9
Nowa wersja JDK 8u151 ma „Nowa właściwość zabezpieczeń do kontroli polityki kryptograficznej”. Teraz zmiana właściwości to zmiana. Najważniejsze: usuń „#” z wiersza „# crypto.policy = unlimited” w „lib \ security \ java.security”, aby umożliwić używanie 256-bitowych kluczy. oracle.com/technetwork/java/javase/8u151-relnotes-3850493.html
hemisphire
1
Dzięki! Ponieważ jest to właściwość zabezpieczeń, możesz także wywołać Security.setProperty („crypto.policy”, „unlimited”). Źródło: link
@hemisphire
42

W przypadku JAVA 7 link do pobrania to jce-7-download

Skopiuj dwa pobrane słoiki z Java \ jdk1.7.0_10 \ jre \ lib \ security
Zrób kopię zapasową starszych słoików, aby być bezpieczniejszym.

W przypadku JAVA 8 link do pobrania to jce-8-download
Skopiuj pobrane słoiki w Javie \ jdk1.8.0_45 \ jre \ lib \ security
Wykonaj kopię zapasową starszych słoików, aby być bezpieczniejszym.

C Deepak
źródło
39

W przypadku Java 9, Java 8u161 , Java 7u171 i Java 6u181 ograniczenie jest teraz domyślnie wyłączone. Zobacz problem w bazie danych błędów Java .


Począwszy od Java 8u151 możesz programowo wyłączyć ograniczenie.

W starszych wersjach pliki jurysdykcji JCE musiały być pobierane i instalowane oddzielnie, aby JDK mógł korzystać z nieograniczonej kryptografii. Kroki pobierania i instalacji nie są już konieczne.

Zamiast tego możesz teraz wywołać następujący wiersz przed pierwszym użyciem klas JCE (tzn. Najlepiej zaraz po uruchomieniu aplikacji):

Security.setProperty("crypto.policy", "unlimited");
Sebastian S.
źródło
Co z Androidem? Na jakim poziomie interfejsu API można rozwiązać te metody ograniczeń?
TheRealChx101
31

Jest to rozwiązanie tylko dla kodu . Nie ma potrzeby pobierania ani bałagania przy użyciu plików konfiguracyjnych.

To rozwiązanie oparte na refleksji, przetestowane na Javie 8

Wywołaj tę metodę raz na początku programu.

//Import

import javax.crypto.Cipher;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Map;

//metoda

public static void fixKeyLength() {
    String errorString = "Failed manually overriding key-length permissions.";
    int newMaxKeyLength;
    try {
        if ((newMaxKeyLength = Cipher.getMaxAllowedKeyLength("AES")) < 256) {
            Class c = Class.forName("javax.crypto.CryptoAllPermissionCollection");
            Constructor con = c.getDeclaredConstructor();
            con.setAccessible(true);
            Object allPermissionCollection = con.newInstance();
            Field f = c.getDeclaredField("all_allowed");
            f.setAccessible(true);
            f.setBoolean(allPermissionCollection, true);

            c = Class.forName("javax.crypto.CryptoPermissions");
            con = c.getDeclaredConstructor();
            con.setAccessible(true);
            Object allPermissions = con.newInstance();
            f = c.getDeclaredField("perms");
            f.setAccessible(true);
            ((Map) f.get(allPermissions)).put("*", allPermissionCollection);

            c = Class.forName("javax.crypto.JceSecurityManager");
            f = c.getDeclaredField("defaultPolicy");
            f.setAccessible(true);
            Field mf = Field.class.getDeclaredField("modifiers");
            mf.setAccessible(true);
            mf.setInt(f, f.getModifiers() & ~Modifier.FINAL);
            f.set(null, allPermissions);

            newMaxKeyLength = Cipher.getMaxAllowedKeyLength("AES");
        }
    } catch (Exception e) {
        throw new RuntimeException(errorString, e);
    }
    if (newMaxKeyLength < 256)
        throw new RuntimeException(errorString); // hack failed
}

Kredyty: Delthas

Jako
źródło
4
Należy pamiętać, że może to naruszać umowę licencyjną Java SE: D. OGRANICZENIA DOTYCZĄCE TECHNOLOGII JAVA. Nie możesz tworzyć, modyfikować ani zmieniać zachowania lub upoważniać swoich licencjobiorców do tworzenia, modyfikowania lub zmiany zachowania klas, interfejsów lub podpakietów, które są w jakikolwiek sposób określane jako „java”, „javax”, „ javafx ”,„ słońce ”,„ wyrocznia ”lub podobna konwencja określona przez Oracle w dowolnym oznaczeniu konwencji nazewnictwa. [...] źródło
SimMac
Dziękuję bardzo
16

Wystąpił ten sam błąd podczas korzystania z systemu Windows 7 x64, Eclipse i JDK 1.6.0_30. W folderze instalacyjnym JDK znajduje się jrefolder. Z początku mnie to zniechęciło, ponieważ bez powodzenia dodawałem wyżej wymienione słoiki do folderu lib / security JDK. Pełna ścieżka:

C:\Program Files\Java\jdk1.6.0_30\jre\lib\security

Pobierz i wyodrębnij pliki zawarte w jcefolderze tego archiwum do tego folderu.

Brian Bowman
źródło
16

W Javie domyślnie AES obsługuje klucz 128-bitowy, jeśli planujesz użyć klucza 192-bitowego lub 256-bitowego, program kompilujący Java wyrzuci wyjątek dotyczący nielegalnego klucza, który otrzymujesz.

Rozwiązanie jest takie, jak sugerował zwycięzca i James, musisz pobrać JCE (Java Cryptography Extension) zgodnie z wersją JRE (java6, java7 lub java8).

Plik zip JCE zawiera następujący plik JAR:

  1. local_policy.jar
  2. US_export_policy.jar

Musisz wymienić te słoiki ze swojego <JAVA_HOME>/jre/lib/security. jeśli korzystasz z systemu uniksowego, prawdopodobnie będzie się to odnosić/home/urs/usr/lib/jvm/java-<version>-oracle/

Czasami po prostu zamiana local_policy.jar, US_export_policy.jar w folderze bezpieczeństwa nie działa na Uniksie, więc sugeruję najpierw skopiować folder bezpieczeństwa na pulpit, zastąpić folder @ Desktop / security w słoiku, usunąć folder bezpieczeństwa z / jre / lib / i przenieś folder zabezpieczeń pulpitu do / jre / lib /.

np. :: sudo mv security /usr/lib/jvm/java-7-oracle/jre/lib

Ketan Vishwakarma
źródło
5

Jest to krótka dyskusja na temat tego, co wydaje się być to problem tutaj . Strona, do której prowadzi, wydaje się zniknąć, ale jedną z odpowiedzi może być to, czego potrzebujesz:

Rzeczywiście, pomogło kopiowanie US_export_policy.jar i local_policy.jar z core / lib / jce do $ JAVA_HOME / jre / lib / security. Dzięki.

RHSeeger
źródło
Dzięki, ale miałem US_export_policy.jari local_policy.jarmoim folderze lib / security już po zainstalowaniu Java .. I nie mógł znaleźć rdzeń / lib / JCE nawiasem mówiąc w moim folderze instalacyjnym Java.
Rihards
5

problemem jest zawartość pliku default_local.policy w local_policy.jar w folderze jre \ lib \ security , jeśli zainstalujesz JRE:

// Some countries have import limits on crypto strength. This policy file
// is worldwide importable.

grant {
    permission javax.crypto.CryptoPermission "DES", 64;
    permission javax.crypto.CryptoPermission "DESede", *;
    permission javax.crypto.CryptoPermission "RC2", 128,
                                     "javax.crypto.spec.RC2ParameterSpec", 128;
    permission javax.crypto.CryptoPermission "RC4", 128;
    permission javax.crypto.CryptoPermission "RC5", 128,
          "javax.crypto.spec.RC5ParameterSpec", *, 12, *;
    permission javax.crypto.CryptoPermission "RSA", *;
    permission javax.crypto.CryptoPermission *, 128;
};

jeśli nie potrzebujesz prawidłowych ustawień na całym świecie, możesz po prostu edytować ten plik i zmienić zawartość na

// Country-specific policy file for countries with no limits on crypto strength.
grant {
    // There is no restriction to any algorithms.
    permission javax.crypto.CryptoAllPermission;
};

to, co otrzymasz, jeśli pobierzesz JCE z Oracle.

max
źródło
4

Dostałem również problem, ale po zamianie istniejącego na pobrany (z JCE) rozwiązałem problem. Nowe pliki kryptograficzne zapewniały nieograniczoną siłę.

Dev G
źródło
2

Domyślnie Java obsługuje szyfrowanie tylko w rozmiarze 128-bitowym (16 bajtów) klucza AES. Jeśli nie potrzebujesz więcej niż obsługiwanej domyślnie, możesz przyciąć klucz do odpowiedniego rozmiaru przed użyciem Cipher. Zobacz javadoc dla domyślnych obsługiwanych kluczy.

Jest to przykład generowania klucza, który działałby z dowolną wersją JVM bez modyfikowania plików zasad. Używaj według własnego uznania.

Oto dobry artykuł na temat tego, czy klucz od 128 do 256 kluczy ma znaczenie na blogu AgileBits

SecretKeySpec getKey() {
    final pass = "47e7717f0f37ee72cb226278279aebef".getBytes("UTF-8");
    final sha = MessageDigest.getInstance("SHA-256");

    def key = sha.digest(pass);
    // use only first 128 bit (16 bytes). By default Java only supports AES 128 bit key sizes for encryption.
    // Updated jvm policies are required for 256 bit.
    key = Arrays.copyOf(key, 16);
    return new SecretKeySpec(key, AES);
}
keaplogik
źródło
Dokumentacja klas szyfrów wskazuje na prawidłowe rozmiary kluczy dla każdego typu szyfrowania.
keaplogik
Zobacz dokument Oracle Algorytmy szyfrowania (szyfrowania) AES: zaawansowany standard szyfrowania określony przez NIST w FIPS 197. Znany również jako algorytm Rijndael autorstwa Joana Daemena i Vincenta Rijmena, AES to 128-bitowy szyfr blokowy obsługujący klucze 128, 192, i 256 bitów.
zaph
To może być prawda, ale wymagana jest tylko wersja 128-bitowa dla każdej wersji Java, jak określono w dokumentacji klas. Przetestuj to sam, a przekonasz się, że będziesz potrzebować słoika polityki z odpowiedzi Jamesa Blacka, aby zrobić inne kluczowe rozmiary
keaplogik
Każda implementacja AES, która nie obsługuje 256-bitowych kluczy, byłaby zasadniczo bezużyteczna, ponieważ nie byłaby w stanie odszyfrować znacznej liczby szyfrów AES przy użyciu 256-bitowych kluczy.
zaph
1
Jeśli potrzebny jest klucz 256-bitowy, najlepszym rozwiązaniem, być może jedynym rozwiązaniem, jest zainstalowanie pliku zasad w razie potrzeby, a nie obcinanie klucza potencjalnie osłabiającego bezpieczeństwo i może nie być możliwe w przypadku interoperacyjności.
zaph
2

Począwszy od Java 9 lub 8u151, możesz użyć komentarza do wiersza w pliku:

<JAVA_HOME>/jre/lib/security/java.security

I zmień:

#crypto.policy=unlimited

do

crypto.policy=unlimited
Ahmed Ashour
źródło
2

Jeśli używasz dystrybucji Linuksa z apt i dodałeś webupd8 PPA, możesz po prostu uruchomić polecenie

apt-get install oracle-java8-unlimited-jce-policy

Inne aktualizacje:

  1. Pliki zasad nieograniczonej jurysdykcji są dołączone do Java 9 i są używane domyślnie
  2. Począwszy od wersji Java 8 Update 161 , Java 8 domyślnie przyjmuje zasady jurysdykcji Unlimited Strength.
  3. Począwszy od wersji Java 8 Update 151 , zasady jurysdykcji nieograniczonej siły są dołączone do Java 8, ale nie są domyślnie używane. Aby go włączyć, musisz edytować plik java.security w <java_home>/jre/lib/security(dla JDK) lub <java_home>/lib/security(dla JRE). Odkomentuj (lub dołącz) linię

    crypto.policy=unlimited

    Upewnij się, że edytujesz plik za pomocą edytora uruchomionego jako administrator. Zmiana zasad obowiązuje dopiero po ponownym uruchomieniu maszyny JVM

Przed aktualizacją Java 8 Update 151 pozostałe odpowiedzi są ważne. Pobierz pliki zasad jurysdykcji JCE Unlimited i wymień je.

Aby uzyskać więcej informacji, zapoznaj się z moim osobistym postem na blogu poniżej - Jak zainstalować pliki zasad jurysdykcji Java Cryptography Extension (JCE) o nieograniczonej sile

Aniket Thakur
źródło
1

istnieją dwie opcje rozwiązania tego problemu

opcja numer 1: użyj certyfikatu o mniejszej długości RSA 2048

opcja numer 2: zaktualizujesz dwa słoiki w jre\lib\security dowolnym języku java http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html

lub korzystasz z serwisu WWW IBM lub dowolnego serwera aplikacji korzystającego z jego Java. główny problem, z którym się spotkałem, użyłem certyfikacji o maksymalnej długości, gdy wdrożyłem uszy w sieci, zgłaszany jest ten sam wyjątek

Java Security: Illegal key size or default parameters?

zaktualizowałem zintegrowany folder Java w websphere za pomocą dwóch słoików https://www14.software.ibm.com/webapp/iwm/web/reg/pick.do?source=jcesdk&lang=en_US

możesz sprawdzić referencję w linku https://www-01.ibm.com/support/docview.wss?uid=swg21663373

Shaaban Ebrahim
źródło
1

Upewnij się, że używasz najnowszej wersji JDK / JRE .

W moim przypadku umieściłem JCE w folderze JRE, ale to nie pomogło. Stało się tak, ponieważ prowadziłem projekt bezpośrednio z IDE (używając JDK).

Następnie zaktualizowałem JDK i JRE do najnowszej wersji (1.8.0_211) i problem zniknął.

Więcej informacji: https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8170157

Ruslan Sheremet
źródło
1

Domyślnie JDK obsługuje szyfrowanie tylko za pomocą 128-bitowych kluczy ze względu na ograniczenia amerykańskie. Aby obsługiwać szyfrowanie z klucza o długości 256 bitów, musimy go wymienić local_policy.jari US_export_policy.jarsw $JAVA_HOME/java-8-oracle/jre/lib/securityfolderze, w przeciwnym razie da:

java.security.InvalidKeyException: Niedozwolony rozmiar klucza lub wartość domyślna

Sulabh Jain
źródło
0

Musisz tam iść

/jdk1.8.0_152 | / jre | / lib | / bezpieczeństwo | java.security i odkomentuj

#crypto.policy=unlimited

do

crypto.policy=unlimited
Fzum
źródło