querystring para net mvc encriptar desencriptar datos contraseƱa como asp algoritmos .net asp.net security cryptography

mvc - Aprovechando ASP.NET machineKey para encriptar mis propios datos



encriptar querystring asp net c# (5)

Tengo algunos datos que quiero encriptar en una aplicación ASP.NET MVC para evitar que los usuarios lo alteren. Puedo usar las clases de criptografía para hacer el cifrado / descifrado real, no hay problema allí. El problema principal es averiguar dónde almacenar la clave de cifrado y gestionar los cambios en ella.

Como ASP.NET ya tiene una MachineKey para varias cosas (cifrado de ViewData, etc.), me preguntaba si había alguna función de ASP.NET que me permitiera encriptar / desencriptar mis propios datos usando machineKey? De esta forma no tendría que idear mi propio sistema de gestión de claves.


Con .NET Framwork 4.5 debes usar la nueva API:

public class StringProtector { private const string Purpose = "Authentication Token"; public string Protect(string unprotectedText) { var unprotectedBytes = Encoding.UTF8.GetBytes(unprotectedText); var protectedBytes = MachineKey.Protect(unprotectedBytes, Purpose); var protectedText = Convert.ToBase64String(protectedBytes); return protectedText; } public string Unprotect(string protectedText) { var protectedBytes = Convert.FromBase64String(protectedText); var unprotectedBytes = MachineKey.Unprotect(protectedBytes, Purpose); var unprotectedText = Encoding.UTF8.GetString(unprotectedBytes); return unprotectedText; } }

Idealmente, el "Propósito" debería ser un valor válido conocido de una sola vez para evitar la falsificación.



La nueva clase MachineKey en ASP.NET 4.0 hace exactamente lo que desea.

Por ejemplo:

public static class StringEncryptor { public static string Encrypt(string plaintextValue) { var plaintextBytes = Encoding.UTF8.GetBytes(plaintextValue); return MachineKey.Encode(plaintextBytes, MachineKeyProtection.All); } public static string Decrypt(string encryptedValue) { try { var decryptedBytes = MachineKey.Decode(encryptedValue, MachineKeyProtection.All); return Encoding.UTF8.GetString(decryptedBytes); } catch { return null; } } }

ACTUALIZACIÓN : Como se menciona here , tenga cuidado de cómo usar esto o podría permitir a alguien forjar un token de autenticación de formularios.


Si está trabajando con 3.5 o anterior, puede evitar una gran cantidad de código y simplemente hacer esto:

public static string Encrypt(string cookieValue) { return FormsAuthentication.Encrypt(new FormsAuthenticationTicket(1, string.Empty, DateTime.Now, DateTime.Now.AddMinutes(20160), true, cookieValue)); } public static string Decrypt(string encryptedTicket) { return FormsAuthentication.Decrypt(encryptedTicket).UserData; }

Uno de mis colegas me convenció y creo que es bastante razonable hacer esto para las cookies personalizadas, si no para las necesidades generales de encriptación.


Supongo que no directamente. No recuerdo de dónde saqué esto, probablemente una combinación de Reflector y algunos blogs.

public abstract class MyAwesomeClass { private static byte[] cryptKey; private static MachineKeySection machineKeyConfig = (MachineKeySection)ConfigurationManager .GetSection("system.web/machineKey"); // ... snip ... static MyAwesomeClass() { string configKey; byte[] key; configKey = machineKeyConfig.DecryptionKey; if (configKey.Contains("AutoGenerate")) { throw new ConfigurationErrorsException( Resources.MyAwesomeClass_ExplicitAlgorithmRequired); } key = HexStringToByteArray(configKey); cryptKey = key; } // ... snip ... protected static byte[] Encrypt(byte[] inputBuffer) { SymmetricAlgorithm algorithm; byte[] outputBuffer; if (inputBuffer == null) { throw new ArgumentNullException("inputBuffer"); } algorithm = GetCryptAlgorithm(); using (var ms = new MemoryStream()) { algorithm.GenerateIV(); ms.Write(algorithm.IV, 0, algorithm.IV.Length); using (var cs = new CryptoStream( ms, algorithm.CreateEncryptor(), CryptoStreamMode.Write)) { cs.Write(inputBuffer, 0, inputBuffer.Length); cs.FlushFinalBlock(); } outputBuffer = ms.ToArray(); } return outputBuffer; } protected static byte[] Decrypt(string input) { SymmetricAlgorithm algorithm; byte[] inputBuffer, inputVectorBuffer, outputBuffer; if (input == null) { throw new ArgumentNullException("input"); } algorithm = GetCryptAlgorithm(); outputBuffer = null; try { inputBuffer = Convert.FromBase64String(input); inputVectorBuffer = new byte[algorithm.IV.Length]; Array.Copy( inputBuffer, inputVectorBuffer, inputVectorBuffer.Length); algorithm.IV = inputVectorBuffer; using (var ms = new MemoryStream()) { using (var cs = new CryptoStream( ms, algorithm.CreateDecryptor(), CryptoStreamMode.Write)) { cs.Write( inputBuffer, inputVectorBuffer.Length, inputBuffer.Length - inputVectorBuffer.Length); cs.FlushFinalBlock(); } outputBuffer = ms.ToArray(); } } catch (FormatException e) { throw new CryptographicException( "The string could not be decoded.", e); } return outputBuffer; } // ... snip ... private static SymmetricAlgorithm GetCryptAlgorithm() { SymmetricAlgorithm algorithm; string algorithmName; algorithmName = machineKeyConfig.Decryption; if (algorithmName == "Auto") { throw new ConfigurationErrorsException( Resources.MyAwesomeClass_ExplicitAlgorithmRequired); } switch (algorithmName) { case "AES": algorithm = new RijndaelManaged(); break; case "3DES": algorithm = new TripleDESCryptoServiceProvider(); break; case "DES": algorithm = new DESCryptoServiceProvider(); break; default: throw new ConfigurationErrorsException( string.Format( CultureInfo.InvariantCulture, Resources.MyAwesomeClass_UnrecognizedAlgorithmName, algorithmName)); } algorithm.Key = cryptKey; return algorithm; } private static byte[] HexStringToByteArray(string str) { byte[] buffer; if (str == null) { throw new ArgumentNullException("str"); } if (str.Length % 2 == 1) { str = ''0'' + str; } buffer = new byte[str.Length / 2]; for (int i = 0; i < buffer.Length; ++i) { buffer[i] = byte.Parse( str.Substring(i * 2, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture); } return buffer; } }

¡Caveat Emptor!