Sto dando una consulenza gratuita per un'organizzazione senza scopo di lucro che vuole un sistema semplice per gestire più gruppi con una componente di pianificazione, ecc. e anche gestire le informazioni mediche dei bambini. È tutto in un file Excel ma il problema è che non è molto conveniente per l'infermiera. Quindi, sto costruendo questa applicazione ASP.NET e colpisco un muro quando cerco di crittografare i dati sensibili. Ho scritto questo codice C # seguendo i libri e le raccomandazioni di questo sito. Lo sto facendo bene?
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);
}
}
Il codice funziona quando inserisco i dati; è crittografato nel database e il sale corretto viene memorizzato con i valori. Quando lo voglio decrittografato in una casella di testo, funziona correttamente.
La mia idea è: l'infermiere immette i dati nel modulo, lo crittografa con una password un numero MediCare crittografato e un valore salt viene generato dal server e quindi inviato al server SQL, il MediCare viene crittografato nella tabella chi assomiglia a questo.
Medicare_ID - int (Primary Key)
Medicar_Number - (varchar(MAX))
Medicare_SALT - (varchar(MAX))
La password di decrittografia non è memorizzata nel database e l'ho fatto apposta.
Non sono sicuro di aver seguito le migliori pratiche qui. Le mie informazioni possono essere facilmente decifrate se il server fisico viene rubato? Hanno ancora bisogno della password per decifrare i dati, giusto? A volte è necessario decrittografarlo in caso di emergenza. Il mio metodo di decodifica è sicuro? Un'altra preoccupazione è che io uso il 1 e il web hosting condiviso.
Ho impostato alcune misure di sicurezza aggiuntive, ad esempio, SSL verrà attivato sul sito Web in modo che le informazioni siano crittografate e impediscano il distacco degli occhi.
Mi assicurerò che le stringhe e gli input delle connessioni siano disinfettati solo nel caso in cui, in teoria, solo 1-2 manager o infermieri manipolino i dati.
L'accesso al sito web è protetto da un nome utente e una password con un controllo di accesso che ho preso in prestito da Visual Studio 2010.