Added MYParsedCertificate, for working with the innards of X.509 certs. Currently it can parse cert data, extract the public key, and verify the signature. More to come.
1.1 --- a/MYASN1Object.m Tue Jun 02 13:16:28 2009 -0700
1.2 +++ b/MYASN1Object.m Wed Jun 03 17:20:53 2009 -0700
1.3 @@ -126,7 +126,10 @@
1.4 [super dealloc];
1.5 }
1.6
1.7 -
1.8 @synthesize bits=_bits, bitCount=_bitCount;
1.9
1.10 +- (NSString*) description {
1.11 + return $sprintf(@"%@%@", [self class], _bits);
1.12 +}
1.13 +
1.14 @end
2.1 --- a/MYBERParser.h Tue Jun 02 13:16:28 2009 -0700
2.2 +++ b/MYBERParser.h Wed Jun 03 17:20:53 2009 -0700
2.3 @@ -15,5 +15,8 @@
2.4 /** Parses a block of BER-formatted data into an object tree. */
2.5 id MYBERParse (NSData *ber, NSError **outError);
2.6
2.7 +size_t MYBERGetLength (NSData *ber, NSError **outError);
2.8 +const void* MYBERGetContents (NSData *ber, NSError **outError);
2.9 +
2.10 NSDateFormatter* MYBERGeneralizedTimeFormatter();
2.11 NSDateFormatter* MYBERUTCTimeFormatter();
3.1 --- a/MYBERParser.m Tue Jun 02 13:16:28 2009 -0700
3.2 +++ b/MYBERParser.m Wed Jun 03 17:20:53 2009 -0700
3.3 @@ -19,6 +19,14 @@
3.4
3.5
3.6 typedef struct {
3.7 + unsigned tag :5;
3.8 + unsigned isConstructed :1;
3.9 + unsigned tagClass :2;
3.10 + unsigned length :7;
3.11 + unsigned isLengthLong :1;
3.12 +} BERHeader;
3.13 +
3.14 +typedef struct {
3.15 const uint8_t *nextChar;
3.16 size_t length;
3.17 } InputData;
3.18 @@ -103,27 +111,23 @@
3.19 }
3.20
3.21
3.22 +static size_t readHeader(InputData *input, BERHeader *header) {
3.23 + memcpy(header, readOrDie(input,2), 2);
3.24 + if (header->tag == 0x1F)
3.25 + [NSException raise: MYBERParserException format: @"Long tags not supported"];
3.26 + if (!header->isLengthLong)
3.27 + return header->length;
3.28 + else {
3.29 + if (header->length == 0)
3.30 + [NSException raise: MYBERParserException format: @"Indefinite length not supported"];
3.31 + return NSSwapBigIntToHost(readBigEndianUnsignedInteger(input,header->length));
3.32 + }
3.33 +}
3.34 +
3.35 +
3.36 static id parseBER(InputData *input) {
3.37 - struct {
3.38 - unsigned tag :5;
3.39 - unsigned isConstructed :1;
3.40 - unsigned tagClass :2;
3.41 - unsigned length :7;
3.42 - unsigned isLengthLong :1;
3.43 - } header;
3.44 - memcpy(&header, readOrDie(input,2), 2);
3.45 -
3.46 - if (header.tag == 0x1F)
3.47 - [NSException raise: MYBERParserException format: @"Long tags not supported"];
3.48 -
3.49 - // Parse the length:
3.50 - size_t length;
3.51 - if (!header.isLengthLong)
3.52 - length = header.length;
3.53 - else if (header.length == 0)
3.54 - [NSException raise: MYBERParserException format: @"Indefinite length not supported"];
3.55 - else
3.56 - length = NSSwapBigIntToHost(readBigEndianUnsignedInteger(input,header.length));
3.57 + BERHeader header;
3.58 + size_t length = readHeader(input,&header);
3.59
3.60 Class defaultClass = [MYASN1Object class];
3.61
3.62 @@ -209,6 +213,16 @@
3.63 Warn(@"parseBER: Returning default %@", result);
3.64 return result;
3.65 }
3.66 +
3.67 +
3.68 +static void exceptionToError (NSException *x, NSError **outError) {
3.69 + if ($equal(x.name, MYBERParserException)) {
3.70 + if (outError)
3.71 + *outError = MYError(1,MYASN1ErrorDomain, @"%@", x.reason);
3.72 + } else {
3.73 + @throw(x);
3.74 + }
3.75 +}
3.76
3.77
3.78 id MYBERParse (NSData *ber, NSError **outError) {
3.79 @@ -216,16 +230,35 @@
3.80 InputData input = {ber.bytes, ber.length};
3.81 return parseBER(&input);
3.82 }@catch (NSException *x) {
3.83 - if ($equal(x.name, MYBERParserException)) {
3.84 - *outError = MYError(1,MYASN1ErrorDomain, @"%@", x.reason);
3.85 - } else {
3.86 - @throw(x);
3.87 - }
3.88 + exceptionToError(x,outError);
3.89 }
3.90 return nil;
3.91 }
3.92
3.93
3.94 +size_t MYBERGetLength (NSData *ber, NSError **outError) {
3.95 + @try{
3.96 + InputData input = {ber.bytes, ber.length};
3.97 + BERHeader header;
3.98 + return readHeader(&input,&header);
3.99 + }@catch (NSException *x) {
3.100 + exceptionToError(x,outError);
3.101 + }
3.102 + return 0;
3.103 +}
3.104 +
3.105 +const void* MYBERGetContents (NSData *ber, NSError **outError) {
3.106 + @try{
3.107 + InputData input = {ber.bytes, ber.length};
3.108 + BERHeader header;
3.109 + readHeader(&input,&header);
3.110 + return input.nextChar;
3.111 + }@catch (NSException *x) {
3.112 + exceptionToError(x,outError);
3.113 + }
3.114 + return NULL;
3.115 +}
3.116 +
3.117
3.118
3.119 #pragma mark -
3.120 @@ -280,6 +313,9 @@
3.121 }
3.122
3.123
3.124 +#import "MYCertificate.h"
3.125 +#import "MYPublicKey.h"
3.126 +
3.127 TestCase(ParseCert) {
3.128 NSData *cert = [NSData dataWithContentsOfFile: @"../../Tests/selfsigned.cer"];
3.129 NSError *error = nil;
3.130 @@ -288,6 +324,14 @@
3.131 CAssertNil(error);
3.132 NSString *dump = [MYASN1Object dump: parsed];
3.133 CAssert(dump);
3.134 + Log(@"Parsed selfsigned.cer:\n%@", dump);
3.135 +
3.136 + MYCertificate *myCert = [[MYCertificate alloc] initWithCertificateData: cert];
3.137 + CAssert(myCert);
3.138 + const CSSM_KEY *pubKey = myCert.publicKey.cssmKey;
3.139 + CSSM_DATA pubKeyData = pubKey->KeyData;
3.140 + id parsedPubKey = MYBERParse([NSData dataWithBytes: pubKeyData.Data length: pubKeyData.Length],NULL);
3.141 + Log(@"Parsed public key:\n%@", [MYASN1Object dump: parsedPubKey]);
3.142
3.143 cert = [NSData dataWithContentsOfFile: @"../../Tests/iphonedev.cer"];
3.144 parsed = MYBERParse(cert,&error);
4.1 --- a/MYCrypto.xcodeproj/project.pbxproj Tue Jun 02 13:16:28 2009 -0700
4.2 +++ b/MYCrypto.xcodeproj/project.pbxproj Wed Jun 03 17:20:53 2009 -0700
4.3 @@ -48,6 +48,9 @@
4.4 27410FF00F99200A00AD413F /* MYSymmetricKey-iPhone.m in Sources */ = {isa = PBXBuildFile; fileRef = 27410FEF0F99200A00AD413F /* MYSymmetricKey-iPhone.m */; };
4.5 274861D50F8E4B5200FE617B /* MYCertGen.m in Sources */ = {isa = PBXBuildFile; fileRef = 27A42ECD0F8689D30063D362 /* MYCertGen.m */; };
4.6 274863A20F8EF39400FE617B /* MYIdentity.m in Sources */ = {isa = PBXBuildFile; fileRef = 274863A10F8EF39400FE617B /* MYIdentity.m */; };
4.7 + 275D9D920FD5FB4100D85A86 /* MYParsedCertificate.h in Headers */ = {isa = PBXBuildFile; fileRef = 275D9D900FD5FB4100D85A86 /* MYParsedCertificate.h */; };
4.8 + 275D9D930FD5FB4100D85A86 /* MYParsedCertificate.m in Sources */ = {isa = PBXBuildFile; fileRef = 275D9D910FD5FB4100D85A86 /* MYParsedCertificate.m */; };
4.9 + 275D9D940FD5FB4100D85A86 /* MYParsedCertificate.m in Sources */ = {isa = PBXBuildFile; fileRef = 275D9D910FD5FB4100D85A86 /* MYParsedCertificate.m */; };
4.10 27A42CBF0F8578B40063D362 /* MYCryptoTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 27A42CBE0F8578B40063D362 /* MYCryptoTest.m */; };
4.11 27A42D1E0F8586CE0063D362 /* MYKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 27E822A10F81C5660019BE60 /* MYKey.m */; };
4.12 27A42D420F858ED80063D362 /* MYSymmetricKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 27A42D410F858ED80063D362 /* MYSymmetricKey.m */; };
4.13 @@ -108,6 +111,8 @@
4.14 2748604D0F8D5C4C00FE617B /* MYCrypto_Release.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = MYCrypto_Release.xcconfig; sourceTree = "<group>"; };
4.15 274863A00F8EF39400FE617B /* MYIdentity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYIdentity.h; sourceTree = "<group>"; };
4.16 274863A10F8EF39400FE617B /* MYIdentity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYIdentity.m; sourceTree = "<group>"; };
4.17 + 275D9D900FD5FB4100D85A86 /* MYParsedCertificate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYParsedCertificate.h; sourceTree = "<group>"; };
4.18 + 275D9D910FD5FB4100D85A86 /* MYParsedCertificate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYParsedCertificate.m; sourceTree = "<group>"; };
4.19 27A42CBE0F8578B40063D362 /* MYCryptoTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYCryptoTest.m; sourceTree = "<group>"; };
4.20 27A42D400F858ED80063D362 /* MYSymmetricKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYSymmetricKey.h; sourceTree = "<group>"; };
4.21 27A42D410F858ED80063D362 /* MYSymmetricKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYSymmetricKey.m; sourceTree = "<group>"; };
4.22 @@ -273,6 +278,8 @@
4.23 274861440F8D757600FE617B /* Certificates */ = {
4.24 isa = PBXGroup;
4.25 children = (
4.26 + 275D9D900FD5FB4100D85A86 /* MYParsedCertificate.h */,
4.27 + 275D9D910FD5FB4100D85A86 /* MYParsedCertificate.m */,
4.28 27A42ECC0F8689D30063D362 /* MYCertGen.h */,
4.29 27A42ECD0F8689D30063D362 /* MYCertGen.m */,
4.30 27B852F30FCF4EB6005631F9 /* MYASN1Object.h */,
4.31 @@ -339,6 +346,7 @@
4.32 27B852FE0FCF4ECB005631F9 /* MYOID.h in Headers */,
4.33 27B855270FD077A6005631F9 /* MYDEREncoder.h in Headers */,
4.34 270A7A730FD58FF200770C4D /* MYBERParser.h in Headers */,
4.35 + 275D9D920FD5FB4100D85A86 /* MYParsedCertificate.h in Headers */,
4.36 );
4.37 runOnlyForDeploymentPostprocessing = 0;
4.38 };
4.39 @@ -440,6 +448,7 @@
4.40 27B852FF0FCF4ECB005631F9 /* MYOID.m in Sources */,
4.41 27B855280FD077A7005631F9 /* MYDEREncoder.m in Sources */,
4.42 270A7A740FD58FF200770C4D /* MYBERParser.m in Sources */,
4.43 + 275D9D930FD5FB4100D85A86 /* MYParsedCertificate.m in Sources */,
4.44 );
4.45 runOnlyForDeploymentPostprocessing = 0;
4.46 };
4.47 @@ -473,6 +482,7 @@
4.48 27B853000FCF4ECB005631F9 /* MYOID.m in Sources */,
4.49 27B855290FD077A7005631F9 /* MYDEREncoder.m in Sources */,
4.50 270A7A750FD58FF200770C4D /* MYBERParser.m in Sources */,
4.51 + 275D9D940FD5FB4100D85A86 /* MYParsedCertificate.m in Sources */,
4.52 );
4.53 runOnlyForDeploymentPostprocessing = 0;
4.54 };
5.1 --- a/MYDEREncoder.m Tue Jun 02 13:16:28 2009 -0700
5.2 +++ b/MYDEREncoder.m Wed Jun 03 17:20:53 2009 -0700
5.3 @@ -338,7 +338,7 @@
5.4
5.5 TestCase(EncodeCert) {
5.6 NSError *error = nil;
5.7 - NSData *cert = [NSData dataWithContentsOfFile: @"../../Tests/selfsigned.cer"]; //TEMP
5.8 + NSData *cert = [NSData dataWithContentsOfFile: @"../../Tests/iphonedev.cer"]; //TEMP
5.9 id certObjects = MYBERParse(cert,&error);
5.10 CAssertNil(error);
5.11 Log(@"Decoded as:\n%@", [MYASN1Object dump: certObjects]);
5.12 @@ -347,6 +347,6 @@
5.13 id reDecoded = MYBERParse(encoded, &error);
5.14 CAssertNil(error);
5.15 Log(@"Re-decoded as:\n%@", [MYASN1Object dump: reDecoded]);
5.16 - [encoded writeToFile: @"../../Tests/selfsigned_reencoded.cer" atomically: YES];
5.17 + [encoded writeToFile: @"../../Tests/iphonedev_reencoded.cer" atomically: YES];
5.18 CAssertEqual(encoded,cert);
5.19 }
6.1 --- a/MYKey.h Tue Jun 02 13:16:28 2009 -0700
6.2 +++ b/MYKey.h Wed Jun 03 17:20:53 2009 -0700
6.3 @@ -30,6 +30,9 @@
6.4 @interface MYKey : MYKeychainItem
6.5 { }
6.6
6.7 +/** Creates a key from encoded data (but does not add it to any keychain.) */
6.8 +- (id) initWithKeyData: (NSData*)data;
6.9 +
6.10 /** The key's raw data. */
6.11 @property (readonly) NSData *keyData;
6.12
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/MYParsedCertificate.h Wed Jun 03 17:20:53 2009 -0700
7.3 @@ -0,0 +1,29 @@
7.4 +//
7.5 +// MYParsedCertificate.h
7.6 +// MYCrypto
7.7 +//
7.8 +// Created by Jens Alfke on 6/2/09.
7.9 +// Copyright 2009 Jens Alfke. All rights reserved.
7.10 +//
7.11 +
7.12 +#import <Foundation/Foundation.h>
7.13 +@class MYCertificate, MYOID;
7.14 +
7.15 +/** A parsed X.509 certificate. Can be used to get more info about an existing cert,
7.16 + or to modify a self-signed cert and regenerate it. */
7.17 +@interface MYParsedCertificate : NSObject
7.18 +{
7.19 + NSData *_data;
7.20 + id _root;
7.21 + MYCertificate *_issuer;
7.22 +}
7.23 +
7.24 ++ (MYOID*) RSAWithSHA1AlgorithmID;
7.25 +
7.26 +- (id) initWithCertificateData: (NSData*)data error: (NSError**)outError;
7.27 +
7.28 +/** Associates the certificate to its issuer.
7.29 + If the cert is not self-signed, you must manually set this property before verifying. */
7.30 +@property (retain) MYCertificate* issuer;
7.31 +
7.32 +@end
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/MYParsedCertificate.m Wed Jun 03 17:20:53 2009 -0700
8.3 @@ -0,0 +1,285 @@
8.4 +//
8.5 +// MYParsedCertificate.m
8.6 +// MYCrypto
8.7 +//
8.8 +// Created by Jens Alfke on 6/2/09.
8.9 +// Copyright 2009 Jens Alfke. All rights reserved.
8.10 +//
8.11 +
8.12 +// References:
8.13 +// <http://en.wikipedia.org/wiki/X.509>
8.14 +// <http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt>
8.15 +
8.16 +
8.17 +#import "MYParsedCertificate.h"
8.18 +#import "MYASN1Object.h"
8.19 +#import "MYOID.h"
8.20 +#import "MYBERParser.h"
8.21 +#import "MYDEREncoder.h"
8.22 +#import "MYPublicKey.h"
8.23 +#import "MYCertificate.h"
8.24 +#import "MYErrorUtils.h"
8.25 +
8.26 +
8.27 +static id $atIf(NSArray *array, NSUInteger index) {
8.28 + return index < array.count ?[array objectAtIndex: index] :nil;
8.29 +}
8.30 +
8.31 +
8.32 +@implementation MYParsedCertificate
8.33 +
8.34 +
8.35 +static MYOID *kRSAAlgorithmID, *kRSAWithSHA1AlgorithmID;
8.36 +
8.37 +
8.38 ++ (void) initialize {
8.39 + if (!kRSAAlgorithmID) {
8.40 + UInt32 components[7] = {1, 2, 840, 113549, 1, 1, 1,};
8.41 + kRSAAlgorithmID = [[MYOID alloc] initWithComponents: components count: 7];
8.42 + }
8.43 + if (!kRSAWithSHA1AlgorithmID) {
8.44 + UInt32 components[7] = {1, 2, 840, 113549, 1, 1, 5};
8.45 + kRSAWithSHA1AlgorithmID = [[MYOID alloc] initWithComponents: components count: 7];
8.46 + }
8.47 +}
8.48 +
8.49 ++ (MYOID*) RSAAlgorithmID {return kRSAAlgorithmID;}
8.50 ++ (MYOID*) RSAWithSHA1AlgorithmID {return kRSAWithSHA1AlgorithmID;}
8.51 +
8.52 +
8.53 ++ (NSString*) validate: (id)root {
8.54 + NSArray *top = $castIf(NSArray,root);
8.55 + if (top.count < 3)
8.56 + return @"Too few top-level components";
8.57 + NSArray *info = $castIf(NSArray, [top objectAtIndex: 0]);
8.58 + if (info.count < 7)
8.59 + return @"Too few identity components";
8.60 + MYASN1Object *version = $castIf(MYASN1Object, [info objectAtIndex: 0]);
8.61 + if (!version || version.tag != 0)
8.62 + return @"Missing or invalid version";
8.63 + NSArray *versionComps = $castIf(NSArray, version.components);
8.64 + if (!versionComps || versionComps.count != 1)
8.65 + return @"Invalid version";
8.66 + NSNumber *versionNum = $castIf(NSNumber, [versionComps objectAtIndex: 0]);
8.67 + if (!versionNum || versionNum.intValue < 0 || versionNum.intValue > 2)
8.68 + return @"Unrecognized version number";
8.69 + return nil;
8.70 +}
8.71 +
8.72 +
8.73 +- (id) initWithCertificateData: (NSData*)data error: (NSError**)outError;
8.74 +{
8.75 + self = [super init];
8.76 + if (self != nil) {
8.77 + if (outError) *outError = nil;
8.78 + id root = MYBERParse(data,outError);
8.79 + NSString *errorMsg = [[self class] validate: root];
8.80 + if (errorMsg) {
8.81 + if (!*outError)
8.82 + *outError = MYError(2, MYASN1ErrorDomain, @"Invalid certificate: %@", errorMsg);
8.83 + [self release];
8.84 + return nil;
8.85 + }
8.86 + _root = [root retain];
8.87 + _data = [data copy];
8.88 + }
8.89 + return self;
8.90 +}
8.91 +
8.92 +- (void) dealloc
8.93 +{
8.94 +
8.95 + [_root release];
8.96 + [_issuer release];
8.97 + [super dealloc];
8.98 +}
8.99 +
8.100 +
8.101 +@synthesize issuer=_issuer;
8.102 +
8.103 +
8.104 +- (NSArray*) info {return $castIf(NSArray,$atIf(_root,0));}
8.105 +
8.106 +- (BOOL) isSelfSigned {
8.107 + id issuer = $atIf(self.info,3);
8.108 + id subject = $atIf(self.info,5);
8.109 + return $equal(issuer,subject);
8.110 +}
8.111 +
8.112 +- (MYPublicKey*) subjectPublicKey {
8.113 + NSArray *keyInfo = $cast(NSArray, $atIf(self.info, 6));
8.114 + MYOID *keyAlgorithmID = $castIf(MYOID, $atIf($castIf(NSArray,$atIf(keyInfo,0)), 0));
8.115 + if (!$equal(keyAlgorithmID, kRSAAlgorithmID))
8.116 + return nil;
8.117 + MYBitString *keyData = $cast(MYBitString, $atIf(keyInfo, 1));
8.118 + if (!keyData) return nil;
8.119 + return [[[MYPublicKey alloc] initWithKeyData: keyData.bits] autorelease];
8.120 + /*
8.121 + NSArray *keyParts = $castIf(NSArray, MYBERParse(keyData, nil));
8.122 + if (!keyParts) return nil;
8.123 + MYBitString *modulus = $castIf(MYBitString, $atIf(keyParts,0));
8.124 + int exponent = [$castIf(NSNumber, $atIf(keyParts,1)) intValue];
8.125 + if (!modulus || exponent<3) return nil;
8.126 + */
8.127 +}
8.128 +
8.129 +- (MYPublicKey*) issuerPublicKey {
8.130 + if (_issuer)
8.131 + return _issuer.publicKey;
8.132 + else if (self.isSelfSigned)
8.133 + return self.subjectPublicKey;
8.134 + else
8.135 + return nil;
8.136 +}
8.137 +
8.138 +
8.139 +- (NSData*) signedData {
8.140 + // The root object is a sequence; we want to extract the 1st object of that sequence.
8.141 + const UInt8 *certStart = _data.bytes;
8.142 + const UInt8 *start = MYBERGetContents(_data, nil);
8.143 + if (!start) return nil;
8.144 + size_t length = MYBERGetLength([NSData dataWithBytesNoCopy: (void*)start
8.145 + length: _data.length - (start-certStart)
8.146 + freeWhenDone: NO],
8.147 + NULL);
8.148 + if (length==0)
8.149 + return nil;
8.150 + return [NSData dataWithBytes: start length: (start + length - certStart)];
8.151 +}
8.152 +
8.153 +- (MYOID*) signatureAlgorithmID {
8.154 + return $castIf(MYOID, $atIf($castIf(NSArray,$atIf(_root,1)), 0));
8.155 +}
8.156 +
8.157 +- (NSData*) signature {
8.158 + id signature = $atIf(_root,2);
8.159 + if ([signature isKindOfClass: [MYBitString class]])
8.160 + signature = [signature bits];
8.161 + return $castIf(NSData,signature);
8.162 +}
8.163 +
8.164 +- (BOOL) validateSignature {
8.165 + if (!$equal(self.signatureAlgorithmID, [MYParsedCertificate RSAWithSHA1AlgorithmID]))
8.166 + return NO;
8.167 + NSData *signedData = self.signedData;
8.168 + NSData *signature = self.signature;
8.169 + MYPublicKey *pubKey = self.issuerPublicKey;
8.170 + if (!signature || !pubKey) return NO;
8.171 + return [pubKey verifySignature: signature ofData: signedData];
8.172 +}
8.173 +
8.174 +
8.175 +@end
8.176 +
8.177 +
8.178 +
8.179 +
8.180 +TestCase(ParsedCert) {
8.181 + auto void testCert(NSString *filename, BOOL selfSigned);
8.182 + testCert(@"../../Tests/selfsigned.cer", YES);
8.183 + testCert(@"../../Tests/iphonedev.cer", NO);
8.184 + auto void testCert(NSString *filename, BOOL selfSigned) {
8.185 + Log(@"--- Creating MYParsedCertificate from %@", filename);
8.186 + NSData *certData = [NSData dataWithContentsOfFile: filename];
8.187 + //Log(@"Cert Data =\n%@", certData);
8.188 + NSError *error = nil;
8.189 + MYParsedCertificate *pcert = [[MYParsedCertificate alloc] initWithCertificateData: certData
8.190 + error: &error];
8.191 + CAssertNil(error);
8.192 + CAssert(pcert != nil);
8.193 +
8.194 + CAssertEq(pcert.isSelfSigned, selfSigned);
8.195 +
8.196 + NSData *signedData = pcert.signedData;
8.197 + //Log(@"Signed Data = (length=%x)\n%@", signedData.length, signedData);
8.198 + CAssertEqual(signedData, [certData subdataWithRange: NSMakeRange(4,signedData.length)]);
8.199 +
8.200 + Log(@"AlgID = %@", pcert.signatureAlgorithmID);
8.201 + Log(@"Signature = %@", pcert.signature);
8.202 + CAssertEqual(pcert.signatureAlgorithmID, [MYParsedCertificate RSAWithSHA1AlgorithmID]);
8.203 + CAssert(pcert.signature != nil);
8.204 + Log(@"Subject Public Key = %@", pcert.subjectPublicKey);
8.205 + CAssert(pcert.subjectPublicKey);
8.206 + if (selfSigned) {
8.207 + Log(@"Issuer Public Key = %@", pcert.issuerPublicKey);
8.208 + CAssert(pcert.issuerPublicKey);
8.209 +
8.210 + CAssert(pcert.validateSignature);
8.211 + }
8.212 + }
8.213 +}
8.214 +
8.215 +
8.216 +
8.217 +/* Parsed form of selfsigned.cer:
8.218 +
8.219 +Sequence: <-- top
8.220 + Sequence: <-- info
8.221 + MYASN1Object[2/0]: <-- version (int, constructed)
8.222 + 2
8.223 + 1 <-- serial number
8.224 + Sequence:
8.225 + {1 2 840 113549 1 1 1} <-- algorithm ID
8.226 + Sequence: <-- issuer
8.227 + Set:
8.228 + Sequence:
8.229 + {2 5 4 4}
8.230 + Widdershins
8.231 + Set:
8.232 + Sequence:
8.233 + {1 2 840 113549 1 9 1}
8.234 + waldo@example.com
8.235 + Set:
8.236 + Sequence:
8.237 + {2 5 4 3}
8.238 + waldo
8.239 + Set:
8.240 + Sequence:
8.241 + {2 5 4 42}
8.242 + Waldo
8.243 + Set:
8.244 + Sequence:
8.245 + {2 5 4 13}
8.246 + Just a fictitious person
8.247 + Sequence: <--validity
8.248 + 2009-04-12 21:54:35 -0700
8.249 + 2010-04-13 21:54:35 -0700
8.250 + Sequence: <-- subject
8.251 + Set:
8.252 + Sequence:
8.253 + {2 5 4 4}
8.254 + Widdershins
8.255 + Set:
8.256 + Sequence:
8.257 + {1 2 840 113549 1 9 1}
8.258 + waldo@example.com
8.259 + Set:
8.260 + Sequence:
8.261 + {2 5 4 3}
8.262 + waldo
8.263 + Set:
8.264 + Sequence:
8.265 + {2 5 4 42}
8.266 + Waldo
8.267 + Set:
8.268 + Sequence:
8.269 + {2 5 4 13}
8.270 + Just a fictitious person
8.271 + Sequence: <-- public key info
8.272 + Sequence:
8.273 + {1 2 840 113549 1 1 1} <-- algorithm ID (RSA)
8.274 + <null>
8.275 + MYBitString<3082010a 02820101 0095713c 360badf2 d8575ebd 278fa26b a2e6d05e 1eb04eaa 9fa6f11b fd341556 038b3077 525c7adb f5aedf3b 249b08e6 7f77af26 7ff2feb8 5f4ccb96 5269dbd2 f01f19b6 55fc4ea3 a85f2ede 11ff80f8 fc23e662 f263f685 06a9ec07 f7ee4249 af184f21 2d9253d8 7f6f7cbc 96e6ba5c abc8f4e7 3bf6100b 06dcf3ee 999d4170 f5dd005d a24a54a1 3edaddd5 0675409d 6728a387 5fa71898 ebf7d93d 4af8742d f9a0e9ad 6dc21cfa fc2d1967 e692575b 56e5376c 8cf008e8 a442d787 6843a92e 9501b144 8a75adef 5e804fec 6d09740d 1ea8442e 67fac3be c5ea3af5 d95d9f95 2c507711 01c45942 28ad1410 23525324 62848476 d987d3c7 d65f9057 daf1e853 77020301 0001> <-- DER-encoded key
8.276 + MYASN1Object[2/3]:
8.277 + Sequence:
8.278 + Sequence:
8.279 + {2 5 29 15}
8.280 + <030202fc>
8.281 + Sequence:
8.282 + {2 5 29 37}
8.283 + <301a0608 2b060105 05070301 06082b06 01050507 03020604 551d2500>
8.284 + Sequence:
8.285 + {1 2 840 113549 1 1 5}
8.286 + <null>
8.287 + MYBitString<79c8e789 50a11fcb 7398f5fe 0cfa2595 b2476f53 62dfbea2 70ae3a8b fdaf5a57 39be6101 fc5e0929 e57a0b2b 41e3ab52 f78ef1b5 ecc8848c da7f42aa b57c3df4 df4125a9 db4e6388 197c2a1c e326c1a5 5203b4ef da057b91 4abc43aa 3eeee6aa fe4303c3 0f000175 16b916b5 72f8b74f c682a06f 920e3bbf a16cdad8 fce3f184 adccc61e 8d3b44e5 8bd103f0 46310f6a 992f240a b290354c 04c519c9 22276df6 310ccb8e 942e38f6 555ca40b 71482e52 146a9988 f021c2c0 2d285db5 59d48eaf 7b20559f 068ea1a0 f07fbaee 29284ada 28bf8344 f435f30f 6263f0c9 9c4920ce a1b7c6c0 9cfa3bbb af5a0fee 5b0e94eb 9c57d28b 1bb9c977 be53e4bb b675ffaa>
8.288 +*/
8.289 \ No newline at end of file
9.1 --- a/MYPrivateKey.m Tue Jun 02 13:16:28 2009 -0700
9.2 +++ b/MYPrivateKey.m Wed Jun 03 17:20:53 2009 -0700
9.3 @@ -236,7 +236,7 @@
9.4 return [NSData dataWithBytes: sigBuf length: sigLen];
9.5 #else
9.6 NSData *signature = nil;
9.7 - CSSM_CC_HANDLE ccHandle = [self _createSignatureContext: CSSM_ALGID_SHA256WithRSA];
9.8 + CSSM_CC_HANDLE ccHandle = [self _createSignatureContext: CSSM_ALGID_SHA1WithRSA];
9.9 if (!ccHandle) return nil;
9.10 CSSM_DATA original = {data.length, (void*)data.bytes};
9.11 CSSM_DATA result = {0,NULL};
10.1 --- a/MYPublicKey.m Tue Jun 02 13:16:28 2009 -0700
10.2 +++ b/MYPublicKey.m Wed Jun 03 17:20:53 2009 -0700
10.3 @@ -70,7 +70,7 @@
10.4 return err==noErr;
10.5
10.6 #else
10.7 - CSSM_CC_HANDLE ccHandle = [self _createSignatureContext: CSSM_ALGID_SHA256WithRSA];
10.8 + CSSM_CC_HANDLE ccHandle = [self _createSignatureContext: CSSM_ALGID_SHA1WithRSA];
10.9 if (!ccHandle) return NO;
10.10 CSSM_DATA original = {data.length, (void*)data.bytes};
10.11 CSSM_DATA sig = {signature.length, (void*)signature.bytes};