All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ecfeed.core.webservice.client.SecurityHelper Maven / Gradle / Ivy

Go to download

An open library used to connect to the ecFeed service. It can be also used as a standalone testing tool. It is integrated with Junit5 and generates a stream of test cases using a selected algorithm (e.g. Cartesian, N-Wise). There are no limitations associated with the off-line version but the user cannot access the on-line computation servers and the model database.

The newest version!
package com.ecfeed.core.webservice.client;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.UnrecoverableEntryException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.util.Optional;

import com.ecfeed.core.utils.ExceptionHelper;
import com.google.common.io.BaseEncoding;

public final class SecurityHelper {

	private final static String[] DEFAULT_STORE_PATH = {
			".ecfeed/security.p12",
			"ecfeed/security.p12",
			System.getProperty("user.home") + "/.ecfeed/security.p12",
			System.getProperty("user.home") + "/ecfeed/security.p12",
			System.getProperty("java.home") + "/lib/security/cacerts"
	};

	public final static String UNIVERSAL_PASSWORD = "changeit";
	public final static String TRUSTED_DOMAIN = "ecfeed.com";

	public final static String ALIAS_CLIENT = "connection";
	public final static String ALIAS_SERVER = "ca";

	private final static String STORE_TYPE = "PKCS12";

	private static KeyStore fLoadedStore = null;
	private static Optional fLoadedStorePath = Optional.empty();

	public static KeyStore getKeyStore() {

		if (fLoadedStore == null) {
			loadKeyStoreFromPath(fLoadedStorePath); // TODO - static method returning fLoadedStore
		}

		return fLoadedStore;
	}

	public static KeyStore getKeyStore(Optional path) {

		if (path == null) {
			ExceptionHelper.reportRuntimeException("The path to the store must be provided.");
		}

		if (!fLoadedStorePath.equals(path)) {
			fLoadedStorePath = path;
			fLoadedStore = null;
		}

		return getKeyStore();
	}

	public static X509Certificate getCertificate(Optional keyStorePath, String alias) {

		if (alias == null) {
			ExceptionHelper.reportRuntimeException("The certificate alias must be provided");
		}

		X509Certificate certificate = null;

		getKeyStore(keyStorePath);

		try {
			certificate = (X509Certificate) fLoadedStore.getCertificate(alias);
		} catch (KeyStoreException e) {
			ExceptionHelper.reportRuntimeException("The store was not initialized: " + alias, e);
		}

		if (certificate == null) {
			ExceptionHelper.reportRuntimeException("The certificate with the requested alias is not in the store.");
		}

		return certificate;
	}

	public static X509Certificate getCertificateFromFile(String path) {

		if (path == null) {
			ExceptionHelper.reportRuntimeException("The path to the certificate must be provided.");
		}

		X509Certificate certificate = null;

		getKeyStore();

		try {
			CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
			certificate = (X509Certificate) certificateFactory.generateCertificate(Files.newInputStream(Paths.get(path)));
		} catch (IOException e) {
			ExceptionHelper.reportRuntimeException("The requested certificate could not be read from file: " + path, e);
		} catch (CertificateException e) {
			ExceptionHelper.reportRuntimeException("The format of the requested certificate is invalid: " + path, e);
		}

		return certificate;
	}

	public static PublicKey getPublicKey(Optional keyStorePath, String alias) {

		if (alias == null) {
			ExceptionHelper.reportRuntimeException("The public key alias must be provided.");
		}

		getKeyStore();

		return getCertificate(keyStorePath, alias).getPublicKey();		
	}

	public static PublicKey getPublicKeyFromFileOpenSSL(String path) {

		// https://stackoverflow.com/questions/47816938/java-ssh-rsa-string-to-public-key
		// https://github.com/jclouds/jclouds/blob/master/compute/src/main/java/org/jclouds/ssh/SshKeys.java

		if (path == null) {
			ExceptionHelper.reportRuntimeException("The path to the public key must be provided.");
		}

		PublicKey publicKey = null;

		try {
			byte[] byteArray = Files.readAllBytes(Paths.get(path));

			String[] segments = new String(byteArray, "UTF-8").split(" ");
			InputStream byteStream = new ByteArrayInputStream(BaseEncoding.base64().decode(segments[1]));

			getPublicKeyReadParameter(byteStream);
			BigInteger publicExponent = getPublicKeyReadParameter(byteStream);
			BigInteger modulus = getPublicKeyReadParameter(byteStream);

			RSAPublicKeySpec keySpecification = new RSAPublicKeySpec(modulus, publicExponent);

			KeyFactory keyFactory = KeyFactory.getInstance("RSA");

			publicKey = keyFactory.generatePublic(keySpecification);
		} catch (IOException e) {
			ExceptionHelper.reportRuntimeException("The requested public key could not be read from file: " + path, e);
		} catch (NoSuchAlgorithmException e) {
			ExceptionHelper.reportRuntimeException("The requested public key could not be read." + e);
		} catch (InvalidKeySpecException e) {
			ExceptionHelper.reportRuntimeException("The format of the requested public key is invalid.", e);
		}

		return publicKey;
	}

	public static PrivateKey getPrivateKey(String alias, String password) {

		if (alias == null || password == null) {
			ExceptionHelper.reportRuntimeException("The path and password to the private key must be provided.");
		}

		PrivateKey privateKey = null;

		getKeyStore();

		try {
			char[] entryPassword = password.toCharArray();
			KeyStore.PasswordProtection entryProtection = new KeyStore.PasswordProtection(entryPassword);
			KeyStore.PrivateKeyEntry entryPrivateKey = (KeyStore.PrivateKeyEntry) fLoadedStore.getEntry(alias, entryProtection);
			privateKey = entryPrivateKey.getPrivateKey();
		} catch (KeyStoreException e) {
			ExceptionHelper.reportRuntimeException("The password associated with the requested key is erroneous: " + alias + ".", e);
		} catch (NoSuchAlgorithmException e) {
			ExceptionHelper.reportRuntimeException("The algorithm for recovering the private key could not be found: " + alias, e);
		} catch (UnrecoverableEntryException e) {
			ExceptionHelper.reportRuntimeException("Not enough information to recover the key: " + alias, e);
		}

		return privateKey;
	}

	public static PrivateKey getPrivateKeyFromFilePKCS8(String path) {

		if (path == null) {
			ExceptionHelper.reportRuntimeException("The path to the public key must be provided.");
		}

		PrivateKey privateKey = null;

		try {
			byte[] byteArray = Files.readAllBytes(Paths.get(path));

			KeyFactory keyFactory = KeyFactory.getInstance("RSA");
			KeySpec keySpecification = new PKCS8EncodedKeySpec(byteArray);
			privateKey = keyFactory.generatePrivate(keySpecification);
		} catch (NoSuchAlgorithmException e) {
			ExceptionHelper.reportRuntimeException("The algorithm for recovering the private key could not be found.", e);
		} catch (InvalidKeySpecException e) {
			ExceptionHelper.reportRuntimeException("The format of the requested private key is invalid.", e);
		} catch (IOException e) {
			ExceptionHelper.reportRuntimeException("The requested public key could not be read from file: " + path, e);
		}

		return privateKey;
	}

	private static void loadKeyStoreFromPath(Optional path) throws IllegalArgumentException {

		if (path.isPresent() && !path.get().equalsIgnoreCase("")) {
			fLoadedStore = prepareLoadedStore(prepareStoreUsingProvidedPath(path.get()));
		} else {
			fLoadedStore = prepareLoadedStore(prepareStoreUsingDefaultLocation());
		}
	}

	private static Path prepareStoreUsingProvidedPath(String path) {

		Path storePath = Paths.get(path);
		Optional storePathError = validateStorePath(storePath);

		if (storePathError.isPresent()) {
			ExceptionHelper.reportRuntimeException("Illegal argument. " + storePathError.get());
		}

		return storePath;
	}

	private static Path prepareStoreUsingDefaultLocation() {

		for (String storePathChain : DEFAULT_STORE_PATH) {
			Path storePath = Paths.get(storePathChain);
			Optional storePathError = validateStorePath(storePath);

			if (storePathError.isPresent()) {
				continue;
			}

			return storePath;
		}

		ExceptionHelper.reportRuntimeException("The required store could not be loaded. Please provide a valid path or use one of the following locations: " + prepareStoreErrorMessage());
		return null;
	}

	private static Optional validateStorePath(Path storePath) {

		if (!Files.exists(storePath)) {
			return Optional.of("The file does not exist: " + storePath.toAbsolutePath());
		}

		if (!Files.isReadable(storePath)) {
			return Optional.of("The file is not readable: " + storePath.toAbsolutePath());
		}

		if (!Files.isRegularFile(storePath)) {
			return Optional.of( "The type of the file is erroneous: " + storePath.toAbsolutePath());
		}

		return Optional.empty();
	}

	private static String prepareStoreErrorMessage() {
		StringBuffer storePathChainError = new StringBuffer();

		for (String storePathChain : DEFAULT_STORE_PATH) {
			storePathChainError.append(System.lineSeparator());
			storePathChainError.append(storePathChain);
		}

		return storePathChainError.toString();
	}

	private static KeyStore prepareLoadedStore(Path path) {
		KeyStore store = null;

		try {
			store = KeyStore.getInstance(STORE_TYPE);
		} catch (KeyStoreException e) {
			ExceptionHelper.reportRuntimeException("The store could not be created.", e);
		}

		InputStream storeInputStream = null;

		try {
			storeInputStream = Files.newInputStream(path);
		} catch (IOException e) {
			ExceptionHelper.reportRuntimeException("The store could not be created.", e);
		}

		try {
			store.load(storeInputStream, UNIVERSAL_PASSWORD.toCharArray());
		} catch (NoSuchAlgorithmException e) {
			ExceptionHelper.reportRuntimeException("The algorithm for checking the store integrity could not be found.", e);
		} catch (CertificateException e) {
			ExceptionHelper.reportRuntimeException("At least one of the certificates included in the store could not be loaded.", e);
		} catch (IOException e) {
			ExceptionHelper.reportRuntimeException("The password is incorrect. Store path: " + path, e);
		}

		fLoadedStorePath = Optional.of(path.toAbsolutePath().toString());

		return store;
	}

	private static BigInteger getPublicKeyReadParameter(InputStream in) throws IOException {
		int length = 0;

		length += in.read() << 24;
		length += in.read() << 16;
		length += in.read() << 8;
		length += in.read() << 0;

		byte[] value = new byte[length];
		in.read(value, 0, length);

		return new BigInteger(value);
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy