มีวิธีแก้ไขปัญหาที่ยกมาทั่วไปสองสามปัญหา น่าเสียดายที่สิ่งเหล่านี้ไม่เป็นที่น่าพอใจอย่างสิ้นเชิง:
- ติดตั้งแฟ้มนโยบายความแข็งแรงไม่ จำกัด แม้ว่านี่จะเป็นทางออกที่เหมาะสมสำหรับเวิร์คสเตชั่นสำหรับการพัฒนาของคุณ แต่มันก็กลายเป็นปัญหาใหญ่อย่างรวดเร็ว (หากไม่ใช่สิ่งกีดขวางบนถนน) เพื่อให้ผู้ใช้ที่ไม่ใช่ด้านเทคนิคติดตั้งไฟล์ในคอมพิวเตอร์ทุกเครื่อง นอกจากนี้ไม่มีทางที่จะแจกจ่ายไฟล์กับโปรแกรมของคุณ; จะต้องติดตั้งในไดเรกทอรี JRE (ซึ่งอาจเป็นแบบอ่านอย่างเดียวเนื่องจากสิทธิ์)
- ข้าม JCE APIและการใช้ห้องสมุดการเข้ารหัสอื่นเช่นปราสาท Bouncy วิธีนี้ต้องใช้ไลบรารี 1MB เพิ่มเติมซึ่งอาจเป็นภาระที่สำคัญขึ้นอยู่กับแอปพลิเคชัน นอกจากนี้ยังรู้สึกว่าโง่กับฟังก์ชั่นซ้ำซ้อนที่รวมอยู่ในไลบรารีมาตรฐาน เห็นได้ชัดว่า API นั้นแตกต่างจากอินเตอร์เฟส JCE ปกติอย่างสิ้นเชิง (BC ใช้ผู้ให้บริการ JCE แต่นั่นไม่ได้ช่วยเพราะข้อ จำกัด ความแข็งแรงของคีย์ถูกนำไปใช้ก่อนส่งมอบให้กับการใช้งาน) โซลูชันนี้จะไม่อนุญาตให้คุณใช้ชุดรหัสเข้ารหัส TLS (SSL) 256 บิตเนื่องจาก ไลบรารี TLS มาตรฐานเรียก JCE ภายในเพื่อพิจารณาข้อ จำกัด ใด ๆ
แต่แล้วก็มีการสะท้อนกลับ มีอะไรที่คุณไม่สามารถใช้การสะท้อนกลับได้หรือไม่?
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"));
}
เพียงโทรremoveCryptographyRestrictions()
จาก static initializer หรือก่อนทำการดำเนินการเข้ารหัสใด ๆ
JceSecurity.isRestricted = false
ส่วนหนึ่งเป็นสิ่งที่จำเป็นในการใช้ยันต์ 256 บิตโดยตรง อย่างไรก็ตามหากไม่มีการดำเนินการอื่นสองรายการCipher.getMaxAllowedKeyLength()
จะยังคงรายงาน 128 และชุดรหัส TLS 256- บิตจะไม่ทำงาน
รหัสนี้ทำงานบน Oracle Java 7 และ 8 และข้ามกระบวนการบน Java 9 และ OpenJDK โดยอัตโนมัติซึ่งไม่จำเป็น เป็นแฮ็คที่น่าเกลียดที่สุดมันอาจไม่ทำงานกับ VM ของผู้ค้ารายอื่น
นอกจากนี้ยังไม่สามารถใช้กับ Oracle Java 6 ได้เนื่องจากคลาส JCE ส่วนตัวนั้นมีความสับสน การทำให้งงงวยไม่ได้เปลี่ยนจากรุ่นเป็นรุ่นดังนั้นจึงยังคงเป็นไปได้ในทางเทคนิคเพื่อรองรับ Java 6