Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between KeyStore and KeyManager/TrustManager

Tags:

What is the difference between using a KeyStore Object for the keystore and truststore; as opposed to using the KeyManager and TrustManager?

Let me explain why I am asking. I am working with RESTEasy and needed to make a REST call over HTTPS with SSL certificates. I needed to augment how RESTEasy created the ClientRequest. Here is what I figured out initially:

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);
}

I ran into a problem with the Peer Certificates and kept getting an exception:

javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated

I then searched around and found articles/blogs about setting up the HttpClient but using TrustManager and KeyManager. I refactored the code to do the following:

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();
}

The second code works just fine. So, what is the a difference between the 2 types of usages?

like image 573
Peter Minearo Avatar asked Dec 21 '12 21:12

Peter Minearo


People also ask

What is KeyManager and TrustManager?

KeyManager and TrustManager performs different job in Java, TrustManager determines whether remote connection should be trusted or not i.e. whether remote party is who it claims to and KeyManager decides which authentication credentials should be sent to the remote host for authentication during SSL handshake.

What is difference between keystore and truststore?

TrustStore is used to store certificates from Certified Authorities (CA) that verify the certificate presented by the server in an SSL connection. While Keystore is used to store private key and identity certificates that a specific program should present to both parties (server or client) for verification.

What is KeyManager in Java?

KeyManager s are responsible for managing the key material which is used to authenticate the local SSLSocket to its peer. If no key material is available, the socket will be unable to present authentication credentials.

How does SSL work with keystore and truststore?

Mobile Security Access Server supports an SSL keystore and SSL truststore. The SSL keystore holds the identity key for the server and the SSL truststore serves as the repository for trusted certificates. The SSL truststore is used for trusting or authenticating client certificates (for two-way SSL).


1 Answers

I think this can help you: Difference between trustStore and keyStore in Java - SSL

First and major difference between trustStore and keyStore is that trustStore is used by TrustManager and keyStore is used by KeyManager class in Java. KeyManager and TrustManager performs different job in Java, TrustManager determines whether remote connection should be trusted or not i.e. whether remote party is who it claims to and KeyManager decides which authentication credentials should be sent to the remote host for authentication during SSL handshake. if you are an SSL Server you will use private key during key exchange algorithm and send certificates corresponding to your public keys to client, this certificate is acquired from keyStore. On SSL client side, if its written in Java, it will use certificates stored in trustStore to verify identity of Server.

Read more: JavaRevisited blog: http://javarevisited.blogspot.com/2012/09/difference-between-truststore-vs-keyStore-Java-SSL.html (Archived here.)

like image 170
jasmine100 Avatar answered Nov 07 '22 05:11

jasmine100