Java-Sicherheit: Unzulässige Schlüsselgröße oder Standardparameter?

409

Ich hatte früher eine Frage dazu gestellt, aber sie wurde nicht richtig beantwortet und führte nirgendwo hin.

Daher habe ich einige Details zu dem Problem geklärt und würde gerne Ihre Ideen dazu hören, wie ich das beheben könnte oder was ich versuchen sollte.

Ich habe Java 1.6.0.12 auf meinem Linux-Server installiert und der folgende Code läuft einfach perfekt.

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);
}

Heute habe ich Java 1.6.0.26 auf meinem Serverbenutzer installiert und beim Versuch, meine Anwendung auszuführen, wird die folgende Ausnahme angezeigt . Ich würde vermuten, dass es etwas mit der Java-Installationskonfiguration zu tun hat, da es in der ersten Version funktioniert, in der späteren Version jedoch nicht.

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

Zeile 25 lautet: c.init(Cipher.DECRYPT_MODE, secretKeySpec);

Hinweise:
* java.security auf Server 1.6.0.12 java Matches fast vollständig mit der 1.6.0.26 java.security Datei. Im ersten gibt es keine zusätzlichen Anbieter.
* Die vorherige Frage ist hier .

Rihards
quelle
4
Dies kann auch als Fehler Caused by: java.security.InvalidKeyException: Illegal key size
ausgegeben werden
Verwenden Sie einfach das OpenJDK und es wird funktionieren.
Rodrigo Asensio
@RodrigoAsensio: Ich benutze das OpenJDK und es funktioniert nicht damit. Sie müssen die JAR-Dateien mit unbegrenzten Richtlinien für die Zuständigkeitsrichtlinie installieren. Und dann wird es funktionieren.
Anjanb
5
Update auf @AniketThakur Antwort. Seit Java 9 und Java 8u151 müssen Gerichtsbarkeitsrichtliniendateien nicht mehr heruntergeladen und manuell installiert werden. Um unbegrenzte Kryptografie zu aktivieren, kann die neue Eigenschaft crypto.policy Security verwendet werden. Wenn die neue Sicherheitseigenschaft (crypto.policy) in der Datei java.security festgelegt oder mithilfe des Aufrufs Security.setProperty () dynamisch festgelegt wurde, bevor das JCE-Framework initialisiert wurde, wird diese Einstellung berücksichtigt. Standardmäßig ist die Eigenschaft undefiniert.
Marcin Kłopotek

Antworten:

722

Höchstwahrscheinlich ist die Datei mit unbegrenzter Stärke jetzt nicht installiert.

Möglicherweise müssen Sie diese Datei herunterladen:

Java Cryptography Extension (JCE) Richtliniendateien mit unbegrenzter Stärke 6

Java Cryptography Extension (JCE) Richtliniendateien mit unbegrenzter Stärke 7 Download

Java Cryptography Extension (JCE) Richtliniendateien mit unbegrenzter Gerichtsbarkeit 8 Herunterladen (nur für Versionen vor Java 8 u162 erforderlich)

Extrahieren Sie die JAR-Dateien aus der Zip-Datei und speichern Sie sie in ${java.home}/jre/lib/security/.

James Black
quelle
2
@JamesBlack - Ja, und um sicherzustellen , dass alle wurden Grundlagen abgedeckt ich die unter JAR setzen Java/jre/lib/security, Java/jdk/lib/securityund Java/jdk/jre/lib/security. Wenn Sie 'java -version' ausführen, werden die erwarteten Details zurückgegeben.
aroth
5
Laden Sie für das IBM SDK (z. B. WebSphere) die Richtliniendateien mit unbegrenzter Gerichtsbarkeit von www14.software.ibm.com/webapp/iwm/web/preLogin.do?source=jcesdk herunter
quietmint
4
Seit Java 9 und Java 8u151 müssen Gerichtsbarkeitsrichtliniendateien nicht mehr heruntergeladen und manuell installiert werden. Um unbegrenzte Kryptografie zu aktivieren, kann die neue Eigenschaft crypto.policy Security verwendet werden. Wenn die neue Sicherheitseigenschaft (crypto.policy) in der Datei java.security festgelegt oder mithilfe des Aufrufs Security.setProperty () dynamisch festgelegt wurde, bevor das JCE-Framework initialisiert wurde, wird diese Einstellung berücksichtigt. Standardmäßig ist die Eigenschaft undefiniert.
Marcin Kłopotek
4
Diese optimierte Antwort ist nun veraltet und veraltet. Wie können wir diese Antwort verbessern oder unterdrücken, damit stackoverflow.com/a/46857694/2808798 die "akzeptierte" Antwort sein kann?
Jesse Adelman
3
@ JesseAdelman - Leider ist dies fast 7 Jahre alt, nicht viel kann getan werden. Wer auch immer gefragt hat, muss es ändern.
James Black
54

Die JRE / JDK / Java 8-Gerichtsbarkeitsdateien finden Sie hier:

Java Cryptography Extension (JCE) Richtliniendateien mit unbegrenzter Stärke 8 Download

Wie James oben sagte:
Installieren Sie die Dateien in ${java.home}/jre/lib/security/.

Saad Malik
quelle
2
Versucht mit 6 und 7, aber sie haben nicht funktioniert. Musste 8 installieren. Danke.
Jason Kim
9
Neue Version JDK 8u151 verfügt über die Eigenschaft "Neue Sicherheit zur Steuerung der Kryptorichtlinie". Jetzt ist es eine Eigenschaftsänderung zu wechseln. Fazit: Entfernen Sie das "#" aus der Zeile "# crypto.policy = unlimited" in "lib \ security \ java.security", um die Verwendung von 256-Bit-Schlüsseln zu aktivieren. oracle.com/technetwork/java/javase/8u151-relnotes-3850493.html
Hemisphire
1
Vielen Dank! Da dies eine Sicherheitseigenschaft ist, können Sie auch Security.setProperty ("crypto.policy", "unbegrenzt") aufrufen. Quelle: @hemisphires Link :)
Fluf
42

Für JAVA 7 lautet der Download-Link jce-7-download

Kopieren Sie die beiden heruntergeladenen Jars in Java \ jdk1.7.0_10 \ jre \ lib \ security. Erstellen Sie aus Sicherheitsgründen
eine Sicherungskopie älterer Jars.

Für JAVA 8 lautet der Download-Link jce-8-download.
Kopieren Sie die heruntergeladenen Jars in Java \ jdk1.8.0_45 \ jre \ lib \ security. Erstellen Sie aus Sicherheitsgründen
eine Sicherungskopie älterer Jars.

C Deepak
quelle
39

Mit Java 9, Java 8u161 , Java 7u171 und Java 6u181 ist die Einschränkung jetzt standardmäßig deaktiviert. Siehe Problem in der Java Bug Database .


Ab Java 8u151 können Sie die Einschränkung programmgesteuert deaktivieren.

In älteren Versionen mussten JCE-Gerichtsbarkeitsdateien separat heruntergeladen und installiert werden, damit das JDK unbegrenzt Kryptografie verwenden konnte. Die Schritte zum Herunterladen und Installieren sind nicht mehr erforderlich.

Stattdessen können Sie jetzt die folgende Zeile aufrufen, bevor Sie JCE-Klassen zum ersten Mal verwenden (dh vorzugsweise direkt nach dem Start der Anwendung):

Security.setProperty("crypto.policy", "unlimited");
Sebastian S.
quelle
Was ist mit Android? Auf welcher API-Ebene können diese Restriktionsmethoden gelöst werden?
TheRealChx101
31

Dies ist eine reine Codelösung . Sie müssen keine Konfigurationsdateien herunterladen oder damit herumspielen.

Es ist eine reflexionsbasierte Lösung, die auf Java 8 getestet wurde

Rufen Sie diese Methode zu Beginn Ihres Programms einmal auf.

// Importe

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

//Methode

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
}

Credits: Delthas

Jako
quelle
4
Bitte beachten Sie, dass dies möglicherweise gegen die Java SE-Lizenzvereinbarung verstößt: D. JAVA TECHNOLOGY RESTRICTIONS. Sie dürfen das Verhalten von Klassen, Schnittstellen oder Unterpaketen, die in irgendeiner Weise als "Java", "Javax", "identifiziert" werden, nicht erstellen, ändern oder ändern oder Ihre Lizenznehmer dazu berechtigen, das Verhalten von Klassen, Schnittstellen oder Unterpaketen zu erstellen, zu ändern oder zu ändern. javafx "," sun "," oracle "oder eine ähnliche Konvention, wie sie von Oracle in einer beliebigen Bezeichnung für eine Namenskonvention angegeben wurde. [...] Quelle
SimMac
Vielen Dank
16

Bei der Verwendung von Windows 7 x64, Eclipse und JDK 1.6.0_30 ist der gleiche Fehler aufgetreten. Im JDK-Installationsordner befindet sich ein jreOrdner. Dies warf mich zunächst ab, als ich die oben genannten Gläser ohne Glück in den Ordner lib / security des JDK einfügte. Vollständigen Pfad:

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

Laden Sie die im jceOrdner dieses Archivs enthaltenen Dateien herunter und extrahieren Sie sie in diesen Ordner.

Brian Bowman
quelle
16

In Java unterstützt AES standardmäßig einen 128-Bit-Schlüssel. Wenn Sie einen 192-Bit- oder 256-Bit-Schlüssel verwenden möchten, löst Java Complier eine Ausnahme für die illegale Schlüsselgröße aus, die Sie erhalten.

Die Lösung ist wie von Victor & James vorgeschlagen. Sie müssen JCE (Java Cryptography Extension) gemäß Ihrer JRE-Version (Java6, Java7 oder Java8) herunterladen.

Die JCE-Zip enthält folgende JAR:

  1. local_policy.jar
  2. US_export_policy.jar

Sie müssen diese Gläser von Ihrem ersetzen <JAVA_HOME>/jre/lib/security. Wenn Sie sich auf einem Unix-System befinden, wird wahrscheinlich darauf verwiesen/home/urs/usr/lib/jvm/java-<version>-oracle/

Manchmal funktioniert das Ersetzen von local_policy.jar, US_export_policy.jar im Sicherheitsordner unter Unix nicht. Ich empfehle daher, zuerst den Sicherheitsordner auf Ihren Desktop zu kopieren, den Ordner @ Desktop / security des JAR zu ersetzen und den Sicherheitsordner aus / jre / lib zu löschen / & Verschieben Sie den Desktop-Sicherheitsordner nach / jre / lib /.

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

Ketan Vishwakarma
quelle
5

Es gibt eine kurze Diskussion darüber , was scheint dieses Problem zu sein hier . Die Seite, auf die verlinkt wird, scheint verschwunden zu sein, aber eine der Antworten könnte die sein, die Sie benötigen:

In der Tat hat das Kopieren von US_export_policy.jar und local_policy.jar von core / lib / jce nach $ JAVA_HOME / jre / lib / security geholfen. Vielen Dank.

RHSeeger
quelle
Danke, aber ich hatte US_export_policy.jarund local_policy.jarin meinem lib / security-Ordner schon einmal Java installiert. Und ich konnte core / lib / jce übrigens nicht in meinem Java-Installationsordner finden.
Rihards
5

Das Problem ist der Inhalt der Datei default_local.policy in local_policy.jar im Ordner jre \ lib \ security , wenn Sie die JRE installieren:

// 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;
};

Wenn Sie keine weltweit gültigen Einstellungen benötigen, können Sie diese Datei einfach bearbeiten und den Inhalt in ändern

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

Dies erhalten Sie, wenn Sie das JCE von Oracle herunterladen.

max
quelle
4

Ich habe auch das Problem erhalten, aber nachdem ich das vorhandene durch das heruntergeladene (von JCE) ersetzt habe, wurde das Problem behoben. Neue Kryptodateien bieten unbegrenzte Stärke.

Dev G.
quelle
2

Standardmäßig unterstützt Java nur AES-128-Bit-Schlüsselgrößen (16 Byte) für die Verschlüsselung. Wenn Sie nicht mehr als die Standardunterstützung benötigen, können Sie den Schlüssel vor der Verwendung auf die richtige Größe zuschneiden Cipher. Siehe javadoc für standardmäßig unterstützte Schlüssel.

Dies ist ein Beispiel für das Generieren eines Schlüssels, der mit jeder JVM-Version funktioniert, ohne die Richtliniendateien zu ändern. Verwendung nach eigenem Ermessen.

Hier ist ein guter Artikel darüber, ob die Schlüsselgrößen 128 bis 256 im AgileBits-Blog von Bedeutung sind

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
quelle
Die Dokumentation zu Cipher- Klassen verweist auf gültige Schlüsselgrößen für jeden Kryptotyp.
Keaplogik
Siehe das Oracle-Dokument Verschlüsselungsalgorithmen (Verschlüsselungsalgorithmen) AES: Advanced Encryption Standard, wie von NIST in FIPS 197 angegeben. AES, auch bekannt als Rijndael-Algorithmus von Joan Daemen und Vincent Rijmen, ist eine 128-Bit-Blockverschlüsselung, die Schlüssel von 128, 192, unterstützt. und 256 Bits.
Zaph
Das mag wahr sein, aber es ist nur von jeder Java-Version erforderlich, 128-Bit zu unterstützen, wie in der Klassendokumentation angegeben. Testen Sie es selbst und Sie werden feststellen, dass Sie das Richtlinienglas aus James Blacks Antwort benötigen, um andere Schlüsselgrößen zu
erstellen
Jede AES-Implementierung, die keine 256-Bit-Schlüssel unterstützt, wäre im Wesentlichen nutzlos, da sie nicht in der Lage wäre, eine erhebliche Anzahl von AES-Verschlüsselungen mit 256-Bit-Schlüsseln zu entschlüsseln.
Zaph
1
Wenn ein 256-Bit-Schlüssel benötigt wird, besteht die beste Lösung, möglicherweise die einzige, darin, die Richtliniendatei bei Bedarf zu installieren, den Schlüssel nicht abzuschneiden, was möglicherweise die Sicherheit schwächt und im Falle der Interoperabilität möglicherweise nicht möglich ist.
Zaph
2

Ab Java 9 oder 8u151 können Sie eine Zeile in der Datei kommentieren:

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

Und ändern:

#crypto.policy=unlimited

zu

crypto.policy=unlimited
Ahmed Ashour
quelle
2

Wenn Sie die Linux-Distribution mit apt verwenden und webupd8 PPA hinzugefügt haben, können Sie den Befehl einfach ausführen

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

Weitere Updates:

  1. Die Richtliniendateien mit unbegrenzter Stärke sind in Java 9 enthalten und werden standardmäßig verwendet
  2. Ab Java 8 Update 161 verwendet Java 8 standardmäßig die Richtlinie für die Zuständigkeit für unbegrenzte Stärke.
  3. Ab Java 8 Update 151 ist die Unlimited Strength Jurisdiction Policy in Java 8 enthalten, wird jedoch nicht standardmäßig verwendet. Um es zu aktivieren, müssen Sie die Datei java.security in <java_home>/jre/lib/security(für JDK) oder <java_home>/lib/security(für JRE) bearbeiten . Kommentieren Sie die Zeile aus (oder fügen Sie sie ein)

    crypto.policy=unlimited

    Stellen Sie sicher, dass Sie die Datei mit einem Editor bearbeiten, der als Administrator ausgeführt wird. Die Richtlinienänderung wird erst nach dem Neustart der JVM wirksam

Vor Java 8 Update 151 gelten die restlichen Antworten. Laden Sie die Richtliniendateien für JCE Unlimited Strength Jurisdiction herunter und ersetzen Sie sie.

Weitere Informationen finden Sie in meinem persönlichen Blog-Beitrag unten - Installieren von JCE-Richtliniendateien (Java Cryptography Extension) mit unbegrenzter Stärke

Aniket Thakur
quelle
1

Es gibt zwei Möglichkeiten, um dieses Problem zu lösen

Option 1: Verwenden Sie ein Zertifikat mit einer geringeren Länge von RSA 2048

Option 2: Sie aktualisieren zwei Gläser in jre\lib\security Java. http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html

oder Sie verwenden IBM Websphere oder einen Anwendungsserver, der Java verwendet. Das Hauptproblem, mit dem ich konfrontiert war, war die Verwendung einer Zertifizierung mit maximaler Länge. Wenn ich Ohren auf Websphere einsetzte, wird dieselbe Ausnahme ausgelöst

Java Security: Illegal key size or default parameters?

Ich habe den Java-Ordner in Websphere mit zwei Gläsern aktualisiert: https://www14.software.ibm.com/webapp/iwm/web/reg/pick.do?source=jcesdk&lang=de_DE

Sie können die Referenz unter dem Link https://www-01.ibm.com/support/docview.wss?uid=swg21663373 überprüfen

Shaaban Ebrahim
quelle
1

Stellen Sie sicher, dass Sie die neueste Version von JDK / JRE verwenden .

In meinem Fall hatte ich JCE in den JRE-Ordner gelegt, aber es hat nicht geholfen. Dies geschah, weil ich mein Projekt direkt von der IDE aus ausführte (mit JDK).

Dann habe ich mein JDK und JRE auf die neueste Version (1.8.0_211) aktualisiert und das Problem war behoben.

Weitere Details: https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8170157

Ruslan Sheremet
quelle
1

Das Standard-JDK unterstützt die Verschlüsselung aufgrund amerikanischer Einschränkungen nur über 128-Bit-Schlüssel. Um die Verschlüsselung von einem 256 Bit langen Schlüssel zu unterstützen, müssen wir ihn ersetzen local_policy.jarund US_export_policy.jarsim $JAVA_HOME/java-8-oracle/jre/lib/securityOrdner, sonst gibt es:

java.security.InvalidKeyException: Unzulässige Schlüsselgröße oder Standard

Sulabh Jain
quelle
0

Du musst dorthin gehen

/jdk1.8.0_152 | / jre | / lib | / Sicherheit | java.security und auskommentieren die

#crypto.policy=unlimited

zu

crypto.policy=unlimited
Fzum
quelle