// проверка подписи
// программа консольная
// параметры запуска: файл CMS в Base64 + Hash подписи в Base64 + файл с бинарным сертификатом
// пример запуска: D:\sign.txt epq6+/GF3ktvZqWElQUmVNs9iHjXMcOWbNhWAh3rvhs= D:\UserCert.cer

import kz.gamma.cms.Pkcs7Data;
import kz.gamma.core.UtilCM;
import kz.gamma.jce.provider.GammaTechProvider;
import kz.gamma.util.encoders.Base64;

import javax.xml.bind.DatatypeConverter;
import java.io.File;
import java.io.FileInputStream;
import java.security.Security;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

public class testSign {
    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;
    }
    /**
     * Проверка cms
     *
     * @param cms        - cms для проверки (pkcs7)
     * @param data - данные, которые были подписаны в cms
     * @param isHash - если true , то вместо данных деолжен быть передан готовый hash
     * @param filename   - файл с бинарным сертификатом, может быть null
     * @return - true/false
     */

    public static boolean verifyPkcs7(byte[] cms, byte[] data, Boolean isHash,String filename) throws Exception {
        Pkcs7Data pkcs7Data = null;
        if(isHash)
            pkcs7Data = new Pkcs7Data(cms, data, isHash);
        else
            pkcs7Data = new Pkcs7Data(cms, data);
        //получаем серийный номер сертификата пользователя из cms
        String serialNumber = UtilCM.array2hex(pkcs7Data.getSignerInformation().getSID().getSerialNumber().toByteArray());
        //получаем сертификат пользователя из cms
        X509Certificate insideCert = pkcs7Data.getCertificateOfSigner();
        System.out.println(pkcs7Data.getSignerInformation().getDigestAlgOID());

        X509Certificate certificate = null;
        if(filename != null && !filename.isEmpty()) {
            //получаем сертификат из файла. Он используется , если в pkcs7 нет сертифката
            certificate = loadCert(filename);
            System.out.println("Cert outside "+certificate.getSubjectDN()+" , "+UtilCM.array2hex(certificate.getSerialNumber().toByteArray()));
        }
        System.out.println("Cert inside "+insideCert.getIssuerDN()+" , "+serialNumber);

        //проверяем cms
        //при проверке получаем хэш из подписи, формируем хэш на данные которые подписывали,
        //сравниваем полученные значения, проверяем подпись
        return  pkcs7Data.verify(certificate);
    }


    static byte[] getFile(String filename){
        File file = new File(filename);
        FileInputStream fi = null;
        try{
            fi = new FileInputStream(file);
            byte[] bt = new byte[fi.available()];
            fi.read(bt);
            return bt;
        }catch(Exception ex1){
            ex1.printStackTrace();
        } finally {
            try {
                if (fi != null)
                    fi.close();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
        return null;
    }
    public static void main(String[] args) {
        try {
            if (args.length != 3) {
                System.out.println("Usage:\n" +
                        "CMS в Base64 \t" + "Hash для подписи в Base64 \t" + "Filename - файл с бинарным сертификатом\t");
                return;
            }

            byte[] cms = Base64.decode(getFile(args[0]));
            byte[] dataToSign = Base64.decode(args[1]);
            String file = args[2];//имя файла

            Security.addProvider(new GammaTechProvider());
            System.out.println("CMS verification result: " + verifyPkcs7(cms, dataToSign, true, file));

        }catch(Exception ex){
            ex.printStackTrace();
        }
    }
}
