Ada beberapa solusi yang biasa dikutip untuk masalah ini. Sayangnya, keduanya tidak sepenuhnya memuaskan:
- Instal file kebijakan kekuatan tidak terbatas . Meskipun ini mungkin solusi yang tepat untuk workstation pengembangan Anda, dengan cepat menjadi masalah besar (jika bukan penghalang jalan) untuk meminta pengguna non-teknis menginstal file di setiap komputer. Tidak ada cara untuk mendistribusikan file dengan program Anda; mereka harus diinstal di direktori JRE (yang bahkan mungkin hanya baca karena izin).
- Lewati API JCE dan gunakan perpustakaan kriptografi lain seperti Bouncy Castle . Pendekatan ini membutuhkan perpustakaan 1MB tambahan, yang mungkin menjadi beban yang signifikan tergantung pada aplikasi. Rasanya konyol menggandakan fungsi yang termasuk dalam perpustakaan standar. Jelas, API juga sangat berbeda dari antarmuka JCE yang biasa. (BC memang mengimplementasikan penyedia JCE, tetapi itu tidak membantu karena pembatasan kekuatan utama diterapkan sebelum menyerahkan implementasi.) Solusi ini juga tidak akan membiarkan Anda menggunakan suar suites 256-bit TLS (SSL), karena pustaka TLS standar memanggil JCE secara internal untuk menentukan batasan apa pun.
Tapi kemudian ada refleksi. Adakah yang tidak bisa Anda lakukan menggunakan refleksi?
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"));
}
Cukup panggil removeCryptographyRestrictions()
dari penginisialisasi statis atau semacamnya sebelum melakukan operasi kriptografis apa pun.
Bagian JceSecurity.isRestricted = false
inilah yang diperlukan untuk menggunakan sandi 256-bit secara langsung; Namun, tanpa dua operasi lainnya, Cipher.getMaxAllowedKeyLength()
masih akan tetap melaporkan 128, dan 256-bit TLS cipher suites tidak akan berfungsi.
Kode ini berfungsi pada Oracle Java 7 dan 8, dan secara otomatis melewatkan proses pada Java 9 dan OpenJDK di tempat yang tidak diperlukan. Bagaimanapun, menjadi peretasan yang buruk, sepertinya tidak bekerja pada VM vendor lain.
Ini juga tidak berfungsi pada Oracle Java 6, karena kelas-kelas JCE pribadi dikaburkan di sana. Kebingungan tidak berubah dari versi ke versi, jadi masih memungkinkan secara teknis untuk mendukung Java 6.