Encriptación AES en iOS y Android, y descifrado en C # .NET

Primero lo primero. Hace algún tiempo necesitaba un simple cifrado AES en Android para cifrar una contraseña y enviarla como un parámetro para un servicio web .net donde se descifró la contraseña.

El siguiente es mi cifrado de Android:

private static String Encrypt(String text, String key) throws Exception { Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); byte[] keyBytes= new byte[16]; byte[] b= key.getBytes("UTF-8"); int len= b.length; if (len > keyBytes.length) len = keyBytes.length; System.arraycopy(b, 0, keyBytes, 0, len); SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES"); IvParameterSpec ivSpec = new IvParameterSpec(keyBytes); cipher.init(Cipher.ENCRYPT_MODE,keySpec,ivSpec); byte[] results = cipher.doFinal(text.getBytes("UTF-8")); String result = Base64.encodeBytes(results); return result; } 

Y luego lo descifré en C # con:

  public static string Decrypt(string textToDecrypt, string key) { System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding(); RijndaelManaged rijndaelCipher = new RijndaelManaged(); rijndaelCipher.Mode = CipherMode.CBC; rijndaelCipher.Padding = PaddingMode.PKCS7; rijndaelCipher.KeySize = 0x80; rijndaelCipher.BlockSize = 0x80; string decodedUrl = HttpUtility.UrlDecode(textToDecrypt); byte[] encryptedData = Convert.FromBase64String(decodedUrl); byte[] pwdBytes = Encoding.UTF8.GetBytes(key); byte[] keyBytes = new byte[0x10]; int len = pwdBytes.Length; if (len > keyBytes.Length) { len = keyBytes.Length; } Array.Copy(pwdBytes, keyBytes, len); rijndaelCipher.Key = keyBytes; rijndaelCipher.IV = keyBytes; byte[] plainText = rijndaelCipher.CreateDecryptor().TransformFinalBlock(encryptedData, 0, encryptedData.Length); return encoding.GetString(plainText); } 

Esto funcionó como un encanto, pero los problemas vinieron cuando traté de hacer lo mismo en iOS. Estoy bastante nuevas aplicaciones en desarrollo para el iphone / ipad, por lo que ofcause lo googled, y casi cada muestra de código proporcionado fue el siguiente:

 - (NSData *)AESEncryptionWithKey:(NSString *)key { char keyPtr[kCCKeySizeAES128]; // room for terminator (unused) bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding) // fetch key data [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; NSUInteger dataLength = [self length]; size_t bufferSize = dataLength + kCCBlockSizeAES128; void *buffer = malloc(bufferSize); size_t numBytesEncrypted = 0; CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, keyPtr, kCCKeySizeAES128, NULL /* initialization vector (optional) */, [self bytes], [self length], /* input */ buffer, bufferSize, /* output */ &numBytesEncrypted); if (cryptStatus == kCCSuccess) { //the returned NSData takes ownership of the buffer and will free it on deallocation return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted]; } free(buffer); //free the buffer; return nil; 

}

Tal vez yo era un poco demasiado optimista, cuando esperaba una transición suave aquí, porque cuando el Android me está lanzando algo así como:

"EgQVKvCLS4VKLoR0xEGexA=="

Entonces el iOS me da:

 "yP42c9gajUra7n0zSEuVJQ==" 

Espero que sea algo que me olvidé, o algunos de los ajustes son malos?

[UPDATE] Los resultados se muestran ahora después de la codificación base64.

La primera nota es que tiene importantes problemas de seguridad en este código. Estás tomando una contraseña de cadena y simplemente dejarla en una clave. Si esa cadena es de tipo humano, entonces usted ha reducido dramáticamente su espacio de claves (convirtiendo AES-128 en algo más como AES-40 o AES-50, quizás incluso peor). Usted necesita salar y estirar la llave usando PBKDF2. Consulte Cifrado correcto con AES con CommonCrypto para una discusión más completa.

También tiene un problema importante de seguridad porque está usando su llave como su IV (vea más abajo, esto es realmente la causa de su síntoma). Esta no es la manera correcta de escoger una IV y hace que su texto cifrado sea predecible. Idéntico texto encriptado cifrado con la misma clave dará el mismo resultado. Esto es similar a no tener IV en absoluto. El IV debe ser aleatorio. Vea el enlace anterior para más información.

Ahora a su síntoma real. El problema es que estás usando la clave como el IV en Java y C #, pero estás usando 0 (NULL) como el IV en iOS (el IV no es opcional, estás pasando 0). Es necesario utilizar el mismo IV en todos los casos.

  • Reaccionar Nativo: ¿Cómo puedo detectar si mi código se está ejecutando en el Simulador?
  • Uber server_token
  • Alternativa a la biblioteca de lectores QR de zxing para Java / Android?
  • ¿Qué tan seguras son las API de GeoLocation en dispositivos móviles?
  • ¿La aplicación móvil HTML5 se está ejecutando mientras la pantalla del teléfono está desactivada?
  • ¿Puede libuv (node.js's async lib) ejecutarse en Apple IOS / Android?
  • Quiero construir una aplicación de videojuegos para android y ios, pero estoy preocupado por dónde empezar
  • Tratando de encajar una "arquitectura limpia" en una aplicación iOS
  • Lista y nombres de los gestos con pantalla táctil
  • Cómo sincronizar datos entre dispositivos en Wi-Fi
  • Cómo conectar un dispositivo Android a un dispositivo iOS a través de BLE (Bluetooth Low Energy)
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.