Desenvolvimento - C#

Criptografando dados com C#

O artigo mostra um exemplo muito fácil de se implementar com C# uma classe que encripta e desencripta dados.

por Everton José Benedicto



                Hoje a segurança da informação está sendo muito importante para nós, temos que nos assegurar que o que enviamos para algum lugar, chegue sem que outra pessoa leiam e intendam o que está no conteúdo da mensagem, e quem receber a mensagem entenda com clareza o que você enviou. Para assegurar que ninguem leia a sua mensagem encriptamos a mensagem com uma chave unica (que geralmente é criada pelo emissor da mensagem)  e um algoritmo de encriptação de dados (que citarei alguns ao decorrer do artigo). Este processo de  encriptação de dados com uma chave única é chamado de “Criptográfia Simétrica”.

Tipo de algoritmos de Criptográfia Simétrica que são mais usados no mercado:

· Rijndael

· RC2

· DES

· TripleDES

Se você fizer pesquisa básica na internet para saber um pouco mais sobre cada um desses algoritmos de criptográfia é muito rápida e fácil, não vou focar muito em cima desses algoritmo pois não é o foco principal do artigo.

Vou mostra um exemplo muito fácil de se implementar com C# uma classe que encripta e desencripta dados. Abra o Visual Studio e crie um projeto Windows Forms Chamado Criptografia (se desejar criar o projeto com outro nome sinta-se a vontade), vamos adicionar ao projeto uma classe chamada Criptografia.cs implentar o seguinte código que está abaixo na listagem 1.

using System;

using System.Collections.Generic;

using System.Text;

using System.Security.Cryptography;

using System.IO;

namespace Criptografia

{

    /// <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

    }

    public class Criptografia

    {

        #region Variáveis e Métodos Privados

        private string _key = string.Empty;

        private CryptProvider _cryptProvider;

        private SymmetricAlgorithm _algorithm;

        /// <summary>

        /// Inicialização do vetor do algoritmo simétrico

        /// </summary>

        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 (Rijndael).

        /// </summary>

        public Criptografia()

        {

            _algorithm = new RijndaelManaged();

            _algorithm.Mode = CipherMode.CBC;

            _cryptProvider = CryptProvider.Rijndael;

        }

        /// <summary>

        /// Construtor com o tipo de criptografia a ser usada Você pode escolher o tipo pelo Enum chamado CryptProvider.

        /// </summary>

        /// <param name="cryptProvider">Tipo de criptografia.</param>

        public Criptografia(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;

            // Ajusta 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.ASCII.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 texto)

        {

            byte[] plainByte = Encoding.UTF8.GetBytes(texto);

            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 textoCriptografado)

        {

            // Converte a base 64 string em num array de bytes

            byte[] cryptoByte = Convert.FromBase64String(textoCriptografado);

            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

    }

}

Listagem 1: Classe Criptográfia

                Coloquei comentários no código que exclarecem possiveis dúvidas. Depois de criar a classe Criptografia.cs vá no Form1 que é criado automáticamente com o projeto Windows Forms e faça uma tela com a layout que você pode visualizar na Figura 1.

Figura 1: Layout da Tela Criptografia.

                Vamos renomear o nome dos componentes para não haver erros de compilação no seu código:

· TextBox (Texto Normal) : mude o nome para “txtNormal”.

· TextBox (Texto Criptografado) : mude o nome para “txtCriptografado” e coloque a propriedade Enabled para False.

· Button (Criptografar) : mude o nome para “btnCriptografar”.

· Button (Decriptar) : mude o nome para “btnDecriptar”.

Depois de ter configurado as propriedades dos componentes da tela vamos criar um evento para o botão “btnCriptografar” e colocar o seguinte código que está abaixo na Listagem 2.

private void btnCriptografar_Click(object sender, EventArgs e)

{

string texto = txtNormal.Text;

string key = "Criptografia"; //Está chave você mesmo é quem escolhe.

Criptografia crip = new Criptografia(CryptProvider.DES);

      crip.Key = key;

      txtCriptografado.Text = crip.Encrypt(texto);

}

Listagem 2: Evento do botão “btnCriptografar”.

                Vamos criar agora o Evento para o botão “btnDecriptar” coloque o código que está na Listagem 3.

private void btnDecriptar_Click(object sender, EventArgs e)

{

string texto = txtCriptografado.Text;

//Está chave tem que ser a mesma que a do texto Encriptado.

      string key = "Criptografia";

      Criptografia crip = new Criptografia(CryptProvider.DES);

      crip.Key = key;

      MessageBox.Show(crip.Decrypt(texto), this.Text, MessageBoxButtons.OK, MessageBoxIcon.Information);

}

Listagem 3: Evento do botão “btnDecriptar”.

                Compile e execute o projeto. Digite uma frase qualquer e clique no botão “Criptografar”, ele colocará o texto criptografado no TextBox ao lado dele, agora se você clicar no botão “Decriptar” ele vai apresentar o texto decriptado no pop-up.

Conclusão

               

                Criptográfia é muito importante para a nossa segurança de informação, e o exemplo que está no artigo é somente para que você consiga ter uma ideia de como funciona  estas classes de criptografia da .Net. Você pode usar este código do exemplo para salvar senhas no banco de dados, dados que não podem ser vistos por outras pessoas, encriptar conteudo de arquivos textos, etc.

Editado por: Everton José Benedicto.

Everton José Benedicto

Everton José Benedicto - Experiência de 3 anos com SQL Server 2000 e 2005, FastReport, Reporting Services e C#.