|
<< Click to Display Table of Contents >> Criptografando |
![]() ![]()
|
Introdução
Alguns desenvolvedores se questionam sobre como montar uma forte camada de segurança dentro de uma aplicação, como criptografar dados e que algoritmos usar. O .Net Framework conta com a namespace System.Security.Cryptography que possui uma série de classes que podem lhe auxiliar ao implementar este tipo de rotinas, incluindo serviços de criptografia, encoder e decorder de dados e muitas outras operações como a criação de Hash.
Existem duas formas básicas de criptografia: simétrica e assimétrica. Neste artigo iremos falar sobre a criptografia simétrica.
Para criptografia de dados, iremos usar as seguintes classes: Rijndael, RC2, DES e TripleDES.
Para criação de Hash de dados, iremos usar as seguintes classes: MD5, SHA1, SHA256, SHA384 e SHA512.
Mão na massa
Classe: Crypt
Objetivo: Criptografar usando uma chave com possibilidade de procedimento reverso
Classe: Hash
Objetivo: Criptografar fortemente sem procedimento reverso
Como usar Crypt
A classe Crypt, todos os algoritmos usados neste exemplo necessitam de um vetor de inicialização, nada mais é que uma matriz de bytes, valores usados internamente pela classe para gerar os dados criptografados em conjunto com a chave enviada.
string texto = "Este texto ficará encriptado";
string chave = "Chave secreta";
Crypt crypt = new Crypt(CryptProvider.DES); // Tipos: DES, RC2, Rijndael e TripleDES
crypt.Key = chave;
string textoCriptografado = crypt.Encrypt(texto);
Console.WriteLine("Cripto:" + textoCriptografado);
string textoDescripto = crypt.Decrypt(textoCriptografado);
Console.WriteLine("Descripto:" + textoDescripto);
Como usar Hash
string texto = "Este texto ficará encriptado";
Hash hash = new Hash(HashProvider.SHA1); // Tipos: MD5, SHA1, SHA256, SHA384, SHA512
string senha = hash.GetHash("Senha123");
Console.WriteLine("Senha1:" + senha);
string novaSenha = hash.GetHash("Senha123");
Console.WriteLine("Senha2:" + novaSenha);
if (senha == novaSenha)
Console.WriteLine("Senhas CONFEREM");
else
Console.WriteLine("Senhas NÃO CONFEREM");
Crypt.cs
using System;
using System.Text;
using System.IO;
using System.Security.Cryptography;
/// <summary>
/// Enumerator com os tipos de classes para criptografia.
/// </summary>
public enum CryptProvider
{
/// <summary>
/// Representa a classe base para implementações criptografia dos algoritmos simétricos Rijndael.
/// </summary>
Rijndael,
/// <summary>
/// Representa a classe base para implementações do algoritmo RC2.
/// </summary>
RC2,
/// <summary>
/// Representa a classe base para criptografia de dados padrões (DES - Data Encryption Standard).
/// </summary>
DES,
/// <summary>
/// Representa a classe base (TripleDES - Triple Data Encryption Standard).
/// </summary>
TripleDES
}
/// <summary>
/// Classe auxiliar com métodos para criptografia de dados.
/// </summary>
public class Crypt
{
#region Private members
private string _key = string.Empty;
private CryptProvider _cryptProvider;
private SymmetricAlgorithm _algorithm;
private void SetIV()
{
switch (_cryptProvider)
{
case CryptProvider.Rijndael:
_algorithm.IV = new byte[] { 0xf, 0x6f, 0x13, 0x2e, 0x35, 0xc2, 0xcd, 0xf9, 0x5, 0x46, 0x9c, 0xea, 0xa8, 0x4b, 0x73, 0xcc };
break;
default:
_algorithm.IV = new byte[] { 0xf, 0x6f, 0x13, 0x2e, 0x35, 0xc2, 0xcd, 0xf9 };
break;
}
}
#endregion
#region Properties
/// <summary>
/// Chave secreta para o algoritmo simétrico de criptografia.
/// </summary>
public string Key
{
get { return _key; }
set { _key = value; }
}
#endregion
#region Constructors
/// <summary>
/// Contrutor padrão da classe, é setado um tipo de criptografia padrão.
/// </summary>
public Crypt()
{
_algorithm = new RijndaelManaged();
_algorithm.Mode = CipherMode.CBC;
_cryptProvider = CryptProvider.Rijndael;
}
/// <summary>
/// Construtor com o tipo de criptografia a ser usada.
/// </summary>
/// <param name="cryptProvider">Tipo de criptografia.</param>
public Crypt(CryptProvider cryptProvider)
{
// Seleciona algoritmo simétrico
switch (cryptProvider)
{
case CryptProvider.Rijndael:
_algorithm = new RijndaelManaged();
_cryptProvider = CryptProvider.Rijndael;
break;
case CryptProvider.RC2:
_algorithm = new RC2CryptoServiceProvider();
_cryptProvider = CryptProvider.RC2;
break;
case CryptProvider.DES:
_algorithm = new DESCryptoServiceProvider();
_cryptProvider = CryptProvider.DES;
break;
case CryptProvider.TripleDES:
_algorithm = new TripleDESCryptoServiceProvider();
_cryptProvider = CryptProvider.TripleDES;
break;
}
_algorithm.Mode = CipherMode.CBC;
}
#endregion
#region Public methods
/// <summary>
/// Gera a chave de criptografia válida dentro do array.
/// </summary>
/// <returns>Chave com array de bytes.</returns>
public virtual byte[] GetKey()
{
string salt = string.Empty;
// Ajuta o tamanho da chave se necessário e retorna uma chave válida
if (_algorithm.LegalKeySizes.Length > 0)
{
// Tamanho das chaves em bits
int keySize = _key.Length * 8;
int minSize = _algorithm.LegalKeySizes[0].MinSize;
int maxSize = _algorithm.LegalKeySizes[0].MaxSize;
int skipSize = _algorithm.LegalKeySizes[0].SkipSize;
if (keySize > maxSize)
{
// Busca o valor máximo da chave
_key = _key.Substring(0, maxSize / 8);
}
else if (keySize < maxSize)
{
// Seta um tamanho válido
int validSize = (keySize <= minSize) ? minSize : (keySize - keySize % skipSize) + skipSize;
if (keySize < validSize)
{
// Preenche a chave com arterisco para corrigir o tamanho
_key = _key.PadRight(validSize / 8, '*');
}
}
}
PasswordDeriveBytes key = new PasswordDeriveBytes(_key, ASCIIEncoding.UTF8.GetBytes(salt));
return key.GetBytes(_key.Length);
}
/// <summary>
/// Encripta o dado solicitado.
/// </summary>
/// <param name="plainText">Texto a ser criptografado.</param>
/// <returns>Texto criptografado.</returns>
public virtual string Encrypt(string plainText)
{
byte[] plainByte = ASCIIEncoding.UTF8.GetBytes(plainText);
byte[] keyByte = GetKey();
// Seta a chave privada
_algorithm.Key = keyByte;
SetIV();
// Interface de criptografia / Cria objeto de criptografia
ICryptoTransform cryptoTransform = _algorithm.CreateEncryptor();
MemoryStream _memoryStream = new MemoryStream();
CryptoStream _cryptoStream = new CryptoStream(_memoryStream, cryptoTransform, CryptoStreamMode.Write);
// Grava os dados criptografados no MemoryStream
_cryptoStream.Write(plainByte, 0, plainByte.Length);
_cryptoStream.FlushFinalBlock();
// Busca o tamanho dos bytes encriptados
byte[] cryptoByte = _memoryStream.ToArray();
// Converte para a base 64 string para uso posterior em um xml
return Convert.ToBase64String(cryptoByte, 0, cryptoByte.GetLength(0));
}
/// <summary>
/// Desencripta o dado solicitado.
/// </summary>
/// <param name="cryptoText">Texto a ser descriptografado.</param>
/// <returns>Texto descriptografado.</returns>
public virtual string Decrypt(string cryptoText)
{
// Converte a base 64 string em num array de bytes
byte[] cryptoByte = Convert.FromBase64String(cryptoText);
byte[] keyByte = GetKey();
// Seta a chave privada
_algorithm.Key = keyByte;
SetIV();
// Interface de criptografia / Cria objeto de descriptografia
ICryptoTransform cryptoTransform = _algorithm.CreateDecryptor();
try
{
MemoryStream _memoryStream = new MemoryStream(cryptoByte, 0, cryptoByte.Length);
CryptoStream _cryptoStream = new CryptoStream(_memoryStream, cryptoTransform, CryptoStreamMode.Read);
// Busca resultado do CryptoStream
StreamReader _streamReader = new StreamReader(_cryptoStream);
return _streamReader.ReadToEnd();
}
catch
{
return null;
}
}
#endregion
}
Hash.cs
using System;
using System.Text;
using System.IO;
using System.Security.Cryptography;
/// <summary>
/// Enumerator com os tipos de classes para criação de Hash.
/// </summary>
public enum HashProvider
{
/// <summary>
/// Computa um hash SHA1 hash para os dados.
/// </summary>
SHA1,
/// <summary>
/// Computa um hash SHA256 hash para os dados.
/// </summary>
SHA256,
/// <summary>
/// Computa um hash SHA384 hash para os dados.
/// </summary>
SHA384,
/// <summary>
/// Computa um hash SHA512 hash para os dados.
/// </summary>
SHA512,
/// <summary>
/// Representa a classe abstrata para implementações dos algoritmos para criação de hash usando MD5.
/// </summary>
MD5
}
/// <summary>
/// Classe auxiliar com métodos para crição de hash dos dados inseridos.
/// </summary>
public class Hash
{
#region Private members
private HashAlgorithm _algorithm;
#endregion
#region Constructors
/// <summary>
/// Contrutor padrão da classe, é setado um tipo de hash padrão.
/// </summary>
public Hash()
{
_algorithm = new SHA1Managed();
}
/// <summary>
/// Construtor com o tipo de hash a ser usado.
/// </summary>
/// <param name="hashProvider">Tipo de Hash.</param>
public Hash(HashProvider hashProvider)
{
switch (hashProvider)
{
case HashProvider.MD5:
_algorithm = new MD5CryptoServiceProvider();
break;
case HashProvider.SHA1:
_algorithm = new SHA1Managed();
break;
case HashProvider.SHA256:
_algorithm = new SHA256Managed();
break;
case HashProvider.SHA384:
_algorithm = new SHA384Managed();
break;
case HashProvider.SHA512:
_algorithm = new SHA512Managed();
break;
}
}
#endregion
#region Public methods
/// <summary>
/// Monta hash para algum dado texto.
/// </summary>
/// <param name="plainText">Texto a ser criado o hash.</param>
/// <returns>Hash do texto inserido.</returns>
public string GetHash(string plainText)
{
byte[] cryptoByte = _algorithm.ComputeHash(ASCIIEncoding.UTF8.GetBytes(plainText));
return Convert.ToBase64String(cryptoByte, 0, cryptoByte.Length);
}
/// <summary>
/// Cria hash para algum tipo de stream.
/// </summary>
/// <param name="fileStream">Stream a ser criado o hash.</param>
/// <returns>Hash do stream inserido.</returns>
public string GetHash(FileStream fileStream)
{
byte[] cryptoByte;
cryptoByte = _algorithm.ComputeHash(fileStream);
fileStream.Close();
return Convert.ToBase64String(cryptoByte, 0, cryptoByte.Length);
}
#endregion
}