多线程环境中带有CCCrypt的NSData

如何解决多线程环境中带有CCCrypt的NSData

| 我有一个使用AES加密的文件。 我使用以下NSData类别:
#import <CommonCrypto/CommonCryptor.h>

@implementation NSData (AES)

- (NSData *)AES256DecryptWithKey:(NSString *)key {

    // \'key\' should be 32 bytes for AES256,will be null-padded otherwise
    char keyPtr[kCCKeySizeAES256+1]; // room for terminator (unused)
    bzero(keyPtr,sizeof(keyPtr)); // fill with zeroes (for padding)

    // fetch key data
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];

    NSUInteger dataLength = [self length];

    //See the doc: For block ciphers,the output size will always be less than or 
    //equal to the input size plus the size of one block.
    //That\'s why we need to add the size of one block here
    size_t bufferSize = dataLength + kCCBlockSizeAES128;

    void *buffer = malloc(bufferSize);

    size_t numBytesDecrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,kCCAlgorithmAES128,kCCOptionPKCS7Padding,keyPtr,kCCKeySizeAES256,NULL /* initialization vector (optional) */,[self bytes],dataLength,/* input */
                                          buffer,bufferSize,/* output */
                                          &numBytesDecrypted);

    NSLog(@\"Bytes decrypted: %d\",numBytesDecrypted);

    if (cryptStatus == kCCSuccess) {
        //the returned NSData takes ownership of the buffer and will free it on deallocation
        return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
    }

    NSLog(@\"Decrypt failed with error code %d\",cryptStatus);
    free(buffer); //free the buffer;
    return nil;
}

@end
当我使用以下代码从文件系统加载整个文件时,解密过程似乎工作正常:
[NSData dataWithContentsOfFile:dataPath];
当不使用上一个调用读取文件,而是使用外部代码对文件进行分块并仅使用少量数据初始化NSData并尝试对其进行解密时,就会发生问题,特别是当不同的线程使用此代码时,会出现问题(或者至少是我的想法):
- (NSData *)readDataOfLength:(NSUInteger)length
{
    HTTPLogTrace2(@\"%@[%p]: readDataOfLength:%lu\",THIS_FILE,self,(unsigned long)length);

    if (![self openFileIfNeeded])
    {
        // File opening failed,// or response has been aborted due to another error.
        return nil;
    }

    // Determine how much data we should read.
    // 
    // It is OK if we ask to read more bytes than exist in the file.
    // It is NOT OK to over-allocate the buffer.

    UInt64 bytesLeftInFile = fileLength - fileOffset;

    NSUInteger bytesToRead = (NSUInteger)MIN(length,bytesLeftInFile);

    // Make sure buffer is big enough for read request.
    // Do not over-allocate.

    if (buffer == NULL || bufferSize < bytesToRead)
    {
        bufferSize = bytesToRead;
        buffer = reallocf(buffer,(size_t)bufferSize);

        if (buffer == NULL)
        {
            HTTPLogError(@\"%@[%p]: Unable to allocate buffer\",self);

            [self abort];
            return nil;
        }
    }

    // Perform the read

    HTTPLogVerbose(@\"%@[%p]: Attempting to read %lu bytes from file\",bytesToRead);

    ssize_t result = read(fileFD,buffer,bytesToRead);

    // Check the results

    if (result < 0)
    {
        HTTPLogError(@\"%@: Error(%i) reading file(%@)\",errno,filePath);

        [self abort];
        return nil;
    }
    else if (result == 0)
    {
        HTTPLogError(@\"%@: Read EOF on file(%@)\",filePath);

        [self abort];
        return nil;
    }
    else // (result > 0)
    {
        HTTPLogVerbose(@\"%@[%p]: Read %d bytes from file\",result);

        fileOffset += result;

        NSData *data = [NSData dataWithBytes:buffer length:result];
        return [data AES256DecryptWithKey:@\"abcdefghijklmnopqrstuvwxyz123456\"];
        //return data;
    }
}
发生的情况是函数CCCrypt在这种情况下失败,错误代码为-4304 AKA \“ kCCDecodeError-输入数据未正确解码或解密。\” 此外,如果在CCCrypt调用中而不是kCCOptionPKCS7Padding传递了0->不填充,则该方法解密第一个数据块,但是在切换线程时,它失败,并显示-4300 AKA \“ kCCParamError-非法参数值。\” 在控制台中显示以下消息:
[Switching to process 13059 thread 0x0]
2011-05-25 18:00:03.631 Drm[1843:6e0b] Bytes decrypted: 131072
2011-05-25 18:00:03.647 Drm[1843:6e0b] Bytes decrypted: 68096
[Switching to process 11779 thread 0x0]
2011-05-25 18:00:04.547 Drm[1843:6e0b] Bytes decrypted: 0
2011-05-25 18:00:04.555 Drm[1843:6e0b] Decrypt failed with error code -4300
有人可以帮忙吗?     

解决方法

AES是一种分组密码。您必须一次解密一个块。 AES块为128位(与
AES256DecryptWithKey
中的\“ 256 \”不相关)。因此,您必须确保传递的数据是16字节的倍数。 我没有尝试过用
CCCrypt()
,这并不是真的。
CCCrypt()
是想要单次解密时的便利功能。当您想进行“随行随用”解密时,可以使用
CCCryptorCreate()
,然后再多次调用
CCCryptorUpdate()
,最后再调用
CCCryptorFinal()
(或者可以先调用
CCCryptorFinal()
,再调用
CCCryptorReset()
,以使用相同的密钥解密更多内容)。最后,您拨打
CCCryptorRelease()
释放密码。 EDIT我对此进行了更多思考,并意识到即使将输入分成16个字节的块,也不能以这种方式使用
CCCrypt()
。每个AES加密块都会修改下一个块的IV,因此您不能只是在流中间开始某人。这就是为什么在整个会话中都需要一个持久的
CCCryptor
对象的原因。     

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-