[java] 응용 프로그램을 배포 할 때“무제한 강도”JCE 정책 파일 설치를 피하는 방법은 무엇입니까?
Java에서 즉시 지원하지 않는 256 비트 AES 암호화를 사용하는 앱이 있습니다. 나는 이것이 올바르게 작동하도록 알고 보안 폴더에 JCE 무제한 강도 항아리를 설치합니다. 이것은 개발자 인 것이 좋습니다. 설치할 수 있습니다.
내 질문은이 앱이 배포되기 때문에 최종 사용자는 이러한 정책 파일을 설치하지 않았을 가능성이 높습니다. 최종 사용자가이를 다운로드하여 앱 기능을 만드는 것은 매력적인 해결책이 아닙니다.
최종 사용자 컴퓨터에서 파일을 덮어 쓰지 않고 앱을 실행하는 방법이 있습니까? 정책 파일을 설치하지 않고 처리 할 수있는 타사 소프트웨어? 또는 JAR 내에서 이러한 정책 파일을 참조하는 방법은 무엇입니까?
답변
이 문제에 대해 일반적으로 인용되는 몇 가지 해결책이 있습니다. 불행히도 이들 중 어느 것도 완전히 만족스럽지 않습니다.
- 무제한 강도 정책 파일을 설치하십시오 . 이것이 아마도 개발 워크 스테이션에 적합한 솔루션 일 수 있지만, 기술이 아닌 사용자가 모든 컴퓨터에 파일을 설치하게하는 것은 큰 번거 로움 (로드 블록이 아닌 경우)이됩니다. 프로그램과 함께 파일을 배포 할 방법 이 없습니다 . 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을 기술적으로 지원하는 것은 여전히 가능합니다.
답변
이제는 더 이상 Java 9 또는 Java 6, 7, 8의 최신 릴리스에 필요하지 않습니다 . 🙂
당 JDK-8170157 , 무제한 암호 정책은 기본적으로 활성화되어 있습니다.
JIRA 문제의 특정 버전 :
- Java 9 (10, 11 등) : 공식 릴리스!
- Java 8u161 이상 ( 현재 사용 가능 )
- Java 7u171 이상 ( ‘My Oracle Support’를 통해서만 사용 가능)
- Java 6u181 이상 ( ‘My Oracle Support’를 통해서만 사용 가능)
이상한 이유로 Java 9에서 이전 동작이 필요한 경우 다음을 사용하여 설정할 수 있습니다.
Security.setProperty("crypto.policy", "limited");
답변
해결책은 다음과 같습니다. http://middlesphere-1.blogspot.ru/2014/06/this-code-allows-to-break-limit-if.html
//this code allows to break limit if client jdk/jre has no unlimited policy files for JCE.
//it should be run once. So this static section is always execute during the class loading process.
//this code is useful when working with Bouncycastle library.
static {
try {
Field field = Class.forName("javax.crypto.JceSecurity").getDeclaredField("isRestricted");
field.setAccessible(true);
field.set(null, java.lang.Boolean.FALSE);
} catch (Exception ex) {
}
}
답변
탄력 성은 여전히 알 수있는 한 항아리를 설치해야합니다.
나는 약간의 테스트를했고 이것을 확인하는 것처럼 보였다.
http://www.bouncycastle.org/wiki/display/JA1/Frequently+Asked+Questions
답변
JDK 8u102로, 반사에 더 이상 작동하지 않습니다 의존하지 솔루션을 게시 : 필드 이러한 솔루션 세트는 지금이다 final
( https://bugs.openjdk.java.net/browse/JDK-8149417 ).
(a) Bouncy Castle을 사용하거나 (b) JCE 정책 파일을 설치 한 것으로 보입니다.
답변
대체 암호화 라이브러리에 대해서는 Bouncy Castle을 살펴보십시오 . AES와 많은 추가 기능이 있습니다. 자유주의적인 오픈 소스 라이브러리입니다. 그래도 작동하려면 가볍고 독점적 인 Bouncy Castle API를 사용해야합니다.
답변
당신은 방법을 사용할 수 있습니다
javax.crypto.Cipher.getMaxAllowedKeyLength(String transformation)
사용 가능한 키 길이를 테스트하려면이 키 길이를 사용하여 사용자에게 진행 상황을 알려주십시오. 예를 들어, 정책 파일이 설치되지 않아서 응용 프로그램이 128 비트 키로 다시 떨어 졌다는 내용이 있습니다. 보안에 민감한 사용자는 정책 파일을 설치하고 다른 사용자는 더 약한 키를 계속 사용합니다.