在iPhone上加密的时候,用System.Security.Cryptography解密.NET服务器上的iOS CCCrypt填充问题器上、时候、问题、Security

2023-09-04 06:04:14 作者:情到深處人孤獨

这是一个头饼刷。它涉及到加密使它特别粗糙!

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

我的Objective-C code,它使用CCCrypt为AES 128加密的消息上,我发送使用协议缓冲区和AsyncSockets一个iPhone。 iOS的code是如下:

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

我定义了AES管理对象如下:

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;

我那么我的服务器上的此数据是使用下面的C#.NET code解密:

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

这完美的作品,当我在iPhone模拟器正在运行,当我从x code调试设备本身。然而,当我创建应用程序(IPA文件)的分发包并将其部署到设备上,我得到这个异​​常的服务器上:

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.

这是我送,导致这个有着4的未加密的数据长度产生的16加密的大小,因为我认为这是AES块大小的数据,这似乎是正确的。调试日志显示,这是在两个部署的应用程序和模拟器的消息的大小。因此,大小似乎并没有错。

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?

在此先感谢。我一直在试图算出这个数天,这是$ P $从得到我的应用程序被苹果测试pventing我。

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.

推荐答案

若干注意事项:

一)你能请出示code派生加密密钥从iOS上共享密钥。

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

您呈现这个code for.NET,但并没有表现出对iOS的。

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

二)确保keyPtr在iOS实际上包含128位(16字节)。如果由于某种原因,它含有较少的,你可能有这样的问题,

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)我不建议做通keyPtr为IV。一般来说这是一个不好的做法。您应当为每个加密文件中创建新的独特的IV。

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.

有关测试的目的,您可以将其设置为NULL(有少操心变量)。

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

D)你能告诉整个.NET code派生的加密密钥。 有几个东西是不明确的:

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

什么是DH.P?

What is DH.P?

Rfc2898DeriveBytes deriveBytes = / *从共享衍生字节* / 据我了解应该是有来像新Rfc2898DeriveBytes(PWD,盐);而且你在使用的PWD和盐不是很明显。

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.

 
精彩推荐