在iPhone上加密时,使用System.Security.Cryptography在.Net服务器上解密时,iOS CCCrypt填充问题

在iPhone上加密时,使用System.Security.Cryptography在.Net服务器上解密时,iOS CCCrypt填充问题,.net,objective-c,ios,cryptography,aes,.net,Objective C,Ios,Cryptography,Aes,这是一个令人头痛的问题。而且它涉及到加密,使得它特别粗糙 我有Objective-C代码,它使用CCCrypt对iPhone上的消息进行加密,我使用协议缓冲区和异步套接字发送该消息。iOS代码如下所示: - (NSData *)AES128EncryptWithKey:(const char *)keyPtr { NSUInteger dataLength = [self length]; //See the doc: For block ciphers, the outpu

这是一个令人头痛的问题。而且它涉及到加密,使得它特别粗糙

我有Objective-C代码,它使用CCCrypt对iPhone上的消息进行加密,我使用协议缓冲区和异步套接字发送该消息。iOS代码如下所示:

- (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;
    }
}
    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;
我将AES托管对象定义如下:

- (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;
    }
}
    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代码在服务器上解密这些数据:

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;
}
当我在iOS模拟器中运行时,以及当我从Xcode调试到设备本身时,这一切都非常有效。但是,当我创建应用程序的分发包(IPA文件)并将其部署到设备时,服务器上会出现以下异常:

System.Security.Cryptography.CryptographicException: Padding is invalid and cannot be removed.
我正在发送的导致这种情况的数据的未加密数据长度为4,这将创建16的加密大小。因为我相信这是AES块大小,所以这似乎是正确的。调试日志显示,这是部署的应用程序和模拟器上消息的大小。所以尺寸看起来没有错

阅读有关此异常的信息向我表明,填充的创建方式有问题。但是,为什么在设备上部署时与通过调试器或模拟器运行时有所不同

提前谢谢。几天来,我一直在努力解决这个问题,这让我无法让苹果对我的应用程序进行测试。

注意:

a) 您能否显示从iOS上的共享密钥派生加密密钥的代码

您为.NET显示了此代码,但没有为iOS显示此代码

b) 确保iOS上的keyPtr实际上包含128位(16字节)。如果出于任何原因,它包含的内容较少,您可能对此有问题

c) 我不建议将keyPtr作为IV通过。一般来说,这是一种不好的做法。您应该为每个加密文件创建新的唯一IV

出于测试目的,您可以将其设置为NULL(以减少一个需要担心的变量)

d) 您能否显示导出加密密钥的整个.NET代码。 有两件事还不清楚:

  • 什么是DH.p

  • Rfc2898DeriveBytes deriveBytes=/*从共享*/ 据我所知,应该有一些新的Rfc2898DeriveBytes(pwd,salt);你用什么做pwd和盐并不明显


我一直在尝试自己做这件事,您的状态有什么更新吗?我很想看看你是如何解决的(希望如此)。到目前为止,这个问题还没有解决。我已经完全重写了代码,但它在.NET方面仍然给了我同样的错误。