Criptografía para principiantes en .NET

El hashing es el proceso de transformación de unos datos de entrada de una longitud arbitraria a un array de bytes de tamaño fijo. El hash es una función de transformación, cuyo resultado no se puede invertir para obtener los datos de entrada originales. Se utiliza muy a menudo para almacenar contraseñas. Incluso si un atacante consigue un hash, nunca podrá recuperar la contraseña. La longitud de un hash está determinado por el algoritmo del hash. En .NET puedes encontrar los siguientes algoritmos hash (todos ellos derivan de la clase base HashAlgorithm)

  • MD5 – 128 bits de longitud
  • SHA – No existe la clase como tal, pero existe SHA1 (160 bits), SHA256, SHA384, SHA512
  • KeydHashAlgorithm – Representado por las siguientes clases de algoritmos: HMAC y MACTripleDES

Si necesitas un hash basado en una clave, entonces (si todas las demás condiciones son iguales), es mejor depender de SHA512. MD5 es antiguo y puede verse comprometido. SHA512 funciona muy rápido (sólo SHA1 es más rápido). El más lento de todos es MACTripleDES. Los algoritmos HMAC son aproximadamente entre 2-4 veces más lentos que SHA.

Los hashes basados ​​en una clave pueden utilizarse para proteger datos de modificaciones. Las solicitudes enviadas al servidor desde el cliente podrán ser verificadas por los hechos de las modificaciones. Si el servidor recibe los datos modificados, los hashes no serán iguales. En el caso de proteger solicitudes de strings, no debes confiar en un hash que no se base en una clave. Porque un atacante puede realizar ataques de fuerza bruta todos los posibles algoritmos hash, encontrar el más buscado, modificar los argumentos de la cadena de la solicitud, adjunte el hash-valor correcto y después que el servidor tenga que aceptar la solicitud. Con el fin de proteger al servidor de esto, puedes utilizar HMACSHA1 como algoritmo basado en clave hash. En este caso, obviamente, surge el problema de almacenar esa clave.

public static byte[] ComputeHmacsha1(byte[] data, byte[] key)
{
      using (var hmac = new HMACSHA1(key))
      {
            return hmac.ComputeHash(data);
      }
}

Puede añadir salt, con el fin de reducir las habilidades del atacante en la recogida de los datos de entrada que corresponden a un hash-valor para su posterior ataque de fuerza bruta. El salt es una "clave" aleatoria adicional, lo que añade un poco de complejidad en el cifrado. El salt puede ser transmitida en texto plano. Puede ser generado y asociado con la sesión actual del usuario. El salt será actualizado en cada nueva sesión, por lo tanto, los valores del hash para las mismas peticiones serán diferentes en diferentes sesiones. Además, con el fin de complicar el ataque por fuerza bruta, se puede agregar salt a contraseñas hash. Es mejor utilizar un generador criptográficamente fuerte como RNGCryptoServiceProvider.

El salt puede ser generado con el siguiente código:

string salt = GenSalt(32);
string GenSalt(int length)
{
    RNGCryptoServiceProvider p = new RNGCryptoServiceProvider();
    var salt = new byte[length];
    p.GetBytes(salt);
    return Convert.ToBase64String(salt);
}

Algoritmos simétricos

Puede encontrar los siguientes algoritmos en .NET que se derivan de la clase base SymmetricAlgorithm:

  • Rijndael
  • DES
  • Triple DES
  • RC2

El algoritmo más recomendado por defecto es Rijndael. Mars, RC6, Serpent, Twofish también son buenas opciones, pero no los encontrará en el paquete estándar de .NET. Rijndael es un block cypher. Esto significa que los datos de entrada se cortaron en bloques, y el algoritmo se aplicará a cada bloque de forma consecutiva.

El padding es un proceso de ajuste (insertando algunos datos adicionales) de los resultados generados por un block cypher con el fin de obtener el resultado en el tamaño requerido.

Rijndael es compatible con varios modos de padding: ceros, números aleatorios, y un par de modos más. El modo más seguro, que añade un poco de complejidad al asunto, es el modo de ISO10126.

Rijndael también es compatible con varios modos de procesamiento de bloques. el modo CBC es la mejor opción por defecto. Este modo ayuda a que cada bloque tome como entrada los resultados de la encriptación del bloque anterior, lo que aumenta la complejidad de nuevo.

IV es el vector de inicialización. Se pasa como entrada para el primer bloque. En caso de Rijndael, IV se generará automáticamente. IV es necesario para descifrar el contenido, por lo que debes pasarle un método de descifrado. Por cierto, se puede pasar en texto plano.

Consideremos el siguiente ejemplo:

string Encrypt()
{
   RijndaelManaged cipher = new RijndaelManaged();
   cipher.KeySize = 256;
   cipher.BlockSize = 256; //use 128 for compatibility with AES
   cipher.Padding = PaddingMode.ISO10126;
   cipher.Mode = CipherMode.CBC;
   cipher.Key = "some_super_secret_key";

   ICryptoTransform t = cipher.CreateEncryptor();
   string text = "some_text_to_encrypt";
   byte[] textInBytes = Encoding.UTF8.GetBytes(text);
   byte[] result = t.TransformFinalBlock(textInBytes, 0, textInBytes.Length);
   return Convert.ToBase64String(result);
}

NET también proporciona una clase interesante llamada CryptoStream. Se utiliza para la integración del cifrado y streams como FileStream y demás. Por ejemplo, un CryptoStream que realiza el cifrado puede transmitir con otro CryptoStream que envuelva FileStream. Después de eso, puedes llamar a Write en el primer CryptoStream con un poco de texto y, como resultado, se cifraría y se escribiría en un archivo.

Algoritmos asimétricos

En el caso de los algoritmos asimétricos, la clave pública se utiliza para el cifrado y la clave privada para el descifrado. Si sólo hay una parte que descifrar mensajes cifrados, la clave privada debe ser almacenada en un único lugar. En caso de encriptación simétrica, una clave privada debe ser compartido entre todos los participantes.

Los algoritmos asimétricos son más lentos que los simétricos, aproximadamente de 100 a 1.000 veces. Es por eso que es algo problemático cifrar grandes fragmentos de datos. El cifrado asimétrico se puede utilizar con el simétrico. Los algoritmos asimétricos generan una nueva clave de sesión, que se utiliza como clave para el cifrado simétrico.

.NET proporciona los siguientes algoritmos asimétricos:

  • RSA
  • DSA (sólo para señales digitales)
  • ECDiffieHellman

Por lo general, la gente usa RSA de 2048 o 4096. RSA de 1024 no es muy fuerte y de hecho, ha sido demostrado. Por lo tanto, debes confiar en los 2048 bits y a una mayor longitud. He aquí un ejemplo del uso de RSA:

public class RsaWithCspKey
    {
        const string ContainerName = "MyContainer";
        public void AssignNewKey()
        {
            CspParameters cspParams = new CspParameters(1);
            cspParams.KeyContainerName = ContainerName;
            cspParams.Flags = CspProviderFlags.UseMachineKeyStore;
            cspParams.ProviderName = "Microsoft Strong Cryptographic Provider";
            var rsa = new RSACryptoServiceProvider(cspParams) { PersistKeyInCsp = true };
        }
        public void DeleteKeyInCsp()
        {
            var cspParams = new CspParameters { KeyContainerName = ContainerName };
            var rsa = new RSACryptoServiceProvider(cspParams) { PersistKeyInCsp = false };
            rsa.Clear();
        }
        public byte[] EncryptData(byte[] dataToEncrypt)
        {
            byte[] cipherbytes;
            var cspParams = new CspParameters { KeyContainerName = ContainerName };
            using (var rsa = new RSACryptoServiceProvider(2048, cspParams))
            {
                cipherbytes = rsa.Encrypt(dataToEncrypt, false);
            }
            return cipherbytes;
        }
        public byte[] DecryptData(byte[] dataToDecrypt)
        {
            byte[] plain;
            var cspParams = new CspParameters { KeyContainerName = ContainerName };
            using (var rsa = new RSACryptoServiceProvider(2048, cspParams))
            {
                plain = rsa.Decrypt(dataToDecrypt, false);
            }
            return plain;
        }
    }

Fuente: EngineerSpock

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP
ARTÍCULO ANTERIOR