1.1 --- a/MYDEREncoder.m Wed Jun 03 17:22:42 2009 -0700
1.2 +++ b/MYDEREncoder.m Thu Jun 04 18:36:30 2009 -0700
1.3 @@ -19,6 +19,7 @@
1.4 @interface MYDEREncoder ()
1.5 - (void) _encode: (id)object;
1.6 @property (retain) NSError *error;
1.7 +@property BOOL _forcePrintableStrings;
1.8 @end
1.9
1.10
1.11 @@ -46,9 +47,15 @@
1.12 {
1.13 [_rootObject release];
1.14 [_output release];
1.15 + [_error release];
1.16 [super dealloc];
1.17 }
1.18
1.19 +- (id) copyWithZone: (NSZone*)zone {
1.20 + MYDEREncoder *copy = [[[self class] alloc] init];
1.21 + copy->_forcePrintableStrings = _forcePrintableStrings;
1.22 + return copy;
1.23 +}
1.24
1.25
1.26 static unsigned sizeOfUnsignedInt (UInt64 n) {
1.27 @@ -185,11 +192,22 @@
1.28
1.29
1.30 - (void) _encodeString: (NSString*)string {
1.31 + static NSMutableCharacterSet *kNotPrintableCharSet;
1.32 + if (!kNotPrintableCharSet) {
1.33 + kNotPrintableCharSet = [[NSMutableCharacterSet characterSetWithCharactersInString: @" '()+,-./:=?"] retain];
1.34 + [kNotPrintableCharSet formUnionWithCharacterSet: [NSCharacterSet alphanumericCharacterSet]];
1.35 + [kNotPrintableCharSet invert];
1.36 + }
1.37 NSData *data = [string dataUsingEncoding: NSASCIIStringEncoding];
1.38 - if (data)
1.39 - [self _writeTag: 19 class: 0 constructed: NO data: data];
1.40 - else
1.41 + if (data) {
1.42 + unsigned tag = 19; // printablestring (a silly arbitrary subset of ASCII defined by ASN.1)
1.43 + if (!_forcePrintableStrings && [string rangeOfCharacterFromSet: kNotPrintableCharSet].length > 0)
1.44 + tag = 20; // IA5string (full 7-bit ASCII)
1.45 + [self _writeTag: tag class: 0 constructed: NO data: data];
1.46 + } else {
1.47 + // fall back to UTF-8:
1.48 [self _writeTag: 12 class: 0 constructed: NO data: [string dataUsingEncoding: NSUTF8StringEncoding]];
1.49 + }
1.50 }
1.51
1.52
1.53 @@ -209,7 +227,7 @@
1.54
1.55
1.56 - (void) _encodeCollection: (id)collection tag: (unsigned)tag class: (unsigned)tagClass {
1.57 - MYDEREncoder *subEncoder = [[[self class] alloc] init];
1.58 + MYDEREncoder *subEncoder = [self copy];
1.59 for (id object in collection)
1.60 [subEncoder _encode: object];
1.61 [self _writeTag: tag class: tagClass constructed: YES data: subEncoder.output];
1.62 @@ -268,7 +286,7 @@
1.63 return _output;
1.64 }
1.65
1.66 -@synthesize error=_error;
1.67 +@synthesize error=_error, _forcePrintableStrings;
1.68
1.69
1.70 @end
1.71 @@ -342,11 +360,13 @@
1.72 id certObjects = MYBERParse(cert,&error);
1.73 CAssertNil(error);
1.74 Log(@"Decoded as:\n%@", [MYASN1Object dump: certObjects]);
1.75 - NSData *encoded = [MYDEREncoder encodeRootObject: certObjects error: &error];
1.76 + MYDEREncoder *encoder = [[MYDEREncoder alloc] initWithRootObject: certObjects];
1.77 + encoder._forcePrintableStrings = YES; // hack for compatibility with the way CDSA writes ASN.1
1.78 + NSData *encoded = encoder.output;
1.79 CAssertNil(error);
1.80 id reDecoded = MYBERParse(encoded, &error);
1.81 CAssertNil(error);
1.82 Log(@"Re-decoded as:\n%@", [MYASN1Object dump: reDecoded]);
1.83 - [encoded writeToFile: @"../../Tests/iphonedev_reencoded.cer" atomically: YES];
1.84 + [encoded writeToFile: @"../../Tests/selfsigned_reencoded.cer" atomically: YES];
1.85 CAssertEqual(encoded,cert);
1.86 }