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

com.identityx.clientSDK.credentialsProviders.AsymCredentialsProvider Maven / Gradle / Ivy

/*
* Copyright Daon.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.identityx.clientSDK.credentialsProviders;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.math.BigInteger;
import java.security.Key;
import java.security.KeyStore;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.List;
import java.util.Properties;

import org.apache.commons.codec.binary.Base64;

import com.identityx.auth.impl.keys.PrivateApiKey;
import com.identityx.auth.impl.keys.PublicApiKey;
import com.identityx.auth.util.CertsUtil;
import com.identityx.clientSDK.def.ICredentialsProvider;
import com.identityx.clientSDK.exceptions.ClientInitializationException;


public class AsymCredentialsProvider implements ICredentialsProvider {

	public static class AsymCredentialsProviderBuilder {

		private X509Certificate serverCACert = null;
		private String serverCertDN = null;
		private boolean revocationEnabled = false;
		private boolean ocspEnabled = false;
		private String baseUrl = null, tokenId = null; 
		private PrivateApiKey apiKey = null;
		private String jksPassword = null, keyAlias = null, keyPassword = null;
		private InputStream jksInputStream = null;		
		private InputStream credentialsInputStream = null;

		public AsymCredentialsProviderBuilder() { }
		
		public AsymCredentialsProviderBuilder setServerCACert(X509Certificate serverCACert) {
			this.serverCACert = serverCACert;
			return this;
		}

		public AsymCredentialsProviderBuilder setRevocationEnabled(boolean revocationEnabled) {
			this.revocationEnabled = revocationEnabled;
			return this;
		}

		public AsymCredentialsProviderBuilder setBaseUrl(String baseUrl) {
			this.baseUrl = baseUrl;
			return this;
		}
		public AsymCredentialsProviderBuilder setTokenId(String tokenId) {
			this.tokenId = tokenId;
			return this;
		}		

		public AsymCredentialsProviderBuilder setJksInputStream(InputStream jksInputStream) {
			this.jksInputStream = jksInputStream;
			return this;
		}
		/*
		public AsymCredentialsProviderBuilder setJksFileName(String jksFileName) {
			this.jksFileName = jksFileName;
			return this;
		}*/		
		public AsymCredentialsProviderBuilder setJksPassword(String jksPassword) {
			this.jksPassword = jksPassword;
			return this;
		}
		public AsymCredentialsProviderBuilder setKeyAlias(String keyAlias) {
			this.keyAlias = keyAlias;
			return this;
		}
		public AsymCredentialsProviderBuilder setKeyPassword(String keyPassword) {
			this.keyPassword = keyPassword;
			return this;
		}
		/*
		public AsymCredentialsProviderBuilder setCredentialsFileName(String credentialsFileName) {
			this.credentialsFileName = credentialsFileName;
			return this;
		}*/		
		public AsymCredentialsProviderBuilder setCredentialsInputStream(InputStream credentialsInputStream) {
			this.credentialsInputStream = credentialsInputStream;
			return this;
		}

		
		public AsymCredentialsProviderBuilder setApiKey(PrivateApiKey apiKey) {
			this.apiKey = apiKey;
			return this;
		}
		
		public AsymCredentialsProviderBuilder setOCSPEnabled(boolean ocspEnabled) {
			if (ocspEnabled) {
				this.revocationEnabled = true;
			}
			this.ocspEnabled = ocspEnabled;
			return this;
		}
		
		
		public AsymCredentialsProviderBuilder setServerCertDN(String serverCertDN) {
			this.serverCertDN = serverCertDN;
			return this;
		}

		
		public AsymCredentialsProvider build() {
			
			AsymCredentialsProvider asymCredentialsProvider = null; 
			
			try {

				Properties properties = new Properties();
				if (apiKey == null || tokenId == null || baseUrl == null || serverCACert == null || serverCertDN == null) {
					if (credentialsInputStream != null) {
						properties.load(credentialsInputStream);
					}
				}
				
				X509Certificate clientCert = null;
				String validationCerts = properties.getProperty("validationCerts");
				if (validationCerts != null && !validationCerts.isEmpty()) {
					List clientCerts = CertsUtil.certsFromString(validationCerts);
					if (clientCerts != null && clientCerts.size() != 0) {
						clientCert = clientCerts.get(0);
					}
				}				
				
				if (apiKey == null) {
					if (jksInputStream == null) {
						throw new IllegalStateException("No api key: an api key is extracted from a file specified by jksInputStream or provided directly by setting the apiKey parameter");
					}
					Key key = extractKeyFromJksInputStream(jksInputStream, jksPassword, keyAlias, keyPassword);
					if (tokenId == null) {
						if (credentialsInputStream == null) {
							throw new IllegalStateException("No tokenId: a tokenId is extracted from a file specified by credentialsInputStream or provided directly by setting the tokenId parameter");
						}					
						tokenId = properties.getProperty("tokenId");
					}	
					// test clientCert matches the key
					if (clientCert != null) {
						RSAPublicKey rsaPublicKey = (RSAPublicKey) clientCert.getPublicKey();
						RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) key;
						boolean match = rsaPublicKey.getModulus().equals( rsaPrivateKey.getModulus())
						    && BigInteger.valueOf(2).modPow(rsaPublicKey.getPublicExponent().multiply(rsaPrivateKey.getPrivateExponent()).subtract(BigInteger.ONE),
						    		rsaPublicKey.getModulus()).equals(BigInteger.ONE);
						if (!match) {
							throw new IllegalStateException("The client cert specified by credentialsInputStream does not match the private key");							
						}
					}
					apiKey = new PrivateApiKey(tokenId, key);
				}
				if (baseUrl == null) {
					if (credentialsInputStream == null) {
						throw new IllegalStateException("No baseUrl: baseUrl is extracted from a file specified by credentialsInputStream or provided directly by setting the baseUrl parameter");
					}
					baseUrl = properties.getProperty("serviceUrl");
				}
				if (serverCACert == null) {
					if (credentialsInputStream == null) {
						throw new IllegalStateException("No serverCACert: serverCACert is extracted from a file specified by credentialsInputStream or provided directly by setting the serverCACert parameter");
					}
					String serverCACertString = properties.getProperty("serverCACert");
					if (serverCACertString == null) {
						throw new IllegalStateException("No serverCACert: serverCACert cannot be extracted from the file specified by credentialsInputStream and is not provided directly by setting the serverCACert parameter");
					}
					byte[] certBytes = Base64.decodeBase64(serverCACertString);
					CertificateFactory fact = CertificateFactory.getInstance("X.509");
					serverCACert = (X509Certificate) fact.generateCertificate(new ByteArrayInputStream(certBytes));
				}
				if (serverCertDN == null) {
					if (credentialsInputStream == null) {
						throw new IllegalStateException("No serverCertDN: serverCertDN is extracted from a file specified by credentialsInputStream or provided directly by setting the serverCertDN parameter");
					}
					serverCertDN = properties.getProperty("serverCertDN").trim();
				}
			
				asymCredentialsProvider = new AsymCredentialsProvider(baseUrl, apiKey, serverCACert, serverCertDN);
				asymCredentialsProvider.setRevocationEnabled(revocationEnabled);
				asymCredentialsProvider.setOcspEnabled(ocspEnabled);
			}
			catch (Exception ex) {
				throw new RuntimeException("An error has occurred while trying to build the AsymCredentialsProvider object", ex);
			}
			return asymCredentialsProvider;
		}
	}
	
	protected static String defaultCredentialsFileName = "credentials.properties"; 
	
	private String baseUrl;
	private PrivateApiKey apiKey;
	private PublicApiKey responseApiKey;
	private X509Certificate serverCACert;
	private String serverCertDN;
	private boolean revocationEnabled = true;
	private boolean ocspEnabled = true;
	
	
	public AsymCredentialsProvider(String baseUrl, PrivateApiKey apiKey, X509Certificate serverCACert, String serverCertDN) {
		this.baseUrl = baseUrl;
		this.apiKey = apiKey;
		if (serverCACert != null) {
			this.setServerCACert(serverCACert);
		}
		if (serverCertDN != null) {
			this.serverCertDN = serverCertDN;
		}

	}

	/*
	public AsymCredentialsProvider(String jksFileName, String jksPassword, String keyAlias, String keyPassword, String credentialsFileName, X509Certificate serverCACert) throws ClientInitializationException {
		this.setServerCACert(serverCACert);
		init(jksFileName, jksPassword, keyAlias, keyPassword, credentialsFileName);
	}
	*/

	public AsymCredentialsProvider(InputStream jksInputStream, String jksPassword, String keyAlias, 
			String keyPassword, InputStream credentialsInputStream, X509Certificate serverCACert, String serverCertDN) throws ClientInitializationException {
		
		init(jksInputStream, jksPassword, keyAlias, keyPassword, credentialsInputStream);
		if (serverCACert != null) {
			this.setServerCACert(serverCACert);
		}
		if (serverCertDN != null) {
			this.serverCertDN = serverCertDN;
		}
	}
	
	/*
	protected void init(String jksFileName, String jksPassword, String keyAlias, String keyPassword, String credentialsFileName) throws ClientInitializationException {
		
		if (jksFileName == null) throw new IllegalArgumentException("Param jksFileName cannot be null");
		if (jksPassword == null) throw new IllegalArgumentException("Param password cannot be null");
		
		InputStream credentialsInputStream = null;
		InputStream jksInputStream = null;
		//if (credentialsFileName == null) credentialsFileName = defaultCredentialsFileName; 

		try {
			
			ClassLoader loader = Thread.currentThread().getContextClassLoader();
			credentialsInputStream = loader.getResourceAsStream(credentialsFileName);
			if (credentialsInputStream == null) throw new IOException("Cannot open the file " + credentialsFileName);
			jksInputStream = loader.getResourceAsStream(jksFileName);
			
			init(jksInputStream, jksPassword, keyAlias, keyPassword, credentialsInputStream);
						
		} catch (Exception ex) {
			throw new ClientInitializationException("Failed to initialize the Credential Provider", ex);
		} finally {
			if (jksInputStream != null) {
				try {
					jksInputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (credentialsInputStream != null) {
				try {
					credentialsInputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}						
		}		
	}
	*/
	protected void init(InputStream jksInputStream, String jksPassword, String keyAlias, String keyPassword, InputStream credentialsInputStream) throws ClientInitializationException {
		
		if (jksInputStream == null) throw new IllegalArgumentException("Param jksInputStream cannot be null");
		if (credentialsInputStream == null) throw new IllegalArgumentException("Param credentialsInputStream cannot be null");
		if (jksPassword == null) throw new IllegalArgumentException("Param password cannot be null");
		
		Properties properties = new Properties();

		try {
						
			properties.load(credentialsInputStream);
			String tokenId = properties.getProperty("tokenId");
			baseUrl = properties.getProperty("serviceUrl");
			
			this.serverCertDN = properties.getProperty("serverCertDN");
			
			Key key = extractKeyFromJksInputStream(jksInputStream, jksPassword, keyAlias, keyPassword);
			apiKey = new PrivateApiKey(tokenId, key);
			
	        
		} catch (Exception ex) {
			throw new ClientInitializationException("Failed to initialize the Credential Provider", ex);
		}
	}
	
	protected static Key extractKeyFromJksInputStream(InputStream jksInputStream, String jksPassword, String keyAlias, String keyPassword) {
		
		try {
			KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
	        ks.load(jksInputStream, jksPassword.toCharArray());
	        
	        // List the aliases
	        boolean foundPrivateKey = false;
	        String alias = keyAlias;
	        if (alias == null) {
		        for (; ks.aliases().hasMoreElements(); ) {
		            String ialias = (String)ks.aliases().nextElement();
		            foundPrivateKey = ks.isKeyEntry(ialias);
		            if (foundPrivateKey) {
		            	alias = ialias;
		            	break;
		            }	            	
		        }
	        }
	        if (alias != null) {
	        	if (keyPassword == null) keyPassword = jksPassword;
	        	Key key = ks.getKey(alias, keyPassword.toCharArray());
	        	return key;
	        }
	        else {
	        	throw new Exception("Failed to find a private key in the supplied jks file");
	        }
		}
		catch (Exception ex) {
			throw new RuntimeException("An error has occurred while extracting the key from the provided stream", ex);
		}
	}
	
	@Override
	public PrivateApiKey getApiKey() {
		return apiKey;
	}

	public void setApiKey(PrivateApiKey apiKey) {
		this.apiKey = apiKey;
	}

	@Override
	public String getBaseUrl() {
		return baseUrl;
	}

	public void setBaseUrl(String baseUrl) {
		this.baseUrl = baseUrl;
	}

	public PublicApiKey getResponseApiKey() {
		if (responseApiKey == null) {
			responseApiKey = new PublicApiKey(null, serverCACert, serverCertDN);
			responseApiKey.setRevocationEnabled(revocationEnabled);
			// Also sets revocationEnabled = true since this needs to be true for the OCSP verification to happen
			if (ocspEnabled) { 
				responseApiKey.setOcspEnabled(ocspEnabled);
				responseApiKey.setRevocationEnabled(true);
			}			
		}
		
		return responseApiKey;
	}

	/*
	public void setResponseApiKey(AsymApiKey responseApiKey) {
		this.responseApiKey = responseApiKey;
	}*/

	public X509Certificate getServerCert() {
		return serverCACert;
	}

	public void setServerCACert(X509Certificate serverCACert) {
		this.serverCACert = serverCACert;
	}

	public boolean isRevocationEnabled() {
		return revocationEnabled;
	}

	public void setRevocationEnabled(boolean revocationEnabled) {
		this.revocationEnabled = revocationEnabled;
		if (!revocationEnabled) {
			this.ocspEnabled = false;
		}
	}

	public boolean isOcspEnabled() {
		return ocspEnabled;
	}

	/**
	 * Also sets revocationEnabled = true since this needs to be true for the OCSP verification to happen
	 * @param ocspEnabled
	 */
	public void setOcspEnabled(boolean ocspEnabled) {
		this.ocspEnabled = ocspEnabled;
		if (ocspEnabled) {
			this.revocationEnabled = true;
		}
	}
	

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy