Encryption 文件结尾缺少RNCryptor字节

Encryption 文件结尾缺少RNCryptor字节,encryption,rncryptor,Encryption,Rncryptor,使用RNCryptor对文件进行加密和解密时出现了一个问题,我似乎无法取回完整的文件 我的密码如下 - (void) encryptDownloadedFile:(NSString*)filename { NSString *outputTmpFilePath = [downloadCacheDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.mov", filename]]; int

使用RNCryptor对文件进行加密和解密时出现了一个问题,我似乎无法取回完整的文件

我的密码如下

- (void) encryptDownloadedFile:(NSString*)filename
{
    NSString *outputTmpFilePath = [downloadCacheDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.mov", filename]];

    int blockSize = 32 * 1024;

    __block NSInputStream *plainTextStream = [NSInputStream inputStreamWithData:[downloadFileStream propertyForKey:NSStreamDataWrittenToMemoryStreamKey]];
    __block NSOutputStream *encryptedStream = [NSOutputStream outputStreamToFileAtPath:outputTmpFilePath append:NO];
    __block NSMutableData *downloadedFileData = [NSMutableData data];

    [plainTextStream open];
    [encryptedStream open];

    __block NSMutableData *data = [NSMutableData dataWithLength:blockSize];
    __block RNEncryptor *encryptor = nil;

    dispatch_block_t readStreamBlock = ^{
        [data setLength:blockSize];
        NSInteger bytesRead = [plainTextStream read:[data mutableBytes] maxLength:blockSize];

        if (bytesRead < 0) {
            // Throw an error
        }

        else if (bytesRead == 0) {
            [encryptor finish];

            [downloadedFileData writeToFile:outputTmpFilePath atomically:YES];

            [plainTextStream close];
            [encryptedStream close];
            [downloadFileStream close];
            plainTextStream = nil;
            encryptedStream = nil;
            downloadFileStream = nil;

        }
        else {
            [data setLength:bytesRead];
            [encryptor addData:data];
        }
    };

    encryptor = [[RNEncryptor alloc] initWithSettings:kRNCryptorAES256Settings
                                         password:@"blah"
                                          handler:^(RNCryptor *cryptor, NSData *data)     {

                                                  [downloadedFileData appendBytes:data.bytes length:data.length];

                                                  if (cryptor.isFinished) {

                                                  }
                                                  else {
                                                      readStreamBlock();
                                                  }
                                              }];
    readStreamBlock();
}
完整性解密在这里

- (void) decryptDownloadedFile:(NSString*)filename
{
    NSString *inputTmpFilePath = [downloadCacheDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.mov", filename]];
    NSString *outputTmpFilePath = [downloadCacheDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"decrypted%@.mov", filename]];

    int blockSize = 32 * 1024;

    NSInputStream *cryptedStream = [NSInputStream inputStreamWithFileAtPath:inputTmpFilePath];
    NSOutputStream *decryptedStream = [NSOutputStream outputStreamToFileAtPath:outputTmpFilePath append:NO];

    [cryptedStream open];
    [decryptedStream open];

    __block NSMutableData *data = [NSMutableData dataWithLength:blockSize];
    __block RNDecryptor *decryptor = nil;

    dispatch_block_t readStreamBlock = ^{
        [data setLength:blockSize];
        NSInteger bytesRead = [cryptedStream read:[data mutableBytes] maxLength:blockSize];
        if (bytesRead < 0) {
            // Throw an error
        }
        else if (bytesRead == 0) {
            [decryptor finish];

            [decryptedStream close];
        }
        else {
            [data setLength:bytesRead];
            [decryptor addData:data];
        }
    };

    decryptor = [[RNDecryptor alloc] initWithPassword:@"blah"
                                          handler:^(RNCryptor *cryptor, NSData *data)     {
                                                  [decryptedStream write:data.bytes maxLength:data.length];
                                                  if (cryptor.isFinished) {

                                                  }
                                                  else {
                                                      readStreamBlock();
                                                  }
                                              }];
    readStreamBlock();    
}

如果我把它和前面的解决方案混合在一起,我会遇到同样的问题

您将流移近了,这可能就是问题所在。在链接的示例中,在
readStreamBlock
中,有以下代码:

else if (bytesRead == 0) {
 [decryptor finish];
}
                                        if (cryptor.isFinished) {
                                          [decryptedStream close];
                                          // call my delegate that I'm finished with decrypting
                                        }
然后在解密处理程序中,有以下代码:

else if (bytesRead == 0) {
 [decryptor finish];
}
                                        if (cryptor.isFinished) {
                                          [decryptedStream close];
                                          // call my delegate that I'm finished with decrypting
                                        }
您已将关闭移动到
readStreamBlock

    else if (bytesRead == 0) {
        [decryptor finish];

        [decryptedStream close];
    }

这意味着流在异步解密完成之前关闭。

我不擅长读取Objective-C-但我知道最终解密的症状。。您是否记得在调用finish之后获取解密程序生成的最后一个加密数据?解密程序模块保留最后一位数据,直到可以确定它是填充数据还是真实数据。Ebbe返回到RNCryptor finishWithError中的CCCryptorFinal,但据我所知,它似乎在做预期的事情。我现在已经停止了这个,以后可能还会继续。最后,我用一个fileMgr copyItemAtPath将输出从decryptedStream复制到另一个文件。这似乎从它们隐藏的地方清除了最后的几个字节。如果有人有更好的解决方案,请告诉我。这似乎不是问题所在。我承认上面发布的代码有您注意到的变化,但正如您所描述的,我在代码中有相反的变化。对我来说,重要的是,在模拟器中运行close时,调用NSFileManager文件属性报告的已完成文件的大小(19614944)小于Finder显示的大小(19615005)。我开始认为这是一个NSOutputStream问题,因为复制前面提到的文件可以解决这个问题。此外,在处理这个问题的过程中,我不断遇到内存问题。我编写了自己的逐字节文件复制器来解决copyItemAtPath内存问题。但也将@autorelease池添加到RNCryptorEngine addData、RNDecryptor decryptData和RNEncryptor addData.Mea Culpa。今天早上我过得很愉快。Rob是正确的,尽管我在正确的位置关闭了流,但我没有做的是从同一位置调用文件处理的下一步,我在readStreamBlock中调用了它。因此,我的流程的下一步是在加密完成之前开始。我并没有在示例代码中实际展示这一点。