Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AES encryption in iOS and Android, and decryption in C#.NET

Tags:

c#

android

ios

aes

First thing first. Some time ago I needed a simple AES encryption in Android to encrypt a password and send it as a parameter for a .net web service where the password was decrypted.

The following is my Android encryption:

    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;
        }

And then I decrypted it in C# with:

        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);
    }

This worked like a charm, but the problems came when I tried to do the same in iOS. I am pretty new developing applications for the iphone/ipad, so ofcause I googled it, and almost every code sample provided was the following:

- (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;

}

Maybe I was a little bit too optimistic, when I was hoping for a smooth transition here, because when the Android is throwing me something like:

"EgQVKvCLS4VKLoR0xEGexA=="

then the iOS gives me:

"yP42c9gajUra7n0zSEuVJQ=="

Hopefully it is just something I forgot, or some of the settings are wrong?

[UPDATE] The results are now showed after the base64 encoding.

like image 522
MBX Avatar asked Aug 14 '12 13:08

MBX


People also ask

How do you AES encrypt and decrypt?

The AES algorithm is a symmetrical block cipher that encrypts and decrypts data in blocks of 256 bits. The decryption block uses the AES algorithm to decrypt the boot loader image and configuration data before configuring the FPGA portion of the device. If encryption is not used, the AES decryptor is bypassed.

What is AES encryption in Android?

The AES algorithm is a symmetric block cipher that can encrypt (encipher) and decrypt (decipher) information. It uses only one secret key to encrypt plain data, and uses 128-, 192-, and 256-bit keys to process 128-bit data locks. This algorithm receives data and encrypts it using a password.

Does Android use AES encryption?

Android offers storage encryption using the Advanced Encryption Standard (AES). And most new Android devices provide AES via Arm's version 8 processor cryptography extensions.

What is AES in iOS?

A container for Advanced Encryption Standard (AES) ciphers. iOS 13.0+ iPadOS 13.0+ macOS 10.15+ Mac Catalyst 13.0+ tvOS 13.0+ watchOS 6.0+


1 Answers

First note is that you have significant security issues in this code. You're taking a string password and just dropping that into a key. If that string human-typable, then you've dramatically constricted your keyspace (turning AES-128 into more like AES-40 or AES-50, maybe even worse). You need to salt and stretch the key using PBKDF2. See Properly encrypting with AES with CommonCrypto for a fuller discussion.

You also have a significant security problem because you're using your key as your IV (see more below; this is actually the cause of your symptom). This is not the correct way to pick an IV and makes your ciphertext predictable. Identical plaintext encrypted with the same key will give the same result. This is similar to having no IV at all. The IV needs to be random. See the above link for more discussion.

Now to your actual symptom. The problem is that you are using the key as the IV in Java and C#, but you're using 0 (NULL) as the IV on iOS (the IV is not optional; you're just passing 0). You need to use the same IV in all cases.

like image 122
Rob Napier Avatar answered Oct 17 '22 07:10

Rob Napier