응용 프로그램을 배포할 때 "무제한 강도" JCE 정책 파일이 설치되지 않도록 하려면 어떻게 해야 합니까?
256비트 AES 암호화를 사용하는 앱이 있는데, 이 앱은 Java에서 지원되지 않습니다.JCE의 무제한 강도 jars를 보안 폴더에 설치합니다.개발자인 저는 이것으로 괜찮습니다.설치할 수 있습니다.
질문입니다만, 이 앱이 배포되기 때문에 최종 사용자는 이러한 정책 파일을 설치하지 않을 가능성이 높습니다.앱 기능을 만들기 위해 최종 사용자에게 다운로드하는 것은 매력적인 솔루션이 아닙니다.
최종 사용자 컴퓨터에서 파일을 덮어쓰지 않고 앱을 실행할 수 있는 방법이 있습니까?정책 파일을 설치하지 않아도 이를 처리할 수 있는 서드파티 소프트웨어?아니면 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"));
}
simply simply simply 하 、 simply 。removeCryptographyRestrictions()
암호화 조작을 실행하기 전에 정적 이니셜라이저 등으로부터 보호합니다.
JceSecurity.isRestricted = false
256비트 직접 하기 위해 두 경우 256비트 암호는 part입니다.Cipher.getMaxAllowedKeyLength()
는 128을 계속 보고하며 256비트 TLS 암호 스위트는 작동하지 않습니다.
이 코드는 Oracle Java 7 및 8에서 작동하며 불필요한 Java 9 및 OpenJDK에서 자동으로 프로세스를 건너뜁니다.결국 다른 벤더의 VM에서는 동작하지 않을 가능성이 있습니다.
또한 Oracle Java 6에서는 작동하지 않습니다. 개인 JCE 클래스가 그곳에서 난독화되기 때문입니다.그러나 버전마다 난독화는 변경되지 않으므로 기술적으로 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) {
}
}
솔루션이 는 현재 JDK 8u102입니다.이러한 솔루션이 설정되어 있는 필드는 현재입니다.final
( https://bugs.openjdk.java.net/browse/JDK-8149417) )를 참조해 주세요.
(a) Bouncy Castle을 사용하거나 (b) JCE 정책 파일을 설치하는 것으로 돌아갑니다.
바운시 캐슬은 여전히 항아리를 설치해야 한다고 내가 말할 수 있다.
간단한 테스트를 해봤더니 확인되는 것 같았습니다.
http://www.bouncycastle.org/wiki/display/JA1/Frequently+Asked+Questions
대체 암호 도서관은 Bouncy Castle을 참조하십시오.AES와 많은 기능이 추가되어 있습니다.리버럴 오픈 소스 라이브러리입니다.다만, 이것을 동작시키려면 , 경량의 독자적인 Bouncy Castle API 를 사용할 필요가 있습니다.
방법을 사용할 수 있습니다.
javax.crypto.Cipher.getMaxAllowedKeyLength(String transformation)
사용 가능한 키 길이를 테스트하려면 이 키를 사용하여 사용자에게 무슨 일이 일어나고 있는지 알려줍니다.예를 들어 정책 파일이 설치되지 않았기 때문에 응용 프로그램이 128비트 키로 폴백하고 있음을 나타냅니다.보안을 중시하는 사용자는 정책 파일을 설치하고 다른 사용자는 약한 키를 계속 사용합니다.
애플리케이션에는 클라이언트 서버 아키텍처가 있으며 서버 레벨에서 데이터 복호화/암호화만 허용했습니다.따라서 필요한 것은 JCE 파일뿐입니다.
클라이언트 머신상의 시큐러티 jar를 갱신할 필요가 있는 또 다른 문제가 있었습니다.JNLP를 사용하면, 그 라이브러리가 덮어쓰기 됩니다.${java.home}/lib/security/
첫 번째 실행 시 JVM을 사용합니다.
그게 효과가 있었어.
다음은 ntoskrnl 응답의 업데이트된 버전입니다.또한 댓글에 언급된 Arjan과 같은 최종 수식어를 삭제하는 기능도 포함되어 있습니다.
이 버전은 JRE 8u111 이후에서 동작합니다.
private static void removeCryptographyRestrictions() {
if (!isRestrictedCryptography()) {
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");
Field isRestrictedField = jceSecurity.getDeclaredField("isRestricted");
isRestrictedField.setAccessible(true);
setFinalStatic(isRestrictedField, true);
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));
}
catch (final Exception e) {
e.printStackTrace();
}
}
static void setFinalStatic(Field field, Object newValue) throws Exception {
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, newValue);
}
private static boolean isRestrictedCryptography() {
// This simply matches the Oracle JRE, but not OpenJDK.
return "Java(TM) SE Runtime Environment".equals(System.getProperty("java.runtime.name"));
}
다음은 @ntoskrnl의 코드 수정 버전입니다.isRestrictedCryptography
slf4j 로깅 및 애플리케이션 부트스트랩으로부터의 싱글톤 초기화를 다음과 같이 실제로 확인합니다.
static {
UnlimitedKeyStrengthJurisdictionPolicy.ensure();
}
@cranphin의 답변에서 예측한 대로 Java 8u162에서 기본적으로 무제한 정책을 사용할 수 있게 되면 이 코드는 리플렉션과 함께 망글링을 올바르게 중지합니다.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.crypto.Cipher;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.security.NoSuchAlgorithmException;
import java.security.Permission;
import java.security.PermissionCollection;
import java.util.Map;
// https://stackoverflow.com/questions/1179672/how-to-avoid-installing-unlimited-strength-jce-policy-files-when-deploying-an
public class UnlimitedKeyStrengthJurisdictionPolicy {
private static final Logger log = LoggerFactory.getLogger(UnlimitedKeyStrengthJurisdictionPolicy.class);
private static boolean isRestrictedCryptography() throws NoSuchAlgorithmException {
return Cipher.getMaxAllowedKeyLength("AES/ECB/NoPadding") <= 128;
}
private static void removeCryptographyRestrictions() {
try {
if (!isRestrictedCryptography()) {
log.debug("Cryptography restrictions removal not needed");
return;
}
/*
* Do the following, but with reflection to bypass access checks:
*
* JceSecurity.isRestricted = false;
* JceSecurity.defaultPolicy.perms.clear();
* JceSecurity.defaultPolicy.add(CryptoAllPermission.INSTANCE);
*/
Class<?> jceSecurity = Class.forName("javax.crypto.JceSecurity");
Class<?> cryptoPermissions = Class.forName("javax.crypto.CryptoPermissions");
Class<?> cryptoAllPermission = Class.forName("javax.crypto.CryptoAllPermission");
Field isRestrictedField = jceSecurity.getDeclaredField("isRestricted");
isRestrictedField.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(isRestrictedField, isRestrictedField.getModifiers() & ~Modifier.FINAL);
isRestrictedField.set(null, false);
Field defaultPolicyField = jceSecurity.getDeclaredField("defaultPolicy");
defaultPolicyField.setAccessible(true);
PermissionCollection defaultPolicy = (PermissionCollection) defaultPolicyField.get(null);
Field perms = cryptoPermissions.getDeclaredField("perms");
perms.setAccessible(true);
((Map<?, ?>) perms.get(defaultPolicy)).clear();
Field instance = cryptoAllPermission.getDeclaredField("INSTANCE");
instance.setAccessible(true);
defaultPolicy.add((Permission) instance.get(null));
log.info("Successfully removed cryptography restrictions");
} catch (Exception e) {
log.warn("Failed to remove cryptography restrictions", e);
}
}
static {
removeCryptographyRestrictions();
}
public static void ensure() {
// just force loading of this class
}
}
프로그램을 설치하는 동안 사용자에게 프롬프트를 표시하고 DOS 배치 스크립트 또는 Bash 셸 스크립트를 다운로드하여 적절한 시스템 위치에 JCE를 복사합니다.
이전에는 서버 웹 서비스에 대해 이 작업을 수행해야 했습니다. 정식 설치 관리자 대신 사용자가 앱을 실행하기 전에 앱을 설정하는 스크립트를 제공했습니다.설치 스크립트를 실행할 때까지 앱을 실행 불가능으로 만들 수 있습니다.JCE가 없어졌다고 앱에 항의하고 앱을 다운로드하여 재시작하도록 요청할 수도 있습니다.
언급URL : https://stackoverflow.com/questions/1179672/how-to-avoid-installing-unlimited-strength-jce-policy-files-when-deploying-an
'programing' 카테고리의 다른 글
Vue.js 디버깅메시지 문제 (0) | 2022.07.31 |
---|---|
개인 메서드를 호출할 방법이 있나요? (0) | 2022.07.31 |
봄에는 자동 배선이 어떻게 작동합니까? (0) | 2022.07.30 |
C에서 2개의 스트링을 연결하려면 어떻게 해야 하나요? (0) | 2022.07.30 |
Cypress에서 Vuex getter에 액세스하는 올바른 방법은 무엇입니까? (0) | 2022.07.30 |