import kz.gamma.asn1.ASN1EncodableVector;
import kz.gamma.cms.CMSGammaEnvelopedData;
import kz.gamma.core.UtilCM;
import kz.gamma.jce.provider.GammaTechProvider;
import kz.gamma.tumarcsp.LibraryWrapper;
import kz.gamma.tumarcsp.TumarCspFunctions;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.security.Security;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

public class pkcs7_decrypt1 {
    public static void main(String[] args) {
        Security.addProvider(new GammaTechProvider());
        try {
            String profile = createProfile("/testCert/db1/db1_client2.bin", "");

            byte[] source = UtilCM.loadFile("/test/cmsJava.bin");
            byte[] bt = dencryptText(source, profile);
            System.out.println("DECRYPTED \"/test/cmsJava.bin\":" + new String(bt));


            source = UtilCM.loadFile("/test/dotnet.bin");
            bt = dencryptText(source, profile);
            System.out.println("DECRYPTED \"/test/dotnet.bin\":" + new String(bt));
        } catch (Exception ex) {
            ex.printStackTrace();
            System.exit(1);
        }

    }

    /**
     * @param keyFile - путь и имя файла контейнера с расширением
     * @param pass    - пароль к к файлу контейнеру
     * @return - Полное наименование профиля
     */
    public static String createProfile(String keyFile, String pass) throws IOException {
        if (keyFile == null || keyFile.isEmpty() || keyFile.length() < 5) {
            System.out.println("Name file key is wrong");
            return null;
        }
        if (keyFile.toLowerCase().startsWith("-p")) {
            String profile = keyFile.substring(2);
            return removeQuote(profile);
        }
        File file = new File(keyFile);
        String path = file.getParent();
        if (path == null) path = "." + File.separator;
        String fileName = file.getName();
        String keyName = fileName.substring(0, fileName.length() - 4);
        String ext = fileName.substring(fileName.length() - 3);
        return createProfile(keyName, path, pass, ext);
    }

    /**
     * @param keyName - имя файла контейнера
     * @param path    - путь к файлу контейнеру
     * @param pass    - пароль к к файлу контейнеру
     * @param ext     - расширение файла контейнера (p12,bin)
     * @return - Полное наименование профиля
     */
    public static String createProfile(String keyName, String path, String pass, String ext) {
        String profile = "";
        Number hProvLocal = null;
        try {
            hProvLocal = TumarCspFunctions.cpAcquireContext("", LibraryWrapper.CRYPT_VERIFYCONTEXT);
            profile = TumarCspFunctions.cpCreateUrl(keyName, "file", keyName, pass, path, ext, 0xA045, 0xAA3A, hProvLocal);
            return profile;
        } finally {
            if (hProvLocal != null && hProvLocal.longValue() != 0)
                TumarCspFunctions.cpReleaseContext(hProvLocal, 0);
        }
    }

    static String removeQuote(String str) {
        if (str.isEmpty())
            return str;
        String result = str;
        if (result.startsWith("\"")) {
            result = result.substring(1);
        }
        if (result.endsWith("\""))
            result = result.substring(0, result.length() - 1);
        return result;
    }

    static X509Certificate loadCert(String filename) {
        File file = new File(filename);
        FileInputStream fi = null;
        try {
            fi = new FileInputStream(file);
            CertificateFactory cf = CertificateFactory.getInstance("X.509", "GAMMA");

            return (X509Certificate) cf.generateCertificate(fi);

        } catch (Exception ex1) {
            ex1.printStackTrace();
        } finally {
            try {
                if (fi != null)
                    fi.close();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }

        return null;
    }

    public static byte[] dencryptText(byte[] cms, String profile) throws Exception {
        // Формируем класс чтения Enveloped cms
        CMSGammaEnvelopedData cmsEn = new CMSGammaEnvelopedData(cms);

        // Загружаем хранилище ключей и сертификатов (собственного закрытого ключа)
        // Можно использовать любые типы хранилища ключей.
        KeyStore store = KeyStore.getInstance("GKS", "GAMMA");
        store.load(new ByteArrayInputStream(profile.getBytes()), "".toCharArray());
        //Получение сертификата отправителя
        X509Certificate certSend = cmsEn.getSenderCert();
        //Получение аттрибутов сообщения
        ASN1EncodableVector unattr = cmsEn.getUnAttr();
        // Расшифровать сообщение
        return cmsEn.decryptText(store, "");
    }

}
