package won.cryptography.service; import net.sf.ehcache.Cache; import net.sf.ehcache.CacheManager; import net.sf.ehcache.Ehcache; import net.sf.ehcache.Element; import org.apache.http.client.HttpClient; import org.apache.http.conn.ssl.*; import org.apache.http.impl.client.HttpClients; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.web.client.RestTemplate; import won.cryptography.ssl.PredefinedAliasPrivateKeyStrategy; import javax.crypto.Cipher; import javax.net.ssl.SSLContext; import java.security.KeyStore; /** * User: fsalcher * Date: 12.06.2014 */ public class CryptographyUtils { public static boolean checkForUnlimitedSecurityPolicy() { try { int size = Cipher.getMaxAllowedKeyLength("RC5"); System.out.println("max allowed key size: " + size); return size < 256; } catch (Exception e) { e.printStackTrace(); return false; } } private static final Ehcache ehcache; static { CacheManager manager = CacheManager.getInstance(); ehcache = new Cache("sslContextCache", 100, false, false, 3600, 600); manager.addCache(ehcache); } private static SSLContext getSSLContext(final KeyStore keyStore, final String ksPass, final PrivateKeyStrategy keyStrategy, final KeyStore trustStore, TrustStrategy trustStrategy, boolean allowCached) throws Exception { if (allowCached && keyStrategy instanceof PredefinedAliasPrivateKeyStrategy) { return getCachedSslContextForPredefinedAlias(keyStore, ksPass, (PredefinedAliasPrivateKeyStrategy) keyStrategy, trustStore, trustStrategy); } else { return createSSLContextBuilder(keyStore, ksPass, keyStrategy, trustStore, trustStrategy).build(); } } private static SSLContext getCachedSslContextForPredefinedAlias(final KeyStore keyStore, final String ksPass, final PredefinedAliasPrivateKeyStrategy keyStrategy, final KeyStore trustStore, final TrustStrategy trustStrategy) throws Exception { String cacheKey = keyStrategy.getAlias(); Element cacheElement = ehcache.get(cacheKey); SSLContext sslContext = null; if (cacheElement == null) { //we want to avoid creating the sslContext multiple times, so we snychronize on an object shared by all threads: synchronized (ehcache) { //now we have to check again (maybe we're in the thread that had to wait - in that case, the //sslContext has been created already cacheElement = ehcache.get(cacheKey); if (cacheElement == null) { sslContext = createSSLContextBuilder(keyStore, ksPass, keyStrategy, trustStore, trustStrategy).build(); cacheElement = new Element(cacheKey, sslContext); ehcache.put(cacheElement); } } } sslContext = (SSLContext) cacheElement.getObjectValue(); return sslContext; } private static SSLContextBuilder createSSLContextBuilder(final KeyStore keyStore, final String ksPass, final PrivateKeyStrategy keyStrategy, final KeyStore trustStore, TrustStrategy trustStrategy) throws Exception { SSLContextBuilder contextBuilder = SSLContexts.custom(); contextBuilder.loadKeyMaterial(keyStore,ksPass.toCharArray(),keyStrategy); // if trustStore is null, default CAs trust store is used contextBuilder.loadTrustMaterial(trustStore, trustStrategy); return contextBuilder; } public static RestTemplate createSslRestTemplate(final KeyStore keyStore, final String ksPass, final PrivateKeyStrategy keyStrategy, final KeyStore trustStore, TrustStrategy trustStrategy, final Integer readTimeout, final Integer connectionTimeout, final boolean allowCached) throws Exception { SSLContext sslContext = getSSLContext(keyStore, ksPass, keyStrategy, trustStore, trustStrategy, allowCached); // here in the constructor, also hostname verifier, protocol version, cipher suits, etc. can be specified SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext); HttpClient httpClient = HttpClients.custom()//.useSystemProperties() .setSSLSocketFactory(sslConnectionSocketFactory).build(); HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(); if (readTimeout != null) { requestFactory.setReadTimeout(readTimeout.intValue()); } if (connectionTimeout != null) { requestFactory.setConnectTimeout(connectionTimeout.intValue()); } requestFactory.setHttpClient(httpClient); RestTemplate restTemplate = new RestTemplate(requestFactory); return restTemplate; } public static RestTemplate createSslRestTemplate(TrustStrategy trustStrategy, final Integer readTimeout, final Integer connectionTimeout) throws Exception { SSLContext sslContext = new SSLContextBuilder() .loadTrustMaterial(null, // if // trustStore is null, default CAs trust store is used trustStrategy) .build(); // here in the constructor, also hostname verifier, protocol version, cipher suits, etc. can be specified SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext); HttpClient httpClient = HttpClients.custom()//.useSystemProperties() .setSSLSocketFactory(sslConnectionSocketFactory).build(); HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(); if (readTimeout != null) { requestFactory.setReadTimeout(readTimeout.intValue()); } if (connectionTimeout != null) { requestFactory.setConnectTimeout(connectionTimeout.intValue()); } requestFactory.setHttpClient(httpClient); RestTemplate restTemplate = new RestTemplate(requestFactory); return restTemplate; } }