2010-03-19 37 views
17

Tengo un problema con el cifrado de C# y el descifrado con RSA. Desarrollé un servicio web al que se enviará información y transacciones financieras delicadas. Lo que me gustaría poder hacer es en el lado del cliente, cifrar los campos determinados utilizando la clave privada RSA de los clientes, una vez que haya llegado a mi servicio, se descifrará con la clave pública del cliente.Encriptación/descifrado de RSA Problema en .NET

Por el momento sigo obteniendo un "Los datos que se descifrarán exceden el máximo para este módulo de 128 bytes". excepción. No he tratado mucho con la criptografía C# RSA, por lo que cualquier ayuda sería muy apreciada.

Este es el método que utilizo para generar las claves

private void buttonGenerate_Click(object sender, EventArgs e) 
{ 
    string secretKey = RandomString(12, true); 

    CspParameters param = new CspParameters(); 
    param.Flags = CspProviderFlags.UseMachineKeyStore; 

    SecureString secureString = new SecureString(); 
    byte[] stringBytes = Encoding.ASCII.GetBytes(secretKey); 
    for (int i = 0; i < stringBytes.Length; i++) 
    { 
     secureString.AppendChar((char)stringBytes[i]); 
    } 
    secureString.MakeReadOnly(); 
    param.KeyPassword = secureString; 

    RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(param); 
    rsaProvider = (RSACryptoServiceProvider)RSACryptoServiceProvider.Create(); 
    rsaProvider.KeySize = 1024; 


    string publicKey = rsaProvider.ToXmlString(false); 
    string privateKey = rsaProvider.ToXmlString(true); 

    Repository.RSA_XML_PRIVATE_KEY = privateKey; 
    Repository.RSA_XML_PUBLIC_KEY = publicKey; 

    textBoxRsaPrivate.Text = Repository.RSA_XML_PRIVATE_KEY; 
    textBoxRsaPublic.Text = Repository.RSA_XML_PUBLIC_KEY; 

    MessageBox.Show("Please note, when generating keys you must sign on to the gateway\n" + 
     " to exhange keys otherwise transactions will fail", "Key Exchange", MessageBoxButtons.OK, MessageBoxIcon.Information); 

} 

una vez que han generado las llaves, i enviar la clave pública al servicio web que almacena como un archivo XML.

Ahora decidí probar esto por lo que aquí está mi método para cifrar una cadena

public static string RsaEncrypt(string dataToEncrypt) 
{ 
    string rsaPrivate = RSA_XML_PRIVATE_KEY; 
    CspParameters csp = new CspParameters(); 
    csp.Flags = CspProviderFlags.UseMachineKeyStore; 

    RSACryptoServiceProvider provider = new RSACryptoServiceProvider(csp); 

    provider.FromXmlString(rsaPrivate); 

    ASCIIEncoding enc = new ASCIIEncoding(); 
    int numOfChars = enc.GetByteCount(dataToEncrypt); 
    byte[] tempArray = enc.GetBytes(dataToEncrypt); 
    byte[] result = provider.Encrypt(tempArray, true); 
    string resultString = Convert.ToBase64String(result); 
    Console.WriteLine("Encrypted : " + resultString); 
    return resultString; 
} 

Yo entiendo lo que parece ser un valor cifrado. En el método de prueba crypto web que creé, tomo estos datos encriptados, intento y descifro los datos usando la clave pública del cliente y los envío de nuevo a la luz. Pero aquí es donde se lanza la excepción. Aquí está mi método responsable de esto.

public string DecryptRSA(string data, string merchantId) 
{ 
    string clearData = null; 
    try 
    { 
     CspParameters param = new CspParameters(); 
     param.Flags = CspProviderFlags.UseMachineKeyStore; 
     RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(param); 

     string merchantRsaPublic = GetXmlRsaKey(merchantId); 
     rsaProvider.FromXmlString(merchantRsaPublic); 
     byte[] asciiString = Encoding.ASCII.GetBytes(data); 

     byte[] decryptedData = rsaProvider.Decrypt(asciiString, false); 

     clearData = Convert.ToString(decryptedData); 
    } 
    catch (CryptographicException ex) 
    { 
     Log.Error("A cryptographic error occured trying to decrypt a value for " + merchantId, ex); 

    } 
    return clearData; 
} 

Si alguien me podría ayudar a que sería impresionante, como ya he dicho que no he hecho mucho con C# RSA cifrado/descifrado.

+0

¿Tiene esto que ver con el cifrado de RSA quebrado recientemente? http://www.engadget.com/2010/03/09/1024-bit-rsa-encryption-cracked-by-carefully-starving-cpu-of-ele/ –

+4

RSA no está rajado. Solo su _implementación_, en un sistema real, está sujeta a ataques de canal lateral: la implementación puede filtrar información en la clave privada a través del consumo de energía, el tiempo y otras medidas físicas que no forman parte del modelo abstracto de una computadora. Esto se conoce desde hace bastante tiempo (los ataques de sincronización se describieron en 1997, creo). Dichas noticias no son noticias ni tampoco un verdadero "crack". –

Respuesta

33

Permítanme un poco de terminología. Hay encriptación asimétrica y hay firma digital.

  • La encriptación asimétrica consiste en mantener la confidencialidad. Algunos datos confidenciales se transforman en algo ilegible, salvo para la entidad que conoce la clave de descifrado. La clave de descifrado es necesariamente la clave privada: si la clave de descifrado es la clave pública, entonces todos pueden descifrar los datos (la clave pública es, bueno, pública) y ya no existe confidencialidad. En el cifrado asimétrico, uno cifra con la clave pública y descifra con la clave privada correspondiente.

  • Las firmas digitales están destinadas a demostrar integridad. Alguien calcula un tipo de suma de verificación con clave sobre los datos, de tal forma que el vínculo entre la suma de comprobación y los datos se puede verificar más adelante. Esta es una "firma" solo porque el poder para calcular esa suma de comprobación requiere el conocimiento de algo que no es público; en palabras simples, la firma utiliza la clave privada . La verificación, sin embargo, debe ser factible por cualquiera, y por lo tanto usar la clave pública.

un poco de confusión está implícito en el hecho de que "el" algoritmo RSA es en realidad una operación matemática que puede ser rechazada en tanto un sistema de cifrado asimétrico, y un sistema de firma digital. La confusión se ve reforzada por el estándar RSA, también conocido como PKCS#1, que se basa implícitamente en cómo se describieron por primera vez las firmas digitales RSA, es decir, como "encriptación inversa" ("el firmante encripta los datos con su clave privada"). Lo que lleva a cosas como firmas RSA llamadas "sha1WithRSAEncryption". Esto es bastante desafortunado.

Por lo tanto, primero debe decidir si desea confidencialidad o firmas. Para la confidencialidad, para los datos enviados de clientes a el servidor, el servidor poseerá una clave privada, y los clientes utilizan la clave pública del servidor para encriptar los datos. Para las firmas, cada cliente debe tener su propia clave privada y usarla para firmar los datos, y el servidor verifica las firmas. Según su descripción, no puedo decir lo que realmente desea, gracias a la confusión a la que aludo anteriormente.

Además, hay algo llamado autenticación que puede parecerse a firmas digitales, pero es más débil. El punto de las firmas es que cualquiera puede verificar la firma. En particular, la firma puede mostrarse a un juez y así servir como arma legal contra el firmante (la firma es legalmente vinculante - al menos si lo hace bien, y en el estado actual de las regulaciones sobre firmas electrónicas, esto no es fácil). En la mayoría de las situaciones, solo necesita algo más débil y simple, en el que el servidor está convencido de que habla con el cliente correcto, pero luego no puede convencer a nadie de que este cliente realmente estaba allí. Cualquier sitio web con contraseñas de usuario está usando dicha autenticación.

Con eso se dice ...

  • RSA cifrado asimétrico cubre sólo los mensajes cortos. Para una clave RSA de 1024 bits (es decir, una clave donde la parte más importante, el "módulo RSA", es un número grande con un valor entre 2^1023 y 2^1024, y los mensajes cifrados tendrán una longitud de 128 bytes), el tamaño máximo de un mensaje cifrado es de 117 bytes (esa es la fuente real de su mensaje de error). Cuando queremos enviar mensajes más largos, utilizamos un sistema híbrido, en el que solo encriptamos un pequeño grupo de bits aleatorios (digamos 128 bits) y usamos ese grupo como clave para un sistema de encriptación simétrica (por ejemplo, AES) que puede procesar mensajes mucho más largos (y mucho más rápido, también).

  • Las firmas RSA, de manera similar, se pueden calcular solo en mensajes cortos, de ahí que el estándar PKCS # 1 exija que una firma se calcule en realidad sobre un valor hash. El valor hash es la salida de una función específica hash, que se calcula sobre el mensaje que se debe firmar. La función hash tiene una salida de tamaño fijo (por ejemplo, 256 bits para SHA-256) pero acepta mensajes de entrada de longitud (casi) arbitraria. Las funciones hash son públicas (no hay ninguna clave en ellas) y, para una seguridad adecuada, deben tener algunas propiedades especiales. SHA-256 es, en este momento, no es una mala elección. SHA-1 (un predecesor de SHA-256) ha demostrado tener algunas debilidades y debe evitarse. MD5 tiene (un tipo de tío de SHA-1) tiene mayores debilidades y no debe ser utilizado.

  • El uso correcto de la encriptación asimétrica, especialmente en un esquema híbrido, y las firmas digitales, es más complicado de lo que el texto anterior puede sugerir. Es terriblemente fácil equivocarse en algún momento, invisiblemente, es decir, el código parecerá funcionar pero filtrará datos útiles para un atacante. El right forma de utilizar el cifrado asimétrico o las firmas digitales es confiar en los protocolos existentes y bien pensados. Un protocolo es un conjunto de elementos criptográficos en un sistema coherente, donde las fugas son atendidas. El mejor ejemplo es TLS, también conocido como SSL. Es un protocolo que garantiza la transmisión confidencial de datos, con integridad y autenticación (posiblemente autenticación mutua). El protocolo HTTPS es una mezcla de HTTP y SSL. El lado positivo es que HTTPS tiene implementaciones existentes, especialmente en C#. El código que es más fácil de implementar y depurar es el código que ya se implementó y depuró. Entonces usa HTTPS y vivirás más tiempo y más feliz.

3

En DecryptRSA, ¿está codificada la base de datos 64? Si es así, debes deshacer eso primero.

Honestamente, creo que no debe implementar esa rutina usted mismo para proteger la "información financiera confidencial", a menos que tenga mucha experiencia en criptografía. Hay demasiadas formas de cometer errores. Es mejor utilizar alguna solución preparada, tal vez SSL y certificados, o solo PGP o GnuPG?

+0

sí lo está codificado en base64, probablemente utilizará como ustedes me han aconsejado, soluciones rady como SSL –

3

RSA se usa principalmente para validar los hashes de datos seguros, en lugar de cifrar los datos en sí. Entonces, dada una gran cantidad de datos, puede usar SHA512 para crear un hash de esa información, luego use RSA para firmar ese hash.

Querrá utilizar un algoritmo de encriptación simétrico para grandes bloques de datos, como AES o 3DES.

Administrar transacciones seguras no es fácil y realmente debería dejarse en manos de aquellos tipos que pasan todo el día y toda la noche pensando en ello. Si expone el servicio a través de la web, solo use SSL que ya encripta y protege sus datos.

+0

Gracias Paul, se porbably sólo tiene que utilizar SSL, pero sólo quería intentar llegar a gribs con encriptación. –

2

Primero decida lo que está tratando de proteger. Si "cifra" algo con la clave privada, cualquiera puede "descifrarlo" con la clave pública, ya que la clave pública es - bueno - pública.

Si realmente desea firmarlo, debe (como lo explica Paul Alexander) firmar un hash con la clave privada que luego se puede verificar en el servidor.

Para cifrar datos utilizando RSA debe generar primero una clave simétrica aleatoria (f.x. AES), cifrar la clave usando una clave públicay cifrar los datos utilizando la clave simétrica.A continuación, puede transmitir la clave cifrada junto con los datos cifrados al titular de la clave privada , que luego puede descifrar primero la clave cifrada con la clave privada y luego descifrar los datos con la clave simétrica.

También podría considerar el uso de SSL, pero recuerde considerar cuidadosamente la autenticación. Es probable que necesite autenticación de cliente y tenga que decidir en qué certificados confiar (no debe aceptar ciegamente ningún certificado emitido por Verisign).

+0

He llegado a la conclusión de que terminaré utilizando AES o 3DES o algún tipo de encriptación como ese. Entiendo lo que dices sobre SSL. Me pregunto si sería excesivo cifrar los datos confidenciales y usar SSL. –

14

Entiendo por qué hace la pregunta. El problema es que RSA no se usa como una cifra de bloque típica (como AES o 3DES) que encripta 8 bytes a la vez, durante todo el día. RSA es una operación matemática que devuelve el resto de una división (el módulo). De vuelta en la escuela primaria, cuando aprendiste la división larga, recuerda que el resto nunca puede ser mayor que el divisor: si estás dividiendo 20 entre 7, tu resto es 6. No importa qué número entero dividas por 7, el resto no puede ser mayor de seis

RSA math es la misma manera. Por ejemplo, si está utilizando una clave pública RSA de 1024 bits, el resto nunca puede ser mayor que 2^1024, que es solo 128 bytes. Por lo tanto, solo puede cifrar 128 bytes a la vez con esta clave. (Esa es una razón por la que medimos el tamaño de las claves RSA por el número de bits).

Técnicamente, podría usar esta clave RSA en un bucle para encriptar 128 bits de bytes de sus datos a la vez. En realidad, casi nunca hacemos esto porque las matemáticas de RSA son GRANDES y LENTAS. En cambio, usamos lo que se llama encriptación "de dos fases". Usamos RSA para encriptar solo una breve "clave de sesión", y luego usamos esa clave de sesión en un cifrado de bloque de clave simétrica rápida (como AES) para encriptar los datos reales.

El conjunto protocolo es:

  1. obtener la clave pública RSA de su destino. Esto a menudo se entrega incrustado en un certificado; si es así, asegúrese de validar el certificado para asegurarse de que la clave sea genuina. Digamos que la clave RSA tiene 2048 bits de longitud.
  2. Genera un número pseudoaleatorio criptográficamente fuerte para usar como clave para el cifrado de bloque (necesitas 256 bits como la clave para AES-256, por ejemplo). Ten en cuenta que 256 < 2048, el máximo que RSA-2048 puede Encriptar de una vez. Llamamos a este número aleatorio la "clave de sesión".
  3. Encripte la clave de sesión utilizando la clave pública RSA de 2048 bits. Le dará 2048 bits de clave de sesión cifrada. Tenga en cuenta que esta operación es muy lenta.
  4. Encripte todos los datos secretos usando AES-256, usando la clave de sesión. Tenga en cuenta que esto es mucho más rápido que el paso 3.
  5. Bundle la clave de identificación pública del certificado, la clave de sesión cifrada RSA, y los datos cifrados AES juntos. También lo etiquetaría con un identificador de formato y un número de versión, para que sepa en qué formato está y cómo descifrarlo.
  6. Envía el paquete a su destino.

  7. En el destino se utiliza el identificador de formato y la versión de desmontar el paquete.

  8. recuperar la clave privada cuya identidad está en el campo ID de clave pública.
  9. Utilice esta clave privada en RSA para descifrar la clave de sesión.
  10. Use la clave de sesión en AES para descifrar los datos.

Si va a hacer esto, debe saber que es exactamente para lo que es el formato CMS (PKCS # 7). Le animo a que aprenda sobre el estándar y lo adopte, en lugar de tratar de inventar su propio formato. El CSP de Microsoft lo admite, por lo que debería ser fácil.

Si usted no sigue un patrón que tendrá que tomar sus propias decisiones acerca de cosas como "qué formato deben ser los bits de la clave AES en el proceso de cifrado RSA?" Lo más probable es que casi con seguridad cometas errores de seguridad y debilites tu sistema. Además, descubrirá que es muy difícil trabajar con herramientas como el CSP si no sigue un estándar.

+0

Para la práctica estándar, ¿necesita "firmarla" con una clave privada en uno de los pasos anteriores? – Dennis

+0

@Dennis, no. Cualquier "práctica estándar" a la que pueda hacer referencia se basa en los requisitos y no se atornilla automáticamente a cada comunicación.Las firmas se utilizan para validar que el mensaje provino de una fuente auténtica, no de confidencialidad. Si la autenticidad era un requisito válido, no se indicó en la pregunta anterior. Si la autenticidad y la integridad de los datos son importantes, entonces agregaría pasos de firma adicionales para la creación del mensaje y la validación de la firma al recibirla. En ese punto, se ha movido más allá del alcance del viejo RSA simple y firmemente en el territorio HMAC. –