package kz.gamma;

import kz.gamma.asn1.ASN1Set;
import kz.gamma.asn1.cms.MSTemplate;
import kz.gamma.asn1.x509.X509Name;
import kz.gamma.cms.CMSSignedData;
import kz.gamma.jce.PKCS10CertificationRequest;
import kz.gamma.jce.provider.GammaTechProvider;
import kz.gamma.jce.provider.JDKKeyPairGenerator;

import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.ldap.ExtendedResponse;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import java.io.ByteArrayInputStream;
import java.io.FileOutputStream;
import java.security.*;
import java.security.cert.CertStore;
import java.security.cert.X509CertSelector;
import java.security.cert.X509Certificate;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;

/**
 * Created by s_moiseyev
 * Date: 17.04.2009
 * Time: 10:49:17
 */
public class CreateRequest {

    /**
     * @param args
     */
    public static void main(String[] args) {
        LdapContext ctx = null;
        try {
            // Данный метод добавляет JCE в окружение java.security.
            Security.addProvider(new GammaTechProvider());
            // Инициализируем генератор. В качестве параметра передаем алгоритм генерации ключа
            // ECGOST34310 - ГОСТ группа, RSA - группа
            // KeyPairGenerator ecGostKpg = KeyPairGenerator.getInstance("ECGOST34310", "GAMMA");
            KeyPairGenerator ecGostKpg = KeyPairGenerator.getInstance("RSA", "GAMMA");

            // Инициализируем алгоритм генерации ключа, если передать 2 то будет сгенерирован
            // ключ в соответствии настроенного профайла.
            Hashtable<String, String> str = GammaTechProvider.algUtil.algKeyName;
            Enumeration en1 = str.keys();
            Enumeration en2 = str.elements();
            while (en1.hasMoreElements()) {
                System.out.println(en1.nextElement());
                if (en2.hasMoreElements())
                    System.out.println(en2.nextElement());
            }
            // if(GammaTechProvider.algUtil.algKey.containsKey("1.3.6.1.4.1.6801.1.5.2"))
            // ecGostKpg.initialize(GammaTechProvider.algUtil.algKey.get("1.3.6.1.4.1.6801.1.5.2"));
            if (GammaTechProvider.algUtil.algKey.containsKey("1.3.6.1.4.1.6801.1.5.20"))
                ecGostKpg.initialize(GammaTechProvider.algUtil.algKey.get("1.3.6.1.4.1.6801.1.5.20"));
            else
                ecGostKpg.initialize(2);

            // Инициализируем профайл. В случае генерации RSA ключа
            // необходимо использовать класс JDKKeyPairGenerator.RSA
            // ((JDKKeyPairGenerator.ECGOST34310)ecGostKpg).setProfName("profile://eToken", "1234567890");
            ((JDKKeyPairGenerator.RSA) ecGostKpg).setProfName("profile://eToken", "1234567890");

            // генерируем пару ключей
            KeyPair pair = ecGostKpg.generateKeyPair();
            // Получаем класс закрытого ключа
            PrivateKey privKey = pair.getPrivate();
            // Получаем класс открытого ключа
            PublicKey pubKey = pair.getPublic();

            // Формирование запроса на сертификат.
            // В случае если необходимо сформировать запрос на ключи RSA то необходимо вместо параметра
            // ECGOST34310 передать SHA1WITHRSA.
            String name = "C=KZ, O=Гамма, CN=Тестирование русского языка";
            ASN1Set set = MSTemplate.getASN1Template("CN=RA_GOST;O=Template;C=KZ;");
            // PKCS10CertificationRequest req = new PKCS10CertificationRequest(
            // "ECGOST34310", new X509Name(name), pubKey, set, privKey);
            PKCS10CertificationRequest req = new PKCS10CertificationRequest(
                    "SHA1WITHRSA", new X509Name(name), pubKey, set, privKey);
            FileOutputStream f0 = new FileOutputStream("c://pkcs10.bin");
            f0.write(req.getDEREncoded());
            f0.close();
            // Проверка запроса PKCS#10
            if (req.verify())
                System.out.println("verify check EC.");
            else
                System.out.println("Failed verify check EC.");

            // Отправка запроса на сервер по протоколу LDAP
            Hashtable<String, String> env = new Hashtable<String, String>();
            env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
            env.put(Context.PROVIDER_URL, "ldap://192.168.12.6:62222");
            // env.put(Context.PROVIDER_URL, "ldap://127.0.0.1:62222");
            env.put(Context.SECURITY_AUTHENTICATION, "SIMPLE");
            env.put(Context.SECURITY_PRINCIPAL, "");
            env.put(Context.SECURITY_CREDENTIALS, "");

            ctx = new InitialLdapContext(env, null);

            RegisterRequest request = new RegisterRequest(req.getDEREncoded(), "1.3.6.1.4.1.6801.11.1.10");
            ExtendedResponse response = ctx.extendedOperation(request);
            byte[] reqdata = response.getEncodedValue();
            CMSSignedData signedData = new CMSSignedData(reqdata);
            CertStore store1 = signedData.getCertificatesAndCRLs("Collection", "GAMMA");
            Collection crtColl = store1.getCertificates(new X509CertSelector());
            Iterator itcert = crtColl.iterator();
            if (itcert.hasNext()) {
                X509Certificate ccer = (X509Certificate) itcert.next();
                // Установка полученного сертификата в контейнер
                KeyStore store = KeyStore.getInstance("GKS", "GAMMA");
                String prof = "profile://eToken";
                store.load(new ByteArrayInputStream(prof.getBytes()), "1234567890".toCharArray());
                store.setCertificateEntry("", ccer);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (ctx != null) {
                try {
                    ctx.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}