terça-feira, 24 de agosto de 2010

Criptografia Assimétrica

Este artigo aplica-se aos seguintes produtos e tecnologias:

• Microsoft .Net Framework 2.0

Introdução

Este artigo é uma continuação de “Criptografia e Certificação Digital”.

Criptografia Assimétrica

Como citado no primeiro artigo desta série, a criptografia de dados usando algoritmos assimétricos dispõe de um par de chaves publica/privada. Quando o dado é criptografado com a chave pública, somente que tem a chave privada pode descriptografar. Esse algoritmo é muito utilizado quando a informação se externa ao sistema e é necessário manter um grau de segurança nos dados, e para que não seja divulgada uma única chave como é feito nos algoritmos simétricos, possuímos um par, e esse é divulgado somente a parte pública.

Imagine o seguinte cenário: Você precisa trocar informações confidenciais com alguns usuários sem precisar divulgar a chave de criptografia que utiliza. Para isso, é criado um par de chaves onde somente uma será divulgada para os usuários que você deseja receber a informação.



Ilustração 1 – Visualização da criptografia assimétrica.

O exemplo de código a seguir exemplifica o cenário mencionado usando o algoritmo RSA. Primeiramente o usuário “UserA” distribui a sua chave pública para aqueles que ele deseja receber a informação de forma segura. Em seguida o “UserB” codifica a mensagem com a chave pública enviada pelo “UserA”. Ressalto que somente quem tem a chave particular “UserA” poderá ler a mensagem.

Exemplos de código


//Instancia a classe RSA
RSACryptoServiceProvider rsaProviderGen = new RSACryptoServiceProvider();

// Obtém os pares de chaves
string publicKey = rsaProviderGen.ToXmlString(false);
string privateKey = rsaProviderGen.ToXmlString(true);
Console.WriteLine(String.Format("{0}{1}\n","Chave Pública.....:", publicKey));
Console.WriteLine(String.Format("{0}{1}\n","Chave Particular..:", privateKey));

// Mensagem a ser Cifrada
string messageToEncr = "Olá Mundo;)";
Console.WriteLine(String.Format("{0}{1}\n","Texto Plano.......:", messageToEncr));

// UserB gera a mensagem cifrada para o UserA utilizando a Chave Pública que lhe foi passada

RSACryptoServiceProvider rsaProviderEncr = new RSACryptoServiceProvider();
rsaProviderEncr.FromXmlString(publicKey);
byte[] messageToDencr = rsaProviderEncr.Encrypt(Encoding.Unicode.GetBytes(messageToEncr),false);
Console.WriteLine(String.Format("{0}{1}\n","Texto Cifrado.....:", System.Convert.ToBase64String(messageToDencr)));

// UserA lê a mensagem utilizando a sua chave partitular
RSACryptoServiceProvider rsaProviderDencr = new RSACryptoServiceProvider();
rsaProviderDencr.FromXmlString(privateKey);

string
plainMessage = Encoding.Unicode.GetString(rsaProviderDencr.Decrypt(messageToDencr,false));
Console.WriteLine(String.Format("{0}{1}\n","Texto Plano.....:", plainMessage));

Dica

Se o “UserA” precisa enviar informações para o “UserB”, é necessário que o “UserB” também crie seu par de chaves. Assim o “UserA” passa a utilziar a chave pública do “UserB” para cifrar a informação.

Links Relacionados

.NET Framework Cryptography Model

Bibliografia Utilizada

• Building Secure ASP.NET Applications, Microsoft Patterns & Practices

domingo, 8 de agosto de 2010

Criptografia Simétrica



Este artigo aplica-se aos seguintes produtos e tecnologias:

• Microsoft .Net Framework 2.0

Introdução

Este artigo é uma continuação de “Criptografia e Certificação Digital”.

Criptografia Simétrica

Como citado no primeiro artigo desta série, a criptografia de dados usando algoritmos simétricos dispõe de uma única chave para criptografar e descriptografar a informação, sendo assim, somente aqueles que possuem acesso à chave podem ler e escrever neste formato de dados.

Imagine o seguinte cenário: Você deseja sigilo nas informações gravadas pelo seu sistema no banco de dados ou então geradas em disco. É comum que administradores de sistemas, de banco de dados, usuários avançados, desenvolvedores e analistas tenham acesso a informação, muitas vezes confidencial, como por exemplo, dados de cartão de crédito, dados bancários, senhas, etc. Para isso a utilização de algoritmos simétricos seria uma escolha inteligente, visto que propicia uma criptografia ágil e segura, escondendo a informação de qualquer acesso não autorizado.
Ilustração 1 – Visualização da criptografia simétrica.

O exemplo de código a seguir exemplifica o cenário mencionado usando o algoritmo Rijndael. O usuário “UserA” cifra a mensagem com a chave e grava no banco de dados. Somente quem conhece a chave e o algoritmo pode recuperar o dado cifrado.

Exemplos de código

// Exemplo usando o algoritmo Rijndael
var cryptoProvider = new RijndaelManaged();

cryptoProvider.GenerateKey();
cryptoProvider.GenerateIV();

byte[] key = cryptoProvider.Key;
byte[] IV = cryptoProvider.IV;

// Define a mensagem
string messageToEncr = "Olá Mundo;)";
Console.WriteLine( String.Format("{0}{1}","Texto Plano..:", messageToEncr));

// Criptografa
string messageToDencr = Encry(messageToEncr, key, IV);
Console.WriteLine( String.Format("{0}{1}","Texto Cifrado:", messageToDencr));


// Descriptografa os dados
string dencrMessage = Dencry(messageToDencr, key, IV);
Console.WriteLine(String.Format("{0}{1}","Texto Plano..:", dencrMessage));

As classes possuem métodos para gerar a chave e o vetor de inicialização que devem ser armazenadas em local seguro, para que seja possível recuperar a o dado cifrado no futuro. No exemplo acima uso a própria classe para gerar, mas caso você já tenha a chave, o que é o mais comum, pode utilizá-las conforme o trecho de código seguinte:

// Chave de criptografia
string MyKey = "M!n8Ch@v3";

// Exemplo usando o algoritmo Rijndael
var cryptoProvider = new RijndaelManaged();

// Usando a chave e o IV derivado da chave
PasswordDeriveBytes pdb = new PasswordDeriveBytes(MyKey, new MD5CryptoServiceProvider().ComputeHash(Encoding.Unicode.GetBytes(MyKey)));

byte[] key = pdb.GetBytes(32);
byte[] IV = pdb.GetBytes(16);

// Define a mensagem 
string messageToEncr = "Olá Mundo;)";
Console.WriteLine(String.Format("{0}{1}", "Texto Plano..:", messageToEncr));

// Criptografa 
string messageToDencr = Encry(messageToEncr, key, IV);
Console.WriteLine(String.Format("{0}{1}", "Texto Cifrado:", messageToDencr));

Não é recomendada a utilização do mesmo vetor de inicialização (VI) para cifrar outros dados, pois se perde o sentido do algoritmo, visto que o vetor de inicialização serve para oferecer a aleatoriedade nos dados gerados.

O método Encry

static string Encry(string plainText, byte[] key, byte[]IV)
{
    RijndaelManaged cryptoProvider = new RijndaelManaged();
    ICryptoTransform cryptoTrans = cryptoProvider.CreateEncryptor(key,IV);

    // Utiliza a classe CryptoStream para transformar o texto plano
    MemoryStream ms = new MemoryStream();
    CryptoStream cryptStream = new CryptoStream(ms, cryptoTrans, CryptoStreamMode.Write);
    StreamWriter sw = new StreamWriter(cryptStream);
    sw.Write(plainText);

    // Fecha Streams
    sw.Close();
    cryptStream.Close();
    ms.Close();

    // Obtém o texto cifrado
    return System.Convert.ToBase64String(ms.ToArray());
}

O método Dencry

static string Dencry(string cipherText, byte[] key, byte[] IV)
{
    RijndaelManaged cryptoProvider = new RijndaelManaged();

    // Utiliza a classe CryptoStream para transformar o texto cifrado
    MemoryStream ms =
new
MemoryStream(System.Convert.FromBase64String(cipherText));

    CryptoStream cryptStream = new CryptoStream(ms, cryptoProvider.CreateDecryptor(key,
IV), CryptoStreamMode.Read);


    StreamReader sr = new StreamReader(cryptStream);
    string descryptedMessageText = sr.ReadToEnd();
    // Fecha Streams    sr.Close();
    cryptStream.Close();
    ms.Close();

    // Obtém o texto plano
    return descryptedMessageText;
}


Chaves

Alguns algoritmos suportam chaves de até 1024bits, porém a maioria das classes implementam até 256bits. Segue algumas informações relacionadas ao tamanho das chaves para cada algoritmo:

• RC2: chaves de 40 a 128 bits
• DES: chaves de 64 bits
• Rijndael: chaves de 128, 192 ou 256(Padrão) bits
• TripleDES: chaves de 128 até 192 bits

Dica

Observe o exemplo da figura “Ilustração – 1”, a senha é a mesma para os dois usuários. Isso significa que embora os usuários sejam diferentes ambos possuem a mesma senha. Isso caracteriza um risco para seu ambiente, ou seja, se um determinado usuário atualizar a senha do usuário “root” com a sua senha pessoal, ele terá acesso de login com as credencias do usuário “root”, pois não há nenhuma inteligência para gerar a chave que cifra os dados. Tente sempre utilizar alguma outra informação junto com a chave de criptografia, ou gerar um IV diferente, como por exemplo, usando o nome do usuário, isso fará com que embora eles tenham a mesma senha, terão valores criptografados diferentes.

Links Relacionados

.NET Framework Cryptography Model

Bibliografia Utilizada

• Building Secure ASP.NET Applications, Microsoft Patterns & Practices