Cifrar el número de la tarjeta de Medicare en C # en ASP.NET

4

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.

    
pregunta metraon 24.04.2012 - 06:07
fuente

1 respuesta

3

Algunas críticas de la criptografía: debe intentar evitar la generación de claves criptográficas a partir de contraseñas (o si es absolutamente necesario debe, debe usar PBKDF2 con un alto número de iteraciones, pero entienda que el esquema resultante probablemente tendrá poca seguridad y puede proporcionar una falsa sensación de seguridad), y debe aplicar un MAC a los datos cifrados . No seguí algunos de los detalles del cripto (por ejemplo, el bit del número de MediCare). En general, en lugar de descubrir cómo usar crypto correctamente por tu cuenta , probablemente estarás más seguro utilizar GPG para cifrar los datos.

Pero más allá de la criptografía -

No estoy seguro de que cifrar los datos para que solo una enfermera pueda descifrarlos sea el enfoque correcto para la configuración médica. ¿Qué sucede si alguien necesita acceder a los datos médicos en una emergencia y la única enfermera no está cerca? Tal vez, en lugar de tratar de limitar tan severamente el acceso, es posible que necesite un "protocolo de ruptura en caso de un protocolo de emergencia" que permita que cualquier personal médico acceda a los datos, combinado con una auditoría y un escrutinio sólidos de los registros de auditoría, para evitar el uso indebido de la información. característica "romper vidrio".

Tenga cuidado al almacenar los datos médicos en un servicio web, para asegurarse de que los datos médicos no se almacenen inadvertidamente en el lado del cliente (donde podría filtrarse). Asegúrese de enviar encabezados sin caché, para que el cliente no los almacene en caché; usar SSL en todo el sitio; y asegúrese de no hacer disponible ningún dato confidencial en un PDF u otro formato que se descargará en la máquina del cliente.

¿Ha confirmado si este sistema debe ser compatible con HIPAA?

    
respondido por el D.W. 24.04.2012 - 07:30
fuente

Lea otras preguntas en las etiquetas