6

Using the example from this post Encryption compatible between Android and C#, I have successfully implemented AES encryption between a .NET application that provides XML feeds to my Android application.

Now, I am trying to use this same implementation for the iOS version of that app. I have found some really good examples of AES for iOS, but so far, none seem to match the scheme that I am currently using. From what I can tell, the problem is the 16-byte key that is shared between C# and Java (rawSecretKey). In the iOS examples, I've not been able to find a similar key to set with this same byte array. It has the passPhrase, but not the byte array.

If anyone knows of a good example that illustrates this type of implementation, it would be very helpful. One iOS example I found was http://dotmac.rationalmind.net/2009/02/aes-interoperability-between-net-and-iphone/, but again, I don't see how to include the 16-byte array as referenced in the first link at the top of my post.

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
Kyle
  • 606
  • 5
  • 16
  • If iOS is deriving the key from a pass phrase, then would it be possible to duplicate the same key derivation function in Android? – rossum Sep 21 '11 at 14:45
  • The passphrase is a constant among the different platforms - that particular key isn't a problem. It's more so the 16-byte array that is used - the iOS examples I've found don't include that value (or at least I'm not smart enough to see it). I also cannot change the Android implementation as it is in production and our users already have data encrypted using the existing methods. I just need to replicate it for iOS. – Kyle Sep 21 '11 at 15:55
  • BTW - the byte key is also a constant, it is not derived from anything. I just created the key and it looks something like: private static byte[] rawSecretKey = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; – Kyle Sep 21 '11 at 16:11
  • You need to look at the iOS documentation to see if there is a way to pass in the byte key, rather than the passphrase. Otherwise you need to determine the passphrase which generates the existing Android key and use that passphrase in iOS. I'm not an iOS expert so I can't be much help at that side. – rossum Sep 21 '11 at 16:28
  • rossum...thanks for the comments, but not quite sure they are what I need. I control the values of both the passphrase and the 16-byte key, and I need to use both of them in the encryption/decryption routines. I can easily set the passphrase in iOS - I just need to tell iOS what the 16-byte key is, like I do in the Java and .NET implementations. Take a look at the first link in my question and you'll see the code that I'm using as a base for Java and .NET. – Kyle Sep 21 '11 at 19:00

1 Answers1

8

.Net and IOS both support PKCS7Padding, but Java doesn't (unless use some third-party library)

.Net and Java both support ISO10126Padding, but IOS doesn't (unless use some third-patry library)

So I think you need to have separate .net encryption code for IOS and Java.

Here are some code examples:

for IOS:

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

for .NET:

public static byte[] AesEncrypt(byte[] bytes, byte[] key, byte[] iv)
{
    if (bytes == null || bytes.Length == 0 || key == null || key.Length == 0 || iv == null || iv.Length == 0)
        throw new ArgumentNullException();

    using (var memoryStream = new MemoryStream())
    {
        using (var rijndaelManaged = new RijndaelManaged { Key = key, IV = iv, Padding = PaddingMode.PKCS7, Mode = CipherMode.CBC })
        {
            using (var cryptoStream = new CryptoStream(memoryStream, rijndaelManaged.CreateEncryptor(key, iv), CryptoStreamMode.Write))
            {
                cryptoStream.Write(bytes, 0, bytes.Length);
            }
        }
        return memoryStream.ToArray();
    }
}

for Java:

public static byte[] encrypt(byte[] bytes, byte[] key, byte[] iv)
        throws Exception
{
    Cipher cipher = Cipher.getInstance("AES/CBC/ISO10126Padding");
    cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"),
            new IvParameterSpec(iv));
    return cipher.doFinal(bytes);
}

I only provide the code for encryption because decryption code is very similar and you can figure it out easily.

Any more question please leave comments.

Tyler Liu
  • 19,552
  • 11
  • 100
  • 84
  • `"PKCS5Padding"` in Java is the same as PKCS#7 padding. In the standards, the padding algorithm only differs in block size (8 bytes for PKCS#5 and 16 bytes for PKCS#7) but in most implementations they are compatible with both block sizes, and in Java (or more precisely, the Oracle and Bouncy Castle providers) they certainly are. – Maarten Bodewes Feb 14 '12 at 21:29
  • @owlstead, as you said, "in most implementations". If the block size is not 8 bytes, they are not the same. I will have a try: PKCS5 in Java and PKCS7 in C#, see if they could talk to each other. – Tyler Liu Feb 16 '12 at 12:34