Codifica il numero di tessera Medicare in C # in ASP.NET

4

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.

    
posta metraon 24.04.2012 - 06:07
fonte

1 risposta

3

Alcune critiche alla crittografia: dovresti cercare di evitare di generare chiavi crittografiche dalle password (o se sei assolutamente deve, si dovrebbe usare PBKDF2 con un elevato numero di iterazioni, ma si capisce che lo schema risultante avrà probabilmente una scarsa sicurezza e potrebbe fornire un falso senso di sicurezza), e è necessario applicare un MAC ai dati crittografati . Non ho seguito alcuni dei dettagli della crittografia (ad esempio, il bit del numero MediCare). In generale, piuttosto che come utilizzare correttamente la crittografia , probabilmente sarai più sicuro solo usa GPG per crittografare i dati.

Ma oltre la crittografia -

Non sono sicuro che la crittografia dei dati in modo che solo una singola infermiera possa decrittografarla è l'approccio giusto per le impostazioni mediche. Cosa succede se qualcuno ha bisogno di accedere ai dati medici in caso di emergenza, e l'unica infermiera non è in giro? Forse invece di cercare di limitare l'accesso in modo così grave, potrebbe essere necessario un "vetro di sicurezza in caso di protocollo di emergenza" che consenta a qualsiasi medico di accedere ai dati, combinato con una strong revisione e controllo dei registri di audit, per prevenire l'uso improprio del funzione "rompi vetro".

Si prega di fare attenzione a conservare i dati medici su un servizio web, per garantire che i dati medici non vengano memorizzati inavvertitamente sul lato client (dove potrebbe essere trapelato). Assicurati di inviare intestazioni no-cache, quindi il client non lo memorizza nella cache; utilizzare SSL in tutto il sito; e assicurati di non rendere disponibili dati riservati in un PDF o altro formato che verrà scaricato sul computer del cliente.

Hai confermato se questo sistema deve essere compatibile con HIPAA?

    
risposta data 24.04.2012 - 07:30
fonte

Leggi altre domande sui tag