Factored out the name accessors of MYParsedCertificate into a new class MYCertificateName, so that both subject and issuer can be accessed. A bit of other cleanup too.
5 // Created by Jens Alfke on 1/4/08.
6 // Copyright 2008 Jens Alfke. All rights reserved.
10 #import <CommonCrypto/CommonDigest.h>
11 #import "MYCrypto_Private.h"
14 #if MYCRYPTO_USE_IPHONE_API
17 CSSM_ALGID_SHA256 = 0x80000000 + 14
22 @implementation MYDigest
24 + (uint32_t) algorithm {
25 AssertAbstractMethod();
29 AssertAbstractMethod();
32 + (void) computeDigest: (void*)dstDigest ofBytes: (const void*)bytes length: (size_t)length {
33 AssertAbstractMethod();
37 - (id) initWithRawDigest: (const void*)rawDigest length: (size_t)length {
38 Assert([self class] != [MYDigest class], @"MYDigest is an abstract class");
39 Assert(rawDigest!=NULL);
40 AssertEq(length,[[self class] length]);
43 _rawDigest = malloc(length);
45 memcpy(_rawDigest,rawDigest,length);
52 if(_rawDigest) free(_rawDigest);
58 if(_rawDigest) free(_rawDigest);
63 - (id) copyWithZone: (NSZone*)zone
68 - (id)initWithCoder:(NSCoder *)decoder
71 const void *bytes = [decoder decodeBytesForKey: @"digest" returnedLength: &length];
72 return [self initWithRawDigest: bytes length: length];
76 - (void)encodeWithCoder:(NSCoder *)coder
78 [coder encodeBytes: self.bytes length: self.length forKey: @"digest"];
82 + (MYDigest*) digestFromDigestData: (NSData*)digestData {
83 return [[[self alloc] initWithRawDigest: digestData.bytes length: digestData.length] autorelease];
86 + (MYDigest*) digestFromHexString: (NSString*)hexString
88 const char *cStr = [hexString UTF8String];
89 const size_t length = [self length];
90 if( !cStr || strlen(cStr)!=2*length )
92 uint8_t digest[length];
93 for( size_t i=0; i<length; i++ ) {
94 if( sscanf(cStr, "%2hhx", &digest[i]) != 1 )
98 return [[[self alloc] initWithRawDigest: &digest length: length] autorelease];
101 + (MYDigest*) digestOfData: (NSData*)data {
102 return [self digestOfBytes: data.bytes length: data.length];
104 + (MYDigest*) digestOfBytes: (const void*)bytes length: (size_t)length {
105 const size_t digestLength = [self length];
106 uint8_t digest[digestLength];
107 [self computeDigest: digest ofBytes: bytes length: length];
108 return [[[self alloc] initWithRawDigest: &digest length: digestLength] autorelease];
111 - (uint32_t) algorithm {
112 return [[self class] algorithm];
116 return [[self class] length];
119 - (const void*) bytes {
124 - (BOOL) isEqual: (id)digest
126 return [digest isKindOfClass: [MYDigest class]]
127 && [digest algorithm] == self.algorithm
128 && memcmp(self.bytes, [digest bytes], self.length)==0;
133 return *(NSUInteger*)self.bytes;
134 //? This makes the hashcode endian-dependent. Does that matter?
137 - (NSComparisonResult) compare: (MYDigest*)other
139 size_t size=self.length, otherSize=other.length;
140 NSComparisonResult cmp = memcmp(self.bytes, other.bytes, MIN(size,otherSize));
141 return cmp ? cmp : ((int)size - (int)otherSize);
147 return [NSData dataWithBytes: self.bytes length: self.length];
150 - (NSString*) description
152 return [NSString stringWithFormat: @"%@[%@]", [self class], [self abbreviatedHexString]];
155 - (NSString*) hexString
157 const uint8_t *bytes = self.bytes;
158 size_t length = self.length;
159 char out[2*length+1];
161 for( size_t i=0; i<length; i+=1 )
162 dst += sprintf(dst,"%02X", bytes[i]);
163 return [[[NSString alloc] initWithBytes: out length: 2*length encoding: NSASCIIStringEncoding]
167 - (NSString*) abbreviatedHexString
169 const uint8_t *bytes = self.bytes;
170 return [NSString stringWithFormat: @"%02hhX%02hhX%02hhX%02hhX...",
171 bytes[0],bytes[1],bytes[2],bytes[3]];
179 @implementation MYSHA1Digest
181 + (void) computeDigest: (void*)dstDigest ofBytes: (const void*)bytes length: (size_t)length {
182 NSParameterAssert(bytes!=NULL);
183 NSParameterAssert(length>0);
184 CC_SHA1(bytes,length, dstDigest);
187 + (uint32_t) algorithm {return CSSM_ALGID_SHA1;}
188 + (size_t) length {return sizeof(RawSHA1Digest);}
190 - (MYSHA1Digest*) initWithRawSHA1Digest: (const RawSHA1Digest*)rawDigest {
191 return [super initWithRawDigest: rawDigest length: sizeof(*rawDigest)];
194 + (MYSHA1Digest*) digestFromRawSHA1Digest: (const RawSHA1Digest*)rawDigest {
195 return [[[self alloc] initWithRawSHA1Digest: rawDigest] autorelease];
198 - (const RawSHA1Digest*) rawSHA1Digest {
207 @implementation MYSHA256Digest
209 + (void) computeDigest: (void*)dstDigest ofBytes: (const void*)bytes length: (size_t)length {
210 NSParameterAssert(bytes!=NULL);
211 NSParameterAssert(length>0);
212 CC_SHA256(bytes,length, dstDigest);
215 + (uint32_t) algorithm {return CSSM_ALGID_SHA256;}
216 + (size_t) length {return sizeof(RawSHA256Digest);}
218 - (MYSHA256Digest*) initWithRawSHA256Digest: (const RawSHA256Digest*)rawDigest {
219 return [super initWithRawDigest: rawDigest length: sizeof(*rawDigest)];
222 + (MYSHA256Digest*) digestFromRawSHA256Digest: (const RawSHA256Digest*)rawDigest {
223 return [[[self alloc] initWithRawSHA256Digest: rawDigest] autorelease];
226 - (const RawSHA256Digest*) rawSHA256Digest {
235 @implementation NSData (MYDigest)
237 - (MYSHA1Digest*) my_SHA1Digest
239 return (MYSHA1Digest*) [MYSHA1Digest digestOfData: self];
242 - (MYSHA256Digest*) my_SHA256Digest
244 return (MYSHA256Digest*) [MYSHA256Digest digestOfData: self];
254 static void testDigestOf( NSData *src, NSString *expectedSHA1Hex, NSString *expectedSHA256Hex )
256 MYSHA1Digest *d1 = [src my_SHA1Digest];
257 NSString *hex = d1.hexString;
258 Log(@"Digesting %u bytes to %@",src.length,hex);
259 if( expectedSHA1Hex )
260 CAssertEqual(hex,expectedSHA1Hex);
261 MYSHA1Digest *d2 = (MYSHA1Digest*) [MYSHA1Digest digestFromHexString: hex];
263 CAssertEqual(d2.hexString,hex);
265 MYSHA256Digest *d256 = [src my_SHA256Digest];
266 hex = d256.hexString;
267 Log(@"Digesting %u bytes to %@",src.length,hex);
268 if( expectedSHA256Hex )
269 CAssertEqual(hex,expectedSHA256Hex);
270 MYSHA256Digest *d256_2 = (MYSHA256Digest*) [MYSHA256Digest digestFromHexString: hex];
271 CAssertEqual(d256,d256_2);
272 CAssertEqual(d256_2.hexString,hex);
277 testDigestOf([@"Pack my box with five dozen liquor jugs, you ugly potatoe pie!"
278 dataUsingEncoding: NSUTF8StringEncoding],
279 @"4F254781ED6C0103BE056DD8418EFBAC0C2EBE3C",
280 @"08AA4BCDDF7654D7AB5CDD25395A4DD8F3BEB5C79FE567D10C1A21B9134F48FD");
281 testDigestOf([NSData dataWithContentsOfFile: @"/Library/Desktop Pictures/Nature/Zen Garden.jpg"],
282 @"62A17839B3B86D3543EB2E34D2718A0FE044FA31",
283 @"FBD25FA6CEE794049973DE3BDF752345617FCA81018C8FC65350BCDD901142DB");
289 Copyright (c) 2009, Jens Alfke <jens@mooseyard.com>. All rights reserved.
291 Redistribution and use in source and binary forms, with or without modification, are permitted
292 provided that the following conditions are met:
294 * Redistributions of source code must retain the above copyright notice, this list of conditions
295 and the following disclaimer.
296 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
297 and the following disclaimer in the documentation and/or other materials provided with the
300 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
301 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
302 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
303 BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
304 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
305 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
306 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
307 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.