cómo usar RSA para cifrar archivos (datos enormes) en C#


Soy nuevo en el cifrado. Necesito implementar el algoritmo de cifrado asimétrico, que creo que utiliza clave privada / pública. Empecé a usar una muestra de RSACryptoServiceProvider. estaba bien con datos pequeños para cifrar. Pero cuando se utiliza en datos relativamente más grandes "2 líneas", obtengo la excepción CriptográficaExcepción"Mala longitud"!

//Create a new instance of RSACryptoServiceProvider.
using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider())
{

    //Import the RSA Key information. This only needs
    //toinclude the public key information.
    //RSA.ImportParameters(RSAKeyInfo);
    byte[] keyValue = Convert.FromBase64String(publicKey);
    RSA.ImportCspBlob(keyValue);

    //Encrypt the passed byte array and specify OAEP padding.  
    //OAEP padding is only available on Microsoft Windows XP or
    //later.  
    encryptedData = RSA.Encrypt(DataToEncrypt, DoOAEPPadding);
}

Luego encontré algunas muestras de cifrar grandes datos (o archivos) mediante el uso de CryptoStream, y solo utilizar algoritmos simétricos como DES o 3DES, que tienen la función CreateEncryptor para devolver ICryptoTransform como una de las entradas para el constructor de CryptoStream!!!

CryptoStream cStream = new CryptoStream(fStream,
                new TripleDESCryptoServiceProvider().CreateEncryptor(Key, IV),
                CryptoStreamMode.Write);

¿Cuál es la forma de cifrar archivos usando RSA?

Author: ala, 2009-07-29

6 answers

Como se mencionó en otras respuestas, el cifrado asimétrico solo está diseñado para cifrar datos más pequeños que su tamaño de clave.

Una opción que he implementado cuando necesito transferir grandes cantidades de datos cifrados entre dos sistemas es tener un par de claves RSA cuya clave pública sea conocida tanto por el remitente como por el receptor. Luego, cuando los datos deben enviarse, el receptor genera un nuevo par de claves RSA, cifra la clave pública de ese par de claves con la clave pública común y envía clave pública cifrada para el remitente. El remitente descifra la clave pública del receptor utilizando su clave privada (que el receptor no necesita saber, al igual que el remitente no necesita saber la clave privada generada por los receptores), genera una clave de cifrado simétrica, cifra los datos con la clave simétrica y luego cifra la clave simétrica utilizando la clave pública recibida del receptor. Tanto la clave simétrica cifrada como los datos cifrados se envían al receptor que utiliza su clave privada generada para descifrar la clave simétrica y luego descifrar los datos.

Puede usar los métodos RSACryptoServiceProvider.ToXMLString() y RSACryptoServiceProvider.FromXMLString() para almacenar la clave pública común como un literal de cadena XML en la aplicación receiver.

No se olvide, cuando se genera la clave de cifrado simétrico para utilizar RNGCryptoServiceProvider() para generar la clave, ya que es un método mucho más seguro de generar (pseudo) números aleatorios.

Además, recomiendo encarecidamente no usar 3DES como su algoritmo de cifrado simétrico, es viejo y empezando a mostrar su edad. Utilice el cifrado simétrico AES con las clases AesCryptoServiceProvicer o RijndaelManaged.

 32
Author: Joe Kuemerle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-22 14:06:41

RSA solo puede cifrar bloques de datos que son más cortos que la longitud de la clave, por lo que lo que normalmente hace es

  1. Genere una clave aleatoria de la longitud correcta requerida para AES (o similar).
  2. Encripte sus datos usando AES o similar usando esa clave
  3. Cifrar la clave aleatoria usando su clave RSA

Luego se publican las salidas de 2 y 3

Para descifrar

  1. Descifre la clave AES usando su clave RSA.
  2. Descifrar los datos utilizando ese AES clave
 57
Author: jcoder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-15 15:32:39

Por lo general, RSA solo se usa para transferir una clave simétrica (al comienzo del flujo, por ejemplo) y luego los datos masivos se cifran con esa clave.

El cifrado asimétrico no es lo suficientemente eficiente como para transferir una gran cantidad de datos.

 20
Author: Henk Holterman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-21 18:34:52

Para búsquedas futuras con respecto a excepciones de longitud incorrecta de RSA...

Puede calcular el número máximo de bytes que se pueden cifrar con un tamaño de clave particular con lo siguiente:

((KeySize - 384) / 8) + 37

Sin embargo, si el parámetro optimal asymmetric encryption padding (OAEP) es true, se puede usar lo siguiente para calcular los bytes máximos:

((KeySize - 384) / 8) + 7

Los tamaños de clave legales son de 384 a 16384 con un tamaño de salto de 8.

 18
Author: ObjectType,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-07-15 07:03:18

Las implementaciones.NET de RSA (y todos los algoritmos de clave pública/privada) no admiten grandes bloques de datos, porque ese no es el objetivo de la clave pública/privada.

En su lugar, lo que haría es generar una nueva clave simétrica y usarla para cifrar los datos. A continuación, utiliza la clave pública/privada para cifrar la clave simétrica e intercambiarla con la otra parte de forma segura. A continuación, descifran la clave simétrica y la utilizan para desencriptar sus datos.

 6
Author: blowdart,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-29 09:52:11

Tenemos:

MaxBlockSize=((KeySize - 384) / 8) + 37

O

MaxBlockSize=((KeySize - 384) / 8) + 7

Por lo tanto, podemos dividir los datos en algunos bloques y luego cifrar cada uno y luego fusionarlos

 1
Author: kazem,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-06 10:23:17