使用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();
}
RNCryptor git页面上的示例非常标准。输入文件是先前使用
抓取的下载文件downloadFileStream = [[NSOutputStream alloc] initToMemory];
解密完整性在这里
- (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();
}
再次非常类似于git页面。
但是,当我加密和解密同一个文件时,我的尾部是60字节。在我开始熟练地支持可恢复下载之前,这不是一个大问题。然后丢失的字节很重要,因为它们出现在文件的中心。
我已经检查了进出的内容,如下所示
我试过了
填充到块大小的工作,然后我可以清理我填充的零,但它不理想。
我在挠头。以前有人经历过这个循环吗?
更新
花了很长时间挠头,意识到我没有能力及时发现问题。然而,我倒退到简单的解决方案,这是有效的,但不适合我,因为这给了我内存问题。
- (void) simpleEncrypt:(NSString*)filename
{
NSLogDebug(@"simpleEncrypt");
NSString *outputTmpFilePath = [downloadCacheDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.mov", filename]];
NSData *data = [downloadFileStream propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
NSError *error;
NSData *encryptedData = [RNEncryptor encryptData:data
withSettings:kRNCryptorAES256Settings
password:@"blah"
error:&error];
[encryptedData writeToFile:outputTmpFilePath options:NSDataWritingAtomic error:&error];
NSLogDebug(@"simpleEncrypt isFinished");
}
- (void) simpleDecrypt:(NSString*)filename
{
NSLogDebug(@"simpleDecrypt");
NSString *inputTmpFilePath = [downloadCacheDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.mov", filename]];
NSString *outputTmpFilePath = [downloadCacheDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"decrypted%@.mov", filename]];
NSData *encryptedData = [[NSFileManager defaultManager] contentsAtPath:inputTmpFilePath];
NSError *error;
NSData *decryptedData = [RNDecryptor decryptData:encryptedData
withPassword:@"blah"
error:&error];
[decryptedData writeToFile:outputTmpFilePath options:NSDataWritingAtomic error:&error];
NSLogDebug(@"simpleDecrypt isFinished");
}
如果我将它与之前的解决方案混合,我会遇到同样的问题。
答案 0 :(得分:1)
您将流移动了,这可能是问题所在。在链接的示例中,在readStreamBlock
中,有以下代码:
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];
}
这意味着在异步解密完成之前关闭流。