Criptografando

<< Click to Display Table of Contents >>

Navigation:  Funções >

Criptografando

Previous pageReturn to chapter overviewNext page

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

}