iOS CCCrypt padding issue when encrypting on iPhone, decrypting on .Net server with System.Security.Cryptography

℡╲_俬逩灬. 提交于 2019-12-23 04:47:14

问题


This is a head-scratcher. And it involves encryption making it particularly gnarly!

I have Objective-C code which uses CCCrypt to AES 128 encrypt a message on an iPhone which I send using Protocol Buffers and AsyncSockets. The iOS code is as follows:

- (NSData *)AES128EncryptWithKey:(const char *)keyPtr {

    NSUInteger dataLength = [self 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, kCCKeySizeAES128, // oorspronkelijk 256
                                          keyPtr /* initialization vector (optional) */,
                                          [self bytes], dataLength, /* 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];
    } else {
        free(buffer); //free the buffer;
        return nil;
    }
}

I define the AES managed object as follows:

    AesManaged AES = new AesManaged();
    AES.Padding = PaddingMode.PKCS7;
    var shared = /* a shared key */
    var salt = shared + DH.P;
    Rfc2898DeriveBytes deriveBytes = /* derived bytes from shared */
    byte[] ekey = deriveBytes.GetBytes(16);
    byte[] eiv = ekey;
    AES.Key = ekey;
    AES.IV = eiv;

I then decrypt this data on my server using the following C# .Net code:

public byte[] Decrypt(byte[] encryptedData)
{
    byte[] dec = null;
    MemoryStream ms = new MemoryStream(encryptedData);
    using (CryptoStream cs = new CryptoStream(ms, AES.CreateDecryptor(), CryptoStreamMode.Read))
    {
         BinaryReader reader = new BinaryReader(cs);
         dec = reader.ReadBytes(encryptedData.Length);
         reader.Close();
    }
    return dec;
}

This works perfectly when I am running in the iOS simulator and when I debug from Xcode to the device itself. However when I create a distribution package of the application (IPA file) and deploy it to the device, I get this exception on the server:

System.Security.Cryptography.CryptographicException: Padding is invalid and cannot be removed.

The data that I am sending that causes this has an unencrypted data length of 4 which creates an encrypted size of 16. Since I believe that this is the AES block size, this seems correct. Debug logs show that this is the size of the message on both the deployed application and the simulator. So the size doesn't seem wrong.

Reading up about this exception indicates to me that there is something wrong with how the padding is being created. But why is this different on the device when deployed versus when it is running via debugger or in the simulator?

Thanks in advance. I've been trying to figure this out for days and it is preventing me from getting my app tested by Apple.


回答1:


Several notes:

a) Can you please show the code which derives encryption key from shared key on iOS.

You showed this code for.NET, but didn't show for iOS.

b) Make sure that keyPtr on iOS actually contains 128 bits(16 bytes). If for any reason it contains less, you may have a problem with this

c) I don't recommend do pass keyPtr as IV. Generally speaking it's a bad practice. You should create new unique IV for each encrypted file.

For the testing purposes you can set it to NULL (to have one less variable to worry about).

d) Can you show whole .NET code which derives encryption key. There are couple things which aren't clear:

  • What is DH.P?

  • Rfc2898DeriveBytes deriveBytes = /* derived bytes from shared */ As I understand there should be come something like new Rfc2898DeriveBytes(pwd, salt); and it's not obvious what are you using as pwd and salt.



来源:https://stackoverflow.com/questions/12410682/ios-cccrypt-padding-issue-when-encrypting-on-iphone-decrypting-on-net-server-w

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!