在iOS上使用RNCryptorasynchronous解密大文件

我需要iOS上的RNCryptorasynchronous解密大文件(以显示进度条)。 我没有发现任何地方的例子,因此已经尝试了我所猜测的是正确的,但是…我得到的东西不起作用:解密程序的处理程序不会被调用,并且线程在发送所有数据后与EXC_BAD_ADDRESS一起崩溃在函数的结尾。

NSOutputStream *decryptedStream = [NSOutputStream outputStreamToFileAtPath:decryptedPath append:NO]; [decryptedStream open]; NSUInteger totalBytesToRead = [[[NSFileManager defaultManager] attributesOfItemAtPath:tempPath error:nil] fileSize]; __block NSUInteger totalBytesRead = 0; LOG("I've got %d bytes to decrypt.", totalBytesToRead); RNDecryptor *decryptor = [[RNDecryptor alloc] initWithPassword:SNCatalogPassword handler:^(RNCryptor *cryptor, NSData *data) { totalBytesRead += data.length; [decryptedStream write:data.bytes maxLength:data.length]; LOG("Decrypted %d bytes : %d / %d bytes treated", data.length, totalBytesRead, totalBytesToRead); if (cryptor.isFinished) { //proceed LOG("Done with decrypting."); [decryptedStream close]; } }]; // Feed data to the decryptor NSInputStream *cryptedStream = [NSInputStream inputStreamWithFileAtPath:tempPath]; [cryptedStream open]; while (cryptedStream.hasBytesAvailable) { uint8_t buf[4096]; NSUInteger bytesRead = [cryptedStream read:buf maxLength:4096]; NSData *data = [NSData dataWithBytes:buf length:bytesRead]; LOG("Sending %d bytes to decryptor...", bytesRead); dispatch_async(dispatch_get_main_queue(), ^{ [decryptor addData:data]; }); } LOG("Sent everything."); [decryptor finish]; [cryptedStream close]; 

(比较而言, tempPath是encryption文件的path; tempPath是解密数据应写入的path)。

另外我是ARC新手,所以这可能是一个内存或调度相关的问题。

谢谢你的帮助。

我今天遇到了同样的问题,这似乎是由于在iOS6中最近弃用dispatch_get_current_queue()而发生的。

通过更改[RNCryptor initWithHandler:]创build一个新的队列,解密工作正常。

 NSString *responseQueueName = [@"net.robnapier.response." stringByAppendingString:NSStringFromClass([self class])]; _responseQueue = dispatch_queue_create([responseQueueName UTF8String], NULL); 

你可以在github的fork上的async_decrypt分支上find修复和相关的unit testing(根据你的代码)。

提交 csteynberg / RNCryptor

你的行为是由于asynchronous执行:在调用addData之前调用[decryptor finish] 要解决这个问题,你应该replace

 while (cryptedStream.hasBytesAvailable) { //... 

通过

 while (YES) { if (!cryptedStream.hasBytesAvailable) { dispatch_async(dispatch_get_main_queue(), ^{ [decryptor finish]; }); break; } //... 

(当然,除去现有的调用[解密完成] )这种方式完成总是调用所有的数据发送。

问候