程序开发

iOS开发丨AES-128-CBC-NoPadding加密解密算

2019-12-25  本文已影响0人  炼心术师

上一篇中介绍了iOS实现AES-128-CBC-PKCS7Padding加密解密的方法,实际使用过程中,也许会用到NoPadding的方式,会稍微有些区别,在于不足16位字节的数据需要自己在数据尾部补0x00,解密的时候同样需要去除数据末尾的0x00,下面给出实现方法:

//加密
+ (NSData *)AES128CBCNoPaddingEncrypt:(NSData *)contentData keyData:(NSData *)keyData ivData:(NSData *)ivData {
    if (!contentData || !keyData || !ivData) {
        return nil;
    }
    void const *keyPtr = keyData.bytes;
    void const *ivPtr = ivData.bytes;
    
    NSUInteger dataLength = [contentData length];
    int diff = kCCKeySizeAES128 - (dataLength % kCCKeySizeAES128);
    NSInteger newSize = 0;
    
    if(diff > 0) {
        newSize = dataLength + diff;
    }
    
    //不足16字节的倍数,则使用0x00自动补齐长度
    char dataPtr[newSize];
    memcpy(dataPtr, [contentData bytes], [contentData length]);
    for(int i = 0; i < diff; i++) {
        dataPtr[i + dataLength] = 0x00;
    }
    
    size_t bufferSize = newSize + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);
    memset(buffer, 0, bufferSize);
    
    size_t numBytesCrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
                                          kCCAlgorithmAES,
                                          0x0000,//NoPadding
                                          keyPtr,
                                          kCCKeySizeAES128,
                                          ivPtr,
                                          dataPtr,
                                          sizeof(dataPtr),
                                          buffer,
                                          bufferSize,
                                          &numBytesCrypted);
    
    if (cryptStatus == kCCSuccess) {
        return [NSData dataWithBytesNoCopy:buffer length:numBytesCrypted];
    }
    free(buffer);
    return nil;
}

//解密
+ (NSData *)AES128CBCNoPaddingDecrypt:(NSData *)contentData keyData:(NSData *)keyData ivData:(NSData *)ivData {
    if (!contentData || !keyData || !ivData) {
        return nil;
    }
    void const *keyPtr = keyData.bytes;
    void const *ivPtr = ivData.bytes;
    
    NSUInteger dataLength = [contentData length];
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);
    
    size_t numBytesCrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,
                                          kCCAlgorithmAES,
                                          0x0000,//NoPadding
                                          keyPtr,
                                          kCCBlockSizeAES128,
                                          ivPtr,
                                          [contentData bytes],
                                          dataLength,
                                          buffer,
                                          bufferSize,
                                          &numBytesCrypted);
    if (cryptStatus == kCCSuccess) {
        NSData *resultData = [NSData dataWithBytesNoCopy:buffer length:numBytesCrypted];
        //去除数据尾部的0x00
        Byte *resultBytes = (Byte *)(resultData.bytes);
        NSInteger i = resultData.length - 1;
        NSInteger c = 0;
        for (; i >= 0; i--) {
            if (resultBytes[i] == 0x00) {
                c++;
            }
            else {
                break;
            }
        }
        return [NSData dataWithBytes:resultBytes length:resultData.length - c];
    }
    free(buffer);
    return nil;
}

keyData和ivData需要保证长度为16字节。

上一篇下一篇

猜你喜欢

热点阅读