SlideShare uma empresa Scribd logo
1 de 12
Baixar para ler offline
Livro: Pro PHP XML and Web Services
Introdução a Estrutura Xml Signature
As assinaturas XML podem verificar a integridade e a origem dos dados e se os dados não foram
alterados de seu estado original. Isso é feito usando chaves. Um dos métodos mais comuns usados é
o método de envelopamento com chaves públicas e privadas. O autor de um documento usaria uma
chave privada para assinar os dados. Isso criaria uma assinatura digital, que é então adicionada a um
documento XML. O destinatário, que deve ter uma cópia da chave pública do autor, usaria essa
chave para verificar os dados assinados. Após uma verificação bem-sucedida, o destinatário sabe
três coisas:
• O autor é o originador genuíno do documento, conhecido como
autenticação do assinador.
• Os dados não foram alterados em sua forma original, que é chamada de integridade.
• Nem os dados nem a soma de verificação foram adulterados, o que pode ocorrer se alguém está
tentando alterar os dados, mantendo a integridade dos dados, a fim de enganar o receptor dos dados.
Isso é comumente conhecido como autenticação de mensagem.
A especificação de sintaxe e processamento de assinatura XML (http://www.w3.org/TR/
xmldsig-core/) especifica as regras de sintaxe e processamento para criar e representar
assinaturas. É chamado assim porque usa a sintaxe XML para a assinatura. Você pode aplicar
assinaturas XML para praticamente qualquer tipo de dados digitais, incluindo dados em um
documento XML como recursos remotos acessíveis a partir de um URI.
Entendendo os Tipos de Assinaturas
Existem três tipos de assinaturas XML: assinaturas envelopadas (enveloped signatures), assinaturas
envolvidas (enveloping signatures) e assinaturas destacadas (detached signatures).
Assinaturas Envelopadas (Enveloped Signatures)
Assinaturas envelopadas são assinaturas contidas no conteúdo XML que está sendo
assinado. Em termos simples, uma assinatura envelopada é uma estrutura de assinatura XML que é
uma ficha de um documento assinado. Por exemplo:
<mydocument>
<mydata1>some data</mydata1>
<mydata2>more data</mydata2>
<Signature>
<!-- Signature Data -->
</Signature>
</mydocument>
A assinatura XML, é definida pelo elemento Signature e seu conteúdo, e é colocada dentro
do documento que está sendo assinado. Neste caso, os dados incluiriam os dados do elemento
mydocument e todo o seu conteúdo, mas exclui a estrutura de assinatura XML real, que começa
com o elemento Signature.
1
Assinaturas Envolvidas (Enveloping Signatures)
Assinaturas XML também podem ser envolvidas. Isso significa que os dados que estão sendo
assinados residem na estrutura de assinatura XML:
<mydocument>
<mydata2>more data</mydata2>
<Signature>
<!-- Signature Data including the reference to the Object element
-->
<Object Id="mydata">
<mydata1>some data</mydata1>
</Object>
</Signature>
</mydocument>
Embora a estrutura da assinatura XML não precise ser incorporada em um XML documento desde a
sua estrutura está no formato XML, eu mostrei desta forma porque você não foi introduzido na
estrutura e como uma assinatura envolvente pode ser encapsulada dentro de outro documento, para
o qual o documento de encapsulamento não tem tendo na assinatura. Nesse caso, a assinatura
incluiria uma referência ao elemento Object. Os dados dentro do elemento Object são os dados
que estão sendo assinados. Vou explicar como dados de referência mais adiante na seção
“Apresentando a Estrutura de Assinatura XML”.
Assinaturas Destacadas (Detached Signatures)
Assinaturas envelopadas significa que a assinatura é encapsulada em um documento que está sendo
assinado.
Não é necessário que todo o documento seja assinado, e é bem possível que você tenha apenas
um único elemento no documento assinado. De fato, também é bem possível que os dados
ser assinado nem mesmo vive dentro do documento e reside remotamente e é acessível
através de um URI. Assinaturas destacadas são usadas apenas para esses propósitos:
<mydocument>
<mydata2>more data</mydata2>
<Signature>
<!-- Signature Data including the reference to the Object element
-->
</Signature>
<Object Id="mydata">
<mydata1>some data</mydata1>
</Object>
</mydocument>
Com este exemplo, os dados dentro do elemento Object estão sendo assinados novamente. Desta
vez, no entanto, o elemento está fora da assinatura e a assinatura está sendo aplicada apenas a
esse elemento em particular e não o documento inteiro:
<Signature>
<!-- Signature Data including the reference to remote data -->
</Signature>
Este exemplo refere-se aos dados que estão sendo assinados e que residem inteiramente fora do
documento. Em vez que referenciando o elemento Object dos exemplos anteriores, a assinatura
2
XML, neste exemplo, faz referência a dados remotos usando um URI. Mais uma vez, explicarei isso
em detalhes na seção "Apresentando a Estrutura de Assinatura XML" quando eu dividir a estrutura.
Assim como no exemplo anterior, também seria válido encapsular a assinatura XML em um
documento, e o documento não tem relação com a assinatura ou os dados referenciados.
Apresentando a estrutura de assinatura XML
A estrutura das assinaturas XML pode ficar bastante complexa. Um livro inteiro poderia ser escrito
sobre este assunto. Por esse motivo, vou manter as coisas simples e cobrir apenas a sintaxe
principal.
Este capítulo apresentará como criar e verificar assinaturas XML básicas usando o PHP. Depois de
você entender isso, você deverá ser capaz de implementar assinaturas mais avançadas com base
nas especificações.
O documento na Listagem 12-2 ilustra uma assinatura de envelope válida.
Os dados que estão sendo assinados neste caso é o elemento Object. Ele fica dentro do elemento
Signature, criando assim uma assinatura envolvente. Usando este exemplo, você verá agora como o
XML assinatura é composta e estruturada.
3
Elemento Signature
O elemento Signature é a raiz de uma assinatura XML e está vinculado ao namespace
http://www.w3.org/2000/09/xmldsig#. Este elemento contém todas as informações necessárias para
verificar Assinatura XML.
Elemento SignatureValue
O elemento SignatureValue contém o valor codificado em Base64 da assinatura digital real,
que na Listagem 12-2 é o valor OUubDO2l6XUIODuLSjKAtjYlaTk =. Explicarei como calcular
este valor mais tarde na seção "Gerando uma assinatura", bem como quando você entrar na verdade
gerando uma assinatura XML.
Elemento SignedInfo
O elemento SignedInfo é um elemento contêiner que fornece informações sobre como
uma assinatura é processada, a localização dos dados assinados e o valor da integridade dos dados.
Esse elemento também aceita um atributo Id opcional. Usando este atributo permite que o elemento
ser referenciado por outras assinaturas ou objetos.
Elemento CanonicalizationMethod
O elemento CanonicalizationMethod define o tipo de canonização que deve ser aplicado
ao elemento SignedInfo ao processar uma assinatura digital. As implementações devem pelo menos
suporte a XML canônico sem comentários, conforme observado pelo valor
http://www.w3.org/TR/2001/REC-xml-c14n-20010315.
Outros valores possíveis incluem, mas não estão limitados a, http://www.w3.org/TR / 2001 / REC-
xml-c14n-20010315 # ComComments, que é XML canônico com comentários e
http://www.w3.org/TR/xml-exc-c14n/, que é XML canônico exclusivo.
Conforme mostrado na Listagem 12-2, o valor para este elemento é
http://www.w3.org/TR/2001/REC-xml-c14n-20010315, então canonical XML processará o
elemento SignedInfo.
Elemento SignatureMethod
O elemento SignatureMethod especifica o algoritmo usado para criar e verificar a assinatura digital.
Dependendo do algoritmo usado, esse elemento pode ter elementos filho, como
HMACOutputLength, para fornecer informações adicionais para o algoritmo. Você especifica o real
algoritmo a ser utilizado no atributo Algorithm. Os algoritmos são especificados por URI e definem
a regra. Você pode encontrar alguns dos valores possíveis em http://www.w3.org/TR/xmldsig-core/
# sec-AlgID dentro da especificação. O valor usado na Listagem 12-2 é http://www.w3.org/2000/
09/xmldsig#hmac-sha1, que corresponde ao HMAC-SHA1. Então, agora é seguro assumir que
o HMAC-SHA1 é o algoritmo usado neste capítulo para assinaturas digitais.
Elemento Reference
Elementos de referência especificam quais dados são assinados. Você pode usar mais de um
elemento de referência.
Para o bem deste capítulo, no entanto, as assinaturas digitais usadas aqui conterão apenas um unico
4
Elemento de referência. Esse elemento pode pegar qualquer um dos três atributos opcionais. Você
pode usar um ID atributo para que o elemento possa ser facilmente referenciado a partir de outros
locais. O atributo Type é um URI que especifica o tipo de dados. Por exemplo, o atributo pode ser
Type = "http://www.w3.org/2000/09/xmldsig#Object" ou Type =
"http://www.w3.org/2000/09/xmldsig#Manifest" . O valor não tem qualquer influência sobre como
a assinatura é gerada. Pode, no entanto, ser usado por um aplicativo para seu próprio propósito. O
último atributo opcional é o URI. Isso tem muito mais impacto nos dados do que os outros
atributos.
O atributo URI identifica o local do objeto de dados, usando um URI como seu valor. o
atributo é considerado opcional, porque é possível que uma aplicação já saiba onde
os dados residem. Por exemplo, se a mesma estrutura XML é sempre usada, pode ser acordado
tanto pelo autor como pelo destinatário do documento, um determinado elemento no documento
será sempre assinado. Normalmente, porém, é mais seguro incluir sempre um URI. O exemplo em
A Listagem 12-2 está usando dados que estão localizados no documento. O atributo URI tem o
valor #objeto. Isso identifica o conjunto de nós que contém o elemento com um ID, definido pelo
atributo Id, do objeto.
Nota: O elemento Transforms, que é um filho opcional de um elemento Reference, será omitido do
este capítulo. Seu uso está fora do escopo, porque é um pouco avançado neste momento tentar usar
o atual Funcionalidade XML em PHP.
Elemento DigestMethod
O elemento DigestMethod define o algoritmo aplicado aos dados que estão sendo assinados. Você
especifica o algoritmo real usando um URI para o valor do atributo Algorithm. Este atributo
funciona da mesma maneira que aquele localizado no elemento SignatureMethod. O exemplo
na Listagem 12-2 usou o valor http://www.w3.org/2000/09/xmldsig#sha1. O resumo será
calculado usando um hash SHA1.
Elemento DigestValue
O elemento DigestValue contém o valor codificado em Base64 do resumo. Usando a assinatura da
Listagem 12-2, o resumo é simplesmente o hash SHA1 da forma canônica dos dados
sendo assinado. Não se preocupe se você não entender completamente isso neste momento. Isso
será feito extremamente claro quando formos criar e verificar as assinaturas nas sessões “Criando
uma Assinatura” e “Verificando uma Assinatura”.
Elemento KeyInfo
O elemento KeyInfo é um elemento opcional que pode permitir que os destinatários obtenham as
chaves, certificados ou informações de gerenciamento de chaves públicas. A assinatura XML neste
capítulo usa a string "secret", que é privada e conhecida apenas pelo autor e destinatário porque
do algoritmo especificado no elemento SignatureMethod. Outros algoritmos usam público / privado
pares de chaves, tornando perfeitamente viável incluir chaves públicas, certificados ou informações
sobre acessando uma chave pública dentro da assinatura XML.
Esse elemento serve como um contêiner para fornecer as informações necessárias, que podem estar
5
contidas em qualquer número de possíveis elementos filho. O conteúdo de um elemento KeyName
é uma string contendo um identificador de chave para o destinatário. Indica à informação do
destinatário que chave para usar no documento. Um elemento KeyValue define uma única chave
pública, como DSA ou RSA chaves públicas, que podem verificar e validar a assinatura. Você pode
usar um elemento Retrieval para informações de referência KeyInfo armazenadas em outro local.
Tem um atributo URI e Type e funciona da mesma maneira que um elemento de referência. Os
restantes elementos possíveis, X509Data, PGPData, SPKIData e MgmtData são usados dependendo
do tipo de algoritmo usado.
Por exemplo, você pode usar certificados X509 e um elemento X509Data pode conter certificado
cadeias, listas de revogação ou um SubjectKeyIdentifier. Mais uma vez, esses elementos estão fora
do escopo deste capítulo, mas são abordadas com mais detalhes na especificação em
http://www.w3.org/TR / xmldsig-core / # sec-KeyInfo.
Elemento ObjectElemento Object
Um elemento Object é um contêiner para armazenar qualquer tipo de dado. Tem três atributos
opcionais.
O atributo Id é um ID usado para referenciar o elemento. A assinatura XML na Listagem 12-2
usa o objeto de nome para o atributo Id, que é então referenciado pelo elemento Reference
através do seu atributo URI. Um atributo MimeType especifica o tipo MIME dos dados. O valor
que deve ser um tipo MIME válido, conforme definido no RFC 2045
(http://www.ietf.org/rfc/rfc2045.txt).
O último atributo é Encoding. O valor define a codificação usada no objeto. Os atributos MimeType
e Encoding são puramente informativos. É completamente até o aplicativo se eles precisam ser
usados.
Criando uma Assinatura
Criar uma assinatura envolve gerar os elementos Reference e SignatureValue. O resto
das informações dentro de um elemento Signature define como os valores são gerados ou, quando
usando uma assinatura envolvente, podem ser dados que estão sendo assinados. Os primeiros passos
são determinar o tipo de algoritmo de criptografia que será usado e determinar quais regras devem
ser usado quando a assinatura é criada; eles também determinam as regras que um aplicativo deve
seguir para verificar a assinatura.
Nesse caso, a assinatura XML que está sendo criada é aquela na Listagem 12-2. A seguir
uma lista de regras que serão usadas para criar a assinatura:
• A assinatura será envolvente. O elemento Reference se referirá a um elemento Object
com o objeto Id dentro do documento. Especificamente, o elemento Object será um filho
do elemento Signature.
• A canonização XML será usada. Isso determina o valor do atributo Algorithm no elemento
CanonicalizationMethod.
• HMAC SHA1, usando a string "secret" para a chave, será usado para a assinatura. este
determina o valor do atributo Algorithm no elemento SignatureMethod.
• SHA1 será usado para a integridade da mensagem. Isso determina o valor do Algorithm
atributo no elemento DigestMethod.
6
Com base nessa lista, você pode criar uma assinatura esquelética, conforme mostrado na Listagem
12-3.
Listing 12-3. Skeleton Enveloping Signature Document
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-
20010315" />
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#hmac-sha1" />
<Reference URI="#object">
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
</Reference>
</SignedInfo>
<Object Id="object">Hello World!</Object>
</Signature>
Nota: Um elemento Reference é criado para cada objeto de dados que está sendo assinado. Este
exemplo tem apenas um único objeto de dados, de modo que o elemento de referência foi criado
com o esqueleto geral em vez de gerá-los porque os elementos DigestValue são calculados para
cada objeto de dados.
A única informação dentro do esqueleto não mencionada na lista é o texto
Hello World!; esse texto, bem como o elemento Object, é a mensagem a ser
assinada. As últimas etapas aqui são para gerar o DigestValue e gerar a assinatura real.
Gerando a Referência
De acordo com a especificação, os DigestValues são criados enquanto os elementos Reference são
criados.
A razão para isso é que vários objetos podem ser usados em uma única assinatura XML. Nesse
caso, os dados são simples e o elemento de referência que aponta para os dados já foi criado.
Nenhuma transformação está sendo usada, portanto, você pode mover diretamente para o cálculo
DigestValue.
Isso é calculado executando as seguintes etapas:
1. Obtenha os dados brutos especificados pelo elemento Reference. Neste caso, é o Object
elemento.
2. Aplique quaisquer transformações. Este exemplo não usa nenhum.
3. Se as transformações (ou os dados brutos no evento não houver transformações definidas)
resultarem em conjunto de nós, use o XML canônico para serializar o conjunto de nós. Neste
exemplo, não há mudança, e os dados brutos são o elemento Object. Canonicalização realizada
neste passo é verdadeiro XML canônico, que significa inclusivo. O valor do método do elemento
canonização não tem nenhuma influência nesta etapa porque esse elemento pertence à geração de
assinatura e não à geração de referência.
4. Usando o algoritmo especificado pelo elemento DigestMethod, calcule o DigestValue
usando os dados resultantes da etapa 3.
7
5. Adicione o DigestValue à árvore. Novamente, as especificações criam o elemento Reference
durante essas etapas, portanto, se você decidir seguir esse método ou tiver uma assinatura complexa
exigindo que as etapas sejam executadas dessa maneira, crie o elemento Referência
e seus filhos neste momento e anexá-lo como filho ao elemento SignedInfo.
Na etapa 1, os dados brutos são o elemento Object. Para este exemplo, vou usar a variável
$ doc, que representa a assinatura esquelética da Listagem 12-3. Isso pode ser carregado
de um arquivo ou ser construído manualmente usando os métodos DOM do Capítulo 6.
Cuidado Ao criar o documento de assinatura manualmente usando a API do DOM, o elemento
Signature define o namespace padrão http://www.w3.org/2000/09/xmldsig#. Elementos dentro de
seu escopo devem ser criado usando métodos de reconhecimento de namespace, como
createElementNS, para que isso funcione corretamente.
For example:
$xPath = new DOMXpath($doc);
/* Following line split into two lines because of length */
$query = '//*[local-name()="Reference" and '.
'namespace-uri()="http://www.w3.org/2000/09/xmldsig#"]';
$nodeset = $xPath->query($query);
$refElement = $nodeset->item(0);
$dataURI = $refElement->getAttribute("URI");
Isso retorna o valor #object. Como um DTD não foi especificado, você não consegue
recupera o elemento Object usando o método getElementByID do DOM. Você deve fazer isso
manualmente. Você pode usar o seguinte código para executar esta operação. Note que ele assume o
O valor do URI contém um ID e não um URL para dados externos:
$ID = substr ($dataURI, 1);
$query = '//*[@Id="'.$ID.'"]';
$nodeset = $xPath->query($query);
$Object = $nodeset->item(0);
A variável $ Object resultante deve ser um objeto DOMElement que referencia o objeto
elemento no documento. Serialização usando $ doc-> saveXML ($ Object) deve produzir o
Segue:
<Object Id="object">Hello World!</Object>
Não há Transformações e o resultado da primeira etapa é um conjunto de nós contendo o Object
elemento. Este conjunto de nós (read: element) deve ser serializado em forma canônica:
<Object xmlns="http://www.w3.org/2000/09/xmldsig#"
Id="object">some text</Object>
O XML canônico é usado aqui, o que é inclusivo. Isso significa que o namespace padrão
definido pelo elemento Signature, que é um ancestral do elemento Object, é serializado
com o nó Object. Uma maneira rápida e simples de canonizar esse elemento é copiá-lo para
outro documento e serializando o novo documento. A cópia deve ser uma cópia profunda para que
8
todos os atributos e filhos são copiados. Durante a cópia, como esse nó se torna o nó de nível
superior, o namespace padrão herdado é recriado na cópia. Por causa da estrutura
da assinatura XML e dos dados com os quais você está trabalhando, essa é a única coisa que você
precisa fazer antes da serialização para resultar na forma canônica correta. Para estruturas mais
complexas, você precisaria usar as técnicas descritas na seção “Introdução à Canonical XML”:
$dom = new DOMDocument();
$copyObject = $dom->importNode($Object, TRUE);
$dom→appendChild($copyObject);
Cuidado Isso funciona apenas porque o conteúdo do elemento Object é um texto simples e não um
XML subárvore. Se o conteúdo fosse uma subárvore, você precisaria aplicar as regras e técnicas
descritas na “Introdução à XML canônica”, de modo que os namespaces e os atributos em particular
sejam gerados corretamente.
Usando o algoritmo do elemento DigestMethod, a forma canônica dos dados gera o resumo. Este
valor é então codificado usando codificação Base64 e definido como o conteúdo de
o elemento DigestValue:
$query = '//*[local-name()="DigestMethod" and ' . 'namespace-
uri()="http://www.w3.org/2000/09/xmldsig#"]';
$nodeset = $xPath->query($query);
$digMethod = $nodeset->item(0);
$algorithm = $digMethod->getAttribute("Algorithm");
if ($algorithm == "http://www.w3.org/2000/09/xmldsig#sha1")
{
$canonical = $dom->saveXML($copyObject);
/* Create SHA1 hash of the canonical form of the Object element */
$hash = sha1($canonical);
$bhash = pack("H*", $hash);
$digValue = base64_encode($bhash);
/* Following is done in example only to add proper whitespacing */
$addPrev = NULL;
$addPost = NULL;
if ($digMethod->previousSibling->nodeType == XML_TEXT_NODE)
{
$addPrev = clone $digMethod->previousSibling;
}
if ($digMethod->nextSibling->nodeType == XML_TEXT_NODE)
{
$addPost = clone $digMethod->nextSibling;
}
/* End custom whitespaces */
/* Create DigestValue element, and append to parent of DigestMethod */
$digestValue = $doc->createElementNS("http://www.w3.org/2000/09/xmldsig#",
"DigestValue", $digValue);
$digMethod->parentNode->appendChild($digestValue);
/* Following is done in example only to add proper whitespacing */
if ($addPrev)
{
$digMethod->parentNode->insertBefore($addPrev, $digestValue);
$digMethod->parentNode->removeChild($digMethod->nextSibling);
}
if ($addPost)
{
$digMethod->parentNode->appendChild($addPost);
9
}
/* End addition of whitespaces */
}
else
{
print "Unhandled Encoding";
exit;
}
Esse trecho de código encontra o algoritmo para o resumo e, se puder ser manipulado, ele continua
o processamento. Neste caso, você está lidando apenas com SHA1. O hash SHA1 da forma
canônica anteriormente obtido é convertido em forma binária. A função sha1 () está sendo usada,
porque é disponível por padrão no PHP. Para evitar a conversão do valor em formato binário, você
pode usar mhash, $ bhash = mhash (MHASH_SHA1, $ canonical) ;, porque retorna o hash como
um binário do que como um hexadecimal. Em qualquer caso, o valor binário é então codificado em
Base64. Um elemento DigestValue é criado usando o método createElementNS e passando o valor
codificado.
O código adicional para manipulação de espaços em branco não é necessário ao gerar uma
assinatura.
A razão pela qual foi adicionado neste exemplo é porque o espaço em branco é significativo em
termos canônicos.
Formato. Para apresentar um documento em uma forma facilmente apresentável, como a mostrada
na Listagem 12-2, Eu adicionei espaços em branco. Esses espaços em branco estão incluídos em
uma assinatura para apresentar você com um formato legível, bem como valores corretos para o
DigestValue e SignatureValue elementos.
Gerando uma Assinatura
Geração de assinatura envolve o uso da chave, que neste caso é a string "secreta", para aplicar
o algoritmo especificado pelo Algorithm no elemento SignatureMethod para o SignedInfo
elemento em forma canônica. Desta vez, a forma canônica é gerada usando o método especificado
pelo elemento CanonicalizationMethod. Em vez de explicar cada passo no processo, porque você
deve ter experiência suficiente neste momento para encontrar nós e valores, vou demonstrar apenas
os passos específicos para gerar a assinatura. Dito isto, o as seguintes variáveis e valores serão
assumidos:
• $canonMethod: "http://www.w3.org/TR/2001/REC-xml-c14n-20010315";
• $signedInfo: DOMElement for SignedInfo element
• $Object: DOMElement for Object element
• $key: "secret";
A Listagem 12-4 define uma função HMAC genérica. Para usar a função sha1 () sem dependências
adicionais, usarei a função na Listagem 12-4 dentro do exemplo.
Listing 12-4. Generic HMAC Function
function hmac($key, $data)
{
$b = 64; // byte length
if (strlen($key) > $b) {
$key = pack("H*", sha1($key));
10
}
$key = str_pad($key, $b, chr(0x00));
$ipad = str_pad('', $b, chr(0x36));
$opad = str_pad('', $b, chr(0x5c));
$k_ipad = $key ^ $ipad;
$k_opad = $key ^ $opad;
return sha1($k_opad . pack("H*", sha1($k_ipad . $data)));
}
O processo para gerar a assinatura é semelhante a gerar o resumo. Diferente o conjunto de nós é
usado e o HMAC SHA1 está sendo executado; no entanto, neste exemplo, o elemento SignedInfo
está sendo convertido em sua forma canônica e o algoritmo de assinatura é aplicado.
O valor resultante é então definido como o conteúdo para o elemento SignatureValue e anexado
como um filho para o elemento de assinatura. Por exemplo:
$dom = new DOMDocument();
$copyInfo = $dom->importNode($signedInfo, TRUE);
$dom→appendChild($copyInfo);
/*
A seguir funciona apenas com o PHP 5.1 e superior. LIBXML_NOEMPTYTAG usado para
Crie tags de início e fim para elementos vazios. Elemento do documento $
copyInfo passado para despejar o nó, que não gera uma saída de declaração XML
*/
$canonical = $dom->saveXML($copyInfo, LIBXML_NOEMPTYTAG);
/* Calculate HMAC SHA1 */
$hmac = hmac($key, $canonical);
print $hmac . "n";
$bhmac = base64_encode(pack("H*", $hmac));
/* Handle whitespaces for presentation layout */
$addPrev = NULL;
$addPost = NULL;
if ($Object->previousSibling->nodeType == XML_TEXT_NODE) {
$addPrev = clone $Object->previousSibling;
}
if ($Object->nextSibling->nodeType == XML_TEXT_NODE) {
$addPost = clone $Object->nextSibling;
}
/* END Handle whitespaces for presentation layout */
/*
Create and append the SignatureValue element as child of Signature element
insertBefore used with whitespacing to generate output in Listing 12-2.
*/
$sigValue = $doc->createElementNS("http://www.w3.org/2000/09/xmldsig#",
"SignatureValue", $bhmac);
if ($addPrev) {
$Object->parentNode->insertBefore($sigValue, $Object->previousSibling);
}
else {
$Object->parentNode->insertBefore($sigValue, $Object);
}
11
/* Following is done in example only to add proper whitespacing */
if ($addPost) {
$Object->parentNode->insertBefore($addPrev, $sigValue);
}
print $doc->saveXML();
O documento resultante deve ser exatamente igual ao documento da Listagem 12-2, até
os mesmos espaços em branco usados.
Tradução: Diogo Rocha
12

Mais conteúdo relacionado

Semelhante a Livro: pro php xml and web services xml signature

A e xtensible markup language (xml)
A e xtensible markup language (xml)A e xtensible markup language (xml)
A e xtensible markup language (xml)Liliana Costa
 
XML e Banco de Dados XML Nativo
XML e Banco de Dados XML NativoXML e Banco de Dados XML Nativo
XML e Banco de Dados XML NativoGPrimola
 
Arquitetura: XML + RDF ate WebSemantica
Arquitetura: XML + RDF ate WebSemanticaArquitetura: XML + RDF ate WebSemantica
Arquitetura: XML + RDF ate WebSemanticaSergio Crespo
 
Modelo de segurança OPC UA
Modelo de segurança OPC UAModelo de segurança OPC UA
Modelo de segurança OPC UADalton Valadares
 
Architecture In A Box - Declarações e Identidades Na Computação Na Nuvem
Architecture In A Box - Declarações e Identidades Na Computação Na NuvemArchitecture In A Box - Declarações e Identidades Na Computação Na Nuvem
Architecture In A Box - Declarações e Identidades Na Computação Na NuvemMarkus Christen
 
Desenvolvimento de apps e games para android parte 8
Desenvolvimento de apps e games para android   parte 8Desenvolvimento de apps e games para android   parte 8
Desenvolvimento de apps e games para android parte 8Erisvaldo Junior
 
Web services, aplicações, acesso a aplicações, XML, API
Web services, aplicações, acesso a aplicações, XML, APIWeb services, aplicações, acesso a aplicações, XML, API
Web services, aplicações, acesso a aplicações, XML, APINuno Pereira
 
Webservices e Xml
Webservices e XmlWebservices e Xml
Webservices e Xmlsys10
 
http https Professor Marlon Sales
http https Professor Marlon Saleshttp https Professor Marlon Sales
http https Professor Marlon Salesmarloninternet
 

Semelhante a Livro: pro php xml and web services xml signature (20)

JWT - Json Web Token
JWT - Json Web TokenJWT - Json Web Token
JWT - Json Web Token
 
A e xtensible markup language (xml)
A e xtensible markup language (xml)A e xtensible markup language (xml)
A e xtensible markup language (xml)
 
Java e XML
Java e XMLJava e XML
Java e XML
 
XML e Banco de Dados XML Nativo
XML e Banco de Dados XML NativoXML e Banco de Dados XML Nativo
XML e Banco de Dados XML Nativo
 
XML
XMLXML
XML
 
Arquitetura: XML + RDF ate WebSemantica
Arquitetura: XML + RDF ate WebSemanticaArquitetura: XML + RDF ate WebSemantica
Arquitetura: XML + RDF ate WebSemantica
 
XML_WS.pdf
XML_WS.pdfXML_WS.pdf
XML_WS.pdf
 
Curso de xml
Curso de xmlCurso de xml
Curso de xml
 
Tp 4 xml
Tp 4   xmlTp 4   xml
Tp 4 xml
 
Modelo de segurança OPC UA
Modelo de segurança OPC UAModelo de segurança OPC UA
Modelo de segurança OPC UA
 
Parte5 xml
Parte5 xmlParte5 xml
Parte5 xml
 
Architecture In A Box - Declarações e Identidades Na Computação Na Nuvem
Architecture In A Box - Declarações e Identidades Na Computação Na NuvemArchitecture In A Box - Declarações e Identidades Na Computação Na Nuvem
Architecture In A Box - Declarações e Identidades Na Computação Na Nuvem
 
Web service
Web serviceWeb service
Web service
 
Desenvolvimento de apps e games para android parte 8
Desenvolvimento de apps e games para android   parte 8Desenvolvimento de apps e games para android   parte 8
Desenvolvimento de apps e games para android parte 8
 
Web services, aplicações, acesso a aplicações, XML, API
Web services, aplicações, acesso a aplicações, XML, APIWeb services, aplicações, acesso a aplicações, XML, API
Web services, aplicações, acesso a aplicações, XML, API
 
Maria certificado
Maria certificadoMaria certificado
Maria certificado
 
Webservices e Xml
Webservices e XmlWebservices e Xml
Webservices e Xml
 
Banco de Dados XML
Banco de Dados XMLBanco de Dados XML
Banco de Dados XML
 
12 sax
12 sax12 sax
12 sax
 
http https Professor Marlon Sales
http https Professor Marlon Saleshttp https Professor Marlon Sales
http https Professor Marlon Sales
 

Último

ATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docx
ATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docxATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docx
ATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docx2m Assessoria
 
Luís Kitota AWS Discovery Day Ka Solution.pdf
Luís Kitota AWS Discovery Day Ka Solution.pdfLuís Kitota AWS Discovery Day Ka Solution.pdf
Luís Kitota AWS Discovery Day Ka Solution.pdfLuisKitota
 
Programação Orientada a Objetos - 4 Pilares.pdf
Programação Orientada a Objetos - 4 Pilares.pdfProgramação Orientada a Objetos - 4 Pilares.pdf
Programação Orientada a Objetos - 4 Pilares.pdfSamaraLunas
 
Boas práticas de programação com Object Calisthenics
Boas práticas de programação com Object CalisthenicsBoas práticas de programação com Object Calisthenics
Boas práticas de programação com Object CalisthenicsDanilo Pinotti
 
ATIVIDADE 1 - ESTRUTURA DE DADOS II - 52_2024.docx
ATIVIDADE 1 - ESTRUTURA DE DADOS II - 52_2024.docxATIVIDADE 1 - ESTRUTURA DE DADOS II - 52_2024.docx
ATIVIDADE 1 - ESTRUTURA DE DADOS II - 52_2024.docx2m Assessoria
 
Padrões de Projeto: Proxy e Command com exemplo
Padrões de Projeto: Proxy e Command com exemploPadrões de Projeto: Proxy e Command com exemplo
Padrões de Projeto: Proxy e Command com exemploDanilo Pinotti
 
ATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docx
ATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docxATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docx
ATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docx2m Assessoria
 
ATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docx
ATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docxATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docx
ATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docx2m Assessoria
 

Último (8)

ATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docx
ATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docxATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docx
ATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docx
 
Luís Kitota AWS Discovery Day Ka Solution.pdf
Luís Kitota AWS Discovery Day Ka Solution.pdfLuís Kitota AWS Discovery Day Ka Solution.pdf
Luís Kitota AWS Discovery Day Ka Solution.pdf
 
Programação Orientada a Objetos - 4 Pilares.pdf
Programação Orientada a Objetos - 4 Pilares.pdfProgramação Orientada a Objetos - 4 Pilares.pdf
Programação Orientada a Objetos - 4 Pilares.pdf
 
Boas práticas de programação com Object Calisthenics
Boas práticas de programação com Object CalisthenicsBoas práticas de programação com Object Calisthenics
Boas práticas de programação com Object Calisthenics
 
ATIVIDADE 1 - ESTRUTURA DE DADOS II - 52_2024.docx
ATIVIDADE 1 - ESTRUTURA DE DADOS II - 52_2024.docxATIVIDADE 1 - ESTRUTURA DE DADOS II - 52_2024.docx
ATIVIDADE 1 - ESTRUTURA DE DADOS II - 52_2024.docx
 
Padrões de Projeto: Proxy e Command com exemplo
Padrões de Projeto: Proxy e Command com exemploPadrões de Projeto: Proxy e Command com exemplo
Padrões de Projeto: Proxy e Command com exemplo
 
ATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docx
ATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docxATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docx
ATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docx
 
ATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docx
ATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docxATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docx
ATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docx
 

Livro: pro php xml and web services xml signature

  • 1. Livro: Pro PHP XML and Web Services Introdução a Estrutura Xml Signature As assinaturas XML podem verificar a integridade e a origem dos dados e se os dados não foram alterados de seu estado original. Isso é feito usando chaves. Um dos métodos mais comuns usados é o método de envelopamento com chaves públicas e privadas. O autor de um documento usaria uma chave privada para assinar os dados. Isso criaria uma assinatura digital, que é então adicionada a um documento XML. O destinatário, que deve ter uma cópia da chave pública do autor, usaria essa chave para verificar os dados assinados. Após uma verificação bem-sucedida, o destinatário sabe três coisas: • O autor é o originador genuíno do documento, conhecido como autenticação do assinador. • Os dados não foram alterados em sua forma original, que é chamada de integridade. • Nem os dados nem a soma de verificação foram adulterados, o que pode ocorrer se alguém está tentando alterar os dados, mantendo a integridade dos dados, a fim de enganar o receptor dos dados. Isso é comumente conhecido como autenticação de mensagem. A especificação de sintaxe e processamento de assinatura XML (http://www.w3.org/TR/ xmldsig-core/) especifica as regras de sintaxe e processamento para criar e representar assinaturas. É chamado assim porque usa a sintaxe XML para a assinatura. Você pode aplicar assinaturas XML para praticamente qualquer tipo de dados digitais, incluindo dados em um documento XML como recursos remotos acessíveis a partir de um URI. Entendendo os Tipos de Assinaturas Existem três tipos de assinaturas XML: assinaturas envelopadas (enveloped signatures), assinaturas envolvidas (enveloping signatures) e assinaturas destacadas (detached signatures). Assinaturas Envelopadas (Enveloped Signatures) Assinaturas envelopadas são assinaturas contidas no conteúdo XML que está sendo assinado. Em termos simples, uma assinatura envelopada é uma estrutura de assinatura XML que é uma ficha de um documento assinado. Por exemplo: <mydocument> <mydata1>some data</mydata1> <mydata2>more data</mydata2> <Signature> <!-- Signature Data --> </Signature> </mydocument> A assinatura XML, é definida pelo elemento Signature e seu conteúdo, e é colocada dentro do documento que está sendo assinado. Neste caso, os dados incluiriam os dados do elemento mydocument e todo o seu conteúdo, mas exclui a estrutura de assinatura XML real, que começa com o elemento Signature. 1
  • 2. Assinaturas Envolvidas (Enveloping Signatures) Assinaturas XML também podem ser envolvidas. Isso significa que os dados que estão sendo assinados residem na estrutura de assinatura XML: <mydocument> <mydata2>more data</mydata2> <Signature> <!-- Signature Data including the reference to the Object element --> <Object Id="mydata"> <mydata1>some data</mydata1> </Object> </Signature> </mydocument> Embora a estrutura da assinatura XML não precise ser incorporada em um XML documento desde a sua estrutura está no formato XML, eu mostrei desta forma porque você não foi introduzido na estrutura e como uma assinatura envolvente pode ser encapsulada dentro de outro documento, para o qual o documento de encapsulamento não tem tendo na assinatura. Nesse caso, a assinatura incluiria uma referência ao elemento Object. Os dados dentro do elemento Object são os dados que estão sendo assinados. Vou explicar como dados de referência mais adiante na seção “Apresentando a Estrutura de Assinatura XML”. Assinaturas Destacadas (Detached Signatures) Assinaturas envelopadas significa que a assinatura é encapsulada em um documento que está sendo assinado. Não é necessário que todo o documento seja assinado, e é bem possível que você tenha apenas um único elemento no documento assinado. De fato, também é bem possível que os dados ser assinado nem mesmo vive dentro do documento e reside remotamente e é acessível através de um URI. Assinaturas destacadas são usadas apenas para esses propósitos: <mydocument> <mydata2>more data</mydata2> <Signature> <!-- Signature Data including the reference to the Object element --> </Signature> <Object Id="mydata"> <mydata1>some data</mydata1> </Object> </mydocument> Com este exemplo, os dados dentro do elemento Object estão sendo assinados novamente. Desta vez, no entanto, o elemento está fora da assinatura e a assinatura está sendo aplicada apenas a esse elemento em particular e não o documento inteiro: <Signature> <!-- Signature Data including the reference to remote data --> </Signature> Este exemplo refere-se aos dados que estão sendo assinados e que residem inteiramente fora do documento. Em vez que referenciando o elemento Object dos exemplos anteriores, a assinatura 2
  • 3. XML, neste exemplo, faz referência a dados remotos usando um URI. Mais uma vez, explicarei isso em detalhes na seção "Apresentando a Estrutura de Assinatura XML" quando eu dividir a estrutura. Assim como no exemplo anterior, também seria válido encapsular a assinatura XML em um documento, e o documento não tem relação com a assinatura ou os dados referenciados. Apresentando a estrutura de assinatura XML A estrutura das assinaturas XML pode ficar bastante complexa. Um livro inteiro poderia ser escrito sobre este assunto. Por esse motivo, vou manter as coisas simples e cobrir apenas a sintaxe principal. Este capítulo apresentará como criar e verificar assinaturas XML básicas usando o PHP. Depois de você entender isso, você deverá ser capaz de implementar assinaturas mais avançadas com base nas especificações. O documento na Listagem 12-2 ilustra uma assinatura de envelope válida. Os dados que estão sendo assinados neste caso é o elemento Object. Ele fica dentro do elemento Signature, criando assim uma assinatura envolvente. Usando este exemplo, você verá agora como o XML assinatura é composta e estruturada. 3
  • 4. Elemento Signature O elemento Signature é a raiz de uma assinatura XML e está vinculado ao namespace http://www.w3.org/2000/09/xmldsig#. Este elemento contém todas as informações necessárias para verificar Assinatura XML. Elemento SignatureValue O elemento SignatureValue contém o valor codificado em Base64 da assinatura digital real, que na Listagem 12-2 é o valor OUubDO2l6XUIODuLSjKAtjYlaTk =. Explicarei como calcular este valor mais tarde na seção "Gerando uma assinatura", bem como quando você entrar na verdade gerando uma assinatura XML. Elemento SignedInfo O elemento SignedInfo é um elemento contêiner que fornece informações sobre como uma assinatura é processada, a localização dos dados assinados e o valor da integridade dos dados. Esse elemento também aceita um atributo Id opcional. Usando este atributo permite que o elemento ser referenciado por outras assinaturas ou objetos. Elemento CanonicalizationMethod O elemento CanonicalizationMethod define o tipo de canonização que deve ser aplicado ao elemento SignedInfo ao processar uma assinatura digital. As implementações devem pelo menos suporte a XML canônico sem comentários, conforme observado pelo valor http://www.w3.org/TR/2001/REC-xml-c14n-20010315. Outros valores possíveis incluem, mas não estão limitados a, http://www.w3.org/TR / 2001 / REC- xml-c14n-20010315 # ComComments, que é XML canônico com comentários e http://www.w3.org/TR/xml-exc-c14n/, que é XML canônico exclusivo. Conforme mostrado na Listagem 12-2, o valor para este elemento é http://www.w3.org/TR/2001/REC-xml-c14n-20010315, então canonical XML processará o elemento SignedInfo. Elemento SignatureMethod O elemento SignatureMethod especifica o algoritmo usado para criar e verificar a assinatura digital. Dependendo do algoritmo usado, esse elemento pode ter elementos filho, como HMACOutputLength, para fornecer informações adicionais para o algoritmo. Você especifica o real algoritmo a ser utilizado no atributo Algorithm. Os algoritmos são especificados por URI e definem a regra. Você pode encontrar alguns dos valores possíveis em http://www.w3.org/TR/xmldsig-core/ # sec-AlgID dentro da especificação. O valor usado na Listagem 12-2 é http://www.w3.org/2000/ 09/xmldsig#hmac-sha1, que corresponde ao HMAC-SHA1. Então, agora é seguro assumir que o HMAC-SHA1 é o algoritmo usado neste capítulo para assinaturas digitais. Elemento Reference Elementos de referência especificam quais dados são assinados. Você pode usar mais de um elemento de referência. Para o bem deste capítulo, no entanto, as assinaturas digitais usadas aqui conterão apenas um unico 4
  • 5. Elemento de referência. Esse elemento pode pegar qualquer um dos três atributos opcionais. Você pode usar um ID atributo para que o elemento possa ser facilmente referenciado a partir de outros locais. O atributo Type é um URI que especifica o tipo de dados. Por exemplo, o atributo pode ser Type = "http://www.w3.org/2000/09/xmldsig#Object" ou Type = "http://www.w3.org/2000/09/xmldsig#Manifest" . O valor não tem qualquer influência sobre como a assinatura é gerada. Pode, no entanto, ser usado por um aplicativo para seu próprio propósito. O último atributo opcional é o URI. Isso tem muito mais impacto nos dados do que os outros atributos. O atributo URI identifica o local do objeto de dados, usando um URI como seu valor. o atributo é considerado opcional, porque é possível que uma aplicação já saiba onde os dados residem. Por exemplo, se a mesma estrutura XML é sempre usada, pode ser acordado tanto pelo autor como pelo destinatário do documento, um determinado elemento no documento será sempre assinado. Normalmente, porém, é mais seguro incluir sempre um URI. O exemplo em A Listagem 12-2 está usando dados que estão localizados no documento. O atributo URI tem o valor #objeto. Isso identifica o conjunto de nós que contém o elemento com um ID, definido pelo atributo Id, do objeto. Nota: O elemento Transforms, que é um filho opcional de um elemento Reference, será omitido do este capítulo. Seu uso está fora do escopo, porque é um pouco avançado neste momento tentar usar o atual Funcionalidade XML em PHP. Elemento DigestMethod O elemento DigestMethod define o algoritmo aplicado aos dados que estão sendo assinados. Você especifica o algoritmo real usando um URI para o valor do atributo Algorithm. Este atributo funciona da mesma maneira que aquele localizado no elemento SignatureMethod. O exemplo na Listagem 12-2 usou o valor http://www.w3.org/2000/09/xmldsig#sha1. O resumo será calculado usando um hash SHA1. Elemento DigestValue O elemento DigestValue contém o valor codificado em Base64 do resumo. Usando a assinatura da Listagem 12-2, o resumo é simplesmente o hash SHA1 da forma canônica dos dados sendo assinado. Não se preocupe se você não entender completamente isso neste momento. Isso será feito extremamente claro quando formos criar e verificar as assinaturas nas sessões “Criando uma Assinatura” e “Verificando uma Assinatura”. Elemento KeyInfo O elemento KeyInfo é um elemento opcional que pode permitir que os destinatários obtenham as chaves, certificados ou informações de gerenciamento de chaves públicas. A assinatura XML neste capítulo usa a string "secret", que é privada e conhecida apenas pelo autor e destinatário porque do algoritmo especificado no elemento SignatureMethod. Outros algoritmos usam público / privado pares de chaves, tornando perfeitamente viável incluir chaves públicas, certificados ou informações sobre acessando uma chave pública dentro da assinatura XML. Esse elemento serve como um contêiner para fornecer as informações necessárias, que podem estar 5
  • 6. contidas em qualquer número de possíveis elementos filho. O conteúdo de um elemento KeyName é uma string contendo um identificador de chave para o destinatário. Indica à informação do destinatário que chave para usar no documento. Um elemento KeyValue define uma única chave pública, como DSA ou RSA chaves públicas, que podem verificar e validar a assinatura. Você pode usar um elemento Retrieval para informações de referência KeyInfo armazenadas em outro local. Tem um atributo URI e Type e funciona da mesma maneira que um elemento de referência. Os restantes elementos possíveis, X509Data, PGPData, SPKIData e MgmtData são usados dependendo do tipo de algoritmo usado. Por exemplo, você pode usar certificados X509 e um elemento X509Data pode conter certificado cadeias, listas de revogação ou um SubjectKeyIdentifier. Mais uma vez, esses elementos estão fora do escopo deste capítulo, mas são abordadas com mais detalhes na especificação em http://www.w3.org/TR / xmldsig-core / # sec-KeyInfo. Elemento ObjectElemento Object Um elemento Object é um contêiner para armazenar qualquer tipo de dado. Tem três atributos opcionais. O atributo Id é um ID usado para referenciar o elemento. A assinatura XML na Listagem 12-2 usa o objeto de nome para o atributo Id, que é então referenciado pelo elemento Reference através do seu atributo URI. Um atributo MimeType especifica o tipo MIME dos dados. O valor que deve ser um tipo MIME válido, conforme definido no RFC 2045 (http://www.ietf.org/rfc/rfc2045.txt). O último atributo é Encoding. O valor define a codificação usada no objeto. Os atributos MimeType e Encoding são puramente informativos. É completamente até o aplicativo se eles precisam ser usados. Criando uma Assinatura Criar uma assinatura envolve gerar os elementos Reference e SignatureValue. O resto das informações dentro de um elemento Signature define como os valores são gerados ou, quando usando uma assinatura envolvente, podem ser dados que estão sendo assinados. Os primeiros passos são determinar o tipo de algoritmo de criptografia que será usado e determinar quais regras devem ser usado quando a assinatura é criada; eles também determinam as regras que um aplicativo deve seguir para verificar a assinatura. Nesse caso, a assinatura XML que está sendo criada é aquela na Listagem 12-2. A seguir uma lista de regras que serão usadas para criar a assinatura: • A assinatura será envolvente. O elemento Reference se referirá a um elemento Object com o objeto Id dentro do documento. Especificamente, o elemento Object será um filho do elemento Signature. • A canonização XML será usada. Isso determina o valor do atributo Algorithm no elemento CanonicalizationMethod. • HMAC SHA1, usando a string "secret" para a chave, será usado para a assinatura. este determina o valor do atributo Algorithm no elemento SignatureMethod. • SHA1 será usado para a integridade da mensagem. Isso determina o valor do Algorithm atributo no elemento DigestMethod. 6
  • 7. Com base nessa lista, você pode criar uma assinatura esquelética, conforme mostrado na Listagem 12-3. Listing 12-3. Skeleton Enveloping Signature Document <Signature xmlns="http://www.w3.org/2000/09/xmldsig#"> <SignedInfo> <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n- 20010315" /> <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#hmac-sha1" /> <Reference URI="#object"> <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /> </Reference> </SignedInfo> <Object Id="object">Hello World!</Object> </Signature> Nota: Um elemento Reference é criado para cada objeto de dados que está sendo assinado. Este exemplo tem apenas um único objeto de dados, de modo que o elemento de referência foi criado com o esqueleto geral em vez de gerá-los porque os elementos DigestValue são calculados para cada objeto de dados. A única informação dentro do esqueleto não mencionada na lista é o texto Hello World!; esse texto, bem como o elemento Object, é a mensagem a ser assinada. As últimas etapas aqui são para gerar o DigestValue e gerar a assinatura real. Gerando a Referência De acordo com a especificação, os DigestValues são criados enquanto os elementos Reference são criados. A razão para isso é que vários objetos podem ser usados em uma única assinatura XML. Nesse caso, os dados são simples e o elemento de referência que aponta para os dados já foi criado. Nenhuma transformação está sendo usada, portanto, você pode mover diretamente para o cálculo DigestValue. Isso é calculado executando as seguintes etapas: 1. Obtenha os dados brutos especificados pelo elemento Reference. Neste caso, é o Object elemento. 2. Aplique quaisquer transformações. Este exemplo não usa nenhum. 3. Se as transformações (ou os dados brutos no evento não houver transformações definidas) resultarem em conjunto de nós, use o XML canônico para serializar o conjunto de nós. Neste exemplo, não há mudança, e os dados brutos são o elemento Object. Canonicalização realizada neste passo é verdadeiro XML canônico, que significa inclusivo. O valor do método do elemento canonização não tem nenhuma influência nesta etapa porque esse elemento pertence à geração de assinatura e não à geração de referência. 4. Usando o algoritmo especificado pelo elemento DigestMethod, calcule o DigestValue usando os dados resultantes da etapa 3. 7
  • 8. 5. Adicione o DigestValue à árvore. Novamente, as especificações criam o elemento Reference durante essas etapas, portanto, se você decidir seguir esse método ou tiver uma assinatura complexa exigindo que as etapas sejam executadas dessa maneira, crie o elemento Referência e seus filhos neste momento e anexá-lo como filho ao elemento SignedInfo. Na etapa 1, os dados brutos são o elemento Object. Para este exemplo, vou usar a variável $ doc, que representa a assinatura esquelética da Listagem 12-3. Isso pode ser carregado de um arquivo ou ser construído manualmente usando os métodos DOM do Capítulo 6. Cuidado Ao criar o documento de assinatura manualmente usando a API do DOM, o elemento Signature define o namespace padrão http://www.w3.org/2000/09/xmldsig#. Elementos dentro de seu escopo devem ser criado usando métodos de reconhecimento de namespace, como createElementNS, para que isso funcione corretamente. For example: $xPath = new DOMXpath($doc); /* Following line split into two lines because of length */ $query = '//*[local-name()="Reference" and '. 'namespace-uri()="http://www.w3.org/2000/09/xmldsig#"]'; $nodeset = $xPath->query($query); $refElement = $nodeset->item(0); $dataURI = $refElement->getAttribute("URI"); Isso retorna o valor #object. Como um DTD não foi especificado, você não consegue recupera o elemento Object usando o método getElementByID do DOM. Você deve fazer isso manualmente. Você pode usar o seguinte código para executar esta operação. Note que ele assume o O valor do URI contém um ID e não um URL para dados externos: $ID = substr ($dataURI, 1); $query = '//*[@Id="'.$ID.'"]'; $nodeset = $xPath->query($query); $Object = $nodeset->item(0); A variável $ Object resultante deve ser um objeto DOMElement que referencia o objeto elemento no documento. Serialização usando $ doc-> saveXML ($ Object) deve produzir o Segue: <Object Id="object">Hello World!</Object> Não há Transformações e o resultado da primeira etapa é um conjunto de nós contendo o Object elemento. Este conjunto de nós (read: element) deve ser serializado em forma canônica: <Object xmlns="http://www.w3.org/2000/09/xmldsig#" Id="object">some text</Object> O XML canônico é usado aqui, o que é inclusivo. Isso significa que o namespace padrão definido pelo elemento Signature, que é um ancestral do elemento Object, é serializado com o nó Object. Uma maneira rápida e simples de canonizar esse elemento é copiá-lo para outro documento e serializando o novo documento. A cópia deve ser uma cópia profunda para que 8
  • 9. todos os atributos e filhos são copiados. Durante a cópia, como esse nó se torna o nó de nível superior, o namespace padrão herdado é recriado na cópia. Por causa da estrutura da assinatura XML e dos dados com os quais você está trabalhando, essa é a única coisa que você precisa fazer antes da serialização para resultar na forma canônica correta. Para estruturas mais complexas, você precisaria usar as técnicas descritas na seção “Introdução à Canonical XML”: $dom = new DOMDocument(); $copyObject = $dom->importNode($Object, TRUE); $dom→appendChild($copyObject); Cuidado Isso funciona apenas porque o conteúdo do elemento Object é um texto simples e não um XML subárvore. Se o conteúdo fosse uma subárvore, você precisaria aplicar as regras e técnicas descritas na “Introdução à XML canônica”, de modo que os namespaces e os atributos em particular sejam gerados corretamente. Usando o algoritmo do elemento DigestMethod, a forma canônica dos dados gera o resumo. Este valor é então codificado usando codificação Base64 e definido como o conteúdo de o elemento DigestValue: $query = '//*[local-name()="DigestMethod" and ' . 'namespace- uri()="http://www.w3.org/2000/09/xmldsig#"]'; $nodeset = $xPath->query($query); $digMethod = $nodeset->item(0); $algorithm = $digMethod->getAttribute("Algorithm"); if ($algorithm == "http://www.w3.org/2000/09/xmldsig#sha1") { $canonical = $dom->saveXML($copyObject); /* Create SHA1 hash of the canonical form of the Object element */ $hash = sha1($canonical); $bhash = pack("H*", $hash); $digValue = base64_encode($bhash); /* Following is done in example only to add proper whitespacing */ $addPrev = NULL; $addPost = NULL; if ($digMethod->previousSibling->nodeType == XML_TEXT_NODE) { $addPrev = clone $digMethod->previousSibling; } if ($digMethod->nextSibling->nodeType == XML_TEXT_NODE) { $addPost = clone $digMethod->nextSibling; } /* End custom whitespaces */ /* Create DigestValue element, and append to parent of DigestMethod */ $digestValue = $doc->createElementNS("http://www.w3.org/2000/09/xmldsig#", "DigestValue", $digValue); $digMethod->parentNode->appendChild($digestValue); /* Following is done in example only to add proper whitespacing */ if ($addPrev) { $digMethod->parentNode->insertBefore($addPrev, $digestValue); $digMethod->parentNode->removeChild($digMethod->nextSibling); } if ($addPost) { $digMethod->parentNode->appendChild($addPost); 9
  • 10. } /* End addition of whitespaces */ } else { print "Unhandled Encoding"; exit; } Esse trecho de código encontra o algoritmo para o resumo e, se puder ser manipulado, ele continua o processamento. Neste caso, você está lidando apenas com SHA1. O hash SHA1 da forma canônica anteriormente obtido é convertido em forma binária. A função sha1 () está sendo usada, porque é disponível por padrão no PHP. Para evitar a conversão do valor em formato binário, você pode usar mhash, $ bhash = mhash (MHASH_SHA1, $ canonical) ;, porque retorna o hash como um binário do que como um hexadecimal. Em qualquer caso, o valor binário é então codificado em Base64. Um elemento DigestValue é criado usando o método createElementNS e passando o valor codificado. O código adicional para manipulação de espaços em branco não é necessário ao gerar uma assinatura. A razão pela qual foi adicionado neste exemplo é porque o espaço em branco é significativo em termos canônicos. Formato. Para apresentar um documento em uma forma facilmente apresentável, como a mostrada na Listagem 12-2, Eu adicionei espaços em branco. Esses espaços em branco estão incluídos em uma assinatura para apresentar você com um formato legível, bem como valores corretos para o DigestValue e SignatureValue elementos. Gerando uma Assinatura Geração de assinatura envolve o uso da chave, que neste caso é a string "secreta", para aplicar o algoritmo especificado pelo Algorithm no elemento SignatureMethod para o SignedInfo elemento em forma canônica. Desta vez, a forma canônica é gerada usando o método especificado pelo elemento CanonicalizationMethod. Em vez de explicar cada passo no processo, porque você deve ter experiência suficiente neste momento para encontrar nós e valores, vou demonstrar apenas os passos específicos para gerar a assinatura. Dito isto, o as seguintes variáveis e valores serão assumidos: • $canonMethod: "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"; • $signedInfo: DOMElement for SignedInfo element • $Object: DOMElement for Object element • $key: "secret"; A Listagem 12-4 define uma função HMAC genérica. Para usar a função sha1 () sem dependências adicionais, usarei a função na Listagem 12-4 dentro do exemplo. Listing 12-4. Generic HMAC Function function hmac($key, $data) { $b = 64; // byte length if (strlen($key) > $b) { $key = pack("H*", sha1($key)); 10
  • 11. } $key = str_pad($key, $b, chr(0x00)); $ipad = str_pad('', $b, chr(0x36)); $opad = str_pad('', $b, chr(0x5c)); $k_ipad = $key ^ $ipad; $k_opad = $key ^ $opad; return sha1($k_opad . pack("H*", sha1($k_ipad . $data))); } O processo para gerar a assinatura é semelhante a gerar o resumo. Diferente o conjunto de nós é usado e o HMAC SHA1 está sendo executado; no entanto, neste exemplo, o elemento SignedInfo está sendo convertido em sua forma canônica e o algoritmo de assinatura é aplicado. O valor resultante é então definido como o conteúdo para o elemento SignatureValue e anexado como um filho para o elemento de assinatura. Por exemplo: $dom = new DOMDocument(); $copyInfo = $dom->importNode($signedInfo, TRUE); $dom→appendChild($copyInfo); /* A seguir funciona apenas com o PHP 5.1 e superior. LIBXML_NOEMPTYTAG usado para Crie tags de início e fim para elementos vazios. Elemento do documento $ copyInfo passado para despejar o nó, que não gera uma saída de declaração XML */ $canonical = $dom->saveXML($copyInfo, LIBXML_NOEMPTYTAG); /* Calculate HMAC SHA1 */ $hmac = hmac($key, $canonical); print $hmac . "n"; $bhmac = base64_encode(pack("H*", $hmac)); /* Handle whitespaces for presentation layout */ $addPrev = NULL; $addPost = NULL; if ($Object->previousSibling->nodeType == XML_TEXT_NODE) { $addPrev = clone $Object->previousSibling; } if ($Object->nextSibling->nodeType == XML_TEXT_NODE) { $addPost = clone $Object->nextSibling; } /* END Handle whitespaces for presentation layout */ /* Create and append the SignatureValue element as child of Signature element insertBefore used with whitespacing to generate output in Listing 12-2. */ $sigValue = $doc->createElementNS("http://www.w3.org/2000/09/xmldsig#", "SignatureValue", $bhmac); if ($addPrev) { $Object->parentNode->insertBefore($sigValue, $Object->previousSibling); } else { $Object->parentNode->insertBefore($sigValue, $Object); } 11
  • 12. /* Following is done in example only to add proper whitespacing */ if ($addPost) { $Object->parentNode->insertBefore($addPrev, $sigValue); } print $doc->saveXML(); O documento resultante deve ser exatamente igual ao documento da Listagem 12-2, até os mesmos espaços em branco usados. Tradução: Diogo Rocha 12