Lo primero es lo primero. Hace algún tiempo necesité un simple cifrado AES en Android para encriptar una contraseña y enviarla como parámetro para un servicio web .net donde se descifraba la contraseña.Encriptación AES en iOS y Android, y descifrado en C# .NET
La siguiente es mi cifrado 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 entonces descifrado 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 llegaron cuando traté de hacer lo lo mismo en iOS. Soy bastante nuevo desarrollo de aplicaciones para el iPhone/iPad, por lo ofcause busqué en Google, y casi todas las muestras 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 era un poco demasiado optimista, cuando Tenía la esperanza de una transición sin problemas aquí, porque cuando el Android me está tirando algo como:
"EgQVKvCLS4VKLoR0xEGexA=="
entonces el iOS me da:
"yP42c9gajUra7n0zSEuVJQ=="
Afortunadamente es solo algo que olvidé, o algunos de los ajustes son incorrectos?
[ACTUALIZACIÓN] Los resultados ahora se muestran después de la codificación base64.
La versión de Android es una cadena base64 con codificación URL que es igual a '" YHH + gTxyIxvAx1cPFLcP0IEW2HcVHQVi9X11656CFsk = "' '(60 71 fe 81 3c 72 23 1b c0 c7 57 0f 14 b7 0f d0 81 16 d8 77 15 1d 05 62 f5 7d 75 eb 9e 82 16 c9) '. – Joe
Woops, lo siento, me olvidé de mencionar eso. Estoy codificando el resultado de la versión iOS también, solo en otro método, pero los resultados son diferentes antes de la codificación. – Morten
Se actualizó la pregunta para mostrar los resultados después de la codificación base64. Se usa la misma contraseña y la misma clave. – Morten