aes解密\0个字符的ios

aes解密\0个字符的ios,ios,encryption,aes,Ios,Encryption,Aes,我有个问题..当我解密从php页面返回的数据时, 如果字符串的长度小于16,则字符\0将附加到字符串。 原始字符串为:100000065912248 我使用此函数解密加密字符串: #define FBENCRYPT_ALGORITHM kCCAlgorithmAES128 #define FBENCRYPT_BLOCK_SIZE kCCBlockSizeAES128 #define FBENCRYPT_KEY_SIZE kCCKeySizeAES256 + (NSDat

我有个问题..当我解密从php页面返回的数据时, 如果字符串的长度小于16,则字符\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;
}
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;
}
我向函数发送一个nil“iv”参数,在函数中使用“cIv”之后,它包含以下内容:

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

为什么??我怎样才能解决这个问题

编辑:

PHP加密函数:

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

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

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

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


AES总是在16个字节上运行,没有选项——所以,如果您有15个字节,那么必须添加一个字节,这就是填充。据我所知(对PHP加密了解不多),PHP并没有真正的PCKS7填充,最好自己填充。在Wikipedia中查找PKCS7。

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

零填充时,纯文本用
00
值字节填充,但仅在需要时。这与总是部署的PKCS#7填充不同。解密后,您可以对解密后生成的明文使用
trim
函数。然后您应该获得原始字符串


这显然不适用于二进制数据,因为它可能以被
trim
函数删除的字符结尾。请注意,PHP中的
trim
似乎会剥离
00
字节。这不是给定的,官方的
00
不是空白,即使许多运行时都是这样处理的。

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

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

但是我的php函数不使用填充(我用php函数编辑了文章),ECB/CBC模式下的AES通常使用填充。流模式不需要填充,ECB/CBC可能部署密文窃取。AES作为一种分组密码确实总是在16字节上运行,但您仍然可以选择一种不需要填充的模式。@owlstead虽然流模式在某些情况下很好,看起来很吸引人,但它们很难正确:从不使用相同的nonce等。因此我个人不推荐它们。我不是在批评答案(我投了赞成票)但我只是想指出,填充的需要取决于分组密码模式,而不是密码本身。@owlstead我同意你的观点。一般来说,密文上的
trim
on ciphertext`不是一个好主意。答案代码将不适用于PHP mcrypt默认的空填充,而这正是OP使用的。对于PKCS#7/PKCS#5填充,需要检查填充是否有效。考虑使用错误的键,<代码> $StPad < /Cord>很可能是错误的,可能是一个大于数据长度的值。但不要返回一个错误的填充错误,它倾向于创建一个填充oracle,而只是什么也不做。大多数库都支持PKCS#7填充,并将在加密时自动添加填充,在解密时删除填充–无需执行更多操作。