PHP AES256加密=> RNCryptor RNDecryptor返回空白/ HMAC不匹配

时间:2013-01-09 22:28:14

标签: php ios encryption aes rncryptor

使用PHP 5.4(mcrypt),RNCryptor 2,iOS 6。

PHP函数使用https://github.com/rnapier/RNCryptor/wiki/Data-Format引用的所有标头创建base64。

PHP解密函数可以解密来自RNEncryptor和PHP Encrypt函数的base64字符串,并按预期返回数据。

在下面的PHP加密函数中使用RNDecryptor和base64时,不会返回任何数据,如下面的XCode输出所示。

PHP功能:

function encrypt($data, $key)
{
    $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);

    $salt = '12345678';

    $_key = $this->pbkdf2('SHA1', $key, $salt, 10000, 32, true);

    $ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $_key, $data, MCRYPT_MODE_CBC, $iv);

    $hmac = $this->pbkdf2('SHA1', $key, $salt, 10000, 32, true);

    $data = mb_convert_encoding(chr(1).chr(0).$salt.$salt.$iv.$ciphertext.$hmac, "BASE64", "UTF-8");

    return $data;
}

PHP函数调用:

encrypt('My Data', 'mykey');

的iOS:

NSError * error;
NSData *decryptedData = [RNDecryptor decryptData:[NSString base64DataFromString:@"AQBpcGhvbmU2MmlwaG9uZTYyrYk2rJnaoywktnx6TZ4X3YKgYuEHCL1EHv+/MqIvQMq5BmZOyMJr QSRs9P4uxShsOJOg67VYniUGhHbFNTSl1Q=="]
                                    withPassword:@"mykey"
                                           error:&error];

NSLog(@"data = %@, %@", decryptedData, error);

XCode输出:

  

data =<>,(null)

当我在RNDecryptor -finish中注释掉HMAC验证时,一旦取消注释这些部分我收到HMAC不匹配错误

  

data =(null),错误域= net.robnapier.RNCryptManager代码= 1“HMAC不匹配”UserInfo = 0x1e564280 {NSLocalizedDescription = HMAC Mismatch}

if (self.hasHMAC) {
  NSMutableData *HMACData = [NSMutableData dataWithLength:self.HMACLength];
  CCHmacFinal(&_HMACContext, [HMACData mutableBytes]);

  if (![HMACData isEqualToData:self.inData]) {
    [self cleanupAndNotifyWithError:[NSError errorWithDomain:kRNCryptorErrorDomain
                                                        code:kRNCryptorHMACMismatch
                                                    userInfo:[NSDictionary dictionaryWithObject:@"HMAC Mismatch"
                                                                                         forKey:NSLocalizedDescriptionKey]]];
    return;
  }
}

2 个答案:

答案 0 :(得分:2)

mb_convert_encoding()会进行base64转换,但会输出 chunked base64。

PHP base64解码器将同时接受chunked和unchunked,但iOS ...?

也许你需要编码:

$data = base64_encode(chr(1).chr(0).$salt.$salt.$iv.$ciphertext.$hmac);

您可能需要查看iOS/PHP kCCDecodeError以了解其他实施方案。

最后,从RNCryptor Wiki数据格式,我看到(连同the PHP implementation on Stack Overflow的链接)

  

使用密文和HMACKey(上图)和SHA-256 PRF生成HMAC。

...但你附加的HMAC在我看来实际上是HMACKey,而不是HMAC ......?

答案 1 :(得分:0)

问题是由于不正确的HMAC(正在通过HMAC密钥)和PHP加密需要PKCS7填充要加密的数据(而不是IV)。

最终的PHP函数......

function AES256Encrypt($data, $key)
{
    $block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
    $pad = $block - (strlen($data) % $block);
    $data .= str_repeat(chr($pad), $pad);

    $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);

    $keySalt = '12345678';
    $hmacSalt = '12345678';

    $_key = $this->pbkdf2('SHA1', $key, $keySalt, 10000, 32, true);
    $_hmacKey = $this->pbkdf2('SHA1', $key, $hmacSalt, 10000, 32, true);

    $ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $_key, $data, MCRYPT_MODE_CBC, $iv);

    $data = base64_encode(chr(1).chr(0).$keySalt.$hmacSalt.$iv.$ciphertext.hash_hmac('SHA256',$ciphertext,$_hmacKey, true));
    return $data;
}