Por Felipe Bueno
felipesallum@terra.com.br
Felipe é líder da célula UNP .NET de Natal e estudante universitário, fazendo curso de Sistemas de Informação

Criptografia em Documentos Xml no Framework 2.0


Uma nova classe presente no framework 2.0 permite a criptografia de documentos Xml completos ou somente alguns elementos do documento. Esta classe, conhecida como EncryptedXml, é responsável pelo processo de encriptação e decriptação do documento e está contida no namespace System.Security.Cryptography.Xml, o qual abriga todas classes que podem ser utilizadas em conjunto com a classe EncryptedXml para utilização da criptografia.

Todas as classes desse namespace seguem as recomendações do W3C , portanto, um documento ou elemento criptografado com a classe EncryptedXml pode ser facilmente descriptografado por outra classe implementada em outra plataforma, mas que siga as recomendações do W3C .

 

Algoritmos Suportados:

- TripleDes;

- AES 128;

- AES 192;

- AES 256;

- RSA;

- X509CertificateEx;

 

O RSA não é utilizado para a encriptação do documento, mas sim, para encriptação da chave de sessão. A encriptação do documento ou elemento(s) deve ser feita por um algoritmo simétrico suportado (3DES, AES). Já que, geralmente, precisamos dispor o documento para outro sistema não seria interessante dispormos juntamente a chave de encriptação simétrica original. Para isso, utilizamos o RSA para encriptar a chave de sessão.

A chave de sessão criptografada fica junto com o documento Xml em um elemento separado, que armazena ela e a chave RSA, localizada em outro arquivo.

Para descriptografar o documento será necessário antes de tudo, ter a chave RSA para descriptografar a chave de sessão e então utilizá-la para descriptografar o documento.

 

Documento Criptografado:

Um exemplo de documento Xml encriptado e armazenando a chave de sessão criptografada.

 

<? xml version = " 1.0 " standalone = " yes " ?> 
< compras > 
< EncryptedData Type = " http://www.w3.org/2001/04/xmlenc#Element " xmlns = " http://www.w3.org/2001/04/xmlenc# " > 
< EncryptionMethod Algorithm = " http://www.w3.org/2001/04/xmlenc#aes256-cbc " /> 
< KeyInfo xmlns = " http://www.w3.org/2000/09/xmldsig# " > 
< EncryptedKey xmlns = " http://www.w3.org/2001/04/xmlenc# " > 
< EncryptionMethod Algorithm = " http://www.w3.org/2001/04/xmlenc#rsa-1_5 " /> 
< KeyInfo xmlns = " http://www.w3.org/2000/09/xmldsig# " > 
< KeyName > vendas_compartilhada </ KeyName > 
</ KeyInfo > 
< CipherData > < CipherValue > u6FAQmvFdq6BHmqR7TVYe4C9ecI9EMuYPpDxjuEjXS5xZWclQx5D8IAgk4LQRaEYmMVtT00a4WZlGnuAKq+AAxwH9eH8c9Y7JbfKCBOQ6cYkPE/4+qvMtxMqCGCm8uheIQdZWVrTN1iOwgvJUTufxR70/MOYwrIbK7kCVPo5Z44= </ CipherValue > 
</ CipherData > 
</ EncryptedKey > 
</ KeyInfo > 
< CipherData > < CipherValue > gh1g28x/Nr5HQoYLmF4K7JXDUQtP3QtxwY0Ws8ZneUlc4ev8KLTteLLOpHWQYMVaqcU5wO6dQNTbh2Wi9/x/Q2ip2Ci85xpEr1ZwjnunFVwudD/FZm02hVr7NMbzeCmwoKDqWpAa5FUCWHfwG955/T8kflQLCm2ZsQB16INiec5dV6UoTjHqqRHYZ9H1ZPLmZPjt6jkao1L+r67qf9KFUs2EYW/8j/w3ZkntqNXkpS9oBHz6wivFiO2lxh1mrcO05jy7G/ynYg3Il/72cpzdzixsdEHXBxyUv0vLaUIGT/A= </ CipherValue > 
</ CipherData > 
</ EncryptedData > 
</ compras > 

 

O elemento <EncryptedData> contém todos os elementos identificadores dos dados criptografados do documento.

O elemento <EncryptationMethod> define o algoritmo utilizado na criptografia do documento. No nosso caso, o AES 256 e o endereço para as recomendações de criptografia do algoritmo.

O elemento <KeyInfo> contém informações sobre a chave de criptografia.

O elemento <EncryptedKey> contém informações sobre o algoritmo utilizado para a criptografia da chave de sessão, como o endereço para as recomendações de criptografia e o nome da chave <KeyName>.

Os elementos <CipherData> podem conter um elemento <CipherValue> que contém os dados criptografados ou pode conter um elemento <CipherReference>.

Os elementos <CipherValue> e <CipherReference> não podem existir juntos, somente um ou outro podem existir num documento. No primeiro caso, o elemento <CipherValue> pertence ao elemento <EncryptedKey> que contém a chave AES 256 criptografada. Logo após as informações sobre a chave temos mais um elemento <CipherData> que representa o elemento criptografado do documento. Todas as informações do elemento <KeyInfo> serão utilizadas pelo recipiente do arquivo Xml para saber qual chave utilizar para descriptar o documento. Não é obrigatório o armazenamento da chave de sessão no documento. Você também pode escolher somente criptografar o conteúdo do elemento e não o elemento por completo.

 

Exemplo:

 

<? xml version = " 1.0 " standalone = " yes " ?> 
< compras > 
< compra id = " 15644 " > 
< cliente id = " 135 " > 
< numero cartao > 02083672203843 </ numero cartao > 
< vencimento > 2007/11 </ vencimento > 
< valor > 125,30 </ valor > 
</ cliente > 
< produto id = " 156 " > 
< quantidade > 3 </ quantidade > 
</ produto > 
</ compra > 
</ compras > 

 

Função para encriptar:

 

Private Sub Encrypt() 
     Try 
               'carrega o documento a ser encriptado 
                Dim xmlDoc As New XmlDocument 
                xmlDoc.Load("..\vendas.xml") 
                'Obtem a chave rsa que irá encriptar a chave de sessão. Levando em consideração que a chave RSA já foi criada. 
                Dim rsa As New RSACryptoServiceProvider 
               Dim reader As New IO.StreamReader("..\vendasrsakey.xml") 
                rsa.FromXmlString(reader.ReadToEnd) 
                'gera chave de sessao 
                Dim chaveSessao As New RijndaelManaged 
                chaveSessao.KeySize = 256 
                'Utiliza a classe EncryptedKey para encriptar a chave de sessao com o RSA 
                Dim chaveEncrip As New EncryptedKey() 
                Dim encrChave() As Byte = EncryptedXml.EncryptKey(chaveSessao.Key, rsa, False ) 
                chaveEncrip.CipherData = New CipherData(encrChave) 
                chaveEncrip.EncryptionMethod = New EncryptionMethod(EncryptedXml.XmlEncRSA1_5Url) 
                'cria o objeto que ira criptografar o documento 
                Dim xmlEncrip As New EncryptedXml(xmlDoc) 
                'define as informacoes sobre a chave compartilhada e adiciona ao objeto de criptografia do documento. 
                Dim nome As New KeyInfoName 
                nome.Value = "vendas_compartilhada" 
                chaveEncrip.KeyInfo.AddClause(nome) 
                xmlEncrip.AddKeyNameMapping(nome.Value, rsa) 
                'seleciona o elemento que será criptografado, o elemento cliente. Você pode selecionar o elemento como você achar melhor, através de um XPath com o SelectSingleNode, ou pelo método GetElementsByTagName ou qualquer outra forma. 
                Dim elemento As XmlElement = CType (xmlDoc.SelectSingleNode("/compras/compra/cliente"), XmlElement) 
                'Executa o método EncryptData que encripta o elemento selecionado utilizando a chave de sessão. 
                Dim elem() As Byte = xmlEncrip.EncryptData(elemento, chaveSessao, False ) 
                'A classe EncryptedData armazena informações sobre o elemento xml criptografado. Algoritmo utilizado, Informações sobre a chave... 
                Dim dadoEncrip As New EncryptedData 
                dadoEncrip.CipherData = New CipherData(elem) 'define o elem criptografado 
                dadoEncrip.Type = EncryptedXml.XmlEncElementUrl 
                dadoEncrip.EncryptionMethod = New EncryptionMethod(EncryptedXml.XmlEncAES256Url) 
                dadoEncrip.KeyInfo.AddClause( New KeyInfoEncryptedKey(chaveEncrip)) 
                'O método ReplaceElement, substitui o elemento original pelo elemento criptografado. 
                EncryptedXml.ReplaceElement(elemento, dadoEncrip, False ) 
                'Salva o documento já criptografado. 
                xmlDoc.Save("..\vendascripto.xml") 
     Catch ex As XmlException 
                MessageBox.Show(ex.Message, "ERRO", MessageBoxButtons.OK, MessageBoxIcon.Error) 
     Catch ex As CryptographicException 
               MessageBox.Show(ex.Message, "ERRO", MessageBoxButtons.OK, MessageBoxIcon.Error) 
     End Try 
End Sub 
  

Função para decriptografar:

 

Private Sub Decrypt() 
      Try 
            'Carrega o documento a ser descriptografado 
             Dim xmlDoc As New XmlDocument 
             xmlDoc.Load("..\vendascripto.xml") 
             Dim rsa As New RSACryptoServiceProvider 
             Dim xmlEncrip As New EncryptedXml(xmlDoc) 
              'obtem e define ao objeto a chave RSA a ser utilizada 
             Dim reader As New IO.StreamReader("..\vendasrsakey.xml") 
             rsa.FromXmlString(reader.ReadToEnd) 
             xmlEncrip.AddKeyNameMapping("vendas_compartilhada", rsa) 'Define que a KeyInfo que tiver o elemento KeyName rsa_compartilhada, será descriptografada utilizando o objeto rsa. 
             xmlEncrip.DecryptDocument() 
             xmlDoc.Save("..\vendas.xml") 
     Catch ex As XmlException 
             MessageBox.Show(ex.Message, "ERRO", MessageBoxButtons.OK, MessageBoxIcon.Error) 
     Catch ex As CryptographicException 
            MessageBox.Show(ex.Message, "ERRO", MessageBoxButtons.OK, MessageBoxIcon.Error) 
     End Try 
End Sub 

 

Como pôde ser visto, a parte mais trabalhosa é a da encriptação, onde tem que ser gerada e encriptada a chave de sessão e algumas informações sobre ela devem ser incluídas no documento.

A classe EncryptedXml e os métodos AddKeyNameMapping e DecryptDocument ficam com o trabalho de descriptografar a chave de sessão, o elemento e efetuar as validações. Caso a chave RSA informada não seja válida, será disparada um CryptographyException.

Vale relembrar que um documento criptografado tente a ter um tamanho bem maior que um documento Xml original, então, analise bem antes de encriptar o documento inteiro e não somente algum elemento.

Para saber mais sobre criptografia de documentos Xml sem criptografia da chave de sessão ou alguns outros exemplos .

Dicas para quem está começando:
Veja os próximos eventos
que você não pode perder :

22/11/2008 SQL Launch -
Linhares - ES
Por : devASPNet


22/11/2008 SQL Launch- SQL Server 2008
Rio Paranaiba - Viçosa - MG
Por : devASPNet


22/11/2008 SQL Launch - SQL Server 2008
Volta Redonda - RJ
Por : devASPNet


22/11/2008 SQL Launch- SQL Server 2008
Franca - SP
Por : devASPNet


22/11/2008 SQL Launch - SQL Server 2008
Canoinhas - SC
Por : devASPNet


22/11/2008 SQL Launch - SQL Server 2008
Tefé - AM
Por : devASPNet


25/11/2008 SQL Launch - SQL Server 2008
Rio de Janeiro - RJ
Por : devASPNet


27/11/2008 SQL Lauch- SQL Server 2008
São Paulo - SP
Por : devASPNet


28/11/2008 SQL Launch - SQL Server 2008
São Paulo - SP
Por : devASPNet


29/11/2008 SQL Launch- SQL Server 2008
Pedro Leopoldo - MG
Por : devASPNet


29/11/2008 SQL Launch- SQL Server 2008
Petropolis - RJ
Por : devASPNet


29/11/2008 SQL Launch
Floriano - PI
Por : devASPNet


29/11/2008 SQL Launch - SQL Server 2008
Rio de Janeiro - RJ
Por : devASPNet


29/11/2008 SQL Launch - SQL Server 2008
Natal - RN
Por : devASPNet


29/11/2008 SQL Launch- SQL Server 2008
Santa Maria - RS
Por : devASPNet


29/11/2008 SQL Launch
Ituiutaba - MG
Por : devASPNet


5/12/2008 Cloud Computing e o Windows Azure
São Paulo - SP
Por : devASPNet


6/12/2008 SQL Server 2008 Community Launch
São Paulo - SP
Por : devASPNet

Leituras imperdíveis para quem está começando:

º Otimizando a performance no ASP.NET::..
º Criando objetos de paginação personalizados na grid::..
º Uma cesta de compras em ASP.NET::..
º Utilizando o Refresh de parâmetros no .NET::..
º ASP.NET FORMS Authentication::..
º Utilizando propriedades dinâmicas no .NET::..
º Corrigindo problemas de deleção em grid com paginação::..
º Cuidado com os componentes de validação::..
º Otimizando o InitializeComponent::..
º Movendo fonte de aplicações entre máquinas::..
º Agilizando a performance da IDE do VS.NET::..
º Utilizando Short Circuit no VB.NET::..


























  Parceiros:
20% de desconto para os membros do grupo na aquisição de livros e inscrição para eventos

Receba dicas de programação e programação .NET:
E-mail:
Incluir Excluir