Асинхронно расшифровывать большой файл с помощью RNCryptor на iOS

Мне нужно асинхронно дешифровать большой файл с помощью RNCryptor на iOS (чтобы показать индикатор выполнения). Я нигде не нашел ни одного примера, и поэтому попробовал то, что, как я догадался, было правильным, но... то, что я придумала, не работает: обработчик расшифровщика никогда не вызывается, а поток завершается с 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];

(Obvsiouly, tempPath путь к зашифрованному файлу; decryptedPath путь, по которому должны быть записаны расшифрованные данные).

Также я новичок в ARC, так что это может быть проблема с памятью или диспетчеризацией.

Спасибо за любую помощь.

2 ответа

Решение

Я столкнулся с той же проблемой сегодня, и, похоже, это происходит из-за недавнего устаревания dispatch_get_current_queue() в iOS6.

Изменяя [RNCryptor initWithHandler:] для создания новой очереди, расшифровка работает правильно.

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

Вы можете найти исправление и связанный с ним модульный тест (на основе вашего кода) в ветке async_decrypt моей ветки на github.

Совершить на Штейнберг / RNCryptor

Ваше поведение связано с асинхронным выполнением: перед вызовом addData вы вызываете [метод окончания расшифровки] : чтобы это исправить, вы должны заменить

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

от

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

(и, конечно, удалите существующий вызов [decryptor finish]), таким образом, final всегда вызывается после отправки всех данных.

С уважением

Другие вопросы по тегам