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> </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">
</td>
<td>
</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>
</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">
</td>
<td>
</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
Nenhum comentário:
Postar um comentário