package kz.kcsd.platform.service.secure.ws.tumar;

import kz.gamma.asn1.DERSet;
import kz.gamma.asn1.pkcs.PKCSObjectIdentifiers;
import kz.gamma.asn1.x509.Attribute;
import kz.gamma.asn1.x509.X509Extensions;
import kz.gamma.asn1.x509.X509Name;
import kz.gamma.certex.cms.web.services.Utils;
import kz.gamma.jce.PKCS10CertificationRequest;
import kz.gamma.jce.provider.GammaTechProvider;
import kz.gamma.jce.provider.JCEECPrivateKey;
import kz.gamma.jce.provider.JCEECPublicKey;
import kz.gamma.tumarcsp.LibraryWrapper;
import kz.gamma.tumarcsp.TumarCspFunctions;
import kz.gamma.util.encoders.Base64;

import java.io.IOException;
import java.security.*;
import java.util.Hashtable;
import java.util.Vector;

public class genKeyAndPkcs10 {

    private static final String KZWITHGOST3410_2015_512 = "KZWITHGOST3410-2015-512";

    public static void main(String[] args) throws Exception {
        try {
            Security.addProvider(new GammaTechProvider());

            PKCS10CertificationRequest req;
            String profile = "profile://FSystem";
            KeyInfo keyInfo = generateGOSTKeyPair2015(profile);
            req = makeGOSTpkcs10Request2015(profile, "C=KZ;O=KISC;CN=Barmaley", keyInfo, "C=KZ, O=Template, CN=GOST_USER_SIGN_1Y");
            System.out.println("GOST2015 PKCS10 Request: " + new String(Base64.encode(req.getEncoded())));
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }

    public static KeyInfo generateGOSTKeyPair2015(String profile)
            throws Exception {
        String key_alg = "2A4C";
        return genKey(profile, (int) Long.parseLong(key_alg, 16));
    }

    public static KeyInfo genKey(String profile, int keyAlg) throws Exception {
        Number hProvLocal = TumarCspFunctions.cpAcquireContext("", LibraryWrapper.CRYPT_VERIFYCONTEXT, LibraryWrapper.PV_TABLE);
        int res2 = TumarCspFunctions.cpReleaseContext(hProvLocal, 0);

        Number hProv = TumarCspFunctions.cpAcquireContext(profile, LibraryWrapper.CRYPT_NEWKEYSET, 0);
        Number hKey = TumarCspFunctions.cpGenKey(hProv, keyAlg, LibraryWrapper.CRYPT_NEWKEYSET);
        System.out.println("Generate key - success");

        //for PKCS10:
        TumarCspFunctions.cpSetKeyParam(hProv, hKey, LibraryWrapper.KP_USER_KEY, null, 0);
        byte[] publicKey = TumarCspFunctions.cpExportKeyData(hProv, hKey, 0, LibraryWrapper.PUBLICKEYBLOB, 0);
        System.out.println("Export public key - success");
        return new KeyInfo(hProv, hKey, publicKey);
    }

    public static PKCS10CertificationRequest makeGOSTpkcs10Request2015(String profile, String dnName, KeyInfo keyInfo, String template)
            throws NoSuchAlgorithmException, NoSuchProviderException,
            InvalidKeyException, SignatureException, IOException {
        Attribute attribute = getAttribute();
        String public_key_oid = "1.2.398.3.10.1.1.2.2";
        JCEECPublicKey pubKey = new JCEECPublicKey(keyInfo.publicKey, public_key_oid);
        PrivateKey privKey = new JCEECPrivateKey(profile, keyInfo.hProv, keyInfo.hKey);
        return new PKCS10CertificationRequest(KZWITHGOST3410_2015_512, new X509Name(dnName), pubKey, MSTemplate.getASN1Template(template, attribute), privKey);
    }

    public static class KeyInfo {
        public KeyInfo(Number hProv, Number hKey, byte[] publicKey) {
            this.hProv = hProv;
            this.hKey = hKey;
            this.publicKey = publicKey;
        }

        public Number hProv;
        public Number hKey;
        public byte[] publicKey;
    }

    public static Attribute getAttribute() {
        Vector<Object> ordering = new Vector<>();
        Hashtable<Object, Object> extensions = new Hashtable<>();
        X509Extensions x509extensions = new X509Extensions(ordering, extensions);
        return new Attribute(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest, new DERSet(x509extensions));
    }
}

