5 // Copyright 2011 GRNET S.A. All rights reserved.
7 // Redistribution and use in source and binary forms, with or
8 // without modification, are permitted provided that the following
11 // 1. Redistributions of source code must retain the above
12 // copyright notice, this list of conditions and the following
15 // 2. Redistributions in binary form must reproduce the above
16 // copyright notice, this list of conditions and the following
17 // disclaimer in the documentation and/or other materials
18 // provided with the distribution.
20 // THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
21 // OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
24 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
27 // USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 // AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 // POSSIBILITY OF SUCH DAMAGE.
33 // The views and conclusions contained in the software and
34 // documentation are those of the authors and should not be
35 // interpreted as representing official policies, either expressed
36 // or implied, of GRNET S.A.
38 #import "HashMapHash.h"
39 #import <CommonCrypto/CommonHMAC.h>
41 @implementation HashMapHash
43 + (NSString *)calculateHashMapHash:(NSArray *)hashes {
44 const char padding[] = {
45 '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0',
46 '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0',
47 '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0',
48 '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0'};
50 if ([hashes count] == 0)
51 return [HashMapHash formatHash:[HashMapHash calculateHash:[NSData dataWithBytes:padding length:0]]];
52 if ([hashes count] == 1)
53 return [hashes objectAtIndex:0];
56 while (s < [hashes count])
59 NSMutableArray *h = [NSMutableArray array];
60 for (int i = 0; i < [hashes count]; i++)
61 [h addObject:[NSMutableData dataWithBytes:[[hashes objectAtIndex:i] UTF8String] length:64]];
62 for (int i = 0; i < s - [hashes count]; i++)
63 [h addObject:[NSMutableData dataWithBytes:padding length:64]];
65 while ([h count] > 1) {
66 for (int i = 0; i < [h count]; i = i + 2) {
67 NSMutableData *bytesData = [h objectAtIndex:i];
68 [bytesData appendData:[h objectAtIndex:i + 1]];
69 [h replaceObjectAtIndex:i withObject:[HashMapHash calculateHash:bytesData]];
72 NSMutableIndexSet *indicesToRemove = [NSMutableIndexSet indexSet];
73 for (int i = 0; i < [h count]; i = i + 2)
74 [indicesToRemove addIndex:i + 1];
75 [h removeObjectsAtIndexes:indicesToRemove];
78 return [HashMapHash formatHash:[h objectAtIndex:0]];
81 + (NSData *)calculateHash:(NSData *)data {
82 unsigned char hash[CC_SHA256_DIGEST_LENGTH];
83 CC_SHA256([data bytes], (unsigned int)[data length], hash);
84 return [NSMutableData dataWithBytes:hash length:CC_SHA256_DIGEST_LENGTH];
87 + (NSString *)formatHash:(NSData *)data {
89 hashString = [NSString stringWithFormat:@"%@", data];
90 hashString = [hashString stringByReplacingOccurrencesOfString:@" " withString:@""];
91 hashString = [hashString stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]];
95 // XXX hardcoded hash algorithm for now
96 + (NSArray *)calculateObjectHashMap:(NSString *)filePath withBlockHash:(NSString *)blockHash andBlockSize:(NSUInteger)blockSize {
97 NSFileHandle *fh = [NSFileHandle fileHandleForReadingAtPath:filePath];
99 NSLog(@"failed to open file: %@", filePath);
103 NSFileManager *fm = [NSFileManager defaultManager];
104 NSDictionary *attributes = [fm attributesOfItemAtPath:filePath error:nil];
105 NSUInteger endOfFile = [attributes fileSize];
107 NSUInteger fileOffset = 0;
108 [fh seekToFileOffset:fileOffset];
110 NSMutableArray *hashes = [[[NSMutableArray alloc] init] autorelease];
112 while(fileOffset < endOfFile){
113 NSData *data = [fh readDataOfLength:blockSize];
115 // Strip trailing slashes.
116 const char *bytes = [data bytes];
118 for (i = [data length] - 1; i >= 0; i--)
119 if (bytes[i] != '\0')
121 if (i != [data length] - 1 && i >= 0)
122 data = [data subdataWithRange:NSMakeRange(0, i + 1)];
124 unsigned char hash[CC_SHA256_DIGEST_LENGTH];
126 if ( CC_SHA256([data bytes], (unsigned int)[data length], hash) ) {
127 NSData *sha256 = [NSData dataWithBytes:hash length:CC_SHA256_DIGEST_LENGTH];
128 NSString *hash = [NSString stringWithFormat:@"%@", sha256];
129 hash = [hash stringByReplacingOccurrencesOfString:@" " withString:@""];
130 hash = [hash stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]];
131 [hashes addObject:hash];
134 fileOffset += blockSize;
135 [fh seekToFileOffset:fileOffset];
140 NSArray *hashMap = [NSArray arrayWithArray:hashes];