AES Cifrado Java a iOS: con contraseña, iv y sal

Estoy desarrollando una aplicación para tres plataforms (Android, iOS y WP8). Esta aplicación se conecta con el server y usa AES para la security.

Tengo list una versión de testing para Android y Windows Phone funcionando bien y el código generado (en base64) con Android se decodifica con el código wp y, por el contrario.

Pero, en iOs obtengo otra respuesta con la misma SALT, KEY y IV. Este es mi código para Android:

public static SecretKeySpec generateKey(char[] password, byte[] salt) throws Exception { SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); KeySpec spec = new PBEKeySpec(password, salt, 1024, 128); SecretKey tmp = factory.generateSecret(spec); SecretKeySpec secret = new SecretKeySpec(tmp.getEncoded(), "AES"); return secret; } public static Map encrypt(String cleartext, byte[] iv, SecretKeySpec secret) throws Exception { Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); // If the IvParameterSpec argument is omitted (null), a new IV will be // created cipher.init(Cipher.ENCRYPT_MODE, secret, iv == null ? null : new IvParameterSpec(iv)); AlgorithmParameters params = cipher.getParameters(); byte[] usediv = params.getParameterSpec(IvParameterSpec.class).getIV(); byte[] ciphertext = cipher.doFinal(cleartext.getBytes("UTF-8")); Map result = new HashMap(); result.put(IV, usediv); result.put(CIPHERTEXT, ciphertext); return result; } public static String decrypt(byte[] ciphertext, byte[] iv, SecretKeySpec secret) throws Exception { Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv)); String plaintext = new String(cipher.doFinal(ciphertext), "UTF-8"); return plaintext; } public static void main(String arg) throws Exception { byte[] salt = new byte[] { -11, 84, 126, 65, -87, -104, 120, 33, -89, 19, 57, -6, -27, -19, -101, 107 }; byte[] interop_iv = Base64.decode("xxxxxxxxxxxxxxx==", Base64.DEFAULT); byte[] iv = null; byte[] ciphertext; SecretKeySpec secret; secret = generateKey("xxxxxxxxxxxxxxx".toCharArray(), salt); Map result = encrypt(arg, iv, secret); ciphertext = (byte[]) result.get(CIPHERTEXT); iv = (byte[]) result.get(IV); System.out.println("Cipher text:" + Base64.encode(ciphertext, Base64.DEFAULT)); System.out.println("IV:" + Base64.encode(iv, Base64.DEFAULT) + " (" + iv.length + "bytes)"); System.out.println("Key:" + Base64.encode(secret.getEncoded(), Base64.DEFAULT)); System.out.println("Deciphenetworking: " + decrypt(ciphertext, iv, secret)); // Interop demonstration. Using a fixed IV that is used in the C# // example result = encrypt(arg, interop_iv, secret); ciphertext = (byte[]) result.get(CIPHERTEXT); iv = (byte[]) result.get(IV); String text = Base64.encodeToString(ciphertext, Base64.DEFAULT); System.out.println(); System.out.println("--------------------------------"); System.out.println("Interop test - using a static IV"); System.out.println("The data below should be used to retrieve the secret message by the receiver"); System.out.println("Cipher text: " + text); System.out.println("IV: " + Base64.encodeToString(iv, Base64.DEFAULT)); decrypt(Base64.decode(text, Base64.DEFAULT), iv, secret); } 

y este es mi código para ios … establezco un IV estático y SALT como en el código de Android … pero no se encuentra:

 - (NSData*)encryptData:(NSData*)data :(NSData*)key :(NSData*)iv { size_t bufferSize = [data length]*2; void *buffer = malloc(bufferSize); size_t encryptedSize = 0; CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, [key bytes], [key length], [iv bytes], [data bytes], [data length], buffer, bufferSize, &encryptedSize); if (cryptStatus == kCCSuccess) return [NSData dataWithBytesNoCopy:buffer length:encryptedSize]; else free(buffer); return NULL; } // =================== - (NSData *)encryptedDataForData:(NSData *)data password:(NSString *)password iv:(NSData *)iv salt:(NSData *)salt error:(NSError *)error { NSData *key = [self AESKeyForPassword:password salt:salt]; size_t outLength = 0; NSMutableData * cipherData = [NSMutableData dataWithLength:data.length + kAlgorithmBlockSize]; const unsigned char iv2[] = {68, 55, -98, -59, 22, -25, 55, -50, -101, -25, 53, 30, 42, -20, -107, 4}; CCCryptorStatus result = CCCrypt(kCCEncrypt, // operation kAlgorithm, // Algorithm kCCOptionPKCS7Padding, // options key.bytes, // key key.length, // keylength iv2,// iv data.bytes, // dataIn data.length, // dataInLength, cipherData.mutableBytes, // dataOut cipherData.length, // dataOutAvailable &outLength); // dataOutMoved if (result == kCCSuccess) { cipherData.length = outLength; } else { if (error) { error = [NSError errorWithDomain:kRNCryptManagerErrorDomain code:result userInfo:nil]; } return nil; } return cipherData; } // =================== - (NSData *)randomDataOfLength:(size_t)length { NSMutableData *data = [NSMutableData dataWithLength:length]; int result = SecRandomCopyBytes(kSecRandomDefault, length, data.mutableBytes); NSAssert(result == 0, @"Unable to generate random bytes: %d", errno); return data; } // =================== // Replace this with a 10,000 hash calls if you don't have CCKeyDerivationPBKDF - (NSData *)AESKeyForPassword:(NSString *)password salt:(NSData *)salt { NSMutableData * derivedKey = [NSMutableData dataWithLength:kAlgorithmKeySize]; int result = CCKeyDerivationPBKDF(kCCPBKDF2, // algorithm password.UTF8String, // password [password lengthOfBytesUsingEncoding:NSUTF8StringEncoding], // passwordLength salt.bytes, // salt salt.length, // saltLen kCCPRFHmacAlgSHA1, // PRF kPBKDFRounds, // rounds derivedKey.mutableBytes, // derivedKey derivedKey.length); // derivedKeyLen // Do not log password here NSAssert(result == kCCSuccess, @"Unable to create AES key for password: %d", result); return derivedKey; } 

Conversión de datos a base64 sigue:

 NSString* dataStr = [encryptedData base64EncodedStringWithOptions:0]; NSLog(@"%@", dataStr); 

SOLUCIÓN

Finalmente uso este código en Android y wp: http://www.dfg-team.com/en/secure-data-on-windows-phone-with-aes-256-encryption/

En el pasado ya tengo un problema como el tuyo. Acabo de encontrar la solución usando esta lib: https://github.com/dev5tec/FBEncryptor

No olvide validar la configuration del algorithm en el file FBEncryptorAES.h