iOS & .NET Produce Different AES256 Results

Sean G

I've been at this for a few days now. My original (and eventual) goal was to use CommonCrypto on iOS to encrypt a password with a given IV and key, then successfully decrypt it using .NET. After tons of research and failures I've narrowed down my goal to simply producing the same encrypted bytes on iOS and .NET, then going from there.

I've created simple test projects in .NET (C#, framework 4.5) and iOS (8.1). Please note the following code is not intended to be secure, but rather winnow down the variables in the larger process. Also, iOS is the variable here. The final .NET encryption code will be deployed by a client so it's up to me to bring the iOS encryption in line. Unless this is confirmed impossible the .NET code will not be changed.

The relevant .NET encryption code:

    static byte[] EncryptStringToBytes_Aes(string plainText, byte[] Key, byte[] IV)
    {
        byte[] encrypted;
        // Create an Aes object 
        // with the specified key and IV. 
        using (Aes aesAlg = Aes.Create())
        {
            aesAlg.Padding = PaddingMode.PKCS7;
            aesAlg.KeySize = 256;
            aesAlg.BlockSize = 128;

            // Create an encryptor to perform the stream transform.
            ICryptoTransform encryptor = aesAlg.CreateEncryptor(Key, IV);

            // Create the streams used for encryption. 
            using (MemoryStream msEncrypt = new MemoryStream())
            {
                using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                {
                    using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                    {
                        //Write all data to the stream.
                        swEncrypt.Write(plainText);
                    }
                    encrypted = msEncrypt.ToArray();
                }
            }
        }
        return encrypted;
    }

The relevant iOS encryption code:

+(NSData*)AES256EncryptData:(NSData *)data withKey:(NSData*)key iv:(NSData*)ivector
{
Byte keyPtr[kCCKeySizeAES256+1]; // Pointer with room for terminator (unused)
// Pad to the required size
bzero(keyPtr, sizeof(keyPtr));

// fetch key data
[key getBytes:keyPtr length:sizeof(keyPtr)];

// -- IV LOGIC
Byte ivPtr[16];
bzero(ivPtr, sizeof(ivPtr));
[ivector getBytes:ivPtr length:sizeof(ivPtr)];

// Data length
NSUInteger dataLength = data.length;

// See the doc: For block ciphers, the output size will always be less than or equal to the input size plus the size of one block.
// That's why we need to add the size of one block here
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);

size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
                                      keyPtr, kCCKeySizeAES256,
                                      ivPtr,
                                      data.bytes, dataLength,
                                      buffer, bufferSize,
                                      &numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
    return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}

free(buffer);
return nil;
}

The relevant code for passing the pass, key, and IV in .NET and printing result:

byte[] c_IV = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
byte[] c_Key = { 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
String passPhrase = "X";

// Encrypt
byte[] encrypted = EncryptStringToBytes_Aes(passPhrase, c_Key, c_IV);
// Print result
for (int i = 0; i < encrypted.Count(); i++)
{
    Console.WriteLine("[{0}] {1}", i, encrypted[i]);
}

The relevant code for passing the parameters and printing the result in iOS:

Byte c_iv[16] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
Byte c_key[16] = { 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
NSString* passPhrase = @"X";
// Convert to data
NSData* ivData = [NSData dataWithBytes:c_iv length:sizeof(c_iv)];
NSData* keyData = [NSData dataWithBytes:c_key length:sizeof(c_key)];
// Convert string to encrypt to data
NSData* passData = [passPhrase dataUsingEncoding:NSUTF8StringEncoding];
NSData* encryptedData = [CryptoHelper AES256EncryptData:passData withKey:keyData iv:ivData];

long size = sizeof(Byte);
for (int i = 0; i < encryptedData.length / size; i++) {
    Byte val;
    NSRange range = NSMakeRange(i * size, size);
    [encryptedData getBytes:&val range:range];
    NSLog(@"[%i] %hhu", i, val);
}

Upon running the .NET code it prints out the following bytes after encryption:

[0] 194
[1] 154
[2] 141
[3] 238
[4] 77
[5] 109
[6] 33
[7] 94
[8] 158
[9] 5
[10] 7
[11] 187
[12] 193
[13] 165
[14] 70
[15] 5

Conversely, iOS prints the following after encryption:

[0] 77
[1] 213
[2] 61
[3] 190
[4] 197
[5] 191
[6] 55
[7] 230
[8] 150
[9] 144
[10] 5
[11] 253
[12] 253
[13] 158
[14] 34
[15] 138

I cannot for the life of me determine what is causing this difference. Some things I've already confirmed:

  1. Both iOS and .NET can successfully decrypt their encrypted data.

  2. The lines of code in the .NET project:

    aesAlg.Padding = PaddingMode.PKCS7;
    aesAlg.KeySize = 256;
    aesAlg.BlockSize = 128;

Do not affect the result. They can be commented and the output is the same. I assume this means they are the default valus. I've only left them in to make it obvious I'm matching iOS's encryption properties as closely as possible for this example.

  1. If I print out the bytes in the iOS NSData objects "ivData" and "keyData" it produces the same list of bytes that I created them with- so I don't think this is a C <-> ObjC bridging problem for the initial parameters.

  2. If I print out the bytes in the iOS variable "passData" it prints the same single byte as .NET (88). So I'm fairly certain they are starting the encryption with the exact same data.

Due to how concise the .NET code is I've run out of obvious avenues of experimentation. My only thought is that someone may be able to point out a problem in my "AES256EncryptData:withKey:iv:" method. That code has been modified from the ubiquitous iOS AES256 code floating around because the key we are provided is a byte array- not a string. I'm pretty studied at ObjC but not nearly as comfortable with the C nonsense- so it's certainly possible I've fumbled the required modifications.

All help or suggestions would be greatly appreciated.

zaph

I notice you are using AES256 but have a 128-bit key! 16-bytes x 8-bits. You can not count on various functions to pad a key the same, that is undefined.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Different results in AES256 encryption in Swift (iOS) and PHP

From Dev

Different AES256 result between Java and OpenSSL on iOS

From Dev

implementing AES256 encryption into IOS

From Dev

Why these assignments produce different results?

From Dev

atof and stringstream produce different results

From Dev

AES256 Encryption/Decryption Error+ IOS SDK 7

From Dev

AES256 Encryption/Decryption Error+ IOS SDK 7

From Dev

Convert .net aes256 encryption code into php

From Dev

JavaScript and jQuery selectors produce different results?

From Dev

Can these two jQuery lines produce different results?

From Dev

How to produce different random results with DEAP?

From Dev

Checkbox combinations to produce different results with jQuery

From Dev

R ginv and Matlab pinv produce different results

From Dev

Why these syntactically identical functions produce different results?

From Dev

Classification Model's parameters produce different results

From Dev

Linq expression and foreach produce different results

From Dev

jQuery and JS equivalent functions produce different results

From Dev

Why these syntactically identical functions produce different results?

From Dev

AES Encryption Android <-> iOS different results on message length > 15 byte

From Dev

The same declaration in a different order produce different results in gcc

From Dev

Different versions of Python 2.7 and Numpy produce different results for the same script

From Dev

Why does different scrypt implementation produce different results?

From Dev

Running selenium tests from different environments produce different results

From Dev

Same code running in different contexts produce different results

From Dev

AES256 encryption get different result between node.js and objective-c

From Java

Can "T t = {};" and "T t{};" produce different results?

From Dev

Multiple OpenSSL RSA signing methods produce different results

From Dev

Why does LINQ GroupBy produce different results when preceded by ToArray()?

From Java

Sharing data between questions – cannot produce different results for second business

Related Related

  1. 1

    Different results in AES256 encryption in Swift (iOS) and PHP

  2. 2

    Different AES256 result between Java and OpenSSL on iOS

  3. 3

    implementing AES256 encryption into IOS

  4. 4

    Why these assignments produce different results?

  5. 5

    atof and stringstream produce different results

  6. 6

    AES256 Encryption/Decryption Error+ IOS SDK 7

  7. 7

    AES256 Encryption/Decryption Error+ IOS SDK 7

  8. 8

    Convert .net aes256 encryption code into php

  9. 9

    JavaScript and jQuery selectors produce different results?

  10. 10

    Can these two jQuery lines produce different results?

  11. 11

    How to produce different random results with DEAP?

  12. 12

    Checkbox combinations to produce different results with jQuery

  13. 13

    R ginv and Matlab pinv produce different results

  14. 14

    Why these syntactically identical functions produce different results?

  15. 15

    Classification Model's parameters produce different results

  16. 16

    Linq expression and foreach produce different results

  17. 17

    jQuery and JS equivalent functions produce different results

  18. 18

    Why these syntactically identical functions produce different results?

  19. 19

    AES Encryption Android <-> iOS different results on message length > 15 byte

  20. 20

    The same declaration in a different order produce different results in gcc

  21. 21

    Different versions of Python 2.7 and Numpy produce different results for the same script

  22. 22

    Why does different scrypt implementation produce different results?

  23. 23

    Running selenium tests from different environments produce different results

  24. 24

    Same code running in different contexts produce different results

  25. 25

    AES256 encryption get different result between node.js and objective-c

  26. 26

    Can "T t = {};" and "T t{};" produce different results?

  27. 27

    Multiple OpenSSL RSA signing methods produce different results

  28. 28

    Why does LINQ GroupBy produce different results when preceded by ToArray()?

  29. 29

    Sharing data between questions – cannot produce different results for second business

HotTag

Archive