Paulo Cabral

Assinaturas Digitais XML

Desde a sua normalização pelo W3C, a linguagem XML tem vindo a ser adoptada por um número crescente de produtores de software como formato base para os documentos utilizados pelas aplicações que desenvolvem. O crescendo de utilização de documentos neste formato revelou o interesse em definir mecanismos que lhes permitissem aportar as características de segurança (origem, não-repúdio e integridade) adequadas a cenários de utilização mais exigentes. Para colmatar essa lacuna, o W3C definiu posteriormente a norma XMLDSIG. Neste artigo vamos-nos debruçar essencialmente no desenvolvimento em C# de uma pequena API para assinar digitalmente documentos XML.

Introdução e Enquadramento

De acordo com o RFC2828 uma assinatura digital define-se como sendo um valor calculado com um algoritmo criptográfico e anexado ao objecto de dados de tal forma que se possa usar essa assinatura para verificar a autenticidade e integridade dos dados.

A forma de funcionamento de uma assinatura digital XML é extremamente fiável. Respeitando escrupulosamente a terceira regra fundamental da criptografia, a integridade, a assinatura não só assegura que a pessoa que assinou o documento é de facto quem se espera, como também que o mesmo se manteve inalterado em todo o seu percurso digital até ao momento em que chegou ao destinatário. Relembrando noções básicas de criptografia assimétrica, “uma mensagem cifrada com uma chave pública apenas pode ser decifrada com a correspondente chave privada.

Percebendo o W3C XML Digital Signature

A especificação XML é responsável pela definição da informação que é usada na verificação de certificados digitais. Assinaturas digitais em XML são representadas pelo elemento XML Signature que contém uma estrutura com as seguintes regras:

  • * representa zero ou mais ocorrências de “algo”.
  • + representa uma ou mais ocorrências de “algo”.
  • ? representa zero ou uma ocorrência de “algo”.

O seguinte XML descreve uma assinatura segundo a especificação W3C, de acordo com as regras descritas.

<Signature ID?>
  <SignedInfo>
   <CanonicalizationMethod/>
    <SignatureMethod/>
     (<Reference URI?>
       (<Transforms>)?
       <DigestMethod>
       <DigestValue>
      </Reference>)+
  </SignedInfo>
  <SignatureValue>
   (<KeyInfo>)?
   (Object ID?)*
</Signature>

Dissecando a especificação XMLDSIG

O elemento Signature é o construtor primário da assinatura, de acordo com a especificação W3C. A assinatura pode serenvelop ou enveloped pela informação que está a ser assinada, ou por outro lado pode referenciar informação que não consta do ficheiro XML, e neste caso será uma assinatura detached. As assinaturas detached são muito úteis para assinar ficheiros externos ao XML, relembro que não existe qualquer limitação sobre o que se está a assinar.

Etapas de uma assinatura

SignedInfo

O elemento SignedInfo representa a informação que está actualmente assinada. Esta informação é processada sequencialmente por várias etapas no processo de assinatura.

Canonicalization

O elemento CanonicalizationMethod contém o algoritmo que foi usado para canonizar/estruturar a informação, numa forma comum “reconhecida” por todos os intervenientes no processo. Este processo é extremamente importante. A canonização pode definir regras como “a definição de um standard para o EOF, remoção de comentários” ou outra qualquer manipulação de um documento assinado que possamos necessitar.

Reference/Transform

O elemento Reference identifica o recurso que vais ser assinado e os algoritmos para processar a informação. Estes algoritmos estão enunciados no elemento Transform e podem incluir operações de Canonizaçãoencoding/decodingcompressão, ou até XPATH ou transformações XSLT.

O elemento Reference pode conter vários elementos TransformNota: O elemento Reference contém um atributo opcional URI. A inclusão de um URI numa assinatura é opcional se a assinatura possuir apenas um elemento Reference. (www.w3.org/TR/2002/REC-xmldsig-core-20020212).

DigestMethod/DigestValue

O elemento DigestMethod representa o algoritmo aplicado à informação após passar pelo processo de transformação, gerando um valor único representado pelo elemento DigestValue. O DigestValue é uma aplicação ao resultado dos processos de Canonização e transformação, sem qualquer referência directa à informação a ser assinada.

KeyInfo

O elemento KeyInfo é opcional e pode conter a assinatura pública do autor para permitir a verificação da autenticidade do documento “automática”.

Tipos de assinaturas XMLDSIG

As assinaturas XMLDSIG podem ser aplicadas em três formas básicas:

  • Detached: O documento XML a ser assinado e a assinatura estão em dois ficheiros distintos, sendo que esta tem uma referência (URI) ao documento que se propõe a assinar.
<signature> ... </signature>
  • Enveloped: O documento XML e a assinatura surgem no mesmo ficheiro de uma forma sequencial.
<document>
   <signature>...</signature>
</document>
  • Enveloping: O documento e a assinatura estão contidos num envelope XML.
<signature>
   <document>...</document>
</signature>

Relembrar Conceitos

Antes de focar a fase de implementação, é necessário rever alguns aspectos importantes da criptografia, bem como certos aspectos organizacionais presentes no sistema operativo Windows. Comecemos pela Criptografia …

Certificados Digitais

Um certificado digital é um arquivo de computador que contém um conjunto de informações referentes à entidade para o qual o certificado foi emitido (seja uma empresa, pessoa física ou computador), mais a chave pública referente e a chave privada que acredita-se ser de posse unicamente da entidade especificada no certificado.

A anatomia de um certificado X.509

Um certificado padrão X.509 contém os seguintes campos:

Versão
Contem a versão do certificado X.509, actualmente versão 3
Número serie
Todo certificado possui um, não é globalmente único, mas único no âmbito de uma AC, ac LCRs usam o número de serie para apontar quais certificados se encontram revogados.
Tipo de algoritmo
Contem um identificador do algoritmo criptográfico usado pela AC para assinar o certificado juntamente com o tipo de função de hash criptográfica usada no certificado
Nome do titular
Nome da entidade para o qual o certificado foi emitido
Nome do emitente
Autoridade Certificadora que emitiu/assinou o certificado
Período de validade
Mostra o período de validade do certificado no formato “Não antes” e “Não depois” (Ex. “Não antes de 05/03/2006 – 14:35:02” “Não depois de 05/03/2007 – 14:03:20”)
Informações de chave pública da entidade
Algoritmo de chave pública
Chave pública
Assinatura da AC
A garantia que a AC provê sobre a veracidade das informações contidas neste certificado de acordo com as políticas da AC
Identificador da chave do titular
É uma extensão do X.509 que possui um identificador numérico para a chave pública contida neste certificado, especialmente útil para que programas de computador possam se referir a ela
Identificador da chave do emitente
A mesma ideia mencionada anteriormente, só que se referindo a chave pública da AC que emitiu o certificado
Atributos ou extensões
A vasta maioria dos certificados X.509 possui campos chamados extensões (OID) que provêem algumas informações extras, como registos adicionais do titular e do emitente, especificações de propósito do certificado, etc.

Criptografia de chave pública

A criptografia de chave pública ou criptografia assimétrica é um método de criptografia que utiliza um par de chaves: uma chave pública e uma chave privada. A chave pública é distribuída livremente para todos os correspondentes via e-mail ou outras formas, enquanto a chave privada deve ser conhecida apenas pelo seu dono.

Num algoritmo de criptografia assimétrica, uma mensagem cifrada com a chave pública pode somente ser decifrada pela sua chave privada correspondente. Do mesmo modo, uma mensagem cifrada com a chave privada pode somente ser decifrada pela sua chave pública correspondente.

Os algoritmos de chave pública podem ser utilizados para autenticidade e confidencialidade. Para confidencialidade, a chave pública é usada para cifrar mensagens, com isso apenas o dono da chave privada pode decifrá-la. Para autenticidade, a chave privada é usada para cifrar mensagens, com isso garante-se que apenas o dono da chave privada poderia ter cifrado a mensagem que foi decifrada com a chave pública.

RSA

RSA é um algoritmo de cifra de dados, que deve o seu nome a três professores do Instituto MIT (fundadores da actual empresa RSA Data Security, Inc.), Ron Rivest, Adi Shamir e Len Adleman, que inventaram este algoritmo — até à data (2005), a mais bem-sucedida implementação de sistemas de chaves assimétricas, e fundamenta-se em Teorias Clássicas dos Números. É considerado dos mais seguros. Foi também o primeiro algoritmo a possibilitar cifra e assinatura digital, é uma das grandes inovações em criptografia de chave pública.

KeyStore

Uma KeyStore é uma base de dados de chaves. As chaves privadas numa KeyStore possuem uma cadeia de certificados associada, que possibilita a autenticação à correspondente chave pública. Uma KeyStore também possui certificados de entidades confiáveis.

O Sistema operativo Windows possui uma KeyStore própria, onde são armazenados todos os certificados instalados. Existem também uma API embebida no sistema operativo que permite fazer a ponte entre SmarCards com certificados digitais, desde que o hardware possua um leitor de smartcards.

Programing, Programing, Program…

Requisitos

Para Prosseguir é necessário termos instalado no nosso computador uma licença do Windows XP ou Superior, com a Framework .NET v2.0.

Ajuda possuir-mos também uma licença do Visual Studio 2005, se bem que não é obrigatório pois existem alternativas OpenSource bastante completas na WWW.

Geração de um Certificado Digital

Vamos gerar um ficheiro PKCS#12. Um ficheiro PKCS12 é um formato que permite o armazenamento de chaves privadas juntamente com o certificado de chave pública, protegidos por uma palavra-chave. Este ficheiro servirá de base para os testes que vamos produzir ao longo do desenvolvimento. Não é obrigatória a geração deste ficheiro. Podemos criar em RunTime um certificado e exportar as respectivas chaves públicas e privadas. Este passo é apenas um exercício didáctico.

Criação das chaves

makecert.exe -sv MyKey.pvk -n "CN=P@P" MyKey.cer

ser-vos-á pedida uma palavra-chave para a criação da chave privada.

Criação do PKCS#12

pvk2pfx.exe -pvk MyKey.pvk -spc MyKey.cer -pfx cert.pfx -po pwd

Este aplicativo permite criar o ficheiro cert.pfx , protegido pela password pwd.