0

我有一个问题..当我解密从我的 php 页面返回的数据时,如果字符串的长度小于 16,则 char \0 将附加到字符串。原始字符串是:100000065912248 我用这个函数解密加密的字符串:

#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;
}

我向函数发送一个 nil“iv”参数,在函数中使用“cIv”之后,它包含以下内容: 文明描述

结果是完全一样的,但是字符串的长度是 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;
}
4

3 回答 3

2

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

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

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

AES 总是在 16 个字节上运行,没有选项——所以,如果你有 15 个字节,则必须添加一个字节,即填充。据我了解(对 PHP 加密知之甚少)PHP 不会做真正的 PCKS7padding,最好自己填充。在 Wikipedia 中查找 PKCS7。

于 2013-02-17T20:51:08.123 回答
0

如果您只对字符串进行操作,您应该可以使用零填充(默认值),但如果只是出于互操作性的原因,我建议使用 PKCS#7 填充。

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

这显然不适用于二进制数据,因为它可能以函数删除的字符结尾trim。请注意,trim在 PHP 中似乎剥离了00字节。这不是给定的,正式00地不是空格,尽管许多运行时都以这种方式对待它。

于 2013-02-18T22:58:24.360 回答
-1

您必须从解密数据中删除填充

function removePadding($decryptedText){
    $strPad = ord($decryptedText[strlen($decryptedText)-1]);
    $decryptedText= substr($decryptedText, 0, -$strPad);
    return $decryptedText;
}
于 2017-12-22T10:49:45.350 回答