iOS 7和iOS 8/9中的AES解密行为不同。

3
下面的方法在iOS 7上的运行结果与iOS 8/9不同。
+ (NSData *)decryptData:(NSData *)data key:(NSData *)key iv:(NSData *)iv;
{
  NSData *result = nil;

  // setup key
  unsigned char cKey[FBENCRYPT_KEY_SIZE];
  bzero(cKey, sizeof(cKey));
  [key getBytes:cKey length:FBENCRYPT_KEY_SIZE];

  // setup iv
  char cIv[FBENCRYPT_BLOCK_SIZE];
  bzero(cIv, FBENCRYPT_BLOCK_SIZE);
  if (iv) {
    [iv getBytes:cIv length:FBENCRYPT_BLOCK_SIZE];
  }

  // setup output buffer
  size_t bufferSize = [data length] + FBENCRYPT_BLOCK_SIZE;
  void *buffer = malloc(bufferSize);

  // do decrypt
  size_t decryptedSize = 0;
  CCCryptorStatus cryptStatus =
      CCCrypt(kCCDecrypt, FBENCRYPT_ALGORITHM, kCCOptionPKCS7Padding, cKey,
              FBENCRYPT_KEY_SIZE, cIv, [data bytes], [data length], buffer,
              bufferSize, &decryptedSize);

  if (cryptStatus == kCCSuccess) {
    result = [NSData dataWithBytesNoCopy:buffer length:decryptedSize];
  } else {
    free(buffer);
    NSLog(@"[ERROR] failed to decrypt| CCCryptoStatus: %d", cryptStatus);
  }

  return result;
}

iOS 7/8/9都支持加密,但在iOS 7上解密结果为nil。

执行后decryptedSize为0,buffer元素仍然为0。

以下是一些定义:

#define FBENCRYPT_ALGORITHM kCCAlgorithmAES128
#define FBENCRYPT_BLOCK_SIZE kCCBlockSizeAES128
#define FBENCRYPT_KEY_SIZE kCCKeySizeAES256

我已经阅读了关于类似 CCCrypt() 问题的 SO 回答。尝试了以下几种方法:

  1. cKey 的长度增加 1。
  2. cKey 的长度增加到 FBENCRYPT_KEY_SIZE * 2 + 1
  3. cKey 的第一个字节设置为 0(有人说当从 NSString 获取密钥字节时,iOS 6 会这样做)。

以上任何一种方法都无法解决问题。


我提供了一些调用该方法时的示例数据。

传递给 decryptData 的三个参数分别是:

  • data:ea1e6896 b5731f40 1d560a18 f0729fa6
  • key:17c76e90 9a6fef8d b1fd45fa 2de18db0 d2236264 db6c8a60 125599ec 2dfb5614,AES256 的密钥长度为 256 位
  • iv:41463531 38453234 44333835 42463636,16 字节,与块大小相同

期望结果(并且在 iOS8/9 上实际结果)是 248e51af 66bf85d3 00003ab6 fe3c0000


我曾提出过一个类似的问题,其中在iOS 7下,明文被截断而不是返回nil结果:http://stackoverflow.com/questions/31850550/ios-7-aes128-decryption-truncates-decrypted-text-no-problems-on-ios-8 - Drakes
提供数据(未加密和加密)、密钥和IV的十六进制形式的示例输入。关注的是密钥和IV的长度,它们应该分别为密钥长度和块大小。请注意,在某些早期版本的“CCCrypt”中,如果填充不正确,则会返回错误,这已更改为不产生错误,因为这是一个安全漏洞。 - zaph
数据是如何加密的,平台、语言和库/函数。特别是加密函数是否使用PKCS#7(或PKCS#5)填充?注意:不要使用FBENCRYPT_*定义代替Common Crypto定义,这只会增加混乱和错误出现的另一个地方。 - zaph
1个回答

1

由于信息有限,以下是一个快速的猜测:

数据使用与PKCS#7(或PKCS#5)不同的填充加密。虽然流行,但mcrypt()是由一些笨蛋编写的,并使用非标准的空填充,既不安全,也无法在数据的最后一个字节为0x00时使用。

有关PKCs#7传递的更多信息,请参见此SO answer

CCCrypt的早期版本会在填充明显不正确时返回错误,这是一个安全错误,后来得到了纠正。我IRC iOS7是最后一个将错误填充报告为错误的版本。


1
我不知道CCrypt中的更改。你有更多相关信息吗?如果填充不正确,会返回什么? - Rob Napier
1
这个问题在苹果论坛上已经讨论过很多次了,Quinn参与了其中很多的讨论。问题是有些开发者将错误返回用于指示不良密钥。基于PKCS#7填充,这种方法相当有效,因为一个不良密钥有大约255/256(左右)的机会造成填充错误。但这是一个安全弱点,所以校验被删除后,一些开发人员感到不满/敌对。现在如果存在校验错误,则不会报错。我会找到那些讨论并看一下。 - zaph
1
@RobNapier,我找到了关于填充错误处理的参考资料,这里是gparker在苹果论坛上的参考资料:由于安全原因,取消了对kCCDecodeError的强制执行。(查找“填充预言攻击”。)还请参阅Quinn的以下回复。 - zaph
谢谢。"或使用经过身份验证的加密算法。" 呵呵...是啊...http://www.openradar.me/11194903 - Rob Napier
同样的,bug报告21468609也是如此,但似乎苹果不太有兴趣更新iOS加密技术。EC也缺失了。 - zaph

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接