이 문제에 대해 일반적으로 인용되는 몇 가지 해결책이 있습니다. 불행히도 이들 중 어느 것도 완전히 만족스럽지 않습니다.
- 무제한 강도 정책 파일을 설치하십시오 . 이것이 아마도 개발 워크 스테이션에 적합한 솔루션 일 수 있지만, 기술이 아닌 사용자가 모든 컴퓨터에 파일을 설치하게하는 것은 큰 번거 로움 (로드 블록이 아닌 경우)이됩니다. 프로그램과 함께 파일을 배포 할 방법 이 없습니다 . JRE 디렉토리에 설치해야합니다 (권한으로 인해 읽기 전용 일 수도 있음).
- JCE API를 건너 뛰고 Bouncy Castle 과 같은 다른 암호화 라이브러리를 사용하십시오 . 이 방법에는 추가 1MB 라이브러리가 필요하며 이는 응용 프로그램에 따라 상당한 부담이 될 수 있습니다. 또한 표준 라이브러리에 포함 된 기능을 복제하는 것은 바보 같은 느낌입니다. 분명히 API는 일반적인 JCE 인터페이스와 완전히 다릅니다. (BC는 JCE 공급자를 구현하지만 구현에 전달 하기 전에 주요 강도 제한이 적용 되기 때문에 도움이되지 않습니다 .)이 솔루션은 256 비트 TLS (SSL) 암호화 제품군을 사용할 수 없습니다 표준 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()
암호화 작업을 수행하기 전에 정적 이니셜 라이저 등에서 호출하면 됩니다.
JceSecurity.isRestricted = false
부분은 직접 256 비트 암호를 사용하는 데 필요한 모든 것입니다; 그러나 다른 두 가지 작업이 없으면 Cipher.getMaxAllowedKeyLength()
계속 128을보고하며 256 비트 TLS 암호 제품군은 작동하지 않습니다.
이 코드는 Oracle Java 7 및 8에서 작동하며 필요하지 않은 Java 9 및 OpenJDK의 프로세스를 자동으로 건너 뜁니다. 결국 추악한 해킹이기 때문에 다른 공급 업체의 VM에서는 작동하지 않을 수 있습니다.
개인 JCE 클래스가 난독 처리되어 있기 때문에 Oracle Java 6에서도 작동하지 않습니다. 난독 화는 버전마다 바뀌지 않으므로 Java 6을 기술적으로 지원하는 것은 여전히 가능합니다.