Крипто-Про CSP

Данный пример демонстрирует проверку подписи XML-документа, а также проверку цепочки сертификатов, начиная с сертификата, на котором осуществлялась подпись.

		
//--------------------------------------------------------------------
// Пример проверки подписи документа MSXML 5.0 на ключе, получаемом из 
// DOM узла <ds:KeyInfo> подписанного XML-документа. 
// Также данная программа осуществляет проверку действительности цепочки
// сертификатов, начиная с сертификата, на котором осуществлялась подпись,
// и заканчивая корневым сертификатом.
// В качестве обязательного аргумента командной строки выступает 
// "out_signature.xml" - имя XML-документа, полученного во время подписи.
// НЕОБХОДИМО установить CAPICOM (http://www.microsoft.com/downloads/details.aspx?FamilyID=860ee43a-a843-462f-abb5-ff88ea5896f6&DisplayLang=en)
//--------------------------------------------------------------------

#include <stdio.h>
#include <tchar.h>

#import <msxml5.dll>
using namespace MSXML2;

#import <capicom.dll>
using namespace CAPICOM;


#define DSIGNS "xmlns:ds='http://www.w3.org/2000/09/xmldsig#'"
#define PROV_GOST_2001_DH 75

//-------------------------------------------------------------
// Объявление и инициализация переменных. 

IXMLDOMDocument3Ptr xmldoc = NULL;
IXMLDigitalSignaturePtr xmldsig = NULL;

VARIANT_BOOL objectsAreInitialized = VARIANT_FALSE;

TCHAR* fileName = NULL; // Имя подписанного XML-документа.

//---------------------------------------------------------------------------
// Описание функции загрузки XML-документа. 
//---------------------------------------------------------------------------

VARIANT_BOOL LoadXML(_bstr_t sigFile)
{
   if (!objectsAreInitialized) 
   {
	printf("Must initialize objects before loading signature.\n");
	return VARIANT_FALSE;
   }

   if (xmldoc->load(sigFile) == VARIANT_FALSE) 
   {
	printf("Can't load %s\n", (LPCSTR)sigFile);
	return VARIANT_FALSE;
   }

   _bstr_t ns= DSIGNS;
   xmldoc->setProperty("SelectionNamespaces", ns);

//------------------------------------------------------------------------------
// Определение свойств подписи в соответствии с DOM узлом <ds:Signature>
// XML-документа.
   xmldsig->signature = xmldoc->selectSingleNode(".//ds:Signature");

   if (xmldsig->signature == NULL) 
   {
	printf("Failed to set the signature property.\n");
	return VARIANT_FALSE;
   }

   return VARIANT_TRUE;

}// Конец описания функции LoadXML

//---------------------------------------------------------------------------
// Описание функции проверки цепочки сертификатов, начиная с сертификата, на
// котором осуществлялась подпись XML-документа. 
//---------------------------------------------------------------------------

VARIANT_BOOL IsCertificateValid(IXMLDSigKeyPtr pKey)
{
   if (pKey == NULL) 
   {
	printf("invalid key object.\n");
	return VARIANT_FALSE;
   }

//---------------------------------------------------------------------------
// Получение сертификата, на котором осуществлялась подпись, из ключа проверки. 

   ICertificatePtr pCert=NULL;

   pCert = pKey->getVerifyingCertificate();
   if (pCert == NULL) 
   {
	printf ("Can't get verifying certificate\n");
	return VARIANT_FALSE;
   }

//---------------------------------------------------------------------------
// Построение и прохождение по доверенной цепочке сертификатов. 

   IChain2Ptr pChain = NULL;
   HRESULT hr = pChain.CreateInstance(__uuidof(Chain));
   if (FAILED(hr)) 
   {
	printf("Can't instantiate a trust chain.\n");
	return VARIANT_FALSE;
   }

   if (VARIANT_FALSE == pChain->Build(pCert)) 
   {
	printf("broken trust chain.\n");
	return VARIANT_FALSE;
   }

   printf("Examining certificate chain:\n");
   long count = pChain->Certificates->Count;
   for (long i=1; i<=count; i++) 
   {
	printf("  Certificate No. %d:\n", i);
	if (pCert) 
	{
		 pCert.Release(); 
		 pCert=NULL; 
}
	pCert = pChain->Certificates->Item[i];
	if (pCert == NULL) 
	{
		 printf("Can't get the %d-th certificate.\n",i);
		 return VARIANT_FALSE;
}
	printf("	 subject: %s\n",(LPSTR)pCert->SubjectName); 
	printf("	 issuer:  %s\n\n",(LPSTR)pCert->IssuerName);
   }
//---------------------------------------------------------------------------
// Проверка корневого сертификата в цепочке. 

   if (pCert) 
   {
	pCert.Release();
	pCert=NULL;
   }

   pCert = pChain->Certificates->Item[count];
   if (pCert == NULL) 
   {
	printf("Can't get root certificate.\n");
	return VARIANT_FALSE;
   }
   printf("Display the Root certificate:\n");
   printf("   subject:  %s\n",(LPSTR)pCert->SubjectName);
   printf("   issuer:   %s\n\n",(LPSTR)pCert->IssuerName);

   if (pCert) pCert.Release();
   if (pChain) pChain.Release();

   return VARIANT_TRUE;
}// Конец описания IsCertificateValid

//---------------------------------------------------------------------------
// Описание функции проверки подписи XML-документа. 
//---------------------------------------------------------------------------

VARIANT_BOOL VerifyXML(XMLDSIG_WRITEKEYINFO fWriteKeyInfo)
{
	MSXML2::IXMLDOMNodePtr pKeyInfo, pNode;
	IXMLDSigKeyPtr pKey, pKeyOut;

	if (xmldsig->signature == NULL) 
	{
	printf("Invalid signature.\n");
	return VARIANT_FALSE;
}

//---------------------------------------------------------------------------
// Проверка DOM узла <ds:KeyInfo> XML-документа. 
   
   switch (fWriteKeyInfo & CERTIFICATES) 
   {
	case CERTIFICATES:
		 pKeyInfo = xmldoc->selectSingleNode(
				".//ds:KeyInfo/ds:X509Data");
		 break;
	case KEYVALUE:
		 pKeyInfo = xmldoc->selectSingleNode(
				".//ds:KeyInfo/ds:KeyValue");
		 break;
   }

   if (pKeyInfo == NULL) 
   {
	printf("Invalid <ds:KeyInfo>\n");
	return VARIANT_FALSE;
   }

//---------------------------------------------------------------------------
// Получение ключа проверки подписи из DOM узла <ds:KeyInfo> XML-документа. 

   pKey = xmldsig->createKeyFromNode(pKeyInfo);
   if (pKey== NULL) 
   {
	printf("Invalid key from <ds:KeyInfo>\n");
	return VARIANT_FALSE;
   }
//---------------------------------------------------------------------------
// Получение ключа проверки цепочки сертификатов и проверка подписи. 

   pKeyOut = xmldsig->verify(pKey);
   if (pKeyOut== NULL) 
   {
	printf("Invalid signature.\n");
	return VARIANT_FALSE;
   }


   printf("Signature verified on the data.\n\n");

//---------------------------------------------------------------------------
// Проверка цепочки сертификатов, начиная с сертификата, на котором осуществлялась подпись. 

   if ( (fWriteKeyInfo & CERTIFICATES) == CERTIFICATES) 
   {
	if (IsCertificateValid(pKeyOut)) 
	{
		 printf("Certificate used is valid.\n");
}
   }

   return VARIANT_TRUE;
}// Конец описания VerifyXML

//-------------------------------------------------------------------------------
// Описание функции инициализации объектов.
//-------------------------------------------------------------------------------

VARIANT_BOOL initObjects()
{
   if (FAILED(xmldsig.CreateInstance(__uuidof(MXDigitalSignature50)) )) 
   {
	printf("Installation of msxml5 is required to run this app.\n");
	return VARIANT_FALSE;
   }

   if (FAILED(xmldoc.CreateInstance(__uuidof(DOMDocument50)) )) 
   {
	printf("Installation of msxml5 is required to run this app.\n");
	return VARIANT_FALSE;
   }
   xmldoc->async = VARIANT_FALSE;
   xmldoc->validateOnParse = VARIANT_FALSE;
   xmldoc->preserveWhiteSpace = VARIANT_TRUE;
   xmldoc->resolveExternals = VARIANT_FALSE;
   objectsAreInitialized = VARIANT_TRUE;

   return VARIANT_TRUE;
}// Конец описания initObjects

//------------------------------------------------------------------------------
// Описание функции очистки объектов.
//-------------------------------------------------------------------------------

void cleanObjects()
{
   if (xmldoc) xmldoc.Release();
   if (xmldsig) xmldsig.Release();
}// Конец описания cleanObjects

//------------------------------------------------------------------------------
// Проверка подписи XML-документа.
//------------------------------------------------------------------------------

void _tmain(int argc, TCHAR **argv)

{
//------------------------------------------------------------------------------
// Инициализация COM библиотеки.

	if ( CoInitialize(NULL) == E_FAIL) 
	{
		printf("can't initialize COM Lib\n");
		exit(-1);
}

//------------------------------------------------------------------------------
// Инициализация объектов.

	if (!initObjects()) 
	{
		cleanObjects();
		exit(-1);
}

//------------------------------------------------------------------------------
// Разбор командной строки.

	if (argc < 1)
		{
			printf("Please, enter tne name of xml-file name!\n");
			exit(-1);
	}
	fileName = argv[1];

	printf("Verifying %s\n\n", fileName);

//------------------------------------------------------------------------------
// Проверка подписи XML-документа.
	if (VARIANT_TRUE == LoadXML(fileName)) 
	{
		VerifyXML(CERTIFICATES);
}

//------------------------------------------------------------------------------
// Очистка.
	cleanObjects();
	CoUninitialize();

}// Конец main
	

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше и MSXML 5.0.

Крипто-Про CSP Версия: 3.0 Сборка 3293
Что Вы думаете по поводу данной статьи?
Закажите CD c Крипто-Про CSP