Estoy dando una consulta gratuita para una organización sin fines de lucro que desea un sistema simple para administrar varios grupos con un componente de programación, etc. y también administrar la información médica de los niños. Todo está en un archivo de Excel, pero el problema es que no es muy conveniente para la enfermera. Entonces, estoy construyendo esta aplicación ASP.NET y golpeo una pared cuando intento el cifrado de datos confidenciales. He escrito este código C # siguiendo los libros y las recomendaciones de este sitio web. Lo estoy haciendo bien?
public partial class SymmetricEncryptionWithPassword : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
/// <summary>
/// Handles the OnClick event of the Encrypt control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
protected void Encrypt_OnClick(object sender, EventArgs e)
{
// Initialize the algorithm from the values on the page.
SymmetricAlgorithm symmetricAlgorithm = new AesManaged();
byte[] generatedKey = null;
byte[] generatedIV = null;
TextBox salt = (TextBox)DetailsView1.FindControl("TextBox2");
TextBox ssn = (TextBox)DetailsView1.FindControl("TextBox1");
salt.Text = Convert.ToBase64String(GenerateSalt());
GetKeyAndIVFromPasswordAndSalt(this.password.Text, Convert.FromBase64String(salt.Text), symmetricAlgorithm, ref generatedKey, ref generatedIV);
symmetricAlgorithm.Key = generatedKey;
symmetricAlgorithm.IV = generatedIV;
ICryptoTransform encryptor = symmetricAlgorithm.CreateEncryptor(symmetricAlgorithm.Key, symmetricAlgorithm.IV);
// Create the streams used for encryption.
MemoryStream memoryStream = new MemoryStream();
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
{
byte[] plainTextAsBytes = new UTF8Encoding(false).GetBytes(ssn.Text);
cryptoStream.Write(plainTextAsBytes, 0, plainTextAsBytes.Length);
}
symmetricAlgorithm.Clear();
byte[] encryptedData = memoryStream.ToArray();
ssn.Text = Convert.ToBase64String(encryptedData);
}
/// <summary>
/// Handles the OnClick event of the Decrypt control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
protected void Decrypt_OnClick(object sender, EventArgs e)
{
// Initialize the algorithm from the values on the page.
SymmetricAlgorithm symmetricAlgorithm = new AesManaged();
byte[] generatedKey = null;
byte[] generatedIV = null;
TextBox txt = (TextBox)DetailsView1.FindControl("TextBox2");
TextBox txt1 = (TextBox)DetailsView1.FindControl("TextBox1");
GetKeyAndIVFromPasswordAndSalt(this.password.Text, Convert.FromBase64String(txt.Text), symmetricAlgorithm, ref generatedKey, ref generatedIV);
symmetricAlgorithm.Key = generatedKey;
symmetricAlgorithm.IV = generatedIV;
ICryptoTransform decryptor = symmetricAlgorithm.CreateDecryptor(symmetricAlgorithm.Key, symmetricAlgorithm.IV);
// Create the streams used for encryption.
MemoryStream memoryStream = new MemoryStream();
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Write))
{
byte[] encryptedDataAsBytes = Convert.FromBase64String(txt1.Text);
cryptoStream.Write(encryptedDataAsBytes, 0, encryptedDataAsBytes.Length);
}
symmetricAlgorithm.Clear();
byte[] decryptedData = memoryStream.ToArray();
txt1.Text = Encoding.UTF8.GetString(decryptedData);
}
/// <summary>
/// Generates a cryptographically secure block of data suitable for salting hashes.
/// </summary>
/// <returns>A cryptographically secure block of data suitable for salting hashes.</returns>
private static byte[] GenerateSalt()
{
const int MinSaltSize = 8;
const int MaxSaltSize = 16;
// Generate a random number to determine the salt size.
Random random = new Random();
int saltSize = random.Next(MinSaltSize, MaxSaltSize);
// Allocate a byte array, to hold the salt.
byte[] saltBytes = new byte[saltSize];
// Initialize the cryptographically secure random number generator.
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
// Fill the salt with cryptographically strong byte values.
rng.GetNonZeroBytes(saltBytes);
return saltBytes;
}
/// <summary>
/// Generates a key and IV from password and salt.
/// </summary>
/// <param name="password">The password.</param>
/// <param name="salt">The salt used in generation.</param>
/// <param name="symmetricAlgorithm">The symmetric algorithm to generate the key and IV for.</param>
/// <param name="key">The generated key.</param>
/// <param name="iv">The generated IV.</param>
private static void GetKeyAndIVFromPasswordAndSalt(string password, byte[] salt, SymmetricAlgorithm symmetricAlgorithm, ref byte[] key, ref byte[] iv)
{
Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, salt);
key = rfc2898DeriveBytes.GetBytes(symmetricAlgorithm.KeySize / 8);
iv = rfc2898DeriveBytes.GetBytes(symmetricAlgorithm.BlockSize / 8);
}
}
El código funciona cuando ingreso datos; está cifrado en la base de datos y la sal adecuada se almacena con los valores. Cuando quiero que se descifre en un cuadro de texto, funciona correctamente.
Mi idea es: la enfermera ingresa los datos en el formulario, la cifra con una contraseña, el número de MediCare y el valor de sal son generados por el servidor y luego enviados al servidor SQL. MediCare se cifra en la tabla que se ve así.
Medicare_ID - int (Primary Key)
Medicar_Number - (varchar(MAX))
Medicare_SALT - (varchar(MAX))
La contraseña de descifrado no está almacenada en la base de datos, y lo hice a propósito.
Simplemente no estoy seguro de seguir las mejores prácticas aquí. ¿Se puede descifrar fácilmente mi información si el servidor físico fue robado? Todavía necesitan la contraseña para descifrar los datos, ¿verdad? A veces necesitamos descifrarlo en caso de una emergencia. ¿Es seguro mi método de descifrado? Otra preocupación es que uso 1 y 1 alojamiento web compartido.
He configurado algunas medidas de seguridad más, por ejemplo, SSL se activará en el sitio web para que la información esté encriptada y evite que se te caiga la vista.
Me aseguraré de que las cadenas de conexión y las entradas se desinfecten por si acaso, pero en teoría solo 1-2 gerentes o enfermeras manipularán los datos.
El acceso al sitio web está protegido con un nombre de usuario y contraseña con un control de inicio de sesión que tomé prestado de Visual Studio 2010.