Проблемы с методом VerifyXml библиотеки KalkanCryptCom

Здравствуйте, подскажите пожалуйста, в чем может быть проблема при проверке подписи методом VerifyXml используя KalkanCryptCom версия 3.0.0.0 используя c#
Пример кода:

var kalkan = new KalkanCryptCOM();
kalkan.Init();
string envelope = string.Empty;
//Получаю XML запрос подписанный SignWsse из файла, для дальнейшей проверки подпсии в нем
using var reader = new StreamReader(@"C:\Temp\rq.txt");
envelope = reader.ReadToEnd();
string err_st = string.Empty;
uint er;
// Пробывал как и с передачей флагов fl так и с передачей 0, результат один 
var fl = 0
         | (int)KALKANCRYPTCOM_FLAGS.KC_IN_PEM
         | (int)KALKANCRYPTCOM_FLAGS.KC_SIGN_CMS;
var xmlVerifyInformation = " ";
kalkan.VerifyXML("", fl, envelope, out xmlVerifyInformation);
kalkan.GetLastErrorString(out err_st, out er);
kalkan.Finalize();

Запрос подписанный из файловой системы:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <SOAP-ENV:Header xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
        <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" SOAP-ENV:mustUnderstand="1">
            <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="sig-aaf13247-7a8b-ecf5-09bb-0755aee017b0">
                <ds:SignedInfo>
                    <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
                        <InclusiveNamespaces xmlns="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="soap"/>
                    </ds:CanonicalizationMethod>
                    <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gost34310-gost34311"/>
                    <ds:Reference URI="#id-90AF1E5BEB3544A88A0930E2D4213F95">
                        <ds:Transforms>
                            <ds:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"/>
                        </ds:Transforms>
                        <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gost34311"/>
                        <ds:DigestValue>3ugrngxKcgF7p3VOghf0UYXk/FrRFRdGzg0Mo7i0l3o=</ds:DigestValue>
                    </ds:Reference>
                </ds:SignedInfo>
                <ds:SignatureValue>loVlIOHjpwjEhahRW7f1OWJ8LGnYgtNKOHnk3T76XGZB6gQm0rqHV6l8B5Q4se8d
8ZuKWLx/7U/hTeLUdxEM9g==</ds:SignatureValue>
                <ds:KeyInfo Id="ki-aaf13247-7a8b-ecf5-09bb-0755aee017b1">
                    <wsse:SecurityTokenReference wsu:Id="str-aaf13247-7a8b-ecf5-09bb-0755aee017b2">
                        <wsse:KeyIdentifier EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3">MIIEaDCCBBKgAwIBAgIUFB5QmYpu7qO3wuPzB98ivbviLLkwDQYJKoMOAwoBAQEC
BQAwUzELMAkGA1UEBhMCS1oxRDBCBgNVBAMMO9Kw0JvQotCi0KvSmiDQmtCj05jQ
m9CQ0J3QlNCr0KDQo9Co0Ksg0J7QoNCi0JDQm9Cr0pogKEdPU1QpMB4XDTIzMTEx
MDExMzYzN1oXDTI0MTEwOTExMzYzN1owgfsxKjAoBgNVBAMMIdCT0JDQl9Cv0JzQ
ntCS0JAg0KHQktCV0KLQm9CQ0J3QkDEZMBcGA1UEBAwQ0JPQkNCX0K/QnNCe0JLQ
kDEYMBYGA1UEBRMPSUlONjIxMDA4NDAxODUyMQswCQYDVQQGEwJLWjFSMFAGA1UE
CgxJ0JDQutGG0LjQvtC90LXRgNC90L7QtSDQvtCx0YnQtdGB0YLQstC+ICLQldCy
0YDQsNC30LjQudGB0LrQuNC5INCx0LDQvdC6IjEYMBYGA1UECwwPQklOOTUwMjQw
MDAwMTEyMR0wGwYDVQQqDBTQodCc0J7Qm9CY0J3QntCS0J3QkDBsMCUGCSqDDgMK
AQEBATAYBgoqgw4DCgEBAQEBBgoqgw4DCgEDAQEAA0MABECzMu4aTu8yN7tJBiHF
1QsWWsSkmaB4TeT3Nq/IwKu3R3r8bfvM3iUNeUC85B9I/TBgdxlsql7J8Gk/yajk
NWkSo4ICAzCCAf8wYwYIKwYBBQUHAQEEVzBVMC8GCCsGAQUFBzAChiNodHRwOi8v
cGtpLmdvdi5rei9jZXJ0L25jYV9nb3N0LmNlcjAiBggrBgEFBQcwAYYWaHR0cDov
L29jc3AucGtpLmdvdi5rejAOBgNVHQ8BAf8EBAMCBsAwKAYDVR0lBCEwHwYIKwYB
BQUHAwQGCCqDDgMDBAECBgkqgw4DAwQBAgQwXgYDVR0gBFcwVTBTBgcqgw4DAwIB
MEgwIQYIKwYBBQUHAgEWFWh0dHA6Ly9wa2kuZ292Lmt6L2NwczAjBggrBgEFBQcC
AjAXDBVodHRwOi8vcGtpLmdvdi5rei9jcHMwWAYDVR0fBFEwTzBNoEugSYYiaHR0
cDovL2NybC5wa2kuZ292Lmt6L25jYV9nb3N0LmNybIYjaHR0cDovL2NybDEucGtp
Lmdvdi5rei9uY2FfZ29zdC5jcmwwXAYDVR0uBFUwUzBRoE+gTYYkaHR0cDovL2Ny
bC5wa2kuZ292Lmt6L25jYV9kX2dvc3QuY3JshiVodHRwOi8vY3JsMS5wa2kuZ292
Lmt6L25jYV9kX2dvc3QuY3JsMB0GA1UdDgQWBBQEHlCZim7uo7fC4/MH3yK9u+Is
uTAPBgNVHSMECDAGgARbanPpMBYGBiqDDgMDBQQMMAoGCCqDDgMDBQEBMA0GCSqD
DgMKAQEBAgUAA0EAaDB+ZHrPW5PeSjsEh7tqaTa/tysxrGwfX+SvE5RBp+uZC/vb
3V1J2+TRNhv8f8q3U80hI3rBLntusylfeCesSw==</wsse:KeyIdentifier>
                    </wsse:SecurityTokenReference>
                </ds:KeyInfo>
            </ds:Signature>
        </wsse:Security>
    </SOAP-ENV:Header>
    <SOAP-ENV:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="id-90AF1E5BEB3544A88A0930E2D4213F95">
        <typ:SendMessage xmlns:typ="http://bip.bee.kz/SyncChannel/v10/Types" xmlns:ns6="http://bip.bee.kz/SyncChannel/v10/Types/Response">
            <request>
                <requestInfo>
                    <messageId>22673887-c3f0-4ca7-8f4f-54567982569a</messageId>
                    <serviceId>enbek-contract-ws-service</serviceId>
                    <messageDate>2023-11-21T16:44:03.479902+06:00</messageDate>
                    <sender>
                        <senderId>id</senderId>
                        <password>password</password>
                    </sender>
                    <sessionId>{22673887-c3f0-4ca7-8f4f-54567982569a}</sessionId>
                </requestInfo>
                <requestData>
                    <data xsi:type="xsd:string">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;ns2:contractRequest&gt;&lt;/ns2:contractRequest&gt;</data>
                </requestData>
            </request>
        </typ:SendMessage>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

На выходе получаю такой итог:
XMLSec Initialize - OK.
XMLSec check version - OK.
XMLSec crypto init - OK.
XMLSec crypto library init - OK.
XMLSec Initialize - OK.
XML parse doc - OK.
XMLSec verify xml - found 1 sign(s).
XMLSec load trusted certificates - OK.
ERROR 0x0c: XMLSec-error:
func=xmlSecOpenSSLEvpDigestVerify:file=digests.c:line=279:obj=gost34311:subj=unknown:error=12:invalid data:data and digest do not match

Signature N 1

  • verify error.
    ERROR 0x8f00023: XMLSec verify xml - FAILED.

Любые идеи, спасибо!

Добрый день!
Дело в том, что добавление к сформированной подписи одного пробела, запятой, переноса или отступа, да и др. символов - может привести к ошибке проверки.
Точно сказать причину, я не могу, так как не знаю изначальный документ, который подписывали.

Вы можете сами с помощью метода SignWSSE() подписать нужные вам данные и увидите, что присланная вами подпись отличается наличием табуляции и переносов.

Здравствуйте, Вы правы, в исходном XML присутствуют спец символы, спасибо!
Еще пожалуйста подскажите, проверка принадлежности подписи в запросе к конкретному отправителю происходит путем сверки сертификата в секции запроса X509Certificate, с тем что находится в его открытой части которая была получена в рамках обмена сертификатами? Если да, подскажите какой функционал (методы) предоставляет по этой части KalkanCryptCOM

Верно!

Метод GetCertFromXML() - извлекает сертификат из XML
Затем сравниваете оба сертификата между собой. Да и сам сертификат также проверяете согласно правилу проверок ЭЦП.

Здравствуйте, можете еще подсказать пожалуйста:

  1. Каким образом KalkanCryptCOM библиотека проверяет отозванные сертификаты, правильно ли я понимаю что “под капотом” она интегрирована с какими то внутренними сервисами НУЦ, тем самым отправляет им запросы касающиеся валидации сертификата?
  2. Для чего необходимо устанавливать корневые сертификаты корневого удостоверяющего центра РК, правильно ли я понимаю что это необходимо для корректного взаимодействия с сервисами НУЦ из пункта 1?

Добрый день!
Есть два способа проверки: OCSP и CRL

  • OCSP.
    KalkanCryptCOM делает запрос в сервис НУЦ РК http://ocsp.pki.gov.kz/. Получает ответ сервиса, проверяет его и выдает результат. Для построения запроса и проверки ответа необходимо, чтобы были установлены корневые сертификаты.
  • CRL.
    Для проверки статуса сертификаты в память KalkanCryptCOM загружается актуальный файл CRL. Сертификат ищется в списке отозванных сертификатов (CRL). Для достоверности CRL, для привязки сертификата и CRL У одному УЦ также необходимы корневые сертификаты.

Как понять какой из способов мы используем при вызове метода VerifyXML? Спасибо за ответ!

Это разные методы - X509ValidateCertificate() и VerifyXML(). Первый метод валидирует сертификат, второй метод проверяет Xml-подпись.