HERE的 ObjectiveC 中的 RNDecryptor 类具有以块为单位解密文件的功能,如下所示:
- (IBAction)decryptWithSemaphore:(id)sender {
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
__block int total = 0;
int blockSize = 32 * 1024;
NSArray *docPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *input = [[docPaths objectAtIndex:0] stringByAppendingPathComponent:@"zhuge.rncryptor"];
NSString *output = [[docPaths objectAtIndex:0] stringByAppendingPathComponent:@"zhuge.decrypted.pdf"];
NSInputStream *cryptedStream = [NSInputStream inputStreamWithFileAtPath:input];
__block NSOutputStream *decryptedStream = [NSOutputStream outputStreamToFileAtPath:output append:NO];
__block NSError *decryptionError = nil;
[cryptedStream open];
[decryptedStream open];
RNDecryptor *decryptor = [[RNDecryptor alloc] initWithPassword:@"12345678901234567890123456789012" handler:^(RNCryptor *cryptor, NSData *data) {
@autoreleasepool {
NSLog(@"Decryptor recevied %d bytes", data.length);
[decryptedStream write:data.bytes maxLength:data.length];
dispatch_semaphore_signal(semaphore);
data = nil;
if (cryptor.isFinished) {
[decryptedStream close];
decryptionError = cryptor.error;
// call my delegate that I'm finished with decrypting
}
}
}];
while (cryptedStream.hasBytesAvailable) {
@autoreleasepool {
uint8_t buf[blockSize];
NSUInteger bytesRead = [cryptedStream read:buf maxLength:blockSize];
if (bytesRead > 0) {
NSData *data = [NSData dataWithBytes:buf length:bytesRead];
total = total + bytesRead;
[decryptor addData:data];
NSLog(@"New bytes to decryptor: %d Total: %d", bytesRead, total);
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
}
}
}
[cryptedStream close];
[decryptor finish];
dispatch_release(semaphore);
}
而RNDecryptor的addData方法如下:
- (void)addData:(NSData *)theData
{
if (self.isFinished) {
return;
}
[self.inData appendData:theData];
if (!self.engine) {
[self consumeHeaderFromData:self.inData];
}
if (self.engine) {
NSUInteger HMACLength = self.HMACLength;
if (self.inData.length > HMACLength) {
NSData *data = [self.inData _RNConsumeToIndex:self.inData.length - HMACLength];
[self decryptData:data];
}
}
}
我在这里不明白这条线实际上试图做什么,这对每一块加密流都被调用:
NSData *data = [self.inData _RNConsumeToIndex:self.inData.length - HMACLength];
假设我的块大小为 1000 字节,HMACLength 为 32。
如果我尝试解密大于块大小的文件,比如说 5000 字节,那么这个 addData 方法将运行第一次迭代,因为
NSData *data = [self.inData _RNConsumeToIndex:1000 - 32];
这是在使用标头从索引 0 到(1000-32)的加密字节之后,但哈希写在加密流的末尾,最后几个字节,而不是每个块。并且,在下一次迭代中,输入流将读取接下来的 1000 个字节,从第一次迭代块中修剪的 32 个字节会发生什么?
可能我很困惑,因为此代码已被证明,但我想了解这一点。
提前致谢。