Skip to content

Instantly share code, notes, and snippets.

@yaakovgamliel
Forked from steipete/NSData+PSPDFFoundation.m
Last active August 29, 2015 14:25
Show Gist options
  • Save yaakovgamliel/fc9176a9e2949d89b7d6 to your computer and use it in GitHub Desktop.
Save yaakovgamliel/fc9176a9e2949d89b7d6 to your computer and use it in GitHub Desktop.
static NSData *PSPDFCalculateSHA256FromFileURL(NSURL *fileURL, CC_LONG dataLength, NSError **error) {
NSCParameterAssert(fileURL);
dispatch_queue_t shaQueue = dispatch_queue_create("com.pspdfkit.sha256-queue", DISPATCH_QUEUE_SERIAL);
__block dispatch_io_t readChannel;
void (^processIntError)(int intError) = ^(int intError) {
if (intError != 0) {
PSPDFLogWarning(@"Stream error: %d", intError);
if (error) *error = [NSError errorWithDomain:@"SHA256Error" code:100 userInfo:@{NSLocalizedDescriptionKey: @"failed to open file for calculating SHA256."}];
}
dispatch_async(shaQueue, ^{
dispatch_io_close(readChannel, DISPATCH_IO_STOP);
});
};
// Open the IO channel
readChannel = dispatch_io_create_with_path(DISPATCH_IO_STREAM, fileURL.path.UTF8String, O_RDONLY, 0, shaQueue, processIntError);
if (!readChannel) {
if (error) *error = [NSError errorWithDomain:@"SHA256Error" code:100 userInfo:@{NSLocalizedDescriptionKey: @"failed to open file for calculating SHA256."}];
return nil;
}
// Prepare SHA hash
__block CC_SHA256_CTX ctx;
CC_SHA256_Init(&ctx);
// Start read and block until we are done.
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
__block int lastIntError = 0;
dispatch_io_set_high_water(readChannel, 512*1024);
dispatch_io_read(readChannel, 0, SIZE_MAX, shaQueue, ^(bool done, dispatch_data_t data, int intError) {
if (intError != 0) {
lastIntError = intError;
processIntError(intError);
return;
}
dispatch_data_apply(data, ^bool(dispatch_data_t region, size_t offset, const void *buffer, size_t size) {
CC_SHA256_Update(&ctx, (const void *)buffer, (CC_LONG)size);
return true;
});
if (done) {
dispatch_semaphore_signal(semaphore);
}
});
// Wait for the signal, then wake up.
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_io_close(readChannel, DISPATCH_IO_STOP);
// Finalize SHA256 calculation unless there's an error.
if (lastIntError == 0) {
unsigned char sha256[CC_SHA256_DIGEST_LENGTH];
CC_SHA256_Final(sha256, &ctx);
NSData *shaData = [NSData dataWithBytes:sha256 length:CC_SHA256_DIGEST_LENGTH];
return shaData;
}
return nil;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment