Es gibt einige häufig zitierte Lösungen für dieses Problem. Leider ist keines davon völlig zufriedenstellend:
- Installieren Sie die Richtliniendateien mit unbegrenzter Stärke . Während dies wahrscheinlich die richtige Lösung für Ihre Entwicklungsarbeitsstation ist, wird es schnell zu einem großen Problem (wenn nicht sogar zu einer Straßensperre), wenn nicht technische Benutzer die Dateien auf jedem Computer installieren. Es gibt keine Möglichkeit , die Dateien mit Ihrem Programm zu verteilen. Sie müssen im JRE-Verzeichnis installiert sein (das aufgrund von Berechtigungen möglicherweise sogar schreibgeschützt ist).
- Überspringen Sie die JCE-API und verwenden Sie eine andere Kryptografie-Bibliothek wie Bouncy Castle . Dieser Ansatz erfordert eine zusätzliche 1-MB-Bibliothek, was je nach Anwendung eine erhebliche Belastung darstellen kann. Es fühlt sich auch albern an, Funktionen zu duplizieren, die in den Standardbibliotheken enthalten sind. Natürlich unterscheidet sich die API auch völlig von der üblichen JCE-Schnittstelle. (BC implementiert zwar einen JCE-Anbieter, dies hilft jedoch nicht, da die Einschränkungen der Schlüsselstärke vor der Übergabe an die Implementierung angewendet werden .) Mit dieser Lösung können Sie auch keine 256-Bit-TLS-Verschlüsselungssuiten (SSL) verwenden, da die Standard-TLS-Bibliotheken rufen das JCE intern auf, um eventuelle Einschränkungen zu ermitteln.
Aber dann gibt es Reflexion. Gibt es etwas, das Sie mit Reflexion nicht tun können?
private static void removeCryptographyRestrictions() {
if (!isRestrictedCryptography()) {
logger.fine("Cryptography restrictions removal not needed");
return;
}
try {
/*
* Do the following, but with reflection to bypass access checks:
*
* JceSecurity.isRestricted = false;
* JceSecurity.defaultPolicy.perms.clear();
* JceSecurity.defaultPolicy.add(CryptoAllPermission.INSTANCE);
*/
final Class<?> jceSecurity = Class.forName("javax.crypto.JceSecurity");
final Class<?> cryptoPermissions = Class.forName("javax.crypto.CryptoPermissions");
final Class<?> cryptoAllPermission = Class.forName("javax.crypto.CryptoAllPermission");
final Field isRestrictedField = jceSecurity.getDeclaredField("isRestricted");
isRestrictedField.setAccessible(true);
final Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(isRestrictedField, isRestrictedField.getModifiers() & ~Modifier.FINAL);
isRestrictedField.set(null, false);
final Field defaultPolicyField = jceSecurity.getDeclaredField("defaultPolicy");
defaultPolicyField.setAccessible(true);
final PermissionCollection defaultPolicy = (PermissionCollection) defaultPolicyField.get(null);
final Field perms = cryptoPermissions.getDeclaredField("perms");
perms.setAccessible(true);
((Map<?, ?>) perms.get(defaultPolicy)).clear();
final Field instance = cryptoAllPermission.getDeclaredField("INSTANCE");
instance.setAccessible(true);
defaultPolicy.add((Permission) instance.get(null));
logger.fine("Successfully removed cryptography restrictions");
} catch (final Exception e) {
logger.log(Level.WARNING, "Failed to remove cryptography restrictions", e);
}
}
private static boolean isRestrictedCryptography() {
// This matches Oracle Java 7 and 8, but not Java 9 or OpenJDK.
final String name = System.getProperty("java.runtime.name");
final String ver = System.getProperty("java.version");
return name != null && name.equals("Java(TM) SE Runtime Environment")
&& ver != null && (ver.startsWith("1.7") || ver.startsWith("1.8"));
}
Rufen Sie einfach removeCryptographyRestrictions()
von einem statischen Initialisierer oder ähnlichem auf, bevor Sie kryptografische Operationen ausführen.
Der JceSecurity.isRestricted = false
Teil ist alles, was benötigt wird, um 256-Bit-Chiffren direkt zu verwenden. Ohne die beiden anderen Vorgänge Cipher.getMaxAllowedKeyLength()
werden jedoch weiterhin 128 gemeldet, und 256-Bit-TLS-Verschlüsselungssuiten funktionieren nicht.
Dieser Code funktioniert unter Oracle Java 7 und 8 und überspringt den Prozess unter Java 9 und OpenJDK automatisch, wenn er nicht benötigt wird. Da es sich schließlich um einen hässlichen Hack handelt, funktioniert es wahrscheinlich nicht auf den VMs anderer Anbieter.
Es funktioniert auch nicht unter Oracle Java 6, da die privaten JCE-Klassen dort verschleiert sind. Die Verschleierung ändert sich jedoch nicht von Version zu Version, sodass es technisch immer noch möglich ist, Java 6 zu unterstützen.