| 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 .