I was searching for a way to get an MD5 or SHA1 checksum of a file in Objective-C for an iOS app. I found lots of solutions for getting the checksum of a string, but nothing for files. The solution was pretty simple, but I had to piece together information from a few sources to get it done. I’m surprised that this isn’t common. Well, here it is.

This is the code. Since this ought to be useful, I’ve implemented it as a class. First, the header file (AiChecksum.h).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#import <Foundation/Foundation.h>
#include <CommonCrypto/CommonDigest.h>
 
@interface AiChecksum : NSObject
{
}
 
/**
 * Get the md5 hash of a file
 *
 * @returns		NSString
 * @since		20140120
 * @author		costmo
 * @param		path		Full path to the file
 */
+(NSString *)md5HashOfPath:(NSString *)path;
 
/**
 * Get the sha1 hash of a file
 *
 * @returns		NSString
 * @since		20140120
 * @author		costmo
 * @param		path		Full path to the file
 */
+(NSString *)shaHashOfPath:(NSString *)path;

And now the implementation (AiChecksum.m).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#import "AiChecksum.h"
 
@implementation AiChecksum
 
+(NSString *)md5HashOfPath:(NSString *)path
{
	NSFileManager *fileManager = [NSFileManager defaultManager];
	// Make sure the file exists
	if( [fileManager fileExistsAtPath:path isDirectory:nil] )
	{
		NSData *data = [NSData dataWithContentsOfFile:path];
		unsigned char digest[CC_MD5_DIGEST_LENGTH];
		CC_MD5( data.bytes, (CC_LONG)data.length, digest );
 
		NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
 
		for( int i = 0; i < CC_MD5_DIGEST_LENGTH; i++ )
		{
			[output appendFormat:@"%02x", digest[i]];
		}
 
		return output;
	}
	else
	{
		return @"";
	}
}
 
+(NSString *)shaHashOfPath:(NSString *)path
{
	NSFileManager *fileManager = [NSFileManager defaultManager];
	// Make sure the file exists
	if( [fileManager fileExistsAtPath:path isDirectory:nil] )
	{
		NSData *data = [NSData dataWithContentsOfFile:path];
		unsigned char digest[CC_SHA1_DIGEST_LENGTH];
		CC_SHA1( data.bytes, (CC_LONG)data.length, digest );
 
		NSMutableString *output = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];
 
		for( int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++ )
		{
			[output appendFormat:@"%02x", digest[i]];
		}
 
		return output;
	}
	else
	{
		return @"";
	}
}

Getting a checksum is simple enough:

1
2
3
4
5
6
7
8
#import "AiChecksum.h"
 
NSString *fullPath = @""; // do whatever you need to get the full path to your file
NSString *md5 = [AiChecksum md5HashOfPath:fullPath];
NSString *sha1 = [AiChecksum shaHashOfPath:fullPath];
 
NSLog( @"MD5: %@", md5 );
NSLog( @"SHA1: %@", sha1 );

That’s all there is to it. Maybe it’ll be useful to someone other than me.