snej@0: // snej@0: // MYDigest.m snej@0: // MYCrypto snej@0: // snej@0: // Created by Jens Alfke on 1/4/08. snej@0: // Copyright 2008 Jens Alfke. All rights reserved. snej@0: // snej@0: snej@0: #import "MYDigest.h" snej@0: #import snej@0: #import "MYCrypto_Private.h" snej@0: snej@0: snej@2: #if MYCRYPTO_USE_IPHONE_API snej@0: enum { snej@0: CSSM_ALGID_SHA1 = 8, snej@0: CSSM_ALGID_SHA256 = 0x80000000 + 14 snej@0: }; snej@0: #endif snej@0: snej@0: snej@0: @implementation MYDigest snej@0: snej@0: + (uint32_t) algorithm { snej@0: AssertAbstractMethod(); snej@0: } snej@0: snej@0: + (size_t) length { snej@0: AssertAbstractMethod(); snej@0: } snej@0: snej@0: + (void) computeDigest: (void*)dstDigest ofBytes: (const void*)bytes length: (size_t)length { snej@0: AssertAbstractMethod(); snej@0: } snej@0: snej@0: snej@0: - (id) initWithRawDigest: (const void*)rawDigest length: (size_t)length { snej@0: Assert([self class] != [MYDigest class], @"MYDigest is an abstract class"); snej@0: Assert(rawDigest!=NULL); snej@0: AssertEq(length,[[self class] length]); snej@0: self = [super init]; snej@0: if (self) { snej@0: _rawDigest = malloc(length); snej@0: Assert(_rawDigest); snej@0: memcpy(_rawDigest,rawDigest,length); snej@0: } snej@0: return self; snej@0: } snej@0: snej@0: - (void) dealloc snej@0: { snej@0: if(_rawDigest) free(_rawDigest); snej@0: [super dealloc]; snej@0: } snej@0: snej@2: - (void) finalize snej@2: { snej@2: if(_rawDigest) free(_rawDigest); snej@2: [super finalize]; snej@2: } snej@2: snej@0: snej@0: - (id) copyWithZone: (NSZone*)zone snej@0: { snej@0: return [self retain]; snej@0: } snej@0: snej@0: - (id)initWithCoder:(NSCoder *)decoder snej@0: { snej@0: NSUInteger length; snej@0: const void *bytes = [decoder decodeBytesForKey: @"digest" returnedLength: &length]; snej@0: return [self initWithRawDigest: bytes length: length]; snej@0: } snej@0: snej@0: snej@0: - (void)encodeWithCoder:(NSCoder *)coder snej@0: { snej@0: [coder encodeBytes: self.bytes length: self.length forKey: @"digest"]; snej@0: } snej@0: snej@0: snej@0: + (MYDigest*) digestFromDigestData: (NSData*)digestData { snej@0: return [[[self alloc] initWithRawDigest: digestData.bytes length: digestData.length] autorelease]; snej@0: } snej@0: snej@0: + (MYDigest*) digestFromHexString: (NSString*)hexString snej@0: { snej@0: const char *cStr = [hexString UTF8String]; snej@0: const size_t length = [self length]; snej@0: if( !cStr || strlen(cStr)!=2*length ) snej@0: return nil; snej@0: uint8_t digest[length]; snej@3: for( size_t i=0; i0); snej@0: CC_SHA1(bytes,length, dstDigest); snej@0: } snej@0: snej@0: + (uint32_t) algorithm {return CSSM_ALGID_SHA1;} snej@0: + (size_t) length {return sizeof(RawSHA1Digest);} snej@0: snej@0: - (MYSHA1Digest*) initWithRawSHA1Digest: (const RawSHA1Digest*)rawDigest { snej@0: return [super initWithRawDigest: rawDigest length: sizeof(*rawDigest)]; snej@0: } snej@0: snej@0: + (MYSHA1Digest*) digestFromRawSHA1Digest: (const RawSHA1Digest*)rawDigest { snej@0: return [[[self alloc] initWithRawSHA1Digest: rawDigest] autorelease]; snej@0: } snej@0: snej@0: - (const RawSHA1Digest*) rawSHA1Digest { snej@0: return self.bytes; snej@0: } snej@0: snej@0: snej@0: @end snej@0: snej@0: snej@0: snej@0: @implementation MYSHA256Digest snej@0: snej@0: + (void) computeDigest: (void*)dstDigest ofBytes: (const void*)bytes length: (size_t)length { snej@0: NSParameterAssert(bytes!=NULL); snej@0: NSParameterAssert(length>0); snej@0: CC_SHA256(bytes,length, dstDigest); snej@0: } snej@0: snej@0: + (uint32_t) algorithm {return CSSM_ALGID_SHA256;} snej@0: + (size_t) length {return sizeof(RawSHA256Digest);} snej@0: snej@0: - (MYSHA256Digest*) initWithRawSHA256Digest: (const RawSHA256Digest*)rawDigest { snej@0: return [super initWithRawDigest: rawDigest length: sizeof(*rawDigest)]; snej@0: } snej@0: snej@0: + (MYSHA256Digest*) digestFromRawSHA256Digest: (const RawSHA256Digest*)rawDigest { snej@0: return [[[self alloc] initWithRawSHA256Digest: rawDigest] autorelease]; snej@0: } snej@0: snej@0: - (const RawSHA256Digest*) rawSHA256Digest { snej@0: return self.bytes; snej@0: } snej@0: snej@0: snej@0: @end snej@0: snej@0: snej@0: snej@0: @implementation NSData (MYDigest) snej@0: snej@0: - (MYSHA1Digest*) my_SHA1Digest snej@0: { snej@0: return (MYSHA1Digest*) [MYSHA1Digest digestOfData: self]; snej@0: } snej@0: snej@0: - (MYSHA256Digest*) my_SHA256Digest snej@0: { snej@0: return (MYSHA256Digest*) [MYSHA256Digest digestOfData: self]; snej@0: } snej@0: snej@0: @end snej@0: snej@0: snej@0: snej@0: #import "Test.h" snej@0: snej@0: snej@0: static void testDigestOf( NSData *src, NSString *expectedSHA1Hex, NSString *expectedSHA256Hex ) snej@0: { snej@0: MYSHA1Digest *d1 = [src my_SHA1Digest]; snej@0: NSString *hex = d1.hexString; snej@0: Log(@"Digesting %u bytes to %@",src.length,hex); snej@0: if( expectedSHA1Hex ) snej@0: CAssertEqual(hex,expectedSHA1Hex); snej@0: MYSHA1Digest *d2 = (MYSHA1Digest*) [MYSHA1Digest digestFromHexString: hex]; snej@0: CAssertEqual(d1,d2); snej@0: CAssertEqual(d2.hexString,hex); snej@0: snej@0: MYSHA256Digest *d256 = [src my_SHA256Digest]; snej@0: hex = d256.hexString; snej@0: Log(@"Digesting %u bytes to %@",src.length,hex); snej@0: if( expectedSHA256Hex ) snej@0: CAssertEqual(hex,expectedSHA256Hex); snej@0: MYSHA256Digest *d256_2 = (MYSHA256Digest*) [MYSHA256Digest digestFromHexString: hex]; snej@0: CAssertEqual(d256,d256_2); snej@0: CAssertEqual(d256_2.hexString,hex); snej@0: } snej@0: snej@0: snej@0: TestCase(MYDigest) { snej@0: testDigestOf([@"Pack my box with five dozen liquor jugs, you ugly potatoe pie!" snej@0: dataUsingEncoding: NSUTF8StringEncoding], snej@0: @"4F254781ED6C0103BE056DD8418EFBAC0C2EBE3C", snej@0: @"08AA4BCDDF7654D7AB5CDD25395A4DD8F3BEB5C79FE567D10C1A21B9134F48FD"); snej@0: testDigestOf([NSData dataWithContentsOfFile: @"/Library/Desktop Pictures/Nature/Zen Garden.jpg"], snej@0: @"62A17839B3B86D3543EB2E34D2718A0FE044FA31", snej@0: @"FBD25FA6CEE794049973DE3BDF752345617FCA81018C8FC65350BCDD901142DB"); snej@0: }