quinta-feira, 18 de julho de 2013

ASP.Net – Criptografia simétrica de dados


Quando falamos em informação logo pensamos nos dados que a compõem, sendo os recursos mais importantes de um sistema. Para que possamos criar sistemas realmente seguros, temos que pensar na segurança de nossos dados.
Em poucas palavras, criptografia é a forma como os dados podem ser transformados de sua forma original para outra ilegível, de forma que possa ser conhecida por apenas seu destinatário, no caso apenas quem possuir o algoritmo (chave) para realizar a descriptografia destes dados. 
A arquitetura .Net Framework implementa uma série de mecanismos para criptografia de dados além de outros inúmeros recursos para esta tarefa. Resumindo possuímos duas principais formas distintas de criptografar dados os de codificação simétrica (que permite a codificação e posteriormente a decodificação de uma string através de uma chave) e os de codificação assimétrica que consiste em um método de criptografia que utiliza um par de chaves (pública e privada). A chave pública é distribuída livremente para todos os correspondentes enquanto a privada deve ser conhecida apenas pelo seu “dono”. Portanto em se tratando deste tipo de codificação uma mensagem cifrada com a chave pública pode somente ser decifrada pela sua chave privada correspondente.
O nosso foco principal neste artigo é demonstrar com classes e exemplos práticos o uso da codificação simétrica de dados.

Codificação Simétrica

Em se tratando de codificação simétrica utilizamos uma determinada chave para realizar a criptografia e descriptografia destes dados.
Veja na ilustração 01 uma demonstração da funcionalidade deste tipo de codificação.

Figura 01: Detalhes do processo de Criptografia.

A arquitetura .Net possui algumas bibliotecas específicas para esta tarefa, sendo a System.Security.Cryptography” uma das principais. Logo em seguida descreverei suas principais classes.

Principais classes

DESCryptoServiceProvider: Define um objeto de conteúdo adicional para acessar a versão do provedor de serviços de criptografia.

CryptoStream: Define um fluxo que transmite dados de links para transformações de criptografia. Esta é a principal classe em se tratando de criptografia simétrica de dados.

No decorrer do artigo abordarei outras classes e tipos necessários para implementação do exemplo neste artigo, sendo:

MemoryStream: Classe responsável pelo armazenamento de dados em memória.

Enconding: Classe para converter uma seqüência de caracteres, sendo um de seus principais conversores o padrão UTF-8.

Convert: Converter para diversos tipos de bases, usaremos neste caso a base64 com os métodos “ToBase64String()” e “FromBase64String()”. Sempre que precisamos representar em forma texto (ASCII) um conjunto de dados binários (bytes) é necessária a conversão dos bytes em um formato textual que possa representar as 255 possíveis combinações de um byte em texto. Contudo uma representação direta não é possível, pois não existe um caractere válido em texto para representar o byte (01) ou byte (254). Criou-se então o formato Base64 que é capaz de lidar com essa representação.

Criando um exemplo prático

Neste exemplo vou envolver todas as classes e métodos descritos anteriormente. Deverá possuir dois métodos principais, um para “Criptografia” e outro para “Descriptografia”. Desenvolverei uma classe que deverá ser utilizada em aplicações Asp.Net, mas que com poucos esforços poderão ser também utilizadas em outros tipos de plataformas no ambiente de desenvolvimento da arquitetura .Net.

Crie um projeto clicando em “File/New/Web Site...” escolhendo a opção “Asp.Net empty web site” para assim criarmos uma página do zero. Adicione um novo item do tipo “.cs” e deixe o nome como “Criptografia.cs”. Ver Figura 02.

Figura 02: Criando a classe Criptografia.

Por padrão será criada uma pasta “App_Code”, local padrão de armazenamento de classes e funções. Ver Imagem 03.

Figura 03: Criação automática da pasta “App_Code”.

Não abordarei conceitos técnicos de criação de classes, aconselho a leitura do artigo “Linguagem C# - Criando Classes e Objetos” do mês de Agosto de 2012 para maiores detalhes.

 Esta classe será do tipo pública possuindo alguns atributos privados e deverá conter duas funções denominadas “Criptografar” e “Descriptografar”. Explicarei todas as etapas e detalhes para a construção desta classe.

Classe “Criptografia.cs”

Importaremos alguns “namespaces” necessários.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Text;
using System.IO;
using System.Security.Cryptography;


/// <summary>
/// Classe responsável pela Criptografia de Dados
/// The Club - O maior clube de Programadores do Brasil.
/// </summary>

public class Criptografia
{
     public Criptografia()
     {
        
     }

No construtor da classe não utilizaremos nenhum código.

    private byte[] chave = { };
    private byte[] iv = {12,34,56,78,90,102,114,126};

Criaremos dois atributos do tipo “byte”, sendo um para armazenar a chave e o outro para realizar a criptografia fazendo uso de um conjunto seqüencial numérico.

public string Criptografar(string valor, string chaveCriptografia)
    {
        DESCryptoServiceProvider des;
        MemoryStream ms;
        CryptoStream cs;
        byte[] ent;

        try
        {
            des = new DESCryptoServiceProvider();
            ms = new MemoryStream();
            ent = Encoding.UTF8.GetBytes(valor);
            chave = Encoding.UTF8.GetBytes(chaveCriptografia.Substring(0, 8));
            cs = new CryptoStream(ms, des.CreateEncryptor(chave, iv), CryptoStreamMode.Write);
            cs.Write(ent, 0, ent.Length);
            cs.FlushFinalBlock();
            return Convert.ToBase64String(ms.ToArray());
        }
        catch (Exception ex)
        {
            return "Valores Inconsistentes! " + ex.Message.ToString();

        }
    }

O primeiro bloco de comandos deverá fazer a criptografia do valor informado utilizando uma chave. Esta função tem como retorno uma string convertida na base 64. Trataremos nossa rotina dentro de um bloco “Try/Catch”, instanciando os objetos “DESCryptoServiceProvider” e “MemoryStream” para serem utilizados posteriormente. A variável “ent” do tipo “array de bytes” armazenará o valor convertido para o padrão “UTF-8” passado por parâmetro na função. A variável “chave” fará o mesmo, mas neste caso   usamos o método “substring” para coletar apenas um pedaço da string. O objeto do tipo “CriptoStream” irá desempenhar o trabalho  de armazenar em um “MemoryStream” terminando o processo de criptografia criando a string criptografada usando o vetor de bytes em questão. Por final Retornando um vetor na base 64.

public string Descriptografar(string valor, string chaveCriptografia)
    {
        DESCryptoServiceProvider des;
        MemoryStream ms;
        CryptoStream cs;
        byte[] sai;

        try
        {
            des = new DESCryptoServiceProvider();
            ms = new MemoryStream();

            sai = new byte[valor.Length];
            sai = Convert.FromBase64String(valor.Replace(" ", "+"));

            chave = Encoding.UTF8.GetBytes(chaveCriptografia.Substring(0, 8));

            cs = new CryptoStream(ms, des.CreateDecryptor(chave, iv), CryptoStreamMode.Write);
            cs.Write(input, 0, input.Length);
            cs.FlushFinalBlock();

            return Encoding.UTF8.GetString(ms.ToArray());
        }
        catch (Exception ex)
        {
           return "Valores Inconsistentes! " + ex.Message.ToString();
        }
    }

}

Esta função fará o inverso da outra. Recebemos como parâmetro o valor e a mesma chave de criptografia informada acima. Teremos como retorno uma string convertida para o padrão “UTF-8”. A lógica será inversa, trataremos dentro de um bloco de comandos “Try/Catch”. O primeiro passo será de armazenar o valor informado em um Vetor de bytes e em seguida recuperamos o valor recebido no padrão Base 64. O método “replace” substituirá espaços em branco (“ “) para sinal de mais (“+”). Pegaremos a chave de criptografia informada no parâmetro armazenando como Bytes e por final faremos o inverso usando o objeto do tipo “CriptoStream”, com o método “CreateDecryptor”, armazenando em um “MemoryStream”. O resultado será retornado no padrão “UTF-8”.

Exemplo de Utilização

Crie uma nova página do tipo “.Aspx” adicionando uma tabela e dentro dela alguns componentes. Nosso exemplo deverá possuir duas etapas, a primeira executando o processo de “Criptografia” e a segunda a “Descriptografia”.
Ver Imagem 04 o layout proposto.

Figura 04: Layout proposto.

O código ASPX correspondente:

<table class="style1">
            <tr>
                <td class="style2">
<asp:Label ID="Label3" runat="server" style="font-weight: 700; font-family: Calibri; font-size: large" Text="Etapa 01 - Criptografia"></asp:Label>
                </td>
                <td>&nbsp;</td>
            </tr>
            <tr>
                <td class="style2">
<asp:Label ID="Label1" runat="server" Text="Valor" CssClass="style5"></asp:Label>
                </td>
                <td>
<asp:Label ID="Label2" runat="server" Text="Chave" CssClass="style5"></asp:Label>
                </td>
            </tr>
            <tr>
                <td class="style2">
<asp:TextBox ID="txtBox1" runat="server" Width="220px" CssClass="style5"></asp:TextBox>
                </td>
                <td>
<asp:TextBox ID="txtBox2" runat="server" Width="220px" CssClass="style5"></asp:TextBox>
                </td>
            </tr>
            <tr>
                <td class="style3" colspan="2">
<asp:Button ID="BtnEncriptar" runat="server" CssClass="style5" onclick="BtnEncriptar_Click" Text="Executar!" />
                </td>
            </tr>
            <tr>
                <td class="style2" colspan="2">
<asp:Label ID="Label9" runat="server" Text="Valor Criptografado:" CssClass="style5"></asp:Label>
                </td>
            </tr>
            <tr>
                <td class="style2" colspan="2">
<asp:Label ID="Label7" runat="server" CssClass="style5" style="font-weight: 700; color: #FF0000"></asp:Label>
                </td>
            </tr>
            <tr>
                <td class="style2">
                    &nbsp;</td>
                <td>
                    &nbsp;</td>
            </tr>
            <tr>
                <td class="style2">
<asp:Label ID="Label4" runat="server" style="font-weight: 700; font-family: Calibri; font-size: large" Text="Etapa 02 - Descriptografia"></asp:Label>
                </td>
                <td>
                    &nbsp;</td>
            </tr>
            <tr>
                <td class="style2">
<asp:Label ID="Label5" runat="server" Text="Valor" CssClass="style5"></asp:Label>
                </td>
                <td>
<asp:Label ID="Label6" runat="server" Text="Chave" CssClass="style5"></asp:Label>
                </td>
            </tr>
            <tr>
                <td class="style2">
<asp:TextBox ID="txtBox3" runat="server" Width="220px" CssClass="style5"></asp:TextBox>
                </td>
                <td>
<asp:TextBox ID="txtBox4" runat="server" Width="220px" CssClass="style5"></asp:TextBox>
                </td>
            </tr>
            <tr>
                <td class="style3" colspan="2">
<asp:Button ID="BtnDescriptar" runat="server" CssClass="style5" onclick="BtnDescriptar_Click" Text="Executar!" />
                </td>
            </tr>
            <tr>
                <td class="style2">
                    &nbsp;</td>
                <td>
                    &nbsp;</td>
            </tr>
            <tr>
                <td class="style2" colspan="2">
<asp:Label ID="Label10" runat="server" Text="Valor Descriptografado:" CssClass="style5"></asp:Label>
                </td>
            </tr>
            <tr>
                <td class="style2" colspan="2">
<asp:Label ID="Label8" runat="server" CssClass="style5" style="font-weight: 700; color: #FF0000"></asp:Label>
                </td>
            </tr>
        </table>

Usaremos apenas o evento “Click()” dos botões, veremos como é simples utilizar a classe criada anteriormente. Para isto é necessário criar um objeto para posteriormente podermos manipular seus métodos. Defina um valor global da classe “Criptografia”.

Criptografia cl_cripto = new Criptografia();
  
Utilize o código abaixo no botão “Encriptar”

protected void BtnEncriptar_Click(object sender, EventArgs e)
{  
Label7.Text = cl_cripto.Criptografar(txtBox1.Text, txtBox2.Text);
}


E para o botão “Descriptar” utilizaremos praticamente o mesmo código, apenas alterando a função.

protected void BtnDescriptar_Click(object sender, EventArgs e)
{  
Label8.Text = cl_cripto.Descriptografar(txtBox3.Text, txtBox4.Text);
}

Os dois métodos possuem dois parâmetros (Valor e Chave) que serão passados através de componentes “TextBox” e retornando o resultado em um “Label”.
Ver Imagem 05 o exemplo em “Run-Time”.

Figura 05: Exemplo em Run-Time.

Este foi apenas um exemplo de utilização, mas reforço que poderemos implementar este recurso em diversas ocasiões, como por exemplo em criptografia de senhas de bancos de dados, arquivos de texto, XML entre outros.

Conclusões

Hoje em dia a maior preocupação no desenvolvimento de um sistema é a segurança de seus dados. A segurança dos dados não implica somente no espaço físico, transporte ou de acesso, e sim no conteúdo a ser acessado indevidamente. A Codificação é uma técnica muito antiga que em épocas recentes como a nossa é muito requisitada e utilizada. A arquitetura .Net nos fornece muito apoio neste caso, disponibilizando alguns pacotes de funções e classes prontas para serem implantadas. Neste artigo procurei criar um exemplo prático para resolver de uma forma rápida algumas das principais dúvidas de nossos sócios. O assunto Criptografia geralmente é muito maçante e cansativo, pois possuem inúmeros tipos de algoritmos e formas de serem implementados. Vimos que com pouquíssimas linhas de código montamos uma classe padrão que resolverá muitos problemas deste tipo.

Fico por aqui, um forte abraço e até o mês que vem!

Referências

 

Wikipédia, a enciclopédia livre - pt.wikipedia.org/





Nenhum comentário:

Postar um comentário