Changed the X.509 version number in generated certs from 1 to 3, so that SecCertificateCreateFromData on iPhone will accept them. :-/
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 + (id) digestFromDigestData: (NSData*)digestData {
83 return [[[self alloc] initWithRawDigest: digestData.bytes length: digestData.length] autorelease];
86 + (id) 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 + (id) digestOfData: (NSData*)data {
102 return [self digestOfBytes: data.bytes length: data.length];
105 + (id) digestOfBytes: (const void*)bytes length: (size_t)length {
106 const size_t digestLength = [self length];
107 uint8_t digest[digestLength];
108 [self computeDigest: digest ofBytes: bytes length: length];
109 return [[[self alloc] initWithRawDigest: &digest length: digestLength] autorelease];
112 - (uint32_t) algorithm {
113 return [[self class] algorithm];
117 return [[self class] length];
120 - (const void*) bytes {
125 - (BOOL) isEqual: (id)digest
127 return [digest isKindOfClass: [MYDigest class]]
128 && [digest algorithm] == self.algorithm
129 && memcmp(self.bytes, [digest bytes], self.length)==0;
134 return *(NSUInteger*)self.bytes;
135 //? This makes the hashcode endian-dependent. Does that matter?
138 - (NSComparisonResult) compare: (MYDigest*)other
140 size_t size=self.length, otherSize=other.length;
141 NSComparisonResult cmp = memcmp(self.bytes, other.bytes, MIN(size,otherSize));
142 return cmp ? cmp : ((int)size - (int)otherSize);
148 return [NSData dataWithBytes: self.bytes length: self.length];
151 - (NSString*) description
153 return [NSString stringWithFormat: @"%@[%@]", [self class], [self abbreviatedHexString]];
156 - (NSString*) hexString
158 const uint8_t *bytes = self.bytes;
159 size_t length = self.length;
160 char out[2*length+1];
162 for( size_t i=0; i<length; i+=1 )
163 dst += sprintf(dst,"%02X", bytes[i]);
164 return [[[NSString alloc] initWithBytes: out length: 2*length encoding: NSASCIIStringEncoding]
168 - (NSString*) abbreviatedHexString
170 const uint8_t *bytes = self.bytes;
171 return [NSString stringWithFormat: @"%02hhX%02hhX%02hhX%02hhX...",
172 bytes[0],bytes[1],bytes[2],bytes[3]];
180 @implementation MYSHA1Digest
182 + (void) computeDigest: (void*)dstDigest ofBytes: (const void*)bytes length: (size_t)length {
183 NSParameterAssert(bytes!=NULL);
184 NSParameterAssert(length>0);
185 CC_SHA1(bytes,length, dstDigest);
188 + (uint32_t) algorithm {return CSSM_ALGID_SHA1;}
189 + (size_t) length {return sizeof(RawSHA1Digest);}
191 - (MYSHA1Digest*) initWithRawSHA1Digest: (const RawSHA1Digest*)rawDigest {
192 return [super initWithRawDigest: rawDigest length: sizeof(*rawDigest)];
195 + (MYSHA1Digest*) digestFromRawSHA1Digest: (const RawSHA1Digest*)rawDigest {
196 return [[[self alloc] initWithRawSHA1Digest: rawDigest] autorelease];
199 - (const RawSHA1Digest*) rawSHA1Digest {
208 @implementation MYSHA256Digest
210 + (void) computeDigest: (void*)dstDigest ofBytes: (const void*)bytes length: (size_t)length {
211 NSParameterAssert(bytes!=NULL);
212 NSParameterAssert(length>0);
213 CC_SHA256(bytes,length, dstDigest);
216 + (uint32_t) algorithm {return CSSM_ALGID_SHA256;}
217 + (size_t) length {return sizeof(RawSHA256Digest);}
219 - (MYSHA256Digest*) initWithRawSHA256Digest: (const RawSHA256Digest*)rawDigest {
220 return [super initWithRawDigest: rawDigest length: sizeof(*rawDigest)];
223 + (MYSHA256Digest*) digestFromRawSHA256Digest: (const RawSHA256Digest*)rawDigest {
224 return [[[self alloc] initWithRawSHA256Digest: rawDigest] autorelease];
227 - (const RawSHA256Digest*) rawSHA256Digest {
236 @implementation NSData (MYDigest)
238 - (MYSHA1Digest*) my_SHA1Digest
240 return (MYSHA1Digest*) [MYSHA1Digest digestOfData: self];
243 - (MYSHA256Digest*) my_SHA256Digest
245 return (MYSHA256Digest*) [MYSHA256Digest digestOfData: self];
255 static void testDigestOf( NSData *src, NSString *expectedSHA1Hex, NSString *expectedSHA256Hex )
257 MYSHA1Digest *d1 = [src my_SHA1Digest];
258 NSString *hex = d1.hexString;
259 Log(@"Digesting %u bytes to %@",src.length,hex);
260 if( expectedSHA1Hex )
261 CAssertEqual(hex,expectedSHA1Hex);
262 MYSHA1Digest *d2 = (MYSHA1Digest*) [MYSHA1Digest digestFromHexString: hex];
264 CAssertEqual(d2.hexString,hex);
266 MYSHA256Digest *d256 = [src my_SHA256Digest];
267 hex = d256.hexString;
268 Log(@"Digesting %u bytes to %@",src.length,hex);
269 if( expectedSHA256Hex )
270 CAssertEqual(hex,expectedSHA256Hex);
271 MYSHA256Digest *d256_2 = (MYSHA256Digest*) [MYSHA256Digest digestFromHexString: hex];
272 CAssertEqual(d256,d256_2);
273 CAssertEqual(d256_2.hexString,hex);
278 testDigestOf([@"Pack my box with five dozen liquor jugs, you ugly potatoe pie!"
279 dataUsingEncoding: NSUTF8StringEncoding],
280 @"4F254781ED6C0103BE056DD8418EFBAC0C2EBE3C",
281 @"08AA4BCDDF7654D7AB5CDD25395A4DD8F3BEB5C79FE567D10C1A21B9134F48FD");
282 testDigestOf([NSData dataWithContentsOfFile: @"/Library/Desktop Pictures/Nature/Zen Garden.jpg"],
283 @"62A17839B3B86D3543EB2E34D2718A0FE044FA31",
284 @"FBD25FA6CEE794049973DE3BDF752345617FCA81018C8FC65350BCDD901142DB");
290 Copyright (c) 2009, Jens Alfke <jens@mooseyard.com>. All rights reserved.
292 Redistribution and use in source and binary forms, with or without modification, are permitted
293 provided that the following conditions are met:
295 * Redistributions of source code must retain the above copyright notice, this list of conditions
296 and the following disclaimer.
297 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
298 and the following disclaimer in the documentation and/or other materials provided with the
301 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
302 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
303 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
304 BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
305 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
306 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
307 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
308 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.