import kz.gamma.asn1.ASN1InputStream;
import kz.gamma.asn1.DEROctetString;
import kz.gamma.asn1.DERSequence;
import kz.gamma.asn1.DERTaggedObject;
import kz.gamma.core.UtilCM;
import kz.gamma.jce.provider.GammaTechProvider;
import kz.gamma.tumarcsp.params.StoreObjectParam;
import kz.gamma.asn1.cms.RevokeRequest;
import java.io.*;
import java.net.Socket;
import java.security.*;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.*;

/**
 * Отзыв сертификата из профайла
 * Date: 06.11.2009
 * Time: 18:29:43
 */
public class RevokeFromProfile {
    public static void main(String[] args) {
        try{
            // Данный метод добавляет JCE в окружение java.security.
            Security.addProvider(new GammaTechProvider());

            //Формируем класс хранилища ключей из профайла. Ключ для отзыва должен быть либо самого пользователя, либо RA.
            KeyStore store = loadKeyStore("profile://RA", "test");
            Enumeration en = store.aliases();
            // В данном примере отзываемый сертификат будет самый последний
            String snold = "";
            //Выбираем последний в списке ключ
            while(en.hasMoreElements()){
                StoreObjectParam prm = (StoreObjectParam) en.nextElement();
                snold = prm.getSn();
            }
            //Получаем закрытый ключ из профайла
            PrivateKey privKey = (PrivateKey) store.getKey(snold, "test".toCharArray());
            X509Certificate ccer = (X509Certificate) store.getCertificate(snold);

            X509Certificate revCert = loadCertFromFile("revokeCert.cer");

            //Формируем запрос на отзыв, ccer - отзываемый сертификат
            RevokeRequest rev = new RevokeRequest(revCert, 3);
            //Подписываем запрос на отзыв
            byte []sreqv = rev.getSignedRequest(privKey, ccer);

            //Отправка запроса на сервер по протоколу HTTP
            byte[] resp = sendTCP(sreqv, "127.0.0.1", 62305);
            System.out.println("revoke return: " + checkRevResp(resp));
        }
        catch (Exception exp){
            exp.printStackTrace();
        }
    }
    public static KeyStore loadKeyStore(String profileName, String pass) throws NoSuchProviderException, KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
        KeyStore store = KeyStore.getInstance("GKS", "GAMMA");
        store.load(new ByteArrayInputStream(profileName.getBytes()), pass.toCharArray());
        return store;
    }

    public static byte[] sendTCP(byte []req, String ip , int port){
        byte[] ret = null;
        try {
            Socket s = new Socket(ip, port);
            s.getOutputStream().write(req);
            byte buf[] = new byte[8 * 1024];
            int r = s.getInputStream().read(buf);
            ret = UtilCM.copyByte(buf, 0, r);
        }catch (Exception ex){
            ex.printStackTrace();
        }
        return ret;
    }

    public static String checkRevResp(byte[] resp) throws IOException {
        ASN1InputStream in = new ASN1InputStream(resp);
        DERSequence reqTBS = (DERSequence) in.readObject();
        DERTaggedObject tag1 = (DERTaggedObject) reqTBS.getObjectAt(1);
        DERSequence revResp = (DERSequence) tag1.getObjectParser(0, true);
        DERSequence revSt = (DERSequence) revResp.getObjectAt(2);
        DERTaggedObject tag2 = (DERTaggedObject) revSt.getObjectAt(1);
        DEROctetString octet = (DEROctetString) tag2.getObjectParser(0, true);
        return new String(octet.getOctets(), "UTF-8");
    }

    // Метод загружает сертификат из файла
    public static X509Certificate loadCertFromFile(String fileName){
        X509Certificate cert = null;
        byte[] buf = null;
        try{
            FileInputStream f = new FileInputStream(fileName);
            buf = new byte[f.available()];
            f.read(buf, 0, f.available());
            f.close();
            // Указываем классу CertificateFactory что необходимо использовать JCE GAMMA.
            CertificateFactory cf = CertificateFactory.getInstance("X.509", "GAMMA");
            cert = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(buf));
        }
        catch(Exception ex){
            ex.printStackTrace();
        }
        return cert;
    }

}

