【问题标题】:iOS CCCrypt padding issue when encrypting on iPhone, decrypting on .Net server with System.Security.Cryptography在 iPhone 上加密、在 .Net 服务器上使用 System.Security.Cryptography 解密时出现 iOS CCCrypt 填充问题
【发布时间】:2012-09-13 16:23:40
【问题描述】:

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

我有 Objective-C 代码,它使用 CCCrypt 到 AES 128 加密我使用协议缓冲区和 AsyncSockets 发送的 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;
    }
}

我将AES托管对象定义如下:

    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 块大小,因此这似乎是正确的。调试日志显示这是已部署应用程序和模拟器上消息的大小。所以大小似乎没有错。

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

提前致谢。几天来,我一直在尝试解决这个问题,这使我无法让 Apple 测试我的应用程序。

【问题讨论】:

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

标签: .net objective-c ios cryptography aes


【解决方案1】:

几个注意事项:

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

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

b) 确保 iOS 上的 keyPtr 实际上包含 128 位(16 字节)。如果由于某种原因它包含较少,您可能对此有疑问

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

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

d) 您能否展示派生加密密钥的整个 .NET 代码。 有几件事不清楚:

  • 什么是 DH.P?

  • Rfc2898DeriveBytes derivedBytes = /* 来自共享的派生字节 */ 据我了解,应该有类似 new Rfc2898DeriveBytes(pwd, salt);你用什么作为密码和盐并不明显。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-22
    • 1970-01-01
    • 2020-04-07
    • 2019-07-29
    • 1970-01-01
    • 1970-01-01
    • 2010-11-11
    相关资源
    最近更新 更多