2013-09-17 3 views
2

Я пытаюсь реализовать WS-Security для своего PHP-клиента SOAP. Первым шагом является возможность генерации действительного XML-дайджеста из исходящего запроса, но я не смог этого сделать. Я искал ответы в течение нескольких дней, но большинство ответов в конечном итоге были чем-то вроде «не решайте сами, просто используйте существующую библиотеку Java». Это невозможно в моей нынешней ситуации.Сгенерировать сборник подписи XML с помощью PHP

Я искал несколько примеров в сети, пытаясь воспроизвести тот же дайджест, который у них есть, например this one от Microsoft. Эта страница содержит список следующий пример:

<ds:Object Id="ts-text"> 
    Wed Jun 4 12:11:06 EDT 
</ds:Object> 

Затем они показывают ожидаемое значение дайджеста:

<ds:Reference URI="#ts-text"> 
    <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> 
    <ds:DigestValue>pN3j2OeC0+/kCatpvy1dYfG1g68=</ds:DigestValue> 
</ds:Reference> 

Это код, который я использую, чтобы вычислить значение дайджеста:

<?php 
$digest = base64_encode(hash('SHA1', $contents, true)); 

Я пробовал много разных комбинаций удаления пробелов или используя только метку времени без XML-тегов без успеха. Я также попробовал более сложные примеры, в которых необходима каннализация. Это один из моих модульных тестов:

public function testCreateDigest(DOMDocument $request, $expectedDigest) { 

    $ns = $request->documentElement->namespaceURI; 
    $body = $request 
      ->getElementsByTagNameNS($ns, 'Body') 
      ->item(0); 

    $firstElement = ''; 
    foreach($body->childNodes as $node){ 
     if ($node->nodeType === XML_ELEMENT_NODE) { 
      $firstElement = $node; 
      break; 
     } 
    } 


    $content = $firstElement->C14N(false, true); 


    $actualDigest = base64_encode(hash('SHA1', $content, true)); 

    $this->assertEquals($expectedDigest, $actualDigest); 

} 

Что именно я должен использовать для хэша? Я пропустил какие-то шаги?

ответ

2

Я нашел решение. Для большинства из примеров, которые я пробовал, искомое преобразование было эксклюзивные канонизации с комментариями: http://www.w3.org/TR/2002/REC-xml-exc-c14n-20020718/#WithComments

Так что моя проблема заключалась в том, что я делаю преобразование неправильно. Первый параметр в функции C14N PHP определяет, использовать ли эксклюзивное преобразование или нет. Это то, что код должен быть (обратите внимание, что я удалил ненужный обход к первому элементу):

public function testCreateDigest(DOMDocument $request, $expectedDigest) { 

    $ns = $request->documentElement->namespaceURI; 
    $body = $request 
     ->getElementsByTagNameNS($ns, 'Body') 
     ->item(0); 

    $content = $body->C14N(true, true); // <-- exclusive, with comments 

    $actualDigest = base64_encode(hash('SHA1', $content, true)); 

    $this->assertEquals($expectedDigest, $actualDigest); 

} 

Так что у вас есть. Это послужило напоминанием о том, что я должен дважды проверить свой XML и понять стандарты, прежде чем я буду идти без кодирования.