// пример для демонстрации работы по шифрованию данных (используются контейнеры с ключом на ключевой обмен алгоритма ГОСТ-2015kz

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

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.*;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

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

        String text = "<CipherData><CipherValue>Test method NATTEST7 11:48</CipherValue></CipherData>";
        byte[] bytes = text.getBytes();
        System.out.println("Data for encrypt (text): " + text);
        System.out.println("Data for encrypt (HEX): " + UtilCM.array2hex(bytes));

        String senderProfile = "Profile://db_client1";
        String recipientProfile = "Profile://db_client2";

        X509Certificate senderCert = getCert(senderProfile);
        X509Certificate recipientCert = getCert(recipientProfile);


        Number hProv = TumarCspFunctions.cpAcquireContext(senderProfile, LibraryWrapper.CRYPT_NEWKEYSETEX, 0);
        Number hKey = TumarCspFunctions.cpGetUserKey(hProv, LibraryWrapper.AT_KEYEXCHANGE);
        JCEECPrivateKey privKey = new JCEECPrivateKey(senderProfile, hProv, hKey);
        byte[] encrypted = encrypt(senderCert, privKey, recipientCert, bytes);
        TumarCspFunctions.cpReleaseContext(hProv, 0);
        System.out.println("Encrypted (HEX): " + UtilCM.array2hex(encrypted));

        byte[] decrypted = decrypt(encrypted);
        System.out.println("Decrypted (HEX): " + UtilCM.array2hex(decrypted));
        System.out.println("Decrypted text: " + new String(decrypted));
    }

    private static byte[] encrypt(X509Certificate senderCert, JCEECPrivateKey senderPrivateKey, X509Certificate recipientCert, byte[] dataBytes) throws Exception {
        CMSGammaEnvelopedData data = new CMSGammaEnvelopedData();
        //data.cryptText(dataBytes, senderPrivateKey); //DH
        data.cryptTextELGAM(dataBytes);
        data.addKeyRecipient(recipientCert);
        EnvelopedData env = data.generateEnvelopedData(senderCert);
        return env.getEncoded();
    }

    public static byte[] decrypt(byte[] cms) throws IOException, CMSException, NoSuchProviderException, NoSuchAlgorithmException, CertificateException, KeyStoreException {
        CMSGammaEnvelopedData cmsEn = new CMSGammaEnvelopedData(cms);
        KeyStore store = KeyStore.getInstance("PKS", "GAMMA");
        store.load(null, null);
        //X509Certificate certSend = cmsEn.getSenderCert();
        return cmsEn.dencryptText(store, "");
    }


    public static X509Certificate getCert(String profile) throws CertificateException, NoSuchProviderException {
        Number hProv = TumarCspFunctions.cpAcquireContext(profile, LibraryWrapper.CRYPT_NEWKEYSETEX, 0);
        Number hKey = TumarCspFunctions.cpGetUserKey(hProv, LibraryWrapper.AT_KEYEXCHANGE);
        byte[] cert = TumarCspFunctions.cpGetKeyParamData(hProv, hKey, LibraryWrapper.KP_CERTIFICATE, LibraryWrapper.ZERO);
        TumarCspFunctions.cpReleaseContext(hProv, 0);
        return getCertFromByteArray(cert);
    }

    public static X509Certificate getCertFromByteArray(byte[] cert) throws CertificateException, NoSuchProviderException {
        CertificateFactory cf = CertificateFactory.getInstance("X.509", GammaTechProvider.PROVIDER_NAME);
        X509Certificate x509TransportCertificate = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(cert));
        return x509TransportCertificate;
    }
}
