web-dev-qa-db-ja.com

KeyStoreとKeyManager / TrustManagerの違い

キーストアとトラストストアにKeyStoreオブジェクトを使用することの違いは何ですか。 KeyManagerとTrustManagerを使用するのとは対照的に?

なぜ私が尋ねているのか説明させてください。私はRESTEasyを使用しており、SSL証明書を使用してHTTPS経由でREST呼び出しを行う必要があります。RESTEasyがClientRequestを作成する方法を拡張する必要がありました。最初に理解したことは、次のとおりです。

public void afterPropertiesSet() throws Exception {
    Assert.isTrue(StringUtils.isNotBlank(getKeystoreName()), "Key Store Name is Blank");
    Assert.isTrue(StringUtils.isNotBlank(getKeystorePassword()), "Key Store Password is Blank.");
    Assert.isTrue(StringUtils.isNotBlank(getKeystorePath()), "Key Store Path is Blank");
    Assert.isTrue(StringUtils.isNotBlank(getTruststoreName()), "Trust Store Name is Blank");
    Assert.isTrue(StringUtils.isNotBlank(getTruststorePassword()), "Trust Store Password is Blank.");
    Assert.isTrue(StringUtils.isNotBlank(getTruststorePath()), "Trust Store Path is Blank");

    // Set the keystore and truststore for mutual authentication
    createKeystore();
    createTruststore();

    if (getHttpClient() == null) {
        // Initialize HTTP Client
        initializeHttpClient();
    }

    Assert.notNull(getHttpClient(), "HTTP Client is NULL after initialization");
}

public ClientRequest createClientRequest(String uri) throws URISyntaxException {
    ClientExecutor clientExecutor = new ApacheHttpClient4Executor(getHttpClient());
    ClientRequestFactory fac = new ClientRequestFactory(clientExecutor, new URI(uri));
    return fac.createRequest(uri);
}

private void createTruststore() throws KeyStoreException, FileNotFoundException, IOException,
        NoSuchAlgorithmException, CertificateException {

    String truststoreFilePath = getTruststorePath() + getTruststoreName();

    KeyStore truststore = KeyStore.getInstance(KeyStore.getDefaultType());
    InputStream truststoreInput = getClass().getClassLoader().getResourceAsStream(truststoreFilePath);
    truststore.load(truststoreInput, getTruststorePassword().toCharArray());
}

private void createKeystore() throws KeyStoreException, FileNotFoundException, IOException,
        NoSuchAlgorithmException, CertificateException {

    String keystoreFilePath = getKeystorePath() + getKeystoreName();
    KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
    InputStream keystoreInput = getClass().getClassLoader().getResourceAsStream(keystoreFilePath);
    keystore.load(keystoreInput, getKeystorePassword().toCharArray());
}

/**
 * Initializes the HTTP Client
 * 
 * @throws KeyStoreException
 * @throws NoSuchAlgorithmException
 * @throws UnrecoverableKeyException
 * @throws KeyManagementException
 */
private void initializeHttpClient() throws KeyManagementException, UnrecoverableKeyException,
        NoSuchAlgorithmException, KeyStoreException {

    // Register https and http with scheme registry
    SchemeRegistry schemeRegistry = new SchemeRegistry();
    SSLSocketFactory sslSocketFactory = new SSLSocketFactory(getKeystore(), getKeystorePassword(), getTrustStore());
    schemeRegistry.register(new Scheme(HTTP, 80, PlainSocketFactory.getSocketFactory()));
    schemeRegistry.register(new Scheme(HTTPS, 443, sslSocketFactory));

    // Set connection params
    HttpConnectionParams.setConnectionTimeout(httpParameters, serviceConnectionTimeout);
    HttpConnectionParams.setSoTimeout(httpParameters, readTimeout);
    HttpConnectionParams.setStaleCheckingEnabled(httpParameters, true);

    // Create Connection Manager
    PoolingClientConnectionManager clientManager = new PoolingClientConnectionManager(schemeRegistry);
    clientManager.setMaxTotal(maxTotalConnections);
    clientManager.setDefaultMaxPerRoute(defaultMaxConnectionsPerHost);

    httpClient = new DefaultHttpClient(clientManager, httpParameters);
}

ピア証明書で問題が発生し、例外が発生し続けました。

javax.net.ssl.SSLPeerUnverifiedException:ピアが認証されていません

次に、HttpClientの設定について、TrustManagerとKeyManagerの使用に関する記事/ブログを検索して見つけました。次のようにコードをリファクタリングしました。

public void afterPropertiesSet() throws Exception {
    Assert.isTrue(StringUtils.isNotBlank(getKeystoreName()), "Key Store Name is Blank");
    Assert.isTrue(StringUtils.isNotBlank(getKeystorePassword()), "Key Store Password is Blank.");
    Assert.isTrue(StringUtils.isNotBlank(getKeystorePath()), "Key Store Path is Blank");
    Assert.isTrue(StringUtils.isNotBlank(getTruststoreName()), "Trust Store Name is Blank");
    Assert.isTrue(StringUtils.isNotBlank(getTruststorePassword()), "Trust Store Password is Blank.");
    Assert.isTrue(StringUtils.isNotBlank(getTruststorePath()), "Trust Store Path is Blank");

    if (getHttpClient() == null) {
        // Initialize HTTP Client
        initializeHttpClient();
    }

    Assert.notNull(getHttpClient(), "HTTP Client is NULL after initialization");
}

public ClientRequest createClientRequest(String uri) throws URISyntaxException {
    ClientExecutor clientExecutor = new ApacheHttpClient4Executor(getHttpClient());
    ClientRequestFactory fac = new ClientRequestFactory(clientExecutor, new URI(uri));
    return fac.createRequest(uri);
}

/**
 * Initializes the HTTP Client
 * 
 * @throws KeyStoreException
 * @throws NoSuchAlgorithmException
 * @throws UnrecoverableKeyException
 * @throws KeyManagementException
 */
private void initializeHttpClient() throws Exception {

    if (isCheckPeerCertificates()) {
        checkPeerCerts();
    }

    // Create Trust and Key Managers
    // Use TrustManager and KeyManager instead of KeyStore
    TrustManager[] trustManagers = getTrustManagers(getTruststorePassword());
    KeyManager[] keyManagers = getKeyManagers(getKeystorePassword());

    // Create SSL Context
    SSLContext ctx = SSLContext.getInstance("TLS");
    ctx.init(keyManagers, trustManagers, new SecureRandom());

    // Create SSL Factory
    SSLSocketFactory sslSocketFactory = new SSLSocketFactory(ctx, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

    // Register https and http with scheme registry
    SchemeRegistry schemeRegistry = new SchemeRegistry();
    schemeRegistry.register(new Scheme(HTTP, 80, PlainSocketFactory.getSocketFactory()));
    schemeRegistry.register(new Scheme(HTTPS, 443, sslSocketFactory));

    // Set connection params
    HttpConnectionParams.setConnectionTimeout(httpParameters, serviceConnectionTimeout);
    HttpConnectionParams.setSoTimeout(httpParameters, readTimeout);
    HttpConnectionParams.setStaleCheckingEnabled(httpParameters, true);

    // Create Connection Manager
    PoolingClientConnectionManager clientManager = new PoolingClientConnectionManager(schemeRegistry);
    clientManager.setMaxTotal(maxTotalConnections);
    clientManager.setDefaultMaxPerRoute(defaultMaxConnectionsPerHost);

    httpClient = new DefaultHttpClient(clientManager, httpParameters);
}

private TrustManager[] getTrustManagers(String trustStorePassword) throws Exception {
    String truststoreFilePath = getTruststorePath() + getTruststoreName();
    InputStream trustStoreInput = getClass().getClassLoader().getResourceAsStream(truststoreFilePath);
    KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
    trustStore.load(trustStoreInput, trustStorePassword.toCharArray());
    TrustManagerFactory tmfactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    tmfactory.init(trustStore);
    return tmfactory.getTrustManagers();
}

private KeyManager[] getKeyManagers(String keyStorePassword) throws Exception {
    String keystoreFilePath = getKeystorePath() + getKeystoreName();
    InputStream keyStoreInput = getClass().getClassLoader().getResourceAsStream(keystoreFilePath);
    KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
    keyStore.load(keyStoreInput, keyStorePassword.toCharArray());
    KeyManagerFactory kmfactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    kmfactory.init(keyStore, keyStorePassword.toCharArray());
    return kmfactory.getKeyManagers();
}

2番目のコードは問題なく機能します。では、2つのタイプの使用法の違いは何ですか?

16
Peter Minearo

これはあなたを助けることができると思います: Java --SSL のtrustStoreとkeyStoreの違い

TrustStoreとkeyStoreの最初の大きな違いは、trustStoreはTrustManagerによって使用され、keyStoreはJavaのKeyManagerクラスによって使用されることです。 KeyManagerとTrustManagerはJavaで異なるジョブを実行し、TrustManagerはリモート接続を信頼するかどうかを決定します。つまり、リモートパーティが要求者であるかどうかを判断し、KeyManagerはSSLハンドシェイク中に認証のためにリモートホストに送信する認証資格情報を決定します。 SSLサーバーの場合、鍵交換アルゴリズム中に秘密鍵を使用し、公開鍵に対応する証明書をクライアントに送信します。この証明書はkeyStoreから取得されます。 SSLクライアント側では、Javaで記述されている場合、trustStoreに格納されている証明書を使用してサーバーのIDを確認します。

続きを読む:JavaRevisitedブログ: http://javarevisited.blogspot.com/2012/09/difference-between-truststore-vs-keyStore-Java-SSL.html (アーカイブ済み ここ 。)

20
jasmine100