Skip to content

Instantly share code, notes, and snippets.

@eugeneek
Created May 30, 2018 09:05
Show Gist options
  • Save eugeneek/acd04c70e08c5d603a6487891b332cd5 to your computer and use it in GitHub Desktop.
Save eugeneek/acd04c70e08c5d603a6487891b332cd5 to your computer and use it in GitHub Desktop.
SSL connection helper classes
package com.eugeneek;
import android.content.Context;
import android.support.annotation.RawRes;
import android.util.Base64;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SignatureException;
import java.security.cert.CertPath;
import java.security.cert.CertPathValidator;
import java.security.cert.CertPathValidatorException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.PKIXParameters;
import java.security.cert.TrustAnchor;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import timber.log.Timber;
public class CertUtils {
public static Certificate getCertificateFromRaw(Context context, @RawRes int rawResId) throws
IOException, CertificateException {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream cert = null;
try {
cert = context.getResources().openRawResource(rawResId);
return cf.generateCertificate(cert);
} catch (CertificateException e) {
Timber.e(e);
} finally {
if (cert != null) {
cert.close();
}
}
return null;
}
public static PrivateKey getPrivateKeyFromRaw(Context context, @RawRes int rawResId)
throws InvalidKeySpecException, NoSuchAlgorithmException, NoSuchProviderException {
InputStream inputStream = context.getResources().openRawResource(rawResId);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte buf[] = new byte[1024];
int len;
try {
while ((len = inputStream.read(buf)) != -1) {
outputStream.write(buf, 0, len);
}
outputStream.close();
inputStream.close();
} catch (IOException e) {
Timber.e(e);
return null;
}
String keyPemStr = outputStream.toString()
.replace("-----BEGIN RSA PRIVATE KEY-----\n", "")
.replace("-----END RSA PRIVATE KEY-----", "")
.replace("\n", "");
byte[] keyBytes = Base64.decode(keyPemStr, Base64.NO_WRAP);
KeyFactory kf = KeyFactory.getInstance("RSA", "BC");
return kf.generatePrivate(new PKCS8EncodedKeySpec(keyBytes));
}
public static KeyStore getClientCertKeyStore(String certStr, byte[] key) throws KeyStoreException,
CertificateException, NoSuchAlgorithmException, IOException, InvalidKeySpecException {
Certificate certificate = CertUtils.createCertFromString(certStr);
PrivateKey privateKey = privateKeyFromByteArray(key);
return getClientCertKeyStore(certificate, privateKey);
}
public static KeyStore getClientCertKeyStore(Certificate certificate, PrivateKey privateKey)
throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException {
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(null, null);
keyStore.setCertificateEntry("alias", certificate);
keyStore.setKeyEntry("alias", privateKey, null, new Certificate[]{certificate});
return keyStore;
}
static boolean validateCertificate(Context context, @RawRes int rootCertResId,
String cert) {
try {
X509Certificate root = (X509Certificate) getCertificateFromRaw(context, rootCertResId);
X509Certificate candidate = createCertFromString(cert);
return validateKeyChain(candidate, root);
} catch (IOException | CertificateException | NoSuchAlgorithmException
| InvalidAlgorithmParameterException | NoSuchProviderException e) {
Timber.e(e);
}
return false;
}
private static boolean validateKeyChain(X509Certificate client,
X509Certificate... trustedCerts)
throws CertificateException, InvalidAlgorithmParameterException,
NoSuchAlgorithmException, NoSuchProviderException {
boolean found = false;
int i = trustedCerts.length;
CertificateFactory cf = CertificateFactory.getInstance("X.509");
TrustAnchor anchor;
Set anchors;
CertPath path;
List list;
PKIXParameters params;
CertPathValidator validator = CertPathValidator.getInstance("PKIX");
while (!found && i > 0) {
anchor = new TrustAnchor(trustedCerts[--i], null);
anchors = Collections.singleton(anchor);
list = Collections.singletonList(client);
path = cf.generateCertPath(list);
params = new PKIXParameters(anchors);
params.setRevocationEnabled(false);
if (client.getIssuerDN().equals(trustedCerts[i].getSubjectDN())) {
try {
validator.validate(path, params);
if (isSelfSigned(trustedCerts[i])) {
found = true;
} else if (!client.equals(trustedCerts[i])) {
found = validateKeyChain(trustedCerts[i], trustedCerts);
}
} catch (CertPathValidatorException e) {
Timber.e(e);
}
}
}
return found;
}
private static boolean isSelfSigned(X509Certificate cert)
throws CertificateException, NoSuchAlgorithmException,
NoSuchProviderException {
try {
PublicKey key = cert.getPublicKey();
cert.verify(key);
return true;
} catch (SignatureException sigEx) {
return false;
} catch (InvalidKeyException keyEx) {
return false;
}
}
private static X509Certificate createCertFromString(String cert) throws CertificateException,
IOException {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream in = new ByteArrayInputStream(Base64.decode(cert, Base64.NO_WRAP));
X509Certificate certificate = (X509Certificate) cf.generateCertificate(in);
in.close();
return certificate;
}
private static PrivateKey privateKeyFromByteArray(byte[] key) throws InvalidKeySpecException,
NoSuchAlgorithmException {
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePrivate(new PKCS8EncodedKeySpec(key));
}
}
package com.eugeneek;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.UnrecoverableEntryException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.util.Arrays;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
public class HttpsHelper {
static SSLSocketFactory getSslSocketFactory(Certificate serverCertificate, KeyStore clientKeyStore)
throws CertificateException, UnrecoverableEntryException, NoSuchAlgorithmException,
IOException, KeyManagementException, KeyStoreException {
return getSSLContext(serverCertificate, clientKeyStore).getSocketFactory();
}
static X509TrustManager getTrustManager(Certificate serverCertificate) throws CertificateException,
NoSuchAlgorithmException, KeyStoreException, IOException {
TrustManager[] trustManagers = getTrustManagers(serverCertificate);
if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
throw new IllegalStateException("Unexpected default trust managers:"
+ Arrays.toString(trustManagers));
}
return (X509TrustManager) trustManagers[0];
}
public static SSLContext getSSLContext(Certificate serverCertificate, KeyStore keyStore)
throws CertificateException, IOException, KeyStoreException, NoSuchAlgorithmException,
KeyManagementException, UnrecoverableEntryException {
SecureRandom random = new SecureRandom();
KeyManager[] keyManagers = keyStore != null ? getKeyManagers(keyStore) : null;
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(keyManagers, getTrustManagers(serverCertificate), random);
return sslContext;
}
private static TrustManager[] getTrustManagers(Certificate serverCertificate) throws KeyStoreException,
NoSuchAlgorithmException, IOException, CertificateException {
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(getServerTrustKeyStore(serverCertificate));
return tmf.getTrustManagers();
}
private static KeyStore getServerTrustKeyStore(Certificate serverCertificate) throws IOException,
CertificateException, KeyStoreException, NoSuchAlgorithmException {
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", serverCertificate);
return keyStore;
}
private static KeyManager[] getKeyManagers(KeyStore keyStore) throws NoSuchAlgorithmException,
KeyStoreException, UnrecoverableEntryException {
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("X509");
keyManagerFactory.init(keyStore, null);
return keyManagerFactory.getKeyManagers();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment