/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.knox.gateway.util;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigInteger;
import java.net.InetAddress;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Date;

import org.apache.commons.codec.binary.Base64;
import org.apache.knox.gateway.i18n.GatewayUtilCommonMessages;
import org.apache.knox.gateway.i18n.messages.MessagesFactory;

public class X509CertificateUtil {

  private static GatewayUtilCommonMessages LOG = MessagesFactory.get(GatewayUtilCommonMessages.class);

  /**
   * Create a self-signed X.509 Certificate
   * @param dn the X.509 Distinguished Name, eg "CN=Test, L=London, C=GB"
   * @param pair the KeyPair
   * @param days how many days from now the Certificate is valid for
   * @param algorithm the signing algorithm, eg "SHA1withRSA"
   * @return self-signed X.509 certificate
   */
  public static X509Certificate generateCertificate(String dn, KeyPair pair, int days, String algorithm) {
    PrivateKey privkey = pair.getPrivate();
    Object x509CertImplObject = null;
    try {
      Date from = new Date();
      Date to = new Date(from.getTime() + days * 86400000L);

      Class<?> certInfoClass = Class.forName(getX509CertInfoModuleName());
      Constructor<?> certInfoConstr = certInfoClass.getConstructor();
      Object certInfoObject = certInfoConstr.newInstance();

      // CertificateValidity interval = new CertificateValidity(from, to);
      Class<?> certValidityClass = Class.forName(getX509CertifValidityModuleName());
      Constructor<?> certValidityConstr = certValidityClass.getConstructor(Date.class, Date.class);
      Object certValidityObject = certValidityConstr.newInstance(from, to);

      BigInteger sn = new BigInteger(64, new SecureRandom());

      // X500Name owner = new X500Name(dn);
      Class<?> x500NameClass = Class.forName(getX509X500NameModuleName());
      Constructor<?> x500NameConstr = x500NameClass.getConstructor(String.class);
      Object x500NameObject = x500NameConstr.newInstance(dn);

      Method methodSET = certInfoObject.getClass().getMethod("set", String.class, Object.class);

      // info.set(X509CertInfo.VALIDITY, interval);
      methodSET.invoke(certInfoObject, getSetField(certInfoObject, "VALIDITY"),certValidityObject);

      // info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(sn));
      Class<?> certificateSerialNumberClass = Class.forName(getCertificateSerialNumberModuleName());
      Constructor<?> certificateSerialNumberConstr = certificateSerialNumberClass
                                                         .getConstructor(BigInteger.class);
      Object certificateSerialNumberObject = certificateSerialNumberConstr.newInstance(sn);
      methodSET.invoke(certInfoObject, getSetField(certInfoObject, "SERIAL_NUMBER"),
          certificateSerialNumberObject);

      // info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(owner));
      try {
        Class<?> certificateSubjectNameClass = Class.forName(getCertificateSubjectNameModuleName());
        Constructor<?> certificateSubjectNameConstr = certificateSubjectNameClass
                                                          .getConstructor(x500NameClass);
        Object certificateSubjectNameObject = certificateSubjectNameConstr
                                                  .newInstance(x500NameObject);
        methodSET.invoke(certInfoObject, getSetField(certInfoObject, "SUBJECT"),
            certificateSubjectNameObject);
      }
      catch (InvocationTargetException ite) {
        methodSET.invoke(certInfoObject, getSetField(certInfoObject, "SUBJECT"),
            x500NameObject);
      }

      // info.set(X509CertInfo.ISSUER, new CertificateIssuerName(owner));
      try {
        Class<?> certificateIssuerNameClass = Class.forName(getCertificateIssuerNameModuleName());
        Constructor<?> certificateIssuerNameConstr = certificateIssuerNameClass
                                                         .getConstructor(x500NameClass);
        Object certificateIssuerNameObject = certificateIssuerNameConstr.newInstance(x500NameObject);
        methodSET.invoke(certInfoObject, getSetField(certInfoObject, "ISSUER"),
            certificateIssuerNameObject);
      }
      catch (InvocationTargetException ite) {
        methodSET.invoke(certInfoObject, getSetField(certInfoObject, "ISSUER"),
            x500NameObject);
      }

      // info.set(X509CertInfo.KEY, new CertificateX509Key(pair.getPublic()));
      Class<?> certificateX509KeyClass = Class.forName(getCertificateX509KeyModuleName());
      Constructor<?> certificateX509KeyConstr = certificateX509KeyClass
                                                    .getConstructor(PublicKey.class);
      Object certificateX509KeyObject = certificateX509KeyConstr.newInstance(pair.getPublic());
      methodSET.invoke(certInfoObject, getSetField(certInfoObject, "KEY"),
          certificateX509KeyObject);
      // info.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3));
      Class<?> certificateVersionClass = Class.forName(getCertificateVersionModuleName());
      Constructor<?> certificateVersionConstr = certificateVersionClass.getConstructor(int.class);
      Constructor<?> certificateVersionConstr0 = certificateVersionClass.getConstructor();
      Object certInfoObject0 = certificateVersionConstr0.newInstance();
      Field v3IntField = certInfoObject0.getClass().getDeclaredField("V3");
      v3IntField.setAccessible(true);
      int fValue = v3IntField.getInt(certInfoObject0);
      Object certificateVersionObject = certificateVersionConstr.newInstance(fValue);
      methodSET.invoke(certInfoObject, getSetField(certInfoObject, "VERSION"),
          certificateVersionObject);

      // AlgorithmId algo = new AlgorithmId(AlgorithmId.md5WithRSAEncryption_oid);
      Class<?> algorithmIdClass = Class.forName(getAlgorithmIdModuleName());
      Field md5WithRSAField = algorithmIdClass.getDeclaredField("md5WithRSAEncryption_oid");
      md5WithRSAField.setAccessible(true);
      Class<?> objectIdentifierClass = Class.forName(getObjectIdentifierModuleName());

      Object md5WithRSAValue = md5WithRSAField.get(algorithmIdClass);

      Constructor<?> algorithmIdConstr = algorithmIdClass.getConstructor(objectIdentifierClass);
      Object algorithmIdObject = algorithmIdConstr.newInstance(md5WithRSAValue);

      // info.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(algo));
      Class<?> certificateAlgorithmIdClass = Class.forName(getCertificateAlgorithmIdModuleName());
      Constructor<?> certificateAlgorithmIdConstr = certificateAlgorithmIdClass
                                                        .getConstructor(algorithmIdClass);
      Object certificateAlgorithmIdObject = certificateAlgorithmIdConstr
                                                .newInstance(algorithmIdObject);
      methodSET.invoke(certInfoObject, getSetField(certInfoObject, "ALGORITHM_ID"),
          certificateAlgorithmIdObject);

      // Set the SAN extension
      Class<?> generalNameInterfaceClass = Class.forName(getGeneralNameInterfaceModuleName());

      Class<?> generalNameClass = Class.forName(getGeneralNameModuleName());
      Constructor<?> generalNameConstr = generalNameClass.getConstructor(generalNameInterfaceClass);

      // GeneralNames generalNames = new GeneralNames();
      Class<?> generalNamesClass = Class.forName(getGeneralNamesModuleName());
      Constructor<?> generalNamesConstr = generalNamesClass.getConstructor();
      Object generalNamesObject = generalNamesConstr.newInstance();
      Method generalNamesAdd = generalNamesObject.getClass().getMethod("add", generalNameClass);

      Class<?> dnsNameClass = Class.forName(getDNSNameModuleName());
      Constructor<?> dnsNameConstr = dnsNameClass.getConstructor(String.class);

      // Pull the hostname out of the DN
      String hostname = dn.split(",", 2)[0].split("=", 2)[1];
      if("localhost".equals(hostname)) {
        String detectedHostname = InetAddress.getLocalHost().getHostName();
        // DNSName dnsName = new DNSName(detectedHostname);
        Object dnsNameObject = dnsNameConstr.newInstance(detectedHostname);
        // GeneralName generalName = new GeneralName(dnsName);
        Object generalNameObject = generalNameConstr.newInstance(dnsNameObject);
        // generalNames.add(generalName);
        generalNamesAdd.invoke(generalNamesObject, generalNameObject);
      }

      // DNSName dnsName = new DNSName(hostname);
      Object dnsNameObject = dnsNameConstr.newInstance(hostname);
      // GeneralName generalName = new GeneralName(dnsName);
      Object generalNameObject = generalNameConstr.newInstance(dnsNameObject);
      // generalNames.add(generalName);
      generalNamesAdd.invoke(generalNamesObject, generalNameObject);

      // SubjectAlternativeNameExtension san = new SubjectAlternativeNameExtension(generalNames);
      Class<?> subjectAlternativeNameExtensionClass = Class.forName(
          getSubjectAlternativeNameExtensionModuleName());
      Constructor<?> subjectAlternativeNameExtensionConstr =
          subjectAlternativeNameExtensionClass.getConstructor(generalNamesClass);
      Object subjectAlternativeNameExtensionObject = subjectAlternativeNameExtensionConstr
                                                         .newInstance(generalNamesObject);

      // CertificateExtensions certificateExtensions = new CertificateExtensions();
      Class<?> certificateExtensionsClass = Class.forName(getCertificateExtensionsModuleName());
      Constructor<?> certificateExtensionsConstr = certificateExtensionsClass.getConstructor();
      Object certificateExtensionsObject = certificateExtensionsConstr.newInstance();

      // certificateExtensions.set(san.getExtensionId().toString(), san);
      Method getExtensionIdMethod = subjectAlternativeNameExtensionObject.getClass()
                                        .getMethod("getExtensionId");
      String sanExtensionId = getExtensionIdMethod.invoke(subjectAlternativeNameExtensionObject)
                                  .toString();
      Method certificateExtensionsSet = certificateExtensionsObject.getClass().getMethod("set",
          String.class, Object.class);
      certificateExtensionsSet.invoke(certificateExtensionsObject, sanExtensionId,
          subjectAlternativeNameExtensionObject);

      // info.set(X509CertInfo.EXTENSIONS, certificateExtensions);
      methodSET.invoke(certInfoObject, getSetField(certInfoObject, "EXTENSIONS"),
          certificateExtensionsObject);

      // Sign the cert to identify the algorithm that's used.
      // X509CertImpl cert = new X509CertImpl(info);
      Class<?> x509CertImplClass = Class.forName(getX509CertImplModuleName());
      Constructor<?> x509CertImplConstr = x509CertImplClass.getConstructor(certInfoClass);
      x509CertImplObject = x509CertImplConstr.newInstance(certInfoObject);

      // cert.sign(privkey, algorithm);
      Method methoSIGN = x509CertImplObject.getClass().getMethod("sign",
          PrivateKey.class, String.class);
      methoSIGN.invoke(x509CertImplObject, privkey, algorithm);

      // Update the algorith, and resign.
      // algo = (AlgorithmId)cert.get(X509CertImpl.SIG_ALG);
      Method methoGET = x509CertImplObject.getClass().getMethod("get", String.class);
      String sig_alg = getSetField(x509CertImplObject, "SIG_ALG");

      String certAlgoIdNameValue = getSetField(certificateAlgorithmIdObject, "NAME");
      String certAlgoIdAlgoValue = getSetField(certificateAlgorithmIdObject, "ALGORITHM");
      // info.set(CertificateAlgorithmId.NAME + "." + CertificateAlgorithmId.ALGORITHM, algo);
      methodSET.invoke(certInfoObject, certAlgoIdNameValue + "." + certAlgoIdAlgoValue,
          methoGET.invoke(x509CertImplObject, sig_alg));

      // cert = new X509CertImpl(info);
      x509CertImplObject = x509CertImplConstr.newInstance(certInfoObject);
      // cert.sign(privkey, algorithm);
      methoSIGN.invoke(x509CertImplObject, privkey, algorithm);
    } catch (Exception e) {
      LOG.failedToGenerateCertificate(e);
    }
    return (X509Certificate) x509CertImplObject;
  }

  private static String getX509CertInfoModuleName() {
    return System.getProperty("java.vendor").contains("IBM") ? "com.ibm.security.x509.X509CertInfo"
               : "sun.security.x509.X509CertInfo";
  }

  private static String getX509CertifValidityModuleName() {
    return System.getProperty("java.vendor").contains("IBM") ?
               "com.ibm.security.x509.CertificateValidity" :
               "sun.security.x509.CertificateValidity";
  }

  private static String getX509X500NameModuleName() {
    return System.getProperty("java.vendor").contains("IBM") ?
               "com.ibm.security.x509.X500Name" :
               "sun.security.x509.X500Name";
  }

  private static String getCertificateSerialNumberModuleName() {
    return System.getProperty("java.vendor").contains("IBM") ?
               "com.ibm.security.x509.CertificateSerialNumber" :
               "sun.security.x509.CertificateSerialNumber";
  }

  private static String getCertificateSubjectNameModuleName() {
    return System.getProperty("java.vendor").contains("IBM") ?
               "com.ibm.security.x509.CertificateSubjectName" :
               "sun.security.x509.CertificateSubjectName";
  }

  private static String getCertificateIssuerNameModuleName() {
    return System.getProperty("java.vendor").contains("IBM") ?
               "com.ibm.security.x509.CertificateIssuerName" :
               "sun.security.x509.CertificateIssuerName";
  }

  private static String getCertificateX509KeyModuleName() {
    return System.getProperty("java.vendor").contains("IBM") ?
               "com.ibm.security.x509.CertificateX509Key" :
               "sun.security.x509.CertificateX509Key";
  }

  private static String getCertificateVersionModuleName() {
    return System.getProperty("java.vendor").contains("IBM") ?
               "com.ibm.security.x509.CertificateVersion" :
               "sun.security.x509.CertificateVersion";
  }

  private static String getAlgorithmIdModuleName() {
    return System.getProperty("java.vendor").contains("IBM") ?
               "com.ibm.security.x509.AlgorithmId" :
               "sun.security.x509.AlgorithmId";
  }

  private static String getObjectIdentifierModuleName() {
    return System.getProperty("java.vendor").contains("IBM") ?
               "com.ibm.security.util.ObjectIdentifier" :
               "sun.security.util.ObjectIdentifier";
  }

  private static String getCertificateAlgorithmIdModuleName() {
    return System.getProperty("java.vendor").contains("IBM") ?
               "com.ibm.security.x509.CertificateAlgorithmId" :
               "sun.security.x509.CertificateAlgorithmId";
  }

  private static String getGeneralNameInterfaceModuleName() {
    return System.getProperty("java.vendor").contains("IBM") ?
               "com.ibm.security.x509.GeneralNameInterface" :// TODO
               "sun.security.x509.GeneralNameInterface";
  }

  private static String getGeneralNameModuleName() {
    return System.getProperty("java.vendor").contains("IBM") ?
               "com.ibm.security.x509.GeneralName" : // TODO
               "sun.security.x509.GeneralName";
  }

  private static String getGeneralNamesModuleName() {
    return System.getProperty("java.vendor").contains("IBM") ?
               "com.ibm.security.x509.GeneralNames" : // TODO
               "sun.security.x509.GeneralNames";
  }

  private static String getDNSNameModuleName() {
    return System.getProperty("java.vendor").contains("IBM") ?
               "com.ibm.security.x509.DNSName" : // TODO
               "sun.security.x509.DNSName";
  }

  private static String getSubjectAlternativeNameExtensionModuleName() {
    return System.getProperty("java.vendor").contains("IBM") ?
               "com.ibm.security.x509.SubjectAlternativeNameExtension" : // TODO
               "sun.security.x509.SubjectAlternativeNameExtension";
  }

  private static String getCertificateExtensionsModuleName() {
    return System.getProperty("java.vendor").contains("IBM") ?
               "com.ibm.security.x509.CertificateExtensions" : // TODO
               "sun.security.x509.CertificateExtensions";
  }

  private static String getX509CertImplModuleName() {
    return System.getProperty("java.vendor").contains("IBM") ?
               "com.ibm.security.x509.X509CertImpl" :
               "sun.security.x509.X509CertImpl";
  }

  private static String getSetField(Object obj, String setString)
      throws Exception {
    Field privateStringField = obj.getClass().getDeclaredField(setString);
    privateStringField.setAccessible(true);
    return (String) privateStringField.get(obj);
  }

  public static void writeCertificateToFile(Certificate cert, final File file)
      throws CertificateEncodingException, IOException {
    byte[] bytes = cert.getEncoded();
    Base64 encoder = new Base64( 76, "\n".getBytes( StandardCharsets.US_ASCII ) );
    try(OutputStream out = Files.newOutputStream(file.toPath()) ) {
      out.write( "-----BEGIN CERTIFICATE-----\n".getBytes( StandardCharsets.US_ASCII ) );
      out.write( encoder.encodeToString( bytes ).getBytes( StandardCharsets.US_ASCII ) );
      out.write( "-----END CERTIFICATE-----\n".getBytes( StandardCharsets.US_ASCII ) );
    }
  }

  /*
   * Writes one certificate into the given keystore file protected by the default password
   */
  private static void writeCertificateToKeyStore(Certificate cert, final File file, String type)
      throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException {
    writeCertificateToKeyStore(cert, file, type, null);
  }

  /*
   * Writes one certificate into the given keystore file protected by the given password
   */
  private static void writeCertificateToKeyStore(Certificate cert, final File file, String type, String keystorePassword)
      throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException {
    writeCertificatesToKeyStore(new Certificate[] { cert }, file, type, keystorePassword);
  }

  /*
   * Writes an arbitrary number of certificates into the given keystore file protected by the given password
   */
  private static void writeCertificatesToKeyStore(Certificate[] certs, final File file, String type, String keystorePassword)
      throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException {
    if (certs != null) {
      KeyStore ks = KeyStore.getInstance(type);

      char[] password = keystorePassword == null ? "changeit".toCharArray() : keystorePassword.toCharArray();
      ks.load(null, password);
      int counter = 0;
      for (Certificate cert : certs) {
        ks.setCertificateEntry("gateway-identity" + (++counter), cert); //it really does not matter what we set as alias for the certificate
      }
      /* Coverity Scan CID 1361992 */
      try (OutputStream fos = Files.newOutputStream(file.toPath())) {
        ks.store(fos, password);
      }
    }
  }

  public static void writeCertificateToJks(Certificate cert, final File file)
      throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException {
    writeCertificateToKeyStore(cert, file, "jks");
  }

  public static void writeCertificateToJks(Certificate cert, final File file, String keystorePassword)
      throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException {
    writeCertificateToKeyStore(cert, file, "jks", keystorePassword);
  }

  public static void writeCertificatesToJks(Certificate[] certs, final File file, String keystorePassword)
      throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException {
    writeCertificatesToKeyStore(certs, file, "jks", keystorePassword);
  }

  public static void writeCertificateToJceks(Certificate cert, final File file)
      throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException {
    writeCertificateToKeyStore(cert, file, "jceks");
  }

  public static void writeCertificateToPkcs12(Certificate cert, final File file)
      throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException {
    writeCertificateToKeyStore(cert, file, "pkcs12");
  }

  /**
   * Tests the X509 certificate to see if it was self-signed.
   * <p>
   * The certificate is determined to be self-signed if the subject DN is the same as the issuer DN
   *
   * @param certificate the {@link X509Certificate} to test
   * @return <code>true</code> if the X509 certficate is self-signed; otherwise <code>false</code>
   */
  public static boolean isSelfSignedCertificate(Certificate certificate) {
    if (certificate instanceof X509Certificate) {
      X509Certificate x509Certificate = (X509Certificate) certificate;
      return x509Certificate.getSubjectDN().equals(x509Certificate.getIssuerDN());
    } else {
      return false;
    }
  }
}
