2013-02-17 38 views
0

我有一个问题..当我解密从我的PHP页面返回的数据, 如果字符串的长度小于16,字符\ 0被追加到字符串。 原始字符串是: 我解密加密字符串使用此功能:aes解密 0字符ios

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

+ (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); 

    int length = [data length]; 

    // do decrypt 
    size_t decryptedSize = 0; 
    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, 
              FBENCRYPT_ALGORITHM, 
              0, 
              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; 
} 

我送一个零“IV”参数的功能后,我在函数中使用“文明”,它包含此: cIv description

结果正好,但字符串的长度是16而不是15(字符串:100000065912248)。实际上,最后一个字符是\ 0。

为什么?我怎么解决?

编辑:

PHP加密函数:

function encrypt($plaintext) { 

    $key = 'a16byteslongkey!a16byteslongkey!'; 

    $base64encoded_ciphertext = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $plaintext, MCRYPT_MODE_CBC)); 
    $base64encoded_ciphertext = trim($base64encoded_ciphertext); 

    return $base64encoded_ciphertext; 
} 
+2

一般去除填充'上ciphertext' trim'是不是一个好主意。 – zaph 2013-02-17 23:55:45

回答

2

AES是块暗号和加密/解密长度的块128位(16个字节)。因此,如果数据不是块大小,则必须添加一些填充。 Apple最受欢迎和支持的是PKCS7。

与PHP接口必须考虑填充和可能的base64编码。

解决方案是在两侧使用相同的填充,PHP和iOS。

AES总是在16个字节上运行,没有选项 - 所以,如果你有15个字节,一个字节将不得不被添加,那就是填充。根据我的理解(对PHP加密不太了解)PHP并没有真正实现PCKS7padding,最好是自己来填充。在Wikipedia中查找PKCS7。

+0

但我在php中的功能不使用填充(我已经编辑过php功能) – 2013-02-17 22:33:39

+0

AES在ECB/CBC模式*通常*使用填充。流模式不需要填充,ECB/CBC可能会部署密文窃取。作为分组密码的AES始终以16字节操作,但您仍然可以选择不需要填充的模式。 – 2013-02-20 01:45:19

+0

@owlstead虽然流模式在某些情况下很好,并且看起来非常有吸引力,但它们很难正确使用:从不使用相同的随机数等等。因此我个人不推荐他们。 – zaph 2013-02-20 02:40:12

0

如果您只对字符串进行操作,那么您应该使用零填充(默认设置),但如果仅出于互操作性原因,我会推荐使用PKCS#7填充。

使用零填充明文填充值为00的值字节,但仅在必要时填充。这与始终部署的PKCS#7填充不同。解密后,您可以在解密后使用上的trim函数产生明文。你应该得到原始的字符串。

这显然不会在二进制数据上工作,因为它可能以trim函数删除的字符结尾。请注意,PHP中的trim似乎会剥离00字节。这不是一个给定的,正式的00不是空白,尽管它在很多运行时都是这样处理的。

-1

你必须从解密的数据

function removePadding($decryptedText){ 
    $strPad = ord($decryptedText[strlen($decryptedText)-1]); 
    $decryptedText= substr($decryptedText, 0, -$strPad); 
    return $decryptedText; 
} 
+0

答案代码将不适用于PHP mcrypt默认使用的null填充,而OP正在使用该填充。对于PKCS#7/PKCS#5填充,需要检查填充是否有效。考虑使用错误的键,'$ strPad'很可能是错误的,可能是一个大于数据长度的值。但是不要返回一个*错误的填充错误*,这往往会创建一个填充oracle,而不会执行任何操作。大多数库支持PKCS#7填充,并将自动添加填充加密和删除解密填充 - 没有更多的需要完成。 – zaph 2017-12-22 13:29:18