.NET - Protegendo os seus dados (Criptografia)


Neste artigo vou escrever um pouco sobre criptografia e como proteger os seus dados.

O assunto é extenso e profundo (criptografia simétrica, criptografia assimétrica, hash e assinaturas digitais) e eu não tenho a pretensão de tratar de todas as possibilidades neste artigo. Vou me ater aos conceitos básicos e de sua utilização prática com alguns exemplos.

O namespace System.Security.Cryptography é principal namespace usado para a criptografia, de modo que você normalmente necessidade de adicionar uma declaração para este namespace no topo do seu código para usar as classes contidas nele.

A criptografia trabalha com bits e bytes, de forma que em geral você deve converter os dados para o formato binário antes de realizar a criptografia. Depois de descriptografar, você deve converter os bytes descriptografados para o tipo original.

Codificação versus Criptografia

Os termos codificar e criptografar não significam a mesma coisa. Assim codificação não é criptografia.

Na codificação, usando o mecanismo de codificação base64 por exemplo, não é preciso usar uma chave de codificação ou decodificação. O mecanismo de codificação Base64 é usando quando você precisa representar dados binários em um ambiente baseado em texto.

Dessa forma o Simple Mail Transfer Protocol (SMTP) é um protocolo baseado em texto para o envio de e-mail. E para enviar um anexo binário você tem que codificar o anexo usando o mecanismo base64.

Para converter para e a partir de base64 podemos usar a classe Convert. Veja exemplo abaixo para VB .NET e C#:

      Dim binario = New Byte() {1, 2, 3, 4, 5}
      Dim codificacao = Convert.ToBase64String(binario)
      Dim retornaBinario = Convert.FromBase64String(codificacao)
Código VB .NET
 
   var binario = new Byte[] { 1, 2, 3, 4, 5 };
   var codificacao = Convert.ToBase64String(binario);
   var retornaBinario = Convert.FromBase64String(codificacao);
Código C#

Criptografia Simétrica

A Criptografia simétrica fornece o tipo mais rápido e mais básico de criptografia. Neste tipo de criptografia, você usa a mesma chave secreta para criptografar e descriptografar dados.

A criptografia simétrica remonta ao Egito antigo, e a cifra de César foi uma maneira bem conhecida de realizar a criptografia simétrica, que remonta a Júlio César. Você já ouviu falar do anel decodificador secreto; você usa o mesmo anel decodificador secreto para criptografar e descriptografar mensagens. Um anel decodificador secreto (ou decodificador secreto) é um dispositivo que permite descodificar uma cifra de substituição simples, ou criptografar uma mensagem, trabalhando no sentido oposto.

A Criptografia simétrica é rápida e existem muitos algoritmos simétricos; sendo tais algoritmos complexos e eficientes, razão pela qual ainda é o núcleo de muitos protocolos de comunicação criptografada.

A Criptografia simétrica usa uma chave secreta para criptografar e descriptografar uma mensagem.

Uma chave secreta, que pode ser um número, uma palavra ou apenas uma seqüência de letras aleatórias, é aplicada ao texto de uma mensagem para alterar o conteúdo de uma maneira específica. Isso pode ser tão simples quanto Deslocar cada letra por um número de locais no alfabeto. Desde que tanto o remetente quanto destinatário saibam a chave secreta, eles podem criptografar e descriptografar todas as mensagens que usam essa chave.

As chaves usadas são relativamente pequenas, geralmente chaves menores que 256 bits de forma a não onerar o processo.

E o que isso significa ?

Significa que quanto maior a chave mais forte é criptografia e mais recursos você terá que usar tanto para criptografar como para decriptografar.

Abaixo temos uma tabela que mostra o tempo médio de busca, através do método de força bruta para a quebra da chave de criptografia simétrica.

fonte : http://www.gta.ufrj.br/grad/07_2/delio/Criptografiasimtrica.html

Assim se você resolver usar uma chave com 1 megabyte de tamanho você vai criar uma criptografia muito forte mas vai gastar muito mais recursos (em tempo de processamento) para criptografar e descriptografar uma mensagem.

Os algoritmos de chave simétrica ou criptografia de chave única são uma classe de algoritmos para a criptografia que usam chaves criptográficas relacionadas para as operações de cifragem ou decifragem.

A chave de cifragem pode ser idêntica à de decifragem ou poderá existir uma transformação simples entre as duas chaves. As chaves representam um segredo, partilhado entre duas ou mais partes, que podem ser usadas para manter um canal confidencial de informação. Usa-se uma única chave, partilhada por ambos os interlocutores, na premissa de que esta é conhecida apenas por eles.(http://pt.wikipedia.org/wiki/Algoritmo_de_chave_simétrica)

Esquema representando o processo de criptografia simétrica. Fonte: http://www.gta.ufrj.br/grad/07_2/delio/Criptografiasimtrica.html

A grande desvantagem da criptografia simétrica é o gerenciamento de chaves e a sua distribuição.

Se você usa a mesma chave para criptografar e descriptografar os dados, como você vai transferir com segurança a chave para alguém descriptografar os dados da mensagem ?

Se um usuário malicioso intercepta a chave, ele pode decodificar suas mensagens. (Uma forma de atenuar este problema é adicionar camadas de segurança na criptografia simétrica.)

Exemplos de algoritmos de criptografia simétrica:

1- O DES ("Data Encryption Standard") - O DES é um mecanismo de cifragem tradicional (simétrico) desenvolvido nos anos setenta, utiliza uma chave de 56 bits que é aplicada a blocos de dados com 64 bits, o objetivo destes algoritmos é que seja muito difícil calcular a chave K, mesmo conhecendo o algoritmo DES, uma mensagem cifrada C e uma mensagem original M: C = DES(K,M);

2- Rivest Ciphers (RC2; RC4 e RC5) - Esta é uma sucessão de algoritmos bastante usados que possuem maior flexibilidade e possibilitam maior segurança do que o DES simples. Todos são algoritmos simétricos (a mesma chave é usada para cifrar e para decifrar).;

3- International Data Encryption Algorithm (IDEA) - É mais uma técnica de cifragem simétrica em bloco que é usada nos dias atuais. Usa blocos fixos com 64 bits (8 bytes) e usa chaves com 128 bits (16 bytes). É considerada segura, mas ao contrário dos algoritmos RC usa chaves de comprimento fixo que podem comprometer segurança;

4-BLOWFISH - É um algoritmo simétrico conhecido pela sua velocidade, sendo mais rápido do que o RC2 e o IDEA. Usa blocos fixos com 64 bits (8 bytes), mas as chaves podem ter qualquer comprimento (128 bits é o mais usado);

5- ARCFOUR - É um algoritmo considerado equivalente ao RC4, tal como o RC4 não usa blocos de entrada mas sim um fluxo contínuo de bytes e as chaves podem ter comprimento variável (128 bits é o mais usado);

O algoritmo simétrico mais usado atualmente é o AES (Advanced Encryption Standard). O Advanced Encryption Standard (AES, ou Padrão de Criptografia Avançada), também conhecido por Rijndael, é uma cifra de bloco adotada como padrão de criptografia pelo governo dos Estados Unidos.

O AES foi anunciado pelo NIST (Instituto Nacional de Padrões e Tecnologia dos EUA) como U.S. FIPS PUB (FIPS 197) em 26 de Novembro de 2001, depois de 5 anos de um processo de padronização. Tornou-se um padrão efetivo em 26 de Maio de 2002.

A plataforma .NET contém o algoritmo Rijndael, que você deve usar para todos os novos projetos que exigem a criptografia simétrica. Assim você pode usar a classe RijndaelManaged para realizar a criptografia e descriptografia simétrica.

Esta classe exige que você forneça uma chave e um vetor de inicialização (VI). O VI ajuda a garantir que ao criptografar a mesma mensagem várias vezes produz-se textos cifrados diferentes. O mensagem criptografada é comumente conhecido como texto cifrado.

Para descriptografar os dados, você deve usar a mesma chave e o VI usado para criptografar os dados. A chave deve ser composta de bytes de dados que compõem o comprimento total da chave.

Por exemplo, uma chave de 128 bit é composta por 16 bytes. Se a chave é gerada pela aplicação, utilizar bytes para a chave não é um problema, no entanto, se um ser humano está gerando a chave, é comum querer que a chave seja uma palavra ou frase. Isso pode ser feito usando a classe Rfc2898DeriveBytes, que pode derivar uma chave de uma senha fornecida.

Exemplo de utilização da classe RijndaelManaged para criptografar uma mensagem

Abra o Visual Basic 2010 Express Edition e crie um novo projeto do tipo Windows Forms Application com o nome CriptografiaSimetrica;

A seguir no formulário form1.vb inclua os controles Label, TextBox e Button conforme o leiaute da figura abaixo:

Vamos declarar os namespaces usados no projeto:

Imports System.Security.Cryptography
Imports System.IO
Imports System.Text

A seguir declare as seguintes variáveis no início do formulário:

Dim textoCifrado As Byte()
Dim sal() As Byte =
{&H0, &H1, &H2, &H3, &H4, &H5, &H6, &H5, &H4, &H3, &H2, &H1, &H0}
Dim senha As String = ""
Dim mensagem As String = ""

Agora no evento Click do botão de comando inclua o código abaixo:

Private Sub btnCriptografar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCriptografar.Click

        senha  = txtSenha.Text
        mensagem  = txtMensagem.Text

        Dim chave As New Rfc2898DeriveBytes(senha, sal)
       
' criptografa os dados
        Dim algoritmo = New RijndaelManaged()
        algoritmo.Key = chave.GetBytes(16)
        algoritmo.IV = chave.GetBytes(16)

        Dim fonteBytes() As Byte = New System.Text.UnicodeEncoding().GetBytes(mensagem)

        Using StreamFonte = New MemoryStream(fonteBytes)
            Using StreamDestino As New MemoryStream()
                Using crypto As New CryptoStream(StreamFonte, algoritmo.CreateEncryptor(), CryptoStreamMode.Read)
                    moveBytes(crypto, StreamDestino)
                    textoCifrado = StreamDestino.ToArray()
                End Using
            End Using
        End Using

      
 'MessageBox.Show(String.Format("Mensagem : {0}{1} Criptografada : {2}", mensagem, Environment.NewLine, Convert.ToBase64String(textoCifrado)))
        txtResultado.Text = txtResultado.Text + Convert.ToBase64String(textoCifrado) + "    ::  senha => " + txtSenha.Text + Environment.NewLine

    End Sub

Digite a seguir o código da rotina moveBytes() abaixo:

Private Sub moveBytes(ByVal fonte As Stream, ByVal destino As Stream)
        Dim bytes(2048) As Byte
        Dim contador = fonte.Read(bytes, 0, bytes.Length - 1)
        While (0 <> contador)
            destino.Write(bytes, 0, contador)
            contador = fonte.Read(bytes, 0, bytes.Length - 1)
        End While
    End Sub

Entendendo o código:

A mensagem a ser criptografada é informada na caixa de texto txtMensagem.Text e atribuída a variável mensagem e o resultado da criptografia é armazenado na variável textoCifrado;

- Estamos usando uma senha e um variável (sal) para criar uma chave usando a classe Rfc2898DeriveBytes : Dim chave As New Rfc2898DeriveBytes(senha, sal)

Para descriptografar a mensagem você deve usar o mesmo valor de sal.

- Em seguida criamos uma instância da classe RijndaelManaged : Dim algoritmo = New RijndaelManaged()

- Preenchemos os valores para a chave e para o Vetor de Inicialização (VI):

algoritmo.Key = chave.GetBytes(16)
algoritmo.IV = chave.GetBytes(16)

- Cada vez que você chama chave.GetBytes(16) obtemos bytes diferentes , logo para descriptografar temos que executar a mesma sequência;

A seguir convertemos os dados binários para que ele possa ser criptografado usando a classe UnicodeEncoding();

New System.Text.UnicodeEncoding().GetBytes(mensagem)

- Criamos 3 Streams para mover os dados:

  1. O primeiro Stream é um objeto MemoryStream e representa a fonte que é preenchida com os bytes dos dados;
  2. O segundo Stream é um objeto MemoryStream e representa o destino;
  3. O próximo Stream é um objeto CryptoStream e é aqui que o serviço é feito

Usamos a rotina auxiliar moveBytes que copia os bytes de um fluxo de origem para um fluxo de destino.

O objeto de Stream de criptografia é passado para moveBytes como a fonte, e o objeto StreamDestino objeto é passado para moveBytes como destino.

Depois da chamada a moveBytes o objeto StreamDestino contém os dados criptografados.

Finalmente, a mensagem criptografada é exibida na caixa de texto :

txtResultado.Text = txtResultado.Text + Convert.ToBase64String(textoCifrado) + " :: senha => " + txtSenha.Text + Environment.NewLine

Executando o projeto iremos obter:

Descriptografando a mensagem

Vamos agora realizar o processo inverso: descriptografar a mensagem cifrada acima.

Para isso vamos incluir um novo controle Button e um controle TextBox no formulário form1.vb;

A seguir vamos incluir no evento Click deste novo botão o código para descriptografar a mensagem:

  Private Sub btnDescriptografar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDescriptografar.Click

        If (textoCifrado Is Nothing) Then
            MessageBox.Show("Os dados não estão criptografados!")
            Return
        End If

        Dim chave As New Rfc2898DeriveBytes(senha, sal)
        Dim algoritmo = New RijndaelManaged()

        algoritmo.Key = chave.GetBytes(16)
        algoritmo.IV = chave.GetBytes(16)
        Using StreamFonte = New MemoryStream(textoCifrado)
            Using StreamDestino As New MemoryStream()
                Using crypto As New CryptoStream(StreamFonte, algoritmo.CreateDecryptor(), CryptoStreamMode.Read)
                    moveBytes(crypto, StreamDestino)
                    Dim bytesDescriptografados() As Byte = StreamDestino.ToArray()
                    Dim mensagemDescriptografada = New UnicodeEncoding().GetString(bytesDescriptografados)
                    txtMensagemDescriptografada.Text = mensagemDescriptografada
                End Using
            End Using
        End Using
    End Sub

Executando o projeto iremos realizar primeiro a criptografia da mensagem e a seguir o processo inverso.

Como sugestão você poderia criar uma classe usando os métodos para criptografar e descriptografar no projeto com métodos estáticos para serem usados.

Pegue o projeto completo aqui: CriptografiaSimetrica.zip

1Tessalonicenses 4:3 Porque esta é a vontade de Deus, a saber, a vossa santificação: que vos abstenhais da prostituição,
1Tessalonicenses 4:4
que cada um de vós saiba possuir o seu vaso em santidade e honra,
1Tessalonicenses 4:5
não na paixão da concupiscência, como os gentios que não conhecem a Deus;

Referências:


José Carlos Macoratti