texto telefono quality infosolutions hill encriptar encriptado desencriptar cifrado c# .net encryption xamarin.ios rijndaelmanaged

telefono - login encriptado c#



¿Por qué no puedo cifrar varias cadenas usando un cifrador en MonoTouch? (1)

Estoy usando la siguiente clase (recortada) para cifrar algunos datos antes de enviarlos desde una aplicación de iPad a un servicio web de WCF.

public class FlawedAlgorithm { protected static byte[] key = { 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42 }; protected static byte[] vector = { 13, 37, 13, 37, 13, 37, 13, 37, 13, 37, 13, 37, 13, 37, 13, 37 }; protected ICryptoTransform encryptor, decryptor; protected UTF8Encoding encoder; public FlawedAlgorithm() { using (var rijndael = new RijndaelManaged()) { this.encryptor = rijndael.CreateEncryptor(key, vector); this.decryptor = rijndael.CreateDecryptor(key, vector); } this.encoder = new UTF8Encoding(); } public string Encrypt(string unencrypted) { var buffer = this.encoder.GetBytes(unencrypted); return Convert.ToBase64String(Encrypt(buffer)); } public string Decrypt(string encrypted) { var buffer = Convert.FromBase64String(encrypted); return this.encoder.GetString(Decrypt(buffer)); } private byte[] Encrypt(byte[] buffer) { var encryptStream = new MemoryStream(); using (var cryptoStream = new CryptoStream(encryptStream, this.encryptor, CryptoStreamMode.Write)) { cryptoStream.Write(buffer, 0, buffer.Length); } return encryptStream.ToArray(); } private byte[] Decrypt(byte[] buffer) { var decryptStream = new MemoryStream(); using (var cryptoStream = new CryptoStream(decryptStream, this.decryptor, CryptoStreamMode.Write)) { cryptoStream.Write(buffer, 0, buffer.Length); } return decryptStream.ToArray(); } }

Cuando ejecuto el siguiente código en el servidor y el iPad, ambos imprimen la misma cadena encriptada.

var algorithm = new FlawedAlgorithm(); Console.WriteLine(algorithm.Encrypt("Some string"));

Sin embargo, cuando intento encriptar un segundo valor, los resultados en el servidor y el iPad son diferentes.

var algorithm = new FlawedAlgorithm(); // The first encryption still functions correctly. Console.WriteLine(algorithm.Encrypt("Some string")); // This second encryption produces a different value on the iPad. Console.WriteLine(algorithm.Encrypt("This text is a bit longer"));

Cuando desencripto el resultado desviado de iPad en el servidor, parte de la cadena descifrada es un galimatías . Los resultados cifrados del servidor descifran correctamente.

El problema no se manifiesta si creo una nueva instancia de FlawedAlgorithm para cada llamada, por ejemplo:

// These statements produce the correct results on the iPad. Console.WriteLine(new FlawedAlgorithm().Encrypt("Some string")); Console.WriteLine(new FlawedAlgorithm().Encrypt("This text is a bit longer"));

Esto me lleva a pensar que el problema se encuentra en algún lugar del estado de los objetos involucrados. He inspeccionado la variable del buffer en el método Encrypt(string) y los valores producidos por la instancia de UTF8Encoding son correctos. Esto implica que el campo del encryptor (o su implementación subyacente) es el culpable .

Cuando empiezo a variar el tamaño del primer valor cifrado, puedo ver los cambios en el resultado de la segunda llamada de cifrado. Esto probablemente significaría que una parte de una transmisión no se borra o sobrescribe correctamente. Pero las secuencias que usa la clase FlawedAlgorithm no son parte de su estado; se vuelven a crear en cada llamada al método. Y el objeto de encryptor no parece ser del tipo que gestiona sus propias transmisiones.

¿Alguien más ha encontrado un problema similar a esto? ¿La clase RijndaelManaged defectuosa? ¿O hay algunas fallas de gestión de flujo y memoria en MonoTouch en juego aquí, sin relación con este ejemplo de criptografía?

PD: He probado esto tanto en el iPad como en el simulador de iPad; ambos muestran este extraño comportamiento.


Al usar la criptografía .NET siempre debe verificar ICryptoTransform.CanReuseTransform (o asumir que devolverá false). Si devuelve falso, no podrá reutilizar el mismo cifrador / descifrador y deberá crear nuevas instancias.

Saltarse este control significa que cualquier cambio en el marco (o mediante archivos de configuración, ya que la criptografía es conectable) probablemente romperá su aplicación en el futuro.

Puedes usar algo como:

ICryptoTransform Decryptor { get { if (decryptor == null || !decryptor.CanReuseTransform) decryptor = rijndael.CreateDecryptor (key, vector); return decryptor; } }

para ocultar esta complejidad de la persona que llama de sus rutinas criptográficas.