package application;

import gui.CertificateTab;
import helpers.FileHelper;
import helpers.Flags;

import java.awt.Component;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.SignatureException;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.text.ParseException;
import java.util.*;

import model.BurpCertificate;
import model.BurpCertificateExtension;
import model.BurpCertificateStore;
import model.ObjectIdentifier;

import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;

import burp.ITab;

public class CertificateTabController extends Observable implements ITab {

	private CertificateTab certificateTab;
	private BurpCertificateStore burpCertificateStore;
	private FileHelper fileHelper;

	public CertificateTabController(CertificateTab certificateTab) {
		this.certificateTab = certificateTab;
		burpCertificateStore = new BurpCertificateStore();
		fileHelper = new FileHelper();
		if (helpers.Flags.DEBUG) {
			importExampleCertificates();
			setCertificateTree();
		}
	}

	/*
	 * Control GUI
	 */

	/**
	 * Update top view with all certificates.
	 */
	public void setCertificateTree() {
		certificateTab.setCertificateRootNode(burpCertificateStore.getRootNode());
		setChanged();
		notifyObservers();
	}

	/**
	 * Setting the status line in GUI or print to STDOUT if no GUI and DEBUG
	 * Flag is set.
	 * 
	 * @param status
	 *            message to display
	 */
	private void setStatus(String status) {
		if (certificateTab != null) {
			certificateTab.setTxtStatus(status);
		} else if (Flags.DEBUG) {
			System.out.println("[Status] " + status);
		}
	}

	/**
	 * Updates the bottom view with detailed certificate information
	 */
	public void setCertificateDetails(BurpCertificate burpCertificate) {
		// Plugin Specific
		certificateTab.setTxtSource(burpCertificate.getSource());
		certificateTab.setChckbxPrivateKey(burpCertificate.hasPrivateKey());
		certificateTab.setSelectedBurpCertificate(burpCertificate);

		// X.509 General
		certificateTab.setTxtVersion(String.valueOf(burpCertificate.getVersionNumber()));
		certificateTab.setTxtSerialNumber(burpCertificate.getSerialNumber());
		certificateTab.setTxtSignatureAlgorithm(burpCertificate.getSignatureAlgorithm());
		certificateTab.setTxtIssuer(burpCertificate.getIssuer());
		certificateTab.setTxtNotBefore(burpCertificate.getNotBefore().toString());
		certificateTab.setTxtNotAfter(burpCertificate.getNotAfter().toString());
		certificateTab.setTxtSubject(burpCertificate.getSubject());
		certificateTab.setTxtPublicKeyAlgorithm(burpCertificate.getPublicKeyAlgorithm());

		if (burpCertificate.getPublicKeyAlgorithm().equals("RSA")) {
			certificateTab.setTxtModulus(burpCertificate.getPublicKeyModulus());
			certificateTab.setTxtExponent(burpCertificate.getPublicKeyExponent());
			certificateTab.setTxtKeySize(String.valueOf(burpCertificate.getKeySize()));
		} else {
			certificateTab.setTxtModulus("");
			certificateTab.setTxtExponent("");
			certificateTab.setTxtKeySize("");
		}
		certificateTab.setTxtSignature(burpCertificate.getSignature());

		// X.509 Extensions
		certificateTab.setIsCa(burpCertificate.isCa());
		if (burpCertificate.isCa()) {
			certificateTab.setTxtPathLimit(burpCertificate.getPathLimit());
			certificateTab.setHasNoPathLimit(burpCertificate.hasNoPathLimit());
		} else {
			certificateTab.setTxtPathLimit("");
		}

		if (burpCertificate.getKeyUsage().size() > 0) {
			certificateTab.setKeyUsage(burpCertificate.getKeyUsage());
		} else {
			certificateTab.setKeyUsage(new LinkedList<String>());
		}

		if (burpCertificate.getExtendedKeyUsage().size() > 0) {
			certificateTab.setExtendedKeyUsage(burpCertificate.getExtendedKeyUsage());
		} else {
			certificateTab.setExtendedKeyUsage(new LinkedList<String>());
		}

		if (burpCertificate.getSubjectAlternativeNames().size() > 0) {
			certificateTab.setSubjectAlternativeNames(burpCertificate.getSubjectAlternativeNames());
		} else {
			certificateTab.setSubjectAlternativeNames(new LinkedList<String>());
		}

		if (burpCertificate.getSubjectKeyIdentifier().length() > 0) {
			certificateTab.setSubjectKeyIdentifier(burpCertificate.getSubjectKeyIdentifier());
		} else {
			certificateTab.setSubjectAlternativeNames(new LinkedList<String>());
		}

		if (burpCertificate.getAuthorityKeyIdentifier().length() > 0) {
			certificateTab.setAuthorityKeyIdentifier(burpCertificate.getAuthorityKeyIdentifier());
		} else {
			certificateTab.setAuthorityKeyIdentifier("");
		}

		if (burpCertificate.getIssuerAlternativeNames().size() > 0) {
			certificateTab.setIssuerAlternativeNames(burpCertificate.getIssuerAlternativeNames());
		} else {
			certificateTab.setIssuerAlternativeNames(new LinkedList<String>());
		}

		// display only unsupported extensions which are not displayed above
		if (burpCertificate.getAllExtensions().size() > 0) {
			List<String> unsupportedExtensions = new LinkedList<>();
			for (BurpCertificateExtension extension : burpCertificate.getAllExtensions()) {
				if (!ObjectIdentifier.extensionsIsSupported(extension.getOid())) {
					if (ObjectIdentifier.getExtension(extension.getOid()) != null) {
						unsupportedExtensions.add(ObjectIdentifier.getExtension(extension.getOid()));
					} else {
						// display OID number if extension name is unknown
						unsupportedExtensions.add(extension.getOid());
					}
				}
			}
			certificateTab.setAllExtensions(unsupportedExtensions);
		}
	}

	/*
	 * Import
	 */

	/**
	 * Import preloaded certificates as examples
	 */
	private void importExampleCertificates() {
		if (fileHelper.startedFromJar()) {
			try {
				BurpCertificate c1 = importCertificate(fileHelper.exportRessourceFromJar("examples/certificate.pem"));
				importPrivateKey(c1, fileHelper.exportRessourceFromJar("examples/private_key_rsa.pem"));
				importCertificateChain(fileHelper.exportRessourceFromJar("examples/example.org_chain.pem"));
				setCertificateDetails(c1);
			} catch (IOException e) {
				setStatus("Error importing example certificates (" + e.getMessage() + ")");
			} catch (Exception e) {
				setStatus("Error (" + e.getMessage() + ")");
			}
		} else {
			BurpCertificate c1 = importCertificate("src/main/resources/examples/certificate.pem");
			importPrivateKey(c1, "src/main/resources/examples/private_key_rsa.pem");
			importCertificateChain("src/main/resources/examples/example.org_chain.pem");
			setCertificateDetails(c1);
		}
	}

	/**
	 * Read an X.509v3 certificate from a file.
	 * 
	 * @param filename
	 *            certificate file to import
	 * @return certificate
	 */
	public BurpCertificate importCertificate(String filename) {
		setStatus("Importing certificate...");
		FileInputStream fis;
		try {
			fis = new FileInputStream(filename);
			byte value[] = new byte[fis.available()];
			fis.read(value);
			ByteArrayInputStream bais = new ByteArrayInputStream(value);
			fis.close();
			CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
			X509Certificate x509certificate = (X509Certificate) certFactory.generateCertificate(bais);
			BurpCertificate certificate = new BurpCertificate(x509certificate);
			certificate.setPublicKey(x509certificate.getPublicKey());
			certificate.setSource("Imported");
			burpCertificateStore.addCertificate(certificate);
			setCertificateTree();
			setStatus("Certificate imported.");
			setCertificateDetails(certificate);
			return certificate;
		} catch (IOException | CertificateException e) {
			setStatus("Error reading file. (" + e.getMessage() + ")");
			e.printStackTrace();
		} catch (Exception e) {
			setStatus("Error (" + e.getMessage() + ")");
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * Read an PEM encoded X.509v3 certificate
	 * 
	 * @param inputString
	 *            PEM encoded X.509 certificate
	 * @return certificate
	 */
	public BurpCertificate importCertificateFromString(String inputString) {
		setStatus("Importing certificate...");
		CertificateFactory certFactory;
		try {
			certFactory = CertificateFactory.getInstance("X.509");
			ByteArrayInputStream bais = new ByteArrayInputStream(Base64.getDecoder().decode(inputString));
			X509Certificate x509certificate = (X509Certificate) certFactory.generateCertificate(bais);
			BurpCertificate certificate = new BurpCertificate(x509certificate);
			certificate.setPublicKey(x509certificate.getPublicKey());
			certificate.setSource("Imported");
			burpCertificateStore.addCertificate(certificate);
			setCertificateTree();
			setStatus("Certificate imported");
			return certificate;
		} catch (CertificateException | IllegalArgumentException e) {
			setStatus("Error reading input certificate. (" + e.getMessage() + ")");
			e.printStackTrace();
		} catch (Exception e) {
			setStatus("Error. (" + e.getMessage() + ")");
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * Read and import an X.509v3 certificate chain.
	 * 
	 * @param filename
	 *            X.509v3 certificate chain (get with
	 *            <code>openssl s_client -connect example.org -showcerts</code>)
	 * @return List with all certificates in chain
	 */
	public List<BurpCertificate> importCertificateChain(String filename) {
		setStatus("Importing certificate chain...");
		FileInputStream fis;
		List<BurpCertificate> certificateChain = new LinkedList<>();

		try {
			fis = new FileInputStream(filename);
			byte value[] = new byte[fis.available()];
			fis.read(value);
			ByteArrayInputStream bais = new ByteArrayInputStream(value);
			fis.close();
			CertificateFactory certFactory = CertificateFactory.getInstance("X.509");

			for (Certificate c : certFactory.generateCertificates(bais)) {
				X509Certificate x509certificate = (X509Certificate) c;
				BurpCertificate certificate = new BurpCertificate(x509certificate);
				certificate.setPublicKey(x509certificate.getPublicKey());
				certificate.setSource("Imported Chain");
				certificateChain.add(certificate);
			}

			burpCertificateStore.addCertificateChain(certificateChain);
			setCertificateTree();
			setStatus("Certificate Chain imported");
			return certificateChain;
		} catch (IOException | CertificateException e) {
			setStatus("Error reading certificate chain. (" + e.getMessage() + ")");
			e.printStackTrace();
		} catch (Exception e) {
			setStatus("Error (" + e.getMessage() + ")");
		}
		return null;
	}

	/**
	 * Import a private RSA key in PEM format from a file and add it to the
	 * selected certificate.
	 * 
	 * @param certificate
	 *            which the private key is for.
	 * @param filename
	 *            of the private RSA key in PEM format
	 */
	public void importPrivateKey(BurpCertificate certificate, String filename) {
		setStatus("Importing private key...");
		BufferedReader br;
		try {
			br = new BufferedReader(new FileReader(filename));
			PEMParser pp = new PEMParser(br);
			PEMKeyPair pemKeyPair = (PEMKeyPair) pp.readObject();
			KeyPair kp = new JcaPEMKeyConverter().getKeyPair(pemKeyPair);
			pp.close();
			setCertificateTree();
			setStatus("Private Key imported.");
			certificate.setPrivateKey(kp.getPrivate());
		} catch (IOException e) {
			setStatus("Error importing private key. (" + e.getMessage() + ")");
			e.printStackTrace();
		} catch (Exception e) {
			setStatus("Error (" + e.getMessage() + ")");
		}
	}

	/**
	 * Import a private Key in PKCS8 format in DER format.
	 * 
	 * @param certificate
	 *            which the private key is for. Possible way to convert to
	 *            PKCS8:
	 *            <code>openssl pkcs8 -topk8 -inform PEM -outform DER -in privatekey.pem -out private_key_pkcs8.pem -nocrypt</code>
	 * @param filename
	 *            of the PKCS8 key
	 * @param password
	 *            for opening the file. Empty if no password is required.
	 */
	public void importPKCS8(BurpCertificate certificate, String filename) {
		setStatus("Importing private key...");
		FileInputStream fis;
		File file = new File(filename);
		PrivateKey privateKey;

		try {
			fis = new FileInputStream(file);
			DataInputStream dis = new DataInputStream(fis);
			byte[] keyBytes = new byte[(int) file.length()];
			dis.readFully(keyBytes);
			dis.close();
			PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
			KeyFactory keyFactory = KeyFactory.getInstance("RSA");
			privateKey = keyFactory.generatePrivate(keySpec);
			certificate.setPrivateKey(privateKey);
			setCertificateTree();
			setStatus("Private Key imported.");
		} catch (IOException | NoSuchAlgorithmException | InvalidKeySpecException e) {
			setStatus("Error importing private Key. (" + e.getMessage() + ")");
			e.printStackTrace();
		} catch (Exception e) {
			setStatus("Error (" + e.getMessage() + ")");
		}
	}

	/*
	 * Export
	 */

	/**
	 * Export the certificate to a file.
	 * 
	 * @param certificate
	 *            to export
	 * @param filename
	 *            for the exported certificate
	 */
	public void exportCertificate(BurpCertificate certificate, String filename) {
		try {
			fileHelper.exportPEMObject(certificate.getCertificate(), filename);
			setStatus("Certificate exported.");
		} catch (IOException e) {
			setStatus("Error exporting certificate (" + e.getMessage() + ")");
			e.printStackTrace();
		} catch (Exception e) {
			setStatus("Error (" + e.getMessage() + ")");
		}
	}

	/**
	 * Export Private RSA Key in PEM format.
	 * 
	 * @param certificate
	 *            to export
	 * @param filename
	 *            for the exported private RSA key
	 */
	public void exportPrivateKey(BurpCertificate certificate, String filename) {
		setStatus("Exporting private key...");
		try {
			fileHelper.exportPEMObject(certificate.getPrivateKey(), filename);
			setStatus("Private Key exported.");
		} catch (IOException e) {
			setStatus("Error exporting private key. (" + e.getMessage() + ")");
			e.printStackTrace();
		} catch (Exception e) {
			setStatus("Error (" + e.getMessage() + ")");
		}
	}

	/*
	 * Clone
	 */

	/**
	 * Copy all X.509v3 general information and all extensions 1:1 from one
	 * source certificat to one destination certificate.
	 * 
	 * @param certificate
	 *            with the original information
	 * @param burpCertificateBuilder
	 *            for generating the destination certificate
	 */
	private void cloneProperties(BurpCertificate certificate, BurpCertificateBuilder burpCertificateBuilder) {
		burpCertificateBuilder.setVersion(certificate.getVersionNumber());
		burpCertificateBuilder.setSerial(certificate.getSerialNumberBigInteger());
		if (certificate.getPublicKeyAlgorithm().equals("RSA")) {
			burpCertificateBuilder.setSignatureAlgorithm(certificate.getSignatureAlgorithm());
		} else {
			burpCertificateBuilder.setSignatureAlgorithm("SHA256withRSA");
		}
		burpCertificateBuilder.setIssuer(certificate.getIssuer());
		burpCertificateBuilder.setNotAfter(certificate.getNotAfter());
		burpCertificateBuilder.setNotBefore(certificate.getNotBefore());
		burpCertificateBuilder.setKeySize(certificate.getKeySize());

		for (BurpCertificateExtension extension : certificate.getAllExtensions()) {
			burpCertificateBuilder.addExtension(extension);
		}
	}

	/**
	 * Clone a certificate from one source certificate. New private key material
	 * is generated.
	 * 
	 * @param certificate
	 *            to clone
	 * @param burpCertificateBuilder
	 *            for generating the new cloned certificate
	 * @return cloned certificate
	 */
	public BurpCertificate cloneCertificate(BurpCertificate certificate, BurpCertificateBuilder burpCertificateBuilder) {
		cloneProperties(certificate, burpCertificateBuilder);
		setStatus("Cloning certificate...");

		BurpCertificate burpCertificate;
		try {
			burpCertificate = burpCertificateBuilder.generateSelfSignedCertificate();
			burpCertificate.setSource("Cloned");
			burpCertificateStore.addCertificate(burpCertificate);
			setStatus("Certificate cloned.");
			setCertificateTree();
			return burpCertificate;
		} catch (IOException e) {
			setStatus("I/O error. (" + e.getMessage() + ")");
			e.printStackTrace();
		} catch (CertificateEncodingException e) {
			setStatus("Problem with certificate encoding. (" + e.getMessage() + ")");
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			setStatus("Invalid Key.");
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			setStatus("Unsupported algorithm specified. (" + e.getMessage() + ")");
			e.printStackTrace();
		} catch (SignatureException e) {
			setStatus("Error creating signature. (" + e.getMessage() + ")");
			e.printStackTrace();
		} catch (InvalidKeySpecException e) {
			setStatus("Unsupported key specifications. (" + e.getMessage() + ")");
			e.printStackTrace();
		} catch (NoSuchProviderException | IllegalStateException e) {
			setStatus("Error cloning certificate. (" + e.getMessage() + ")");
			e.printStackTrace();
		} catch (Exception e) {
			setStatus("Error (" + e.getMessage() + ")");
		}
		return null;
	}

	/**
	 * Clone a certificate and sign it with another private key from an issuer.
	 * 
	 * @param certificate
	 *            to clone
	 * @param burpCertificateBuilder
	 *            for the cloned certificate
	 * @param issuerCertificate
	 *            for signing the new certificate
	 * @return cloned certificate
	 */
	public BurpCertificate cloneAndSignCertificate(BurpCertificate certificate, BurpCertificateBuilder burpCertificateBuilder, BurpCertificate issuerCertificate) {
		cloneProperties(certificate, burpCertificateBuilder);

		try {
			if (!issuerCertificate.hasPrivateKey()) {
				throw new Exception("No private key found.");
			}
		} catch (Exception e) {
			setStatus("No private key found");
			e.printStackTrace();
		}

		BurpCertificate burpCertificate;
		try {
			burpCertificate = burpCertificateBuilder.generateCertificate(issuerCertificate);
			burpCertificate.setSource("Cloned and signed by cloned " + issuerCertificate.getSubject());
			burpCertificateStore.addCertificate(burpCertificate);
			setCertificateTree();
			setStatus("Certificate cloned and signed.");
			return burpCertificate;
		} catch (CertificateEncodingException | InvalidKeyException | IllegalStateException | NoSuchAlgorithmException | SignatureException | NoSuchProviderException | InvalidKeySpecException
				| IOException e) {
			setStatus("Error cloning certificate. (" + e.getMessage() + ")");
			e.printStackTrace();
		} catch (Exception e) {
			setStatus("Error (" + e.getMessage() + ")");
		}
		return null;
	}

	/**
	 * Clone whole certificate chain
	 * 
	 * @param certificateChain
	 *            to clone
	 * @return List of cloned certificates. According to RFC 5246: Next
	 *         Certificate must sign previous.
	 */
	public List<BurpCertificate> cloneCertificateChain(List<BurpCertificate> certificateChain) {
		List<BurpCertificate> certificates = new LinkedList<>();

		// b/c of RFC 5246 I generate them in reverse order
		Collections.reverse(certificateChain);
		BurpCertificate currentCertificate;
		BurpCertificate previousCertificate = null;
		for (BurpCertificate c : certificateChain) {
			if (previousCertificate == null) { // self-sign
				currentCertificate = cloneCertificate(c, new BurpCertificateBuilder(c.getSubject()));
			} else {
				currentCertificate = cloneAndSignCertificate(c, new BurpCertificateBuilder(c.getSubject()), previousCertificate);
			}
			// remove b/c already added in called methods above
			burpCertificateStore.removeCertificate(currentCertificate);
			certificates.add(currentCertificate);
			previousCertificate = currentCertificate;
		}
		Collections.reverse(certificates); // Restore original order
		burpCertificateStore.addCertificateChain(certificates);
		setStatus("Certificate chain cloned");
		setCertificateTree();
		return certificates;
	}

	/*
	 * Create new
	 */

	/**
	 * Create a new X.509v3 certificate from certificate tab form. All entered
	 * fields are applied and the unsupported extensions are cloned from
	 * burpCertificate parameter if this option is activated.
	 * 
	 * @param burpCertificate
	 *            Unsupported extensions to clone.
	 */
	public void createBurpCertificate(BurpCertificate burpCertificate) {
		setStatus("Creating certificate...");
		try {

			// X.509 General

			BurpCertificateBuilder burpCertificateBuilder = new BurpCertificateBuilder(certificateTab.getTxtSubject());
			burpCertificateBuilder.setVersion(3);
			burpCertificateBuilder.setSerial(certificateTab.getTxtSerialNumber());
			burpCertificateBuilder.setSignatureAlgorithm(certificateTab.getTxtSignatureAlgorithm());
			burpCertificateBuilder.setIssuer(certificateTab.getTxtIssuer());

			burpCertificateBuilder.setNotBefore(certificateTab.getTxtNotBefore());
			burpCertificateBuilder.setNotAfter(certificateTab.getTxtNotAfter());

			burpCertificateBuilder.setKeySize(Integer.valueOf(certificateTab.getTxtKeySize()));

			// Extensions

			if (!certificateTab.getChckbxIgnoreBasicConstraints()) {
				burpCertificateBuilder.setHasBasicConstraints(true);
				burpCertificateBuilder.setIsCA(certificateTab.isCa());
				if (certificateTab.isCa() && certificateTab.hasNoPathLimit()) {
					burpCertificateBuilder.setHasNoPathLimit(true);
				} else if (certificateTab.isCa() && !certificateTab.hasNoPathLimit()) {
					if (certificateTab.getTxtPathLimit() >= 0) {
						burpCertificateBuilder.setPathLimit(certificateTab.getTxtPathLimit());
					} else {
						burpCertificateBuilder.setPathLimit(0);
					}
				}
			}

			if (certificateTab.getKeyUsage().size() > 0) {
				burpCertificateBuilder.setKeyUsage(certificateTab.getKeyUsage());
			}

			if (certificateTab.getExtendedKeyUsage().size() > 0) {
				burpCertificateBuilder.setExtendedKeyUsage(certificateTab.getExtendedKeyUsage());
			}

			if (certificateTab.getSubjectAlternativeNames().size() > 0) {
				for (String s : certificateTab.getSubjectAlternativeNames()) {
					burpCertificateBuilder.addSubjectAlternativeName(s);
				}
			}

			if (certificateTab.getIssuerAlternativeNames().size() > 0) {
				for (String s : certificateTab.getIssuerAlternativeNames()) {
					burpCertificateBuilder.addIssuerAlternativeName(s);
				}
			}

			if (certificateTab.isAutoSubjectKeyIdentifier()) {
				burpCertificateBuilder.setSubjectKeyIdentifier(true);
			} else if (certificateTab.getSubjectKeyIdentifier().length() > 0) {
				burpCertificateBuilder.setSubjectKeyIdentifier(certificateTab.getSubjectKeyIdentifier());
			}

			if (certificateTab.isAutoAuthorityKeyIdentifier()) {
				burpCertificateBuilder.setAuthorityKeyIdentifier(true);
			} else if (certificateTab.getAuthorityKeyIdentifier().length() > 0) {
				burpCertificateBuilder.setAuthorityKeyIdentifier(certificateTab.getAuthorityKeyIdentifier());
			}

			// Unsupported Extensions - copy only unsupported ones which are not
			// implemented above
			if (certificateTab.getChckbxCopyUnsupportedExtensions()) {
				for (BurpCertificateExtension extension : burpCertificate.getAllExtensions()) {
					if (!ObjectIdentifier.extensionsIsSupported(extension.getOid())) {
						burpCertificateBuilder.addExtension(extension);
					}
				}
			}

			BurpCertificate newCertificate;
			newCertificate = burpCertificateBuilder.generateSelfSignedCertificate();
			burpCertificateStore.addCertificate(newCertificate);
			setStatus("New certificate created.");
			setCertificateTree();
		} catch (CertificateEncodingException e) {
			setStatus("Problem with certificate encoding. (" + e.getMessage() + ")");
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			setStatus("Invalid Key. (" + e.getMessage() + ")");
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			setStatus("Unsupported algorithm specified. (" + e.getMessage() + ")");
			e.printStackTrace();
		} catch (SignatureException e) {
			setStatus("Error creating signature. (" + e.getMessage() + ")");
			e.printStackTrace();
		} catch (InvalidKeySpecException e) {
			setStatus("Unsupported key specifications. (" + e.getMessage() + ")");
			e.printStackTrace();
		} catch (IOException e) {
			setStatus("I/O error (" + e.getMessage() + ")");
			e.printStackTrace();
		} catch (NoSuchProviderException | IllegalStateException e) {
			setStatus("Error creating certificate. (" + e.getMessage() + ")");
			e.printStackTrace();
		} catch (ParseException e) {
			setStatus("Could not Parse Date. (" + e.getMessage() + ")");
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			setStatus("Error reading input form. (" + e.getMessage() + ")");
			e.printStackTrace();
		} catch (Exception e) {
			setStatus("Error (" + e.getMessage() + ")");
			e.printStackTrace();
		}
	}

	/*
	 * Read
	 */

	/**
	 * Get all certificates which have a private key.
	 * 
	 * @return List of certificates with private key.
	 */
	public List<BurpCertificate> getCertificatesWithPrivateKey() {
		return burpCertificateStore.getBurpCertificatesWithPrivateKey();
	}

	/*
	 * Remove
	 */

	/**
	 * Removes a certifiate from the certificate tree.
	 * 
	 * @param burpCertificate
	 *            to remove
	 */
	public void removeBurpCertificate(BurpCertificate burpCertificate) {
		burpCertificateStore.removeCertificate(burpCertificate);
		setStatus("Certificate removed.");
		setCertificateTree();
	}

	/*
	 * Implement ITab for BurpExtender
	 */

	@Override
	public String getTabCaption() {
		return "SAML Raider Certificates";
	}

	@Override
	public Component getUiComponent() {
		return certificateTab;
	}
	
	public String getSamlRequestParameterName() {
		return certificateTab.getSamlRequestParameterName();
	}
	
	public String getSamlResponseParameterName() {
		return certificateTab.getSamlResponseParameterName();
	}
}