IT Share you

Java 및 기본 신뢰 저장소 사용

shareyou 2021. 1. 8. 21:44
반응형

Java 및 기본 신뢰 저장소 사용


HTTPS를 통해 두 개의 웹 서버에 연결하는 Java로 애플리케이션을 작성하고 있습니다. 하나는 기본 신뢰 체인을 통해 신뢰할 수있는 인증서를 받았으며 다른 하나는 자체 서명 된 인증서를 사용합니다. 물론 첫 번째 서버에 연결하는 것은 즉시 작동하는 반면, 자체 서명 된 인증서로 서버에 연결하는 것은 해당 서버의 인증서로 trustStore를 만들 때까지 작동하지 않았습니다. 그러나 기본적으로 신뢰할 수있는 서버에 대한 연결은 더 이상 작동하지 않습니다. 내 자신을 만들면 기본 trustStore가 무시되기 때문입니다.

내가 찾은 한 가지 해결책은 기본 trustStore의 인증서를 내 인증서에 추가하는 것이 었습니다. 그러나이 솔루션은 신뢰 저장소를 계속 관리해야하기 때문에 마음에 들지 않습니다. (이 인증서가 가까운 장래에 정적으로 유지된다고 가정 할 수는 없습니다.)

그 외에도 비슷한 문제가있는 두 개의 5 년 된 스레드를 발견했습니다.

JVM에 여러 키 저장소 등록

Java 서버에 대해 여러 SSL 인증서를 가질 수있는 방법

둘 다 Java SSL 인프라에 깊이 들어가 있습니다. 지금 쯤이면 내 코드의 보안 검토에서 쉽게 설명 할 수있는보다 편리한 솔루션이 있기를 바랐습니다.


이전 답변 에서 언급 한 것과 유사한 패턴을 사용할 수 있습니다 (다른 문제에 대해).

기본적으로 기본 신뢰 관리자를 확보하고 자체 신뢰 저장소를 사용하는 두 번째 신뢰 관리자를 작성하십시오. 둘 다 호출을 위임하는 사용자 지정 신뢰 관리자 구현으로 둘 다 래핑합니다 (하나가 실패하면 다른 하나로 대체 됨).

TrustManagerFactory tmf = TrustManagerFactory
    .getInstance(TrustManagerFactory.getDefaultAlgorithm());
// Using null here initialises the TMF with the default trust store.
tmf.init((KeyStore) null);

// Get hold of the default trust manager
X509TrustManager defaultTm = null;
for (TrustManager tm : tmf.getTrustManagers()) {
    if (tm instanceof X509TrustManager) {
        defaultTm = (X509TrustManager) tm;
        break;
    }
}

FileInputStream myKeys = new FileInputStream("truststore.jks");

// Do the same with your trust store this time
// Adapt how you load the keystore to your needs
KeyStore myTrustStore = KeyStore.getInstance(KeyStore.getDefaultType());
myTrustStore.load(myKeys, "password".toCharArray());

myKeys.close();

tmf = TrustManagerFactory
    .getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(myTrustStore);

// Get hold of the default trust manager
X509TrustManager myTm = null;
for (TrustManager tm : tmf.getTrustManagers()) {
    if (tm instanceof X509TrustManager) {
        myTm = (X509TrustManager) tm;
        break;
    }
}

// Wrap it in your own class.
final X509TrustManager finalDefaultTm = defaultTm;
final X509TrustManager finalMyTm = myTm;
X509TrustManager customTm = new X509TrustManager() {
    @Override
    public X509Certificate[] getAcceptedIssuers() {
        // If you're planning to use client-cert auth,
        // merge results from "defaultTm" and "myTm".
        return finalDefaultTm.getAcceptedIssuers();
    }

    @Override
    public void checkServerTrusted(X509Certificate[] chain,
            String authType) throws CertificateException {
        try {
            finalMyTm.checkServerTrusted(chain, authType);
        } catch (CertificateException e) {
            // This will throw another CertificateException if this fails too.
            finalDefaultTm.checkServerTrusted(chain, authType);
        }
    }

    @Override
    public void checkClientTrusted(X509Certificate[] chain,
            String authType) throws CertificateException {
        // If you're planning to use client-cert auth,
        // do the same as checking the server.
        finalDefaultTm.checkClientTrusted(chain, authType);
    }
};


SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[] { customTm }, null);

// You don't have to set this as the default context,
// it depends on the library you're using.
SSLContext.setDefault(sslContext);

해당 컨텍스트를 기본 컨텍스트로 설정할 필요가 없습니다. 사용 방법은 사용중인 클라이언트 라이브러리 (및 소켓 팩토리를 가져 오는 위치)에 따라 다릅니다.


원칙적으로 어쨌든 필요에 따라 항상 신뢰 저장소를 업데이트해야합니다. Java 7 JSSE 참조 가이드에는 이에 대한 "중요한 참고 사항"이 있으며, 이제 동일한 가이드의 버전 8에서 "참고"로 다운 그레이드되었습니다 .

The JDK ships with a limited number of trusted root certificates in the java-home/lib/security/cacerts file. As documented in keytool reference pages, it is your responsibility to maintain (that is, add and remove) the certificates contained in this file if you use this file as a truststore.

Depending on the certificate configuration of the servers that you contact, you may need to add additional root certificates. Obtain the needed specific root certificates from the appropriate vendor.


As I figured out, you can also use SSLContextBuilder class from the Apache HttpComponents library to add your custom keystore to a SSLContext:

SSLContextBuilder builder = new SSLContextBuilder();
try {
     keyStore.load(null, null);
     builder.loadTrustMaterial(keyStore, null);
     builder.loadKeyMaterial(keyStore, null);
} catch (NoSuchAlgorithmException | KeyStoreException | CertificateException | IOException
          | UnrecoverableKeyException e) {
     log.error("Can not load keys from keystore '{}'", keyStore.getProvider(), e);
}
return builder.build();

ReferenceURL : https://stackoverflow.com/questions/24555890/using-a-custom-truststore-in-java-as-well-as-the-default-one

반응형