package cybervillains.ca;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jcajce.provider.config.ConfigurableProvider;
import org.openqa.selenium.security.CertificateGenerator;
import org.openqa.selenium.security.KeyAndCert;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.SignatureException;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.CertificateParsingException;
import java.security.cert.X509Certificate;
import java.security.spec.DSAParameterSpec;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.crypto.spec.DHParameterSpec;

/**
 * This is the main entry point into the Cybervillains CA.
 * 
 * This class handles generation, storage and the persistent mapping of input to duplicated
 * certificates and mapped public keys.
 * 
 * Default setting is to immediately persist changes to the store by writing out the keystore and
 * mapping file every time a new certificate is added. This behavior can be disabled if desired, to
 * enhance performance or allow temporary testing without modifying the certificate store.
 * 
 *************************************************************************************** 
 * Copyright (c) 2007, Information Security Partners, LLC All rights reserved.
 * 
 * In a special exception, Selenium/OpenQA is allowed to use this code under the Apache License 2.0.
 * 
 * @author Brad Hill
 * 
 */
public class KeyStoreManager {

  static Logger log = Logger.getLogger(KeyStoreManager.class.getName());
  private final String CERTMAP_SER_FILE = "certmap.ser";
  private final String SUBJMAP_SER_FILE = "subjmap.ser";

  @SuppressWarnings("FieldCanBeLocal")
  private final String EXPORTED_CERT_NAME = "cybervillainsCA.cer";

  private final char[] _keypassword = "password".toCharArray();
  private final char[] _keystorepass = "password".toCharArray();
  private final String _caPrivateKeystore = "cybervillainsCA.jks";
  private final String _caCertAlias = "signingCert";
  public static final String _caPrivKeyAlias = "signingCertPrivKey";

  X509Certificate _caCert;
  PrivateKey _caPrivKey;
  KeyStore _ks;

  private HashMap<PublicKey, PrivateKey> _rememberedPrivateKeys;
  private HashMap<PublicKey, PublicKey> _mappedPublicKeys;
  private HashMap<String, String> _certMap;
  private HashMap<String, String> _subjectMap;

  private final String KEYMAP_SER_FILE = "keymap.ser";
  private final String PUB_KEYMAP_SER_FILE = "pubkeymap.ser";

  public final String RSA_KEYGEN_ALGO = "RSA";
  public final String DSA_KEYGEN_ALGO = "DSA";
  public final KeyPairGenerator _rsaKpg;
  public final KeyPairGenerator _dsaKpg;


  private boolean persistImmediately = true;
  private File root;
  private final String certificateRevocationList;

  @SuppressWarnings("unchecked")
  public KeyStoreManager(File root, String certificateRevocationList) {
    this.root = root;
    this.certificateRevocationList = certificateRevocationList;

    ConfigurableProvider bcProv = new BouncyCastleProvider();
    DHParameterSpec  dhSpec = new DHParameterSpec(
            new BigInteger("f7e1a085d69b3ddecbbcab5c36b857b97994afbbfa3aea82f95"
                + "74c0b3d0782675159578ebad4594fe67107108180b449167123e84c28161"
                + "3b7cf09328cc8a6e13c167a8b547c8d28e0a3ae1e2bb3a675916ea37f0bf"
                + "a213562f1fb627a01243bcca4f1bea8519089a883dfe15ae59f06928b665"
                + "e807b552564014c3bfecf492a", 16),
            new BigInteger("fd7f53811d75122952df4a9c2eece4e7f611b7523cef4400c31"
                + "e3f80b6512669455d402251fb593d8d58fabfc5f5ba30f6cb9b556cd7813"
                + "b801d346ff26660b76b9950a5a49f9fe8047b1022c24fbba9d7feb7c61bf"
                + "83b57e7c6a8a6150f04fb83f6d3c51ec3023554135a169132f675f3ae2b6"
                + "1d72aeff22203199dd14801c7", 16),
            512);

    bcProv.setParameter(ConfigurableProvider.DH_DEFAULT_PARAMS, dhSpec);

    Security.insertProviderAt((Provider) bcProv, 2);

    SecureRandom _sr = new SecureRandom();

    try
    {
      _rsaKpg = KeyPairGenerator.getInstance(RSA_KEYGEN_ALGO);
      _dsaKpg = KeyPairGenerator.getInstance(DSA_KEYGEN_ALGO);
    } catch (Throwable t)
    {
      throw new Error(t);
    }

    try {

      File privKeys = new File(root, KEYMAP_SER_FILE);


      if (!privKeys.exists())
      {
        _rememberedPrivateKeys = new HashMap<PublicKey, PrivateKey>();
      }
      else
      {
        ObjectInputStream in = new ObjectInputStream(new FileInputStream(privKeys));
        // Deserialize the object
        _rememberedPrivateKeys = (HashMap<PublicKey, PrivateKey>) in.readObject();
        in.close();
      }


      File pubKeys = new File(root, PUB_KEYMAP_SER_FILE);

      if (!pubKeys.exists())
      {
        _mappedPublicKeys = new HashMap<PublicKey, PublicKey>();
      }
      else
      {
        ObjectInputStream in = new ObjectInputStream(new FileInputStream(pubKeys));
        // Deserialize the object
        _mappedPublicKeys = (HashMap<PublicKey, PublicKey>) in.readObject();
        in.close();
      }

    } catch (FileNotFoundException e) {
      // check for file exists, won't happen.
      e.printStackTrace();
    } catch (IOException e) {
      // we could correct, but this probably indicates a corruption
      // of the serialized file that we want to know about; likely
      // synchronization problems during serialization.
      e.printStackTrace();
      throw new Error(e);
    } catch (ClassNotFoundException e) {
      // serious problem.
      e.printStackTrace();
      throw new Error(e);
    }


    BigInteger p = new BigInteger(
            "fd7f53811d75122952df4a9c2eece4e7f611b7523cef4400c31e3f80b6512669"
          + "455d402251fb593d8d58fabfc5f5ba30f6cb9b556cd7813b801d346ff26660b7"
          + "6b9950a5a49f9fe8047b1022c24fbba9d7feb7c61bf83b57e7c6a8a6150f04fb"
          + "83f6d3c51ec3023554135a169132f675f3ae2b61d72aeff22203199dd14801c7", 16);
    BigInteger q = new BigInteger("9760508f15230bccb292b982a2eb840bf0581cf5", 16);
    BigInteger g = new BigInteger(
            "f7e1a085d69b3ddecbbcab5c36b857b97994afbbfa3aea82f9574c0b3d078267"
          + "5159578ebad4594fe67107108180b449167123e84c281613b7cf09328cc8a6e1"
          + "3c167a8b547c8d28e0a3ae1e2bb3a675916ea37f0bfa213562f1fb627a01243b"
          + "cca4f1bea8519089a883dfe15ae59f06928b665e807b552564014c3bfecf492a", 16);

    DSAParameterSpec dsaParameterSpec = new DSAParameterSpec(p, q, g);

    _rsaKpg.initialize(1024, _sr);
    try {
        _dsaKpg.initialize(dsaParameterSpec, _sr);
    } catch (InvalidAlgorithmParameterException e) {
        e.printStackTrace();
        _dsaKpg.initialize(1024, _sr);
    }

    try
    {
      _ks = KeyStore.getInstance("JKS");

      reloadKeystore();
    } catch (FileNotFoundException fnfe)
    {
      try
      {
        createKeystore();
      } catch (Exception e)
      {
        throw new Error(e);
      }
    } catch (Exception e)
    {
      throw new Error(e);
    }


    try {

      File file = new File(root, CERTMAP_SER_FILE);

      if (!file.exists())
      {
        _certMap = new HashMap<String, String>();
      }
      else
      {
        ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));
        // Deserialize the object
        _certMap = (HashMap<String, String>) in.readObject();
        in.close();
      }

    } catch (FileNotFoundException e) {
      // won't happen, check file.exists()
      e.printStackTrace();
    } catch (IOException e) {
      // corrupted file, we want to know.
      e.printStackTrace();
      throw new Error(e);
    } catch (ClassNotFoundException e) {
      // something very wrong, exit
      e.printStackTrace();
      throw new Error(e);
    }


    try {

      File file = new File(root, SUBJMAP_SER_FILE);

      if (!file.exists())
      {
        _subjectMap = new HashMap<String, String>();
      }
      else
      {
        ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));
        // Deserialize the object
        _subjectMap = (HashMap<String, String>) in.readObject();
        in.close();
      }

    } catch (FileNotFoundException e) {
      // won't happen, check file.exists()
      e.printStackTrace();
    } catch (IOException e) {
      // corrupted file, we want to know.
      e.printStackTrace();
      throw new Error(e);
    } catch (ClassNotFoundException e) {
      // something very wrong, exit
      e.printStackTrace();
      throw new Error(e);
    }


  }

  private void reloadKeystore() throws IOException,
      NoSuchAlgorithmException, CertificateException, KeyStoreException, UnrecoverableKeyException {
    InputStream is = new FileInputStream(new File(root, _caPrivateKeystore));

    _ks.load(is, _keystorepass);
    _caCert = (X509Certificate) _ks.getCertificate(_caCertAlias);
    _caPrivKey = (PrivateKey) _ks.getKey(_caPrivKeyAlias, _keypassword);
  }

  /**
   * Creates, writes and loads a new keystore and CA root certificate.
   */
  protected void createKeystore() {

    Certificate signingCert;
    PrivateKey caPrivKey;

    if (_caCert == null || _caPrivKey == null)
    {
      try
      {
        log.fine("Keystore or signing cert & keypair not found.  Generating...");

        KeyPair caKeypair = getRSAKeyPair();
        caPrivKey = caKeypair.getPrivate();
        signingCert = CertificateCreator.createTypicalMasterCert(caKeypair);

        log.fine("Done generating signing cert");
        log.fine(String.valueOf(signingCert));

        _ks.load(null, _keystorepass);

        _ks.setCertificateEntry(_caCertAlias, signingCert);
        _ks.setKeyEntry(_caPrivKeyAlias, caPrivKey, _keypassword, new Certificate[] {signingCert});

        File caKsFile = new File(root, _caPrivateKeystore);

        OutputStream os = new FileOutputStream(caKsFile);
        _ks.store(os, _keystorepass);

        log.fine("Wrote JKS keystore to: " +
            caKsFile.getAbsolutePath());

        // also export a .cer that can be imported as a trusted root
        // to disable all warning dialogs for interception

        File signingCertFile = new File(root, EXPORTED_CERT_NAME);

        FileOutputStream cerOut = new FileOutputStream(signingCertFile);

        byte[] buf = signingCert.getEncoded();

        log.fine("Wrote signing cert to: " + signingCertFile.getAbsolutePath());

        cerOut.write(buf);
        cerOut.flush();
        cerOut.close();

        _caCert = (X509Certificate) signingCert;
        _caPrivKey = caPrivKey;
      } catch (Exception e)
      {
        log.log(Level.SEVERE, "Fatal error creating/storing keystore or signing cert.", e);
        throw new Error(e);
      }
    }
    else
    {
      log.fine("Successfully loaded keystore.");
      log.fine(String.valueOf(_caCert));

    }

  }

  /**
   * Stores a new certificate and its associated private key in the keystore.
   * 
   * @throws KeyStoreException
   * @throws CertificateException
   * @throws NoSuchAlgorithmException
   */
  public synchronized void addCertAndPrivateKey(String hostname, final X509Certificate cert,
      final PrivateKey privKey)
      throws KeyStoreException, CertificateException, NoSuchAlgorithmException
  {
    // String alias = ThumbprintUtil.getThumbprint(cert);

    _ks.deleteEntry(hostname);

    _ks.setCertificateEntry(hostname, cert);
    _ks.setKeyEntry(hostname, privKey, _keypassword, new Certificate[] {cert});

    if (persistImmediately)
    {
      persist();
    }

  }

  /**
   * Writes the keystore and certificate/keypair mappings to disk.
   * 
   * @throws KeyStoreException
   * @throws NoSuchAlgorithmException
   * @throws CertificateException
   */
  public synchronized void persist() throws KeyStoreException, NoSuchAlgorithmException,
      CertificateException {
    try
    {
      FileOutputStream kso = new FileOutputStream(new File(root, _caPrivateKeystore));
      _ks.store(kso, _keystorepass);
      kso.flush();
      kso.close();
      persistCertMap();
      persistSubjectMap();
      persistKeyPairMap();
      persistPublicKeyMap();
    } catch (IOException ioe)
    {
      ioe.printStackTrace();
    }
  }

  /**
   * Returns the aliased certificate. Certificates are aliased by their SHA1 digest.
   * 
   * @see ThumbprintUtil
   * @throws KeyStoreException
   */
  public synchronized X509Certificate getCertificateByAlias(final String alias)
      throws KeyStoreException {
    return (X509Certificate) _ks.getCertificate(alias);
  }

  /**
   * Returns the aliased certificate. Certificates are aliased by their hostname.
   * 
   * @see ThumbprintUtil
   * @throws KeyStoreException
   * @throws UnrecoverableKeyException
   * @throws NoSuchProviderException
   * @throws NoSuchAlgorithmException
   * @throws CertificateException
   * @throws SignatureException
   * @throws CertificateNotYetValidException
   * @throws CertificateExpiredException
   * @throws InvalidKeyException
   * @throws CertificateParsingException
   */
  public synchronized X509Certificate getCertificateByHostname(final String hostname)
      throws KeyStoreException, InvalidKeyException, SignatureException, CertificateException,
             NoSuchAlgorithmException, NoSuchProviderException, UnrecoverableKeyException {

    String alias = _subjectMap.get(getSubjectForHostname(hostname));

    if (alias != null) {
      return (X509Certificate) _ks.getCertificate(alias);
    }
    return getMappedCertificateForHostname(hostname);
  }

  /**
   * Gets the authority root signing cert.
   * 
   * @throws KeyStoreException
   */
  public synchronized X509Certificate getSigningCert() throws KeyStoreException {
    return _caCert;
  }

  /**
   * Gets the authority private signing key.
   * 
   * @throws KeyStoreException
   * @throws NoSuchAlgorithmException
   * @throws UnrecoverableKeyException
   */
  public synchronized PrivateKey getSigningPrivateKey() throws KeyStoreException,
      NoSuchAlgorithmException, UnrecoverableKeyException {
    return _caPrivKey;
  }

  /**
   * This method returns the mapped certificate for a hostname, or generates a "standard" SSL server
   * certificate issued by the CA to the supplied subject if no mapping has been created. This is
   * not a true duplication, just a shortcut method that is adequate for web browsers.
   * 
   * @throws CertificateParsingException
   * @throws InvalidKeyException
   * @throws CertificateExpiredException
   * @throws CertificateNotYetValidException
   * @throws SignatureException
   * @throws CertificateException
   * @throws NoSuchAlgorithmException
   * @throws NoSuchProviderException
   * @throws KeyStoreException
   * @throws UnrecoverableKeyException
   */
  public X509Certificate getMappedCertificateForHostname(String hostname)
      throws InvalidKeyException, SignatureException, CertificateException,
      NoSuchAlgorithmException, NoSuchProviderException, KeyStoreException,
      UnrecoverableKeyException
  {
    String subject = getSubjectForHostname(hostname);

    String thumbprint = _subjectMap.get(subject);

    if (thumbprint == null) {
      KeyAndCert keyAndCert = new CertificateGenerator(root).generateCertificate(
          hostname, certificateRevocationList);
      X509Certificate newCert = keyAndCert.getCertificate();

      addCertAndPrivateKey(hostname, newCert, keyAndCert.getPrivateKey());

      thumbprint = ThumbprintUtil.getThumbprint(newCert);

      _subjectMap.put(subject, thumbprint);

      if (persistImmediately) {
        persist();
      }

      return newCert;

    }
    return getCertificateByAlias(thumbprint);


  }

  private String getSubjectForHostname(String hostname) {
    return "CN=" + hostname + ", OU=Test, O=CyberVillainsCA, L=Seattle, S=Washington, C=US";
  }

  private synchronized void persistCertMap() {
    try {
      ObjectOutput out =
          new ObjectOutputStream(new FileOutputStream(new File(root, CERTMAP_SER_FILE)));
      out.writeObject(_certMap);
      out.flush();
      out.close();
    } catch (FileNotFoundException e) {
      // writing, this shouldn't happen...
      e.printStackTrace();
    } catch (IOException e) {
      // big problem!
      e.printStackTrace();
      throw new Error(e);
    }
  }



  private synchronized void persistSubjectMap() {
    try {
      ObjectOutput out =
          new ObjectOutputStream(new FileOutputStream(new File(root, SUBJMAP_SER_FILE)));
      out.writeObject(_subjectMap);
      out.flush();
      out.close();
    } catch (FileNotFoundException e) {
      // writing, this shouldn't happen...
      e.printStackTrace();
    } catch (IOException e) {
      // big problem!
      e.printStackTrace();
      throw new Error(e);
    }
  }

  /**
   * Generate an RSA Key Pair
   */
  public KeyPair getRSAKeyPair()
  {
    KeyPair kp = _rsaKpg.generateKeyPair();
    rememberKeyPair(kp);
    return kp;

  }

  private synchronized void persistPublicKeyMap() {
    try {
      ObjectOutput out =
          new ObjectOutputStream(new FileOutputStream(new File(root, PUB_KEYMAP_SER_FILE)));
      out.writeObject(_mappedPublicKeys);
      out.flush();
      out.close();
    } catch (FileNotFoundException e) {
      // writing, won't happen
      e.printStackTrace();
    } catch (IOException e) {
      // very bad
      e.printStackTrace();
      throw new Error(e);
    }
  }

  private synchronized void persistKeyPairMap() {
    try {
      ObjectOutput out =
          new ObjectOutputStream(new FileOutputStream(new File(root, KEYMAP_SER_FILE)));
      out.writeObject(_rememberedPrivateKeys);
      out.flush();
      out.close();
    } catch (FileNotFoundException e) {
      // writing, won't happen.
      e.printStackTrace();
    } catch (IOException e) {
      // very bad
      e.printStackTrace();
      throw new Error(e);
    }
  }

  private synchronized void rememberKeyPair(final KeyPair kp)
  {
    _rememberedPrivateKeys.put(kp.getPublic(), kp.getPrivate());
    if (persistImmediately) {
      persistKeyPairMap();
    }
  }

  public KeyStore getKeyStore() {
    return _ks;
  }
}
