MYOID.m
changeset 18 a06e44b9b898
child 21 2c300b15b381
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/MYOID.m	Wed Jun 03 17:22:42 2009 -0700
     1.3 @@ -0,0 +1,152 @@
     1.4 +//
     1.5 +//  MYOID.m
     1.6 +//  MYCrypto
     1.7 +//
     1.8 +//  Created by Jens Alfke on 5/28/09.
     1.9 +//  Copyright 2009 Jens Alfke. All rights reserved.
    1.10 +//
    1.11 +
    1.12 +#import "MYOID.h"
    1.13 +
    1.14 +
    1.15 +@implementation MYOID
    1.16 +
    1.17 +
    1.18 +- (id) initWithComponents: (const UInt32*)components count: (unsigned)count
    1.19 +{
    1.20 +    self = [super init];
    1.21 +    if (self != nil) {
    1.22 +        _data = [[NSData alloc] initWithBytes: components length: count*sizeof(UInt32)];
    1.23 +    }
    1.24 +    return self;
    1.25 +}
    1.26 +
    1.27 +- (id) initWithBEREncoding: (NSData*)encoding
    1.28 +{
    1.29 +    self = [super init];
    1.30 +    if (self != nil) {
    1.31 +        size_t len = encoding.length;
    1.32 +        const UInt8 *src = encoding.bytes;
    1.33 +        const UInt8 *end = src+len;
    1.34 +        NSMutableData *data = [NSMutableData dataWithLength: (len+1)*sizeof(UInt32)];
    1.35 +        UInt32* dst = data.mutableBytes;
    1.36 +        
    1.37 +        if (len >= 2) {
    1.38 +            *dst++ = *src / 40;
    1.39 +            *dst++ = *src % 40;
    1.40 +            src++; 
    1.41 +        }
    1.42 +        while (src < end) {
    1.43 +            UInt32 component = 0;
    1.44 +            UInt8 byte;
    1.45 +            do{
    1.46 +                if (src >= end) {
    1.47 +                    [self release];
    1.48 +                    return nil;
    1.49 +                }
    1.50 +                byte = *src++;
    1.51 +                component = (component << 7) | (byte & 0x7F);
    1.52 +            }while (byte & 0x80);
    1.53 +            *dst++ = component;
    1.54 +        }
    1.55 +        data.length = (UInt8*)dst - (UInt8*)data.mutableBytes;
    1.56 +        _data = [data copy];
    1.57 +    }
    1.58 +    return self;
    1.59 +}
    1.60 +
    1.61 ++ (MYOID*) OIDWithEncoding: (NSData*)encoding {
    1.62 +    return [[[self alloc] initWithBEREncoding: encoding] autorelease];
    1.63 +}
    1.64 +
    1.65 +
    1.66 +- (id) copyWithZone: (NSZone*)zone {
    1.67 +    return [self retain];
    1.68 +}
    1.69 +
    1.70 +- (void) dealloc
    1.71 +{
    1.72 +    [_data release];
    1.73 +    [super dealloc];
    1.74 +}
    1.75 +
    1.76 +
    1.77 +- (NSString*) description {
    1.78 +    NSMutableString *desc = [NSMutableString stringWithString: @"{"];
    1.79 +    const UInt32* components = self.components;
    1.80 +    unsigned count = self.componentCount;
    1.81 +    for (unsigned i=0; i<count; i++) {
    1.82 +        if (i>0)
    1.83 +            [desc appendString: @" "];
    1.84 +        [desc appendFormat: @"%u", components[i]];
    1.85 +    }
    1.86 +    [desc appendString: @"}"];
    1.87 +    return desc;
    1.88 +}
    1.89 +
    1.90 +
    1.91 +- (NSData*) componentData       {return _data;}
    1.92 +- (const UInt32*) components    {return (const UInt32*)_data.bytes;}
    1.93 +- (unsigned) componentCount     {return _data.length / sizeof(UInt32);}
    1.94 +
    1.95 +- (NSUInteger)hash {
    1.96 +    return _data.hash;
    1.97 +}
    1.98 +
    1.99 +- (BOOL)isEqual:(id)object {
   1.100 +    return [object isKindOfClass: [MYOID class]] && [_data isEqual: [object componentData]];
   1.101 +}
   1.102 +
   1.103 +
   1.104 +- (NSData*) DEREncoding {
   1.105 +    unsigned count = self.componentCount;
   1.106 +    UInt8 encoding[5*count]; // worst-case size
   1.107 +    const UInt32 *src=self.components, *end=src+count;
   1.108 +    UInt8 *dst = encoding;
   1.109 +    if (count >= 2 && src[0]<=3 && src[1]<40) {
   1.110 +        // Weird collapsing of 1st two components into one byte:
   1.111 +        *dst++ = src[0]*40 + src[1];
   1.112 +        src += 2;
   1.113 +    }
   1.114 +    while (src<end) {
   1.115 +        UInt32 component = *src++;
   1.116 +        // Write the component in 7-bit groups, most significant first:
   1.117 +        BOOL any = NO;
   1.118 +        for (int shift=28; shift>=0; shift -= 7) {
   1.119 +            UInt8 byte = (component >> shift) & 0x7F;
   1.120 +            if (byte || any) {
   1.121 +                if (any)
   1.122 +                    dst[-1] |= 0x80;
   1.123 +                *dst++ = byte;
   1.124 +                any = YES;
   1.125 +            }
   1.126 +        }
   1.127 +    }
   1.128 +    return [NSData dataWithBytes: encoding length: dst-encoding];
   1.129 +}
   1.130 +
   1.131 +
   1.132 +@end
   1.133 +
   1.134 +
   1.135 +
   1.136 +#define $data(BYTES...)    ({const uint8_t bytes[] = {BYTES}; [NSData dataWithBytes: bytes length: sizeof(bytes)];})
   1.137 +
   1.138 +#define $components(INTS...)    ({const UInt32 components[] = {INTS}; components;})
   1.139 +
   1.140 +TestCase(OID) {
   1.141 +    CAssertEqual([[MYOID OIDWithEncoding: $data(0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01)] description],
   1.142 +                 @"{1 2 840 113549 1 1 1}");
   1.143 +    CAssertEqual([[MYOID OIDWithEncoding: $data(0x55,0x04,0x04)] description],
   1.144 +                 @"{2 5 4 4}");
   1.145 +    CAssertEqual([[MYOID OIDWithEncoding: $data(0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x09,0x01)] description],
   1.146 +                 @"{1 2 840 113549 1 9 1}");
   1.147 +
   1.148 +    CAssertEqual([[[MYOID alloc] initWithComponents: $components(1,2,840,113549,1,1,1) count: 7] description],
   1.149 +                 @"{1 2 840 113549 1 1 1}");
   1.150 +
   1.151 +    CAssertEqual([[[MYOID alloc] initWithComponents: $components(1,2,840,113549,1,1,1) count: 7] DEREncoding],
   1.152 +                 $data(0x2a, 0x86, 0x48, 0x86,  0xf7, 0x0d, 0x01, 0x01,  0x01));
   1.153 +    CAssertEqual([[[MYOID alloc] initWithComponents: $components(2,5,4,4) count: 4] DEREncoding],
   1.154 +                 $data(0x55,0x04,0x04));
   1.155 +}