c# - online - Cifrado simétrico(AES): ¿Es seguro y correcto guardar la IV y la Sal junto con los datos cifrados?
rijndael (2)
Estoy tratando de entender cómo manejar y administrar un vector de iniciación y sal (cuando corresponda) al cifrar y descifrar datos utilizando un algoritmo de cifrado simétrico, en este caso AES.
He deducido de diferentes hilos de SO y varios otros sitios web que ni la IV ni la sal deben ser secretas, solo únicas para defenderse de ataques criptoanalíticos como un ataque de fuerza bruta. Teniendo esto en cuenta, pensé que sería viable almacenar mi pseudoaleatorio IV con los datos cifrados. Estoy preguntando si el método que estoy usando es correcto y, además, ¿debería tratar mi sal codificada actualmente de la misma manera? Que lo esté escribiendo en el flujo de memoria junto a la IV
Mi código:
private const ushort ITERATIONS = 300;
private static readonly byte[] SALT = new byte[] { 0x26, 0xdc, 0xff, 0x00, 0xad, 0xed, 0x7a, 0xee, 0xc5, 0xfe, 0x07, 0xaf, 0x4d, 0x08, 0x22, 0x3c };
private static byte[] CreateKey(string password, int keySize)
{
DeriveBytes derivedKey = new Rfc2898DeriveBytes(password, SALT, ITERATIONS);
return derivedKey.GetBytes(keySize >> 3);
}
public static byte[] Encrypt(byte[] data, string password)
{
byte[] encryptedData = null;
using (AesCryptoServiceProvider provider = new AesCryptoServiceProvider())
{
provider.GenerateIV();
provider.Key = CreateKey(password, provider.KeySize);
provider.Mode = CipherMode.CBC;
provider.Padding = PaddingMode.PKCS7;
using (MemoryStream memStream = new MemoryStream(data.Length))
{
memStream.Write(provider.IV, 0, 16);
using (ICryptoTransform encryptor = provider.CreateEncryptor(provider.Key, provider.IV))
{
using (CryptoStream cryptoStream = new CryptoStream(memStream, encryptor, CryptoStreamMode.Write))
{
cryptoStream.Write(data, 0, data.Length);
cryptoStream.FlushFinalBlock();
}
}
encryptedData = memStream.ToArray();
}
}
return encryptedData;
}
public static byte[] Decrypt(byte[] data, string password)
{
byte[] decryptedData = new byte[data.Length];
using (AesCryptoServiceProvider provider = new AesCryptoServiceProvider())
{
provider.Key = CreateKey(password, provider.KeySize);
provider.Mode = CipherMode.CBC;
provider.Padding = PaddingMode.PKCS7;
using (MemoryStream memStream = new MemoryStream(data))
{
byte[] iv = new byte[16];
memStream.Read(iv, 0, 16);
using (ICryptoTransform decryptor = provider.CreateDecryptor(provider.Key, iv))
{
using (CryptoStream cryptoStream = new CryptoStream(memStream, decryptor, CryptoStreamMode.Read))
{
cryptoStream.Read(decryptedData, 0, decryptedData.Length);
}
}
}
}
return decryptedData;
}
También estoy abierto a cualquier otra información sobre el cifrado simétrico con respecto a la práctica adecuada.
Almacenar la IV y la Sal junto con el texto cifrado es correcto y es una buena práctica. La codificación de la sal no es útil, siendo aleatorio es importante, la codificación de las iteraciones está perfectamente bien, pero suele ser mucho mayor que 300 (de hecho, al menos 1000 y normalmente es mucho más alto si su máquina / uso puede manejarlo como en 10 segundos). de miles).
Debido a que he visto tantos ejemplos malos (o antiguos) de encriptación c # de desbordamiento de pila, cortar y pegar en código fuente abierto, escribí un poco de código de encriptación para cortar y pegar Ejemplos modernos de cifrado simétrico simétrico de una cadena. que trato de mantener actualizado y revisado. Almacena el iv y salt con el texto cifrado, también autentica el texto cifrado y los valores incluidos con el texto cifrado.
Idealmente, aunque una mejor práctica sería utilizar una biblioteca de cifrado de alto nivel que manejaría las mejores prácticas como la iv para usted, sin embargo, esas no han existido para csharp. He estado trabajando en una versión csharp nativa de la biblioteca keyczar de google. Si bien está funcionalmente listo para su uso, he querido ver más de cerca el código antes del primer lanzamiento oficial estable.
Sí, tanto la IV como la sal son valores públicos. Lo que es más importante es garantizar que estos sean valores aleatorios para cada operación de cifrado.
Para dar un ejemplo de esto en la naturaleza, eche un vistazo al formato de datos rncryptor . Aquí el salt y el IV se empaquetan en un formato de datos, junto con el texto cifrado y un valor MAC. (Nota: este es un ejemplo de objetivo-c).