
04/12/2007 21:12 por
zorry
En el proyecto en el que estoy trabajando, hemos tenido que securizar una transacción de datos mediante RSA. Este cifrado se emplea para asegurar que nadie puede obtener un usuario y contraseña que se envía entre una aplicación Windows Forms de cliente, y nuestra aplicación ASP.Net.
Si bien el cifrado se realiza sin problemas en la aplicación Windows Forms, cifrando con la clave pública, estaba teniendo problemas en el descifrado de los datos.
El código original era el siguiente:
1: RSACryptoServiceProvider rsaCryptoServiceProvider = new RSACryptoServiceProvider(dwKeySize);
2: rsaCryptoServiceProvider.FromXmlString(xmlString);
3: byte[] encryptedBytes = System.Web.HttpServerUtility.UrlTokenDecode(inputString);
4: byte[] clearBytes = rsaCryptoServiceProvider.Decrypt(encryptedBytes, false);
5: return Encoding.UTF8.GetString(clearBytes);
Este código me estaba elevando una excepción en la línea 2, al tratar de leer la configuración de un string con el Xml y la clave privada. El error era un tanto críptico: CryptographicException: The system cannot find the file specified.
Navegando por la red, encontré un blog en el que especifica que el usuario que corre la aplicación debería poder realizar esta operación atacando el store de la máquina, con lo que me quedó este código:
1: CspParameters csp = new CspParameters();
2: csp.Flags = CspProviderFlags.UseMachineKeyStore;
3: RSACryptoServiceProvider rsaCryptoServiceProvider = new RSACryptoServiceProvider(dwKeySize, csp);
4: rsaCryptoServiceProvider.FromXmlString(xmlString);
5: byte[] encryptedBytes = System.Web.HttpServerUtility.UrlTokenDecode(inputString);
6: byte[] clearBytes = rsaCryptoServiceProvider.Decrypt(encryptedBytes, false);
7: return Encoding.UTF8.GetString(clearBytes);
Esto es, añadiendo las dos primeras líneas y pasando los parámetros del CSP al constructor del Provider.
No obstante, los problemas no han acabado aquí. Como el resto del proceso corre impersonado, al parecer el GC da problemas al tratar de eliminar la clave privada del store. Aproximadamente al minuto de la ejecución del descifrado, se elevaba una excepcion CryptographicException: Keyset not found y se moría el proceso w3wp... Maldita sea...
Tras más investigaciones, logré averiguar que el GC trata de eliminar la clave del almacén, pero con las credenciales de otro usuario, por lo que no encuentra la clave y el proceso de IIS se muere.
Pero al final logré arreglarlo mediante el siguiente código:
1: CspParameters csp = new CspParameters();
2: csp.Flags = CspProviderFlags.UseMachineKeyStore;
3: RSACryptoServiceProvider rsaCryptoServiceProvider = new RSACryptoServiceProvider(dwKeySize, csp);
4: rsaCryptoServiceProvider.FromXmlString(xmlString);
5: byte[] encryptedBytes = System.Web.HttpServerUtility.UrlTokenDecode(inputString);
6: byte[] clearBytes = rsaCryptoServiceProvider.Decrypt(encryptedBytes, false);
7: rsaCryptoServiceProvider.Clear();
8: return Encoding.UTF8.GetString(clearBytes);
Esto es, insertando la línea 7. Esta línea elimina la clave del almacén de manera explícita, con lo que el GC no tiene que hacerlo con posterioridad y el proceso finaliza correctamente... Por fin y tras dos días pegándome con ello :-(
8a6b1ae0-4549-4764-a1bd-beab150c9f6a|0|.0