#include <stdio.h>
#include <time.h>
#include <sys/stat.h>
#ifdef _WIN32
  #include <windows.h>
  #define strlib "lib\\strlib.dll"
#else
  #define GetProcAddress dlsym
  #define FreeLibrary dlclose
  #include <string>
  #include  <unistd.h>
  #include  <dlfcn.h>
  #define strlib "lib/libstr.1.0.0.sl"
  #define _cdecl
  #define TRUE 1
  #define FALSE 0
#endif
#define CRYPT_VERIFYCONTEXT     0xF0000000
#ifndef _WIN32
  typedef unsigned long DWORD;
  typedef unsigned char BYTE;
  typedef void *HINSTANCE;
  typedef char CHAR;
#endif
typedef unsigned long hCERTSTORE;
typedef unsigned long hCERTCONTEXT;
typedef unsigned long hCERTCOLLECTION;
typedef unsigned long hCRYPTMSG;
typedef unsigned long HCRYPTPROV;
//Сертификаты пользователя и УЦ соответственно. В формате Base64:
#define CERTIFICATE  "MIICXzCCAgigAwIBAgIgO0T0MYRC19fT8rl+dj+yofSgDwNMDM9bGo+6XcY39HgwDgYKKwYBBAG1EQECAgUAMDMxEDAOBg\
                      NVBAMUB0FETUlOQ0ExEjAQBgNVBAoTCUdBTU1BVEVDSDELMAkGA1UEBhMCS1owIhgPMjAwODAxMzAwMDAwMDBaGA8yMDA5\
                      MDEzMDAwMDAwMFowNDERMA8GA1UEAxQIVEVTVDAwMTgxEjAQBgNVBAoTCUdBTU1BVEVDSDELMAkGA1UEBhMCS1owYzAOBg\
                        orBgEEAbURAQICBQADUQAGAgAAOqoAAABFQzEAAgAA2gkP2M0iQUqblqogXdjhzAuRsr1Vm6jWry6maOvqn0Z9z5vSUH8t\
                      EapuAcORYYANh7lp5CZIAkpXFgYndvnvEqOB2jCB1zBVBgNVHSMETjBMgCDNPCV7wKSpQboeIEmS2XRx+CDnV7BOcvQMli+\
                      FqmVWUqEGhwR/AAABgiDNPCV7wKSpQboeIEmS2XRx+CDnV7BOcvQMli+FqmVWUjApBgNVHQ4EIgQgO0T0MYRC19fT8rl+dj\
                      +yofSgDwNMDM9bGo+6XcY39HgwCwYDVR0PBAQDAgXgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMEB\
                      TADAgEAMBkGA1UdHwQSMBAwDqAIoAaHBH8AAAGBAgFmMA4GCisGAQQBtREBAgIFAANBAE6CdQj+0DmD539H0ptSvXlDOiHl\
                      OcFIDJt4E1ymqNNnQ+16NPZe1m5E5yvoakEpshAT2DnNDozk9ww0jNcW9RU="
#define CA            "MIICxTCCAm6gAwIBAgIgzTwle8CkqUG6HiBJktl0cfgg51ewTnL0DJYvhaplVlIwDgYKKwYBBAG1EQECAgUAMDMxEDAOBgN\
                      VBAMUB0FETUlOQ0ExEjAQBgNVBAoTCUdBTU1BVEVDSDELMAkGA1UEBhMCS1owIhgPMjAwODAxMDEwMTAxMDFaGA8yMDE4MD\
                      EwMTAxMDEwMVowMzEQMA4GA1UEAxQHQURNSU5DQTESMBAGA1UEChMJR0FNTUFURUNIMQswCQYDVQQGEwJLWjBjMA4GCisGA\
                      QQBtREBAgIFAANRAAYCAAA6qgAAAEVDMQACAADw2qYY1mq4OVlDu7PpgXZc8zZshw6tM0INZDijLHnLOkSe+SaJGDBqd4gb\
                      Oy2nGvRY3/fu4sLIJi8mUQVsPFjbo4IBQDCCATwwVQYDVR0jBE4wTIAgzTwle8CkqUG6HiBJktl0cfgg51ewTnL0DJYvhap\
                      lVlKhBocEfwAAAYIgzTwle8CkqUG6HiBJktl0cfgg51ewTnL0DJYvhaplVlIwKQYDVR0OBCIEIM08JXvApKlBuh4gSZLZdH\
                      H4IOdXsE5y9AyWL4WqZVZSMA4GA1UdDwEBAQQEAwIBBjASBgNVHRMBAQEECDAGAQEBAgECMIGTBgNVHSAEgYswgYgwgYUGC\
                      CsGAQQBtREDMHkwHwYIKwYBBQUHAgEWE2h0dHA6Ly93d3cuZ2FtbWEua3owVgYIKwYBBQUHAgIwSjAcFhXNyMsgw+Ds7OAg\
                      0uX17e7r7uPo/y4wAwIBARoqz/Do7OXwIO/u6+jy6OroIOjx7+7r/Ofu4uDt6P8g8eXw8uj06Org8uAuMA4GCisGAQQBtRE\
                      BAgIFAANBAPzmGiBKNMZtSDuuPLgGIqzR+pP9a8SWdn+Z6pzrLbGiY5MRymCwl8TZxjOkIvJZzsv7ggxHqkkCS44SuEDSUDI="
typedef int (_cdecl *cspopencontext)
							(HCRYPTPROV *phProv,
							CHAR *pszContainer,
							DWORD dwProvType,
							DWORD dwProvParam,
							DWORD dwFlags,
							BYTE * pbSignature,
							DWORD dwSigLen,
							BYTE * pbContainer,
							DWORD * dwContLen,
							HINSTANCE *phLib);
typedef int (_cdecl *crtopenstore)
							(DWORD StoreProvider,
							HCRYPTPROV hProv,
							unsigned long dwFlags,
							bool  bFlag,
							const void *pvParam,
							hCERTSTORE *phStore);
typedef int (_cdecl *crtclosestore)                     (hCERTSTORE *phStore);
typedef int (_cdecl *cspclosecontext)                   (HCRYPTPROV *phProv);
typedef char* (_cdecl *errorstring)                     (const int err);
typedef int (_cdecl *basetobin)
							(unsigned char *inBuf,
							long inSize,
							unsigned char *ouBuf,
							long *outSize);
typedef int (_cdecl *crptverifycertificatesignature)
							(const hCERTSTORE hStore,
							const unsigned char *certBody,
							const unsigned long certSize,
							const unsigned char *CABody,
							const unsigned long caSize);							

cspopencontext					CSPOpenContext;
crtopenstore					CrtOpenStore;
crtclosestore					CrtCloseStore;
cspclosecontext					CSPCloseContext;
errorstring						ErrorString;	
basetobin						BaseToBin;				
crptverifycertificatesignature	CrptVerifyCertificateSignature;  

HINSTANCE load_lib(char *lib)
{
   #ifdef _WIN32
	  return LoadLibraryA(lib);
   #else
	  return dlopen(lib,RTLD_LAZY);
   #endif
}
void lib_free( HINSTANCE Instance )
{
#ifdef _WIN32
  FreeLibrary(Instance);
#else
  dlclose(Instance);
#endif
}
int get_func(HINSTANCE lib)
{
   CSPOpenContext = (cspopencontext) GetProcAddress(lib,"CSPOpenContext");
   if(!CSPOpenContext)
   {
       printf("error load function - %s", "CSPOpenContext");
       return 1;
   }
   CrtOpenStore = (crtopenstore) GetProcAddress(lib,"CrtOpenStore");
   if(!CrtOpenStore)
   {
       printf("error load function - %s", "CrtOpenStore");
       return 1;
   }
   CSPCloseContext= (cspclosecontext) GetProcAddress(lib,"CSPCloseContext");
   if(!CSPCloseContext)
   {
       printf("error load function - %s", "CSPCloseContext");
       return 1;
   }
   CrtCloseStore= (crtclosestore) GetProcAddress(lib,"CrtCloseStore");
   if(!CrtCloseStore)
   {
       printf("error load function - %s", "CrtCloseStore");
       return 1;
   }
   ErrorString = (errorstring) GetProcAddress(lib,"ErrorString");
   if(!ErrorString)
   {
       printf("error load function - %s", "ErrorString");
       return 1;
   }   
   BaseToBin = (basetobin) GetProcAddress(lib,"BaseToBin");
   if(!BaseToBin)
   {
       printf("error load function - %s", "BaseToBin");
       return 1;
   }  
   CrptVerifyCertificateSignature = (crptverifycertificatesignature) GetProcAddress (lib, "CrptVerifyCertificateSignature");
   if (!CrptVerifyCertificateSignature)
   {
        printf ("error load function - %s", "CrptVerifyCertificateSignature");
        return 1;
   }
   return 0;
}
//---------------------------------------------------------------------------
 int main(int argc, char* argv[])
 {
   int ret  			= 0;
   HINSTANCE lib		=  NULL;
   int code 			= 0;
   hCERTSTORE hStore	= 0;
   HCRYPTPROV hP     	= 0;
   unsigned char *userCert = NULL, *CACert=NULL;
   long userSize=0, CASize=0;

   try
   {
     lib = load_lib(strlib);
     if( get_func(lib) )
     {
       printf("error load func.\n");
	   exit(1);
	 }    
     //Открыть контекст CSP
     code = CSPOpenContext(&hP,NULL, 25, 0, CRYPT_VERIFYCONTEXT, NULL, 0,NULL,NULL, NULL);
     if( code )
     {
       printf("%s [CSPOpenContext: error = %d]\n",ErrorString(code), code);
       throw code;
     }
     // Открыть конекст хранилища
     code = CrtOpenStore(0, hP, 0, false, NULL, &hStore);
     if( code )
     {
       printf("%s [CrtOpenStore: error = %d]\n",ErrorString(code), code);
       throw code;
     }
     // Конвертация сертификата пользователя 
     userCert = (unsigned char*) calloc (sizeof(CERTIFICATE),sizeof(unsigned char));
     code = BaseToBin ((unsigned char *) CERTIFICATE, sizeof(CERTIFICATE), userCert, &userSize);
     if (code)
     {
       printf("%s [BaseToBin: error = %d]\n", ErrorString(code), code);
       throw code;
     }
     // Конвертация сертификата центра сертификации
     CACert = (unsigned char*) calloc (sizeof(CA),sizeof(unsigned char));
     code = BaseToBin ((unsigned char *) CA, sizeof(CA), CACert, &CASize);
     if (code)
     {
       printf("%s [BaseToBin: error = %d]\n", ErrorString(code), code);
       throw code;
     }
     // Проверка ЭЦП сертификата пользователя
     code = CrptVerifyCertificateSignature(hStore,userCert, userSize,CACert,CASize);
     if (code)
     {
       printf("%s [CrptVerifyCertificateSignature: error = %d]\n", ErrorString(code), code);
       throw code;
     }
     printf("Signature is correct.\n");
   }
   catch(int er){ret=er;}
   if( userCert ) { free(userCert); userCert = NULL;}
   if( CACert   ) {free(CACert); CACert = NULL;}
   if( hStore   ) { CrtCloseStore(&hStore); hStore = 0;}
   if( hP       ) { CSPCloseContext(&hP); hP = 0;}
   if (lib) lib_free( lib );
   return ret;
 }
