Проблемы со значением дайджеста XML (для Управления данных здравоохранения Дании)
Я хочу создать некоторый XML, который должен содержать значение дайджеста , т. е. хэш-значение в кодировке BASE64 некоторого XML в канонической (C14N) форме, но получатель не принимает ни значение, вычисляемое моим кодом, ни XML, когда это делается в соответствии с к (ошибочной) документации (и расчеты соответствуют ожидаемому значению) - если только я не сделаю грязный хак, который не имеет для меня смысла.
К счастью, у меня есть доступ к существующей системе, которая позволяет мне сравнивать то, что ожидает получатель, и там я мог видеть, что мой расчет дал другой результат, чем существующая система, рассчитанная, когда мой код создал тот же XML, что и существующая система, но я понял (после прочтения (ошибочная) документация), что XML должен был иметь некоторые дополнительные атрибуты пространства имен - и вдруг мой код вычислил правильное значение дайджеста!?!
То есть я могу рассчитать правильное значение дайджеста, создав XML за два прохода! Один с неправильным XML (как описано в (ошибочной) документации) и хранит вычисленное значение, а затем вторая версия, в которой код вставляет вычисленное значение из первого прохода.
Кому-нибудь это звонит в колокол? Кто-нибудь работает с Датским управлением данных о здоровье ?
У меня есть следующие вспомогательные функции:
function createElement(\DOMDocument $xml, \DOMNode /*DOMDocument&DOMElement*/ $parent, string $name) : \DOMElement {
$node = $xml->createElement($name) or die("<span class=\"fail\">createElement($name) failed</span>");
return $parent->appendChild($node);
}
function createElementNS(\DOMDocument $xml, \DOMNode /*DOMDocument&DOMElement*/ $parent, string $ns, string $name) : \DOMElement {
$node = $xml->createElementNS($ns, $name) or die("<span class=\"fail\">createElementNS(..., $ns, $name) failed</span>");
return $parent->appendChild($node);
}
function createAttribute(\DOMDocument $xml, \DOMElement $parent, string $name, string $value) : \DOMAttr {
$attribute = $xml->createAttribute($name) or die("<span class=\"fail\">createAttribute(..., $name, $value) failed</span>");
$attribute->value = $value;
return $parent->appendChild($attribute);
}
function createAttributeNS(\DOMDocument $xml, \DOMElement $parent, string $name, string $value) : \DOMAttr {
$attribute = $xml->createAttribute($name) or die("<span class=\"fail\">createAttribute{NS}(..., $name, $value) failed</span>");
$attribute->value = $value;
return $parent->appendChild($attribute);
}
function createTextNode(\DOMDocument $xml, \DOMElement $parent, string $text) : \DOMText {
$text_node = $xml->createTextNode($text) or die("<span class=\"fail\">createTextNode($text) failed</span>");
return $parent->appendChild($text_node);
}
и фрагменты кода выглядят так
$hack_pass = 0;
while (++$hack_pass <= 2) {
$xml = new \DOMDocument('1.0', 'UTF-8');
$xml_soapenv_envelope = createElementNS($xml, $xml, 'http://schemas.xmlsoap.org/soap/envelope/', 'soapenv:Envelope');
createAttributeNS($xml, $xml_soapenv_envelope, 'xmlns:ds', 'http://www.w3.org/2000/09/xmldsig#');
...
createAttribute($xml, $xml_soapenv_envelope, 'id', 'Envelope');
$xml_soapenv_header = createElement($xml, $xml_soapenv_envelope, 'soapenv:Header');
$xml_wsse_security = createElement($xml, $xml_soapenv_header, 'wsse:Security');
$xml_wsu_timestamp = createElement($xml, $xml_wsse_security, 'wsu:Timestamp');
$xml_wsu_created = createElement($xml, $xml_wsu_timestamp, 'wsu:Created');
createTextNode($xml, $xml_wsu_created, $created);
if ($hack_pass == 1) {
$xml_saml_assertion = createElementNS($xml, $xml_wsse_security, 'urn:oasis:names:tc:SAML:2.0:assertion', 'saml:Assertion');
} else {
$xml_saml_assertion = createElement($xml, $xml_wsse_security, 'saml:Assertion'); // Final XML
}
...
if ($hack_pass < 2) {
$c14n = $xml_saml_assertion->C14N(TRUE);
$DigestValue = base64_encode(hash('sha1', $c14n, TRUE));
}
...
}