Создаю службу которая использует шифрование.
Если вот так, то все работает нормально:
int main(void)
{
MSCrypt ms;
ms.SignMS();
return 0;
}
int MSCrypt::SignMS(void)
{
std::string pbEncodedBlobBase64;
std::string str;
str = "Security is our business."; //сообщение
SignMessage(str, "ayushchenko@rapida.ru", "533BC65000020000E4B0", "My",pbEncodedBlobBase64);
printf("SignMessage DONE \n\n");
printf("CLEAN MEMORY \n\n");
//CleanUP();
VerifyMessage(pbEncodedBlobBase64, "ayushchenko@rapida.ru", "533BC65000020000E4B0", "My");
printf("VerifyMessage DONE \n\n");
return 0;
}
void MSCrypt::SignMessage(std::string &psCont, char *CertMail, std::string CertSN, char *psStoreName, std::string &pbEncodedBlobBase64)
{
byte *pbEncodedBlob = NULL;
HCRYPTPROV hCryptProv = 0; /* Дескриптор провайдера*/
HCERTSTORE hStoreHandle=0; //Дeскриптор сторе
PCCERT_CONTEXT pRecipientCert = NULL; /* Сертификат, используемый для формирования ЭЦП*/
PCCERT_CONTEXT pRecipientCertArray[1];
DWORD keytype = AT_KEYEXCHANGE; /* Тип ключа (возвращается)*/
HCRYPTMSG hMsg = 0; /* Дескриптор сообщения*/
CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm; /* Идентификатор алгоритма хэширования*/
DWORD HashAlgSize;
CMSG_SIGNER_ENCODE_INFO SignerEncodeInfo; /* Структура, описывающая отправителя*/
CMSG_SIGNER_ENCODE_INFO SignerEncodeInfoArray[1]; /* Массив структур, описывающих отправителя*/
CERT_BLOB SignerCertBlob;
CERT_BLOB SignerCertBlobArray[1];
CMSG_SIGNED_ENCODE_INFO SignedMsgEncodeInfo; /* Структура, описывающая подписанное сообщение*/
BOOL bReleaseContext;
DWORD flags = 0;
DWORD cbContent = (DWORD)(psCont.size());//длина сообщения
DWORD cbEncodedBlob;
byte *pbContent = (byte*)psCont.c_str();
//--------------------------------------------------------------------
// Начало обработки данных.
//printf("About to begin with the message %s.\n",pbContent);
//printf("The message length is %d bytes. \n", cbContent);
//--------------------------------------------------------------------
// Открытие системного хранилища сертификатов.
hStoreHandle = CertOpenSystemStore( 0, (LPCSTR)psStoreName);
if(hStoreHandle)
{
printf("The MY store is open. \n");
}
else
{
HandleError( "Error getting store handle.");
}
//--------------------------------------------------функции GetRecipientCert.
pRecipientCert = GetRecipientCert(
hStoreHandle, CertMail, CertSN);
if(pRecipientCert)
{
printf("A recipient's certificate has been acquired. \n");
}
else
{
printf("No certificate with a CERT_KEY_CONTEXT_PROP_ID \n");
printf("property and an AT_KEYEXCHANGE private key available. \n");
printf("While the message could be sign, in this case, \n");
printf("it could not be veryfy in this program. \n");
printf("For more information, see the documentation \n");
HandleError( "No Certificate with AT_KEYEXCHANGE key in store.");
}
//--------------------------------------------------------------------
// Получение закрытого ключа
if (!CryptAcquireCertificatePrivateKey(pRecipientCert,
0,
NULL,
&hCryptProv,
&keytype,
&bReleaseContext))
{
HandleError( "Cannot acquire the certificate private key");
}
//--------------------------------------------------------------------
// Создание RecipientCertArray.
pRecipientCertArray[0] = pRecipientCert;
//--------------------------------------------------------------------
// Инициализация структуры идентификатора алгоритма.
HashAlgSize = sizeof(HashAlgorithm);
//--------------------------------------------------------------------
// Инициализация структуры с нулем.
memset(&HashAlgorithm, 0, HashAlgSize);
//--------------------------------------------------------------------
// Установка необходимого элемента.
//HashAlgorithm.pszObjId = szOID_CP_GOST_R3411;
printf(":%s; :%d; :%s; :%d;",pRecipientCert->pCertInfo->SignatureAlgorithm.pszObjId, pRecipientCert->pCertInfo->SignatureAlgorithm.pszObjId, szOID_CP_GOST_R3411_R3410EL,szOID_CP_GOST_R3411_R3410EL);
HashAlgorithm.pszObjId = pRecipientCert->pCertInfo->SignatureAlgorithm.pszObjId;
//HashAlgorithm.pszObjId = szOID_CP_GOST_R3411;
//szOID_RSA_SHA1RSA;
/*--------------------------------------------------------------------*/
/* Инициализируем структуру CMSG_SIGNER_ENCODE_INFO*/
memset(&SignerEncodeInfo, 0, sizeof(CMSG_SIGNER_ENCODE_INFO));
SignerEncodeInfo.cbSize = sizeof(CMSG_SIGNER_ENCODE_INFO);
SignerEncodeInfo.pCertInfo = pRecipientCert->pCertInfo;
SignerEncodeInfo.hCryptProv = hCryptProv;
SignerEncodeInfo.dwKeySpec = keytype;
// SignerEncodeInfo.dwKeySpec = AT_KEYEXCHANGE;
SignerEncodeInfo.HashAlgorithm = HashAlgorithm;
SignerEncodeInfo.pvHashAuxInfo = NULL;
/*--------------------------------------------------------------------*/
/* Создадим массив отправителей. Сейчас только из одного.*/
SignerEncodeInfoArray[0] = SignerEncodeInfo;
/*--------------------------------------------------------------------*/
/* Инициализируем структуру CMSG_SIGNED_ENCODE_INFO*/
SignerCertBlob.cbData = pRecipientCert->cbCertEncoded;
SignerCertBlob.pbData = pRecipientCert->pbCertEncoded;
/*--------------------------------------------------------------------*/
/* Инициализируем структуру массив структур CertBlob.*/
SignerCertBlobArray[0] = SignerCertBlob;
memset(&SignedMsgEncodeInfo, 0, sizeof(CMSG_SIGNED_ENCODE_INFO));
SignedMsgEncodeInfo.cbSize = sizeof(CMSG_SIGNED_ENCODE_INFO);
SignedMsgEncodeInfo.cSigners = 1;
SignedMsgEncodeInfo.rgSigners = SignerEncodeInfoArray;
SignedMsgEncodeInfo.cCertEncoded = 0;
SignedMsgEncodeInfo.rgCertEncoded = NULL;
SignedMsgEncodeInfo.rgCrlEncoded = NULL;
/*--------------------------------------------------------------------*/
/* Определим длину подписанного сообщения*/
cbEncodedBlob = CryptMsgCalculateEncodedLength(
TYPE_DER, /* Message encoding type*/
flags, /* Flags*/
CMSG_SIGNED, /* Message type*/
&SignedMsgEncodeInfo, /* Pointer to structure*/
NULL, /* Inner content object ID*/
(DWORD)cbContent); /* Size of content*/
if(cbEncodedBlob)
{
printf("The length of the data has been calculated. \n");
} else
{
HashAlgorithm.pszObjId = szOID_RSA_SHA1RSA;
SignerEncodeInfo.HashAlgorithm = HashAlgorithm;
SignerEncodeInfoArray[0] = SignerEncodeInfo;
SignedMsgEncodeInfo.rgSigners = SignerEncodeInfoArray;
cbEncodedBlob = CryptMsgCalculateEncodedLength(
TYPE_DER, /* Message encoding type*/
flags, /* Flags*/
CMSG_SIGNED, /* Message type*/
&SignedMsgEncodeInfo, /* Pointer to structure*/
NULL, /* Inner content object ID*/
(DWORD)cbContent); /* Size of content*/
if(cbEncodedBlob)
{
printf("The length of the data has been calculated. \n");
} else
HandleError("Getting cbEncodedBlob length failed.");
}
/*--------------------------------------------------------------------*/
/* Резервируем память, требуемой длины*/
pbEncodedBlob = (BYTE *) malloc(cbEncodedBlob);
if (!pbEncodedBlob)
HandleError("Memory allocation failed");
/*--------------------------------------------------------------------*/
/* Создадим дескриптор сообщения*/
hMsg = CryptMsgOpenToEncode(
TYPE_DER, /* Encoding type*/
flags, /* Flags (CMSG_DETACHED_FLAG )*/
CMSG_SIGNED, /* Message type*/
&SignedMsgEncodeInfo, /* Pointer to structure*/
NULL, /* Inner content object ID*/
NULL); /* Stream information (not used)*/
if(hMsg) {
printf("The message to be encoded has been opened. \n");
} else {
HandleError("OpenToEncode failed");
}
/*--------------------------------------------------------------------*/
/* Поместим в сообщение подписываемые данные*/
if(CryptMsgUpdate(
hMsg, /* Handle to the message*/
pbContent, /* Pointer to the content*/
cbContent, /* Size of the content*/
TRUE)) { /* Last call*/
printf("Content has been added to the encoded message. \n");
} else {
HandleError("MsgUpdate failed");
}
/*--------------------------------------------------------------------*/
/* Вернем подписанное сообщение*/
if(CryptMsgGetParam(
hMsg, /* Handle to the message*/
CMSG_CONTENT_PARAM, /* Parameter type*/
0, /* Index*/
pbEncodedBlob, /* Pointer to the blob*/
&cbEncodedBlob)) { /* Size of the blob*/
printf("Message encoded successfully. \n");
} else {
HandleError("MsgGetParam failed");
}
//освобождение памяти
if(hMsg)
CryptMsgClose(hMsg);
if(hCryptProv && bReleaseContext)
CryptReleaseContext(hCryptProv,0);
pbEncodedBlobBase64.append((char*)pbEncodedBlob, cbEncodedBlob);
pbEncodedBlobBase64 = aria2::Base64::encode(pbEncodedBlobBase64);
//printf("pbEncodedBlob in bas64 is %s \n", pbEncodedBlobBase64.data());
//printf("cbEncodedBlob 1= %d \n", cbEncodedBlob);
}//end of SignMessage
А если переделывают функцию main как службу windows
void WINAPI ServiceMain(int argc, char** argv);
void WINAPI ControlHandler(DWORD request);
int InstallService();
int RemoveService();
int MSStartService();
bool InitService();
bool addLogMessage(std::string log);
SERVICE_STATUS serviceStatus;
SERVICE_STATUS_HANDLE hStatus;
SERVICE_STATUS_HANDLE serviceStatusHandle;
LPTSTR serviceName = TEXT("CryptoGW");
LPTSTR servicePath = TEXT("c:\\CryptoMS.exe");
void __cdecl _tmain(int argc, _TCHAR* argv[])
{
//servicePath = LPTSTR(argv[0]);
if(argc - 1 == 0)
{
SERVICE_TABLE_ENTRY ServiceTable[1];
ServiceTable[0].lpServiceName = serviceName;
ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
if(!StartServiceCtrlDispatcher(ServiceTable))
{
addLogMessage("Error: StartServiceCtrlDispatcher");
}
} else if( strcmp(argv[argc-1], _T("install")) == 0) {
InstallService();
} else if( strcmp(argv[argc-1], _T("remove")) == 0) {
RemoveService();
} else if( strcmp(argv[argc-1], _T("start")) == 0 ){
MSStartService();
}
}
void WINAPI ServiceMain(int argc, char** argv) {
int error;
unsigned int i = 0;
serviceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
serviceStatus.dwCurrentState = SERVICE_START_PENDING;
serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
serviceStatus.dwWin32ExitCode = 0;
serviceStatus.dwServiceSpecificExitCode = 0;
serviceStatus.dwCheckPoint = 0;
serviceStatus.dwWaitHint = 0;
serviceStatusHandle = RegisterServiceCtrlHandler(serviceName, (LPHANDLER_FUNCTION)ControlHandler);
if (serviceStatusHandle == (SERVICE_STATUS_HANDLE)0)
{
return;
}
error = InitService();
if (error) {
serviceStatus.dwCurrentState = SERVICE_STOPPED;
serviceStatus.dwWin32ExitCode = -1;
SetServiceStatus(serviceStatusHandle, &serviceStatus);
return;
}
serviceStatus.dwCurrentState = SERVICE_RUNNING;
SetServiceStatus (serviceStatusHandle, &serviceStatus);
while (serviceStatus.dwCurrentState == SERVICE_RUNNING)
{
char buffer[255];
//SMTP smtp("C:\\Server Log.txt", "C:\\MailRules.ini", "fs3.int.rapida.ru", "127.0.0.1", 25, 26); //beorc2.int.rapida.ru
//smtp.RunServer();
//SignMessage(str, "ayushchenko@rapida.ru", "533BC65000020000E4B0", "My",pbEncodedBlobBase64);
MSCrypt ms;
ms.SignMS();
//SMTP smtp("C:\\Server Log.txt", "C:\\MailRules.ini", "fs3.int.rapida.ru", "127.0.0.1", 25, 26); //beorc2.int.rapida.ru
//smtp.RunServer();
addLogMessage("a");
/*try
{
SMTP smtp("C:\\Server Log.txt", "C:\\MailRules.ini", "fs3.int.rapida.ru", "127.0.0.1", 25, 26); //beorc2.int.rapida.ru
smtp.RunServer();
addLogMessage("a");
}
catch(...)
{
sprintf_s(buffer, "Error in message number %u", i);
addLogMessage(buffer);
serviceStatus.dwCurrentState = SERVICE_STOPPED;
serviceStatus.dwWin32ExitCode = -1;
SetServiceStatus(serviceStatusHandle, &serviceStatus);
return;
}*/
sprintf_s(buffer, "Message number: %u is ok", i);
addLogMessage(buffer);
i++;
}
return;
}
bool InitService()
{
return false;
}
void WINAPI ControlHandler(DWORD request) {
switch(request)
{
case SERVICE_CONTROL_STOP:
addLogMessage("Stopped.");
serviceStatus.dwWin32ExitCode = 0;
serviceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus (serviceStatusHandle, &serviceStatus);
return;
case SERVICE_CONTROL_SHUTDOWN:
addLogMessage("Shutdown.");
serviceStatus.dwWin32ExitCode = 0;
serviceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus (serviceStatusHandle, &serviceStatus);
return;
default:
break;
}
SetServiceStatus (serviceStatusHandle, &serviceStatus);
return;
}
int InstallService() {
SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
if(!hSCManager) {
addLogMessage("Error: Can't open Service Control Manager");
return -1;
}
SC_HANDLE hService = CreateService(
hSCManager,
serviceName,
serviceName,
SERVICE_ALL_ACCESS,
SERVICE_WIN32_OWN_PROCESS,
SERVICE_DEMAND_START,
SERVICE_ERROR_NORMAL,
servicePath,
NULL, NULL, NULL, NULL, NULL
);
if(!hService) {
int err = GetLastError();
switch(err) {
case ERROR_ACCESS_DENIED:
addLogMessage("Error: ERROR_ACCESS_DENIED");
break;
case ERROR_CIRCULAR_DEPENDENCY:
addLogMessage("Error: ERROR_CIRCULAR_DEPENDENCY");
break;
case ERROR_DUPLICATE_SERVICE_NAME:
addLogMessage("Error: ERROR_DUPLICATE_SERVICE_NAME");
break;
case ERROR_INVALID_HANDLE:
addLogMessage("Error: ERROR_INVALID_HANDLE");
break;
case ERROR_INVALID_NAME:
addLogMessage("Error: ERROR_INVALID_NAME");
break;
case ERROR_INVALID_PARAMETER:
addLogMessage("Error: ERROR_INVALID_PARAMETER");
break;
case ERROR_INVALID_SERVICE_ACCOUNT:
addLogMessage("Error: ERROR_INVALID_SERVICE_ACCOUNT");
break;
case ERROR_SERVICE_EXISTS:
addLogMessage("Error: ERROR_SERVICE_EXISTS");
break;
default:
addLogMessage("Error: Undefined");
}
CloseServiceHandle(hSCManager);
return -1;
}
CloseServiceHandle(hService);
CloseServiceHandle(hSCManager);
addLogMessage("Success install service!");
return 0;
}
int RemoveService() {
SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if(!hSCManager) {
addLogMessage("Error: Can't open Service Control Manager");
return -1;
}
SC_HANDLE hService = OpenService(hSCManager, serviceName, SERVICE_STOP | DELETE);
if(!hService) {
addLogMessage("Error: Can't remove service");
CloseServiceHandle(hSCManager);
return -1;
}
DeleteService(hService);
CloseServiceHandle(hService);
CloseServiceHandle(hSCManager);
addLogMessage("Success remove service!");
return 0;
}
int MSStartService()
{
SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if(!hSCManager)
{
std::string err = "hSCManager error: ";
char buf[100];
sprintf(buf, "hService error: %ld", GetLastError());
err.append(buf);
addLogMessage(err);
}
SC_HANDLE hService = OpenService(hSCManager, serviceName, SERVICE_ALL_ACCESS);
if(!hService)
{
std::string err = "hService error: ";
char buf[100];
sprintf(buf, "hService error: %ld", GetLastError());
err.append(buf);
addLogMessage(err);
}
if(!StartService(hService, 0, NULL))
{
CloseServiceHandle(hSCManager);
char buf[100];
DWORD errn = GetLastError();
switch(errn)
{
case ERROR_ACCESS_DENIED:
addLogMessage("ERROR_ACCESS_DENIED");
break;
case ERROR_INVALID_HANDLE:
addLogMessage("ERROR_INVALID_HANDLE");
break;
case ERROR_INVALID_NAME:
addLogMessage("ERROR_INVALID_NAME");
break;
case ERROR_SERVICE_DOES_NOT_EXIST:
addLogMessage("ERROR_SERVICE_DOES_NOT_EXIST");
break;
case ERROR_FILE_NOT_FOUND:
addLogMessage("ERROR_FILE_NOT_FOUND");
break;
default:
addLogMessage("Undefined");
break;
}
sprintf(buf, "StartService error: %ld Error: Can't start service", GetLastError());
addLogMessage(buf);
return -1;
}
CloseServiceHandle(hService);
CloseServiceHandle(hSCManager);
return 0;
}
bool addLogMessage(std::string log)
{
FILE *stream;
stream = fopen("C:\\servicelog.txt", "a+");
log +="\n";
fwrite(log.c_str(), sizeof(char), log.length(), stream);
fclose(stream);
return false;
}
То вываливается ошибка в функции MSCrypt::GetRecipientCert(HCERTSTORE hCertStore, char *CertMail, std::string CertSN)
if (!pCertContext)
break;
Т.е. ни одного сертификата не находит, при чем на первой же стадии.
No certificate with a CERT_KEY_CONTEXT_PROP_ID
property and an AT_KEYEXCHANGE private key available.
While the message could be sign, in this case,
it could not be veryfy in this program.
For more information, see the documentation
No Certificate with AT_KEYEXCHANGE key in store.