使用 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 个字节。在我开始巧妙地支持可恢复下载之前,这不是一个大问题。然后丢失的字节很关键,因为它们出现在文件的中心。
我已经检查了进出的内容,如下所示
- 发送到加密器的字节数 19,615,005(文件大小)
- 加密器创建的加密字节数 19,615,026
- 解密收到的字节数或 19,615,026
- 来自解密器的解密字节数 19,614,944
我努力了
- 在 RNCryptor.h 中更改 .options = kCCOptionPKCS7Padding
- 我自己尝试填充到块大小和 16 字节边界
- 更改了加密器完成和 readStreamBlock 调用以确保它不是时间问题
- 调查RNCryptorEngine中的finishWithError,但没有错误
填充到块大小有点工作,因为我可以清理我填充的零,但它并不理想。
我在挠头。以前有人经历过这个循环吗?
更新:
花了很长时间摸不着头脑,意识到我没有能力及时找出问题所在。但是,我退回到简单的解决方案,这很有效,但对我来说不是,因为这会给我带来记忆问题。
- (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");
}
如果我将它与以前的解决方案混合,我会遇到同样的问题。