package com.alterdekim.hearthhack.util; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.cert.X509CertificateHolder; import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.openssl.PEMDecryptorProvider; import org.bouncycastle.openssl.PEMEncryptedKeyPair; import org.bouncycastle.openssl.PEMKeyPair; import org.bouncycastle.openssl.PEMParser; import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder; import javax.net.ssl.*; import java.io.FileReader; import java.security.KeyPair; import java.security.KeyStore; import java.security.Security; import java.security.cert.Certificate; import java.security.cert.X509Certificate; @Slf4j public class Util { private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray(); public static SSLServerSocketFactory getSocketFactory(final String caCrtFile, final String crtFile, final String keyFile, final String password) { try { /** * Add BouncyCastle as a Security Provider */ Security.addProvider(new BouncyCastleProvider()); JcaX509CertificateConverter certificateConverter = new JcaX509CertificateConverter().setProvider("BC"); /** * Load Certificate Authority (CA) certificate */ PEMParser reader = new PEMParser(new FileReader(caCrtFile)); X509CertificateHolder caCertHolder = (X509CertificateHolder) reader.readObject(); reader.close(); X509Certificate caCert = certificateConverter.getCertificate(caCertHolder); /** * Load client certificate */ reader = new PEMParser(new FileReader(crtFile)); X509CertificateHolder certHolder = (X509CertificateHolder) reader.readObject(); reader.close(); X509Certificate cert = certificateConverter.getCertificate(certHolder); /** * Load client private key */ reader = new PEMParser(new FileReader(keyFile)); Object keyObject = reader.readObject(); reader.close(); PEMDecryptorProvider provider = new JcePEMDecryptorProviderBuilder().build(password.toCharArray()); JcaPEMKeyConverter keyConverter = new JcaPEMKeyConverter().setProvider("BC"); KeyPair key; if (keyObject instanceof PEMEncryptedKeyPair) { key = keyConverter.getKeyPair(((PEMEncryptedKeyPair) keyObject).decryptKeyPair(provider)); } else { key = keyConverter.getKeyPair((PEMKeyPair) keyObject); } /** * CA certificate is used to authenticate server */ KeyStore caKeyStore = KeyStore.getInstance(KeyStore.getDefaultType()); caKeyStore.load(null, null); caKeyStore.setCertificateEntry("ca-certificate", caCert); TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance( TrustManagerFactory.getDefaultAlgorithm()); trustManagerFactory.init(caKeyStore); /** * Client key and certificates are sent to server so it can authenticate the client */ KeyStore clientKeyStore = KeyStore.getInstance(KeyStore.getDefaultType()); clientKeyStore.load(null, null); clientKeyStore.setCertificateEntry("certificate", cert); clientKeyStore.setKeyEntry("private-key", key.getPrivate(), password.toCharArray(), new Certificate[]{cert}); KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance( KeyManagerFactory.getDefaultAlgorithm()); keyManagerFactory.init(clientKeyStore, password.toCharArray()); /** * Create SSL socket factory */ SSLContext context = SSLContext.getInstance("TLSv1.2"); context.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null); /** * Return the newly created socket factory object */ return context.getServerSocketFactory(); } catch (Exception e) { e.printStackTrace(); } return null; } public static String bytesToHex(byte[] bytes) { char[] hexChars = new char[bytes.length * 2]; for (int j = 0; j < bytes.length; j++) { int v = bytes[j] & 0xFF; hexChars[j * 2] = HEX_ARRAY[v >>> 4]; hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F]; } return new String(hexChars); } public static byte[] hexStringToByteArray(String s) { int len = s.length(); byte[] data = new byte[len / 2]; for (int i = 0; i < len; i += 2) { data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i+1), 16)); } return data; } public static String intToHex(int i) { String s = Integer.toHexString(i).toUpperCase(); return s.length() % 2 == 0 ? s : "0" + s; } }