import java.io.*;
import java.nio.file.*;
import java.util.*;
import java.security.*;
import java.security.cert.*;
import javax.security.auth.x500.*;

public class X509Cert {

  public static void main(String[] args) {

    try {
      KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
      kpg.initialize(1024); // keysize bit
      KeyPair kp = kpg.generateKeyPair();
      PublicKey publicKey = kp.getPublic();
      PrivateKey privateKey = kp.getPrivate();

      Asn1Object pub = new Asn1Object(publicKey.getEncoded());

      GregorianCalendar calendar = new GregorianCalendar();

      //calendar.add(Calendar.DAY_OF_MONTH, -1);
      Date BeginDate = calendar.getTime();
      calendar.add(Calendar.YEAR, 1);
      Date EndDate = calendar.getTime();

      Asn1Object Issuer =  new Asn1Object(new X500Principal("CN=Issuer").getEncoded());
      Asn1Object Subject =  new Asn1Object(new X500Principal("CN=Subject").getEncoded());

      Asn1Object tsb =
        new Asn1Object(Asn1Object.CONSTRUCTED, Asn1Object.SEQUENCE).addAll(
          new Asn1Object(Asn1Object.CONTEXT | Asn1Object.CONSTRUCTED, 0).addAll(
            new Asn1Object(Asn1Object.UNIVERSAL, Asn1Object.INTEGER, Integer.valueOf(2))
          ),
          new Asn1Object(Asn1Object.UNIVERSAL, Asn1Object.INTEGER, Integer.valueOf(1)),
          new Asn1Object(Asn1Object.CONSTRUCTED, Asn1Object.SEQUENCE).addAll(
            new Asn1Object(Asn1Object.UNIVERSAL, Asn1Object.OBJECT_IDENTIFIER, "1.2.840.113549.1.1.5"),
            new Asn1Object(Asn1Object.UNIVERSAL, Asn1Object.NULL)
          ),
          Issuer,
          new Asn1Object(Asn1Object.CONSTRUCTED, Asn1Object.SEQUENCE).addAll(
            new Asn1Object(Asn1Object.UNIVERSAL, Asn1Object.UTC_TIME, BeginDate),
            new Asn1Object(Asn1Object.UNIVERSAL, Asn1Object.UTC_TIME, EndDate)
          ),
          Subject,
          pub
        );

      Signature instance = Signature.getInstance("SHA1withRSA");
      instance.initSign(privateKey);
      instance.update(tsb.getBytes());
      byte[] sha1rsa = instance.sign();

      Asn1Object root =
        new Asn1Object(Asn1Object.CONSTRUCTED, Asn1Object.SEQUENCE).addAll(
          tsb,
          new Asn1Object(Asn1Object.CONSTRUCTED, Asn1Object.SEQUENCE).addAll(
            new Asn1Object(Asn1Object.UNIVERSAL, Asn1Object.OBJECT_IDENTIFIER, "1.2.840.113549.1.1.5"),
            new Asn1Object(Asn1Object.UNIVERSAL, Asn1Object.NULL)
          ),
          new Asn1Object(Asn1Object.UNIVERSAL, Asn1Object.BIT_STRING, new Object[] { Integer.valueOf(0), sha1rsa })
        );

      root.print();

      byte[] bytes = root.getBytes();
      ByteArrayInputStream in = new ByteArrayInputStream(bytes);

      CertificateFactory cf = CertificateFactory.getInstance("X.509");
      X509Certificate cert = (X509Certificate)cf.generateCertificate(in);
      //in.close();

      cert.verify(cert.getPublicKey());
      System.out.println("Done!");

      Files.write(Paths.get("certificate.cer"), Base64.getMimeEncoder().encode(bytes));

      Files.write(Paths.get("private.key"), Base64.getMimeEncoder().encode(privateKey.getEncoded()));

      Asn1Object pkcs7 =
        new Asn1Object(Asn1Object.CONSTRUCTED, Asn1Object.SEQUENCE).addAll(
          new Asn1Object(Asn1Object.UNIVERSAL, Asn1Object.OBJECT_IDENTIFIER, "1.2.840.113549.1.7.2"),
          new Asn1Object(Asn1Object.CONTEXT | Asn1Object.CONSTRUCTED, 0).addAll(
            new Asn1Object(Asn1Object.CONSTRUCTED, Asn1Object.SEQUENCE).addAll(
              new Asn1Object(Asn1Object.UNIVERSAL, Asn1Object.INTEGER, Integer.valueOf(1)),
              new Asn1Object(Asn1Object.CONSTRUCTED, Asn1Object.SET),
              new Asn1Object(Asn1Object.CONSTRUCTED, Asn1Object.SEQUENCE).addAll(
                new Asn1Object(Asn1Object.UNIVERSAL, Asn1Object.OBJECT_IDENTIFIER, "1.2.840.113549.1.7.1")
              ),
              new Asn1Object(Asn1Object.CONTEXT | Asn1Object.CONSTRUCTED, 0).addAll(
                root
              ),
              new Asn1Object(Asn1Object.CONSTRUCTED, Asn1Object.SET)
            )
          )
        );

      Files.write(Paths.get("certificate.p7b"), Base64.getMimeEncoder().encode(pkcs7.getBytes()));

      KeyStore keyStore = KeyStore.getInstance("PKCS12");
      keyStore.load(null, null);
     
      keyStore.setKeyEntry("private", privateKey, "password".toCharArray(), new X509Certificate[] { cert });

      try (OutputStream os = Base64.getMimeEncoder().wrap(new FileOutputStream("keystore.p12"))) {
        keyStore.store(os, "password".toCharArray());
      }

    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}