Крипто-Про 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.
Что Вы
думаете по поводу данной статьи? |
Закажите CD c Крипто-Про CSP |