jens@16
|
1 |
//
|
jens@16
|
2 |
// MYOID.m
|
jens@16
|
3 |
// MYCrypto
|
jens@16
|
4 |
//
|
jens@16
|
5 |
// Created by Jens Alfke on 5/28/09.
|
jens@16
|
6 |
// Copyright 2009 Jens Alfke. All rights reserved.
|
jens@16
|
7 |
//
|
jens@16
|
8 |
|
jens@16
|
9 |
#import "MYOID.h"
|
jens@16
|
10 |
|
jens@16
|
11 |
|
jens@16
|
12 |
@implementation MYOID
|
jens@16
|
13 |
|
jens@16
|
14 |
|
jens@16
|
15 |
- (id) initWithComponents: (const UInt32*)components count: (unsigned)count
|
jens@16
|
16 |
{
|
jens@16
|
17 |
self = [super init];
|
jens@16
|
18 |
if (self != nil) {
|
jens@16
|
19 |
_data = [[NSData alloc] initWithBytes: components length: count*sizeof(UInt32)];
|
jens@16
|
20 |
}
|
jens@16
|
21 |
return self;
|
jens@16
|
22 |
}
|
jens@16
|
23 |
|
jens@16
|
24 |
- (id) initWithBEREncoding: (NSData*)encoding
|
jens@16
|
25 |
{
|
jens@16
|
26 |
self = [super init];
|
jens@16
|
27 |
if (self != nil) {
|
jens@16
|
28 |
size_t len = encoding.length;
|
jens@16
|
29 |
const UInt8 *src = encoding.bytes;
|
jens@16
|
30 |
const UInt8 *end = src+len;
|
jens@16
|
31 |
NSMutableData *data = [NSMutableData dataWithLength: (len+1)*sizeof(UInt32)];
|
jens@16
|
32 |
UInt32* dst = data.mutableBytes;
|
jens@16
|
33 |
|
jens@16
|
34 |
if (len >= 2) {
|
jens@16
|
35 |
*dst++ = *src / 40;
|
jens@16
|
36 |
*dst++ = *src % 40;
|
jens@16
|
37 |
src++;
|
jens@16
|
38 |
}
|
jens@16
|
39 |
while (src < end) {
|
jens@16
|
40 |
UInt32 component = 0;
|
jens@16
|
41 |
UInt8 byte;
|
jens@16
|
42 |
do{
|
jens@16
|
43 |
if (src >= end) {
|
jens@16
|
44 |
[self release];
|
jens@16
|
45 |
return nil;
|
jens@16
|
46 |
}
|
jens@16
|
47 |
byte = *src++;
|
jens@16
|
48 |
component = (component << 7) | (byte & 0x7F);
|
jens@16
|
49 |
}while (byte & 0x80);
|
jens@16
|
50 |
*dst++ = component;
|
jens@16
|
51 |
}
|
jens@16
|
52 |
data.length = (UInt8*)dst - (UInt8*)data.mutableBytes;
|
jens@16
|
53 |
_data = [data copy];
|
jens@16
|
54 |
}
|
jens@16
|
55 |
return self;
|
jens@16
|
56 |
}
|
jens@16
|
57 |
|
jens@16
|
58 |
+ (MYOID*) OIDWithEncoding: (NSData*)encoding {
|
jens@16
|
59 |
return [[[self alloc] initWithBEREncoding: encoding] autorelease];
|
jens@16
|
60 |
}
|
jens@16
|
61 |
|
jens@16
|
62 |
|
jens@16
|
63 |
- (id) copyWithZone: (NSZone*)zone {
|
jens@16
|
64 |
return [self retain];
|
jens@16
|
65 |
}
|
jens@16
|
66 |
|
jens@16
|
67 |
- (void) dealloc
|
jens@16
|
68 |
{
|
jens@16
|
69 |
[_data release];
|
jens@16
|
70 |
[super dealloc];
|
jens@16
|
71 |
}
|
jens@16
|
72 |
|
jens@16
|
73 |
|
jens@16
|
74 |
- (NSString*) description {
|
jens@16
|
75 |
NSMutableString *desc = [NSMutableString stringWithString: @"{"];
|
jens@16
|
76 |
const UInt32* components = self.components;
|
jens@16
|
77 |
unsigned count = self.componentCount;
|
jens@16
|
78 |
for (unsigned i=0; i<count; i++) {
|
jens@16
|
79 |
if (i>0)
|
jens@16
|
80 |
[desc appendString: @" "];
|
jens@16
|
81 |
[desc appendFormat: @"%u", components[i]];
|
jens@16
|
82 |
}
|
jens@16
|
83 |
[desc appendString: @"}"];
|
jens@16
|
84 |
return desc;
|
jens@16
|
85 |
}
|
jens@16
|
86 |
|
jens@16
|
87 |
|
jens@16
|
88 |
- (NSData*) componentData {return _data;}
|
jens@16
|
89 |
- (const UInt32*) components {return (const UInt32*)_data.bytes;}
|
jens@16
|
90 |
- (unsigned) componentCount {return _data.length / sizeof(UInt32);}
|
jens@16
|
91 |
|
jens@16
|
92 |
- (NSUInteger)hash {
|
jens@16
|
93 |
return _data.hash;
|
jens@16
|
94 |
}
|
jens@16
|
95 |
|
jens@16
|
96 |
- (BOOL)isEqual:(id)object {
|
jens@16
|
97 |
return [object isKindOfClass: [MYOID class]] && [_data isEqual: [object componentData]];
|
jens@16
|
98 |
}
|
jens@16
|
99 |
|
jens@16
|
100 |
|
jens@16
|
101 |
- (NSData*) DEREncoding {
|
jens@16
|
102 |
unsigned count = self.componentCount;
|
jens@16
|
103 |
UInt8 encoding[5*count]; // worst-case size
|
jens@16
|
104 |
const UInt32 *src=self.components, *end=src+count;
|
jens@16
|
105 |
UInt8 *dst = encoding;
|
jens@16
|
106 |
if (count >= 2 && src[0]<=3 && src[1]<40) {
|
jens@16
|
107 |
// Weird collapsing of 1st two components into one byte:
|
jens@16
|
108 |
*dst++ = src[0]*40 + src[1];
|
jens@16
|
109 |
src += 2;
|
jens@16
|
110 |
}
|
jens@16
|
111 |
while (src<end) {
|
jens@16
|
112 |
UInt32 component = *src++;
|
jens@16
|
113 |
// Write the component in 7-bit groups, most significant first:
|
jens@16
|
114 |
BOOL any = NO;
|
jens@16
|
115 |
for (int shift=28; shift>=0; shift -= 7) {
|
jens@16
|
116 |
UInt8 byte = (component >> shift) & 0x7F;
|
jens@16
|
117 |
if (byte || any) {
|
jens@16
|
118 |
if (any)
|
jens@16
|
119 |
dst[-1] |= 0x80;
|
jens@16
|
120 |
*dst++ = byte;
|
jens@16
|
121 |
any = YES;
|
jens@16
|
122 |
}
|
jens@16
|
123 |
}
|
jens@16
|
124 |
}
|
jens@16
|
125 |
return [NSData dataWithBytes: encoding length: dst-encoding];
|
jens@16
|
126 |
}
|
jens@16
|
127 |
|
jens@16
|
128 |
|
jens@16
|
129 |
@end
|
jens@16
|
130 |
|
jens@16
|
131 |
|
jens@16
|
132 |
|
jens@16
|
133 |
#define $data(BYTES...) ({const uint8_t bytes[] = {BYTES}; [NSData dataWithBytes: bytes length: sizeof(bytes)];})
|
jens@16
|
134 |
|
jens@16
|
135 |
#define $components(INTS...) ({const UInt32 components[] = {INTS}; components;})
|
jens@16
|
136 |
|
jens@16
|
137 |
TestCase(OID) {
|
jens@16
|
138 |
CAssertEqual([[MYOID OIDWithEncoding: $data(0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01)] description],
|
jens@16
|
139 |
@"{1 2 840 113549 1 1 1}");
|
jens@16
|
140 |
CAssertEqual([[MYOID OIDWithEncoding: $data(0x55,0x04,0x04)] description],
|
jens@16
|
141 |
@"{2 5 4 4}");
|
jens@16
|
142 |
CAssertEqual([[MYOID OIDWithEncoding: $data(0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x09,0x01)] description],
|
jens@16
|
143 |
@"{1 2 840 113549 1 9 1}");
|
jens@16
|
144 |
|
jens@16
|
145 |
CAssertEqual([[[MYOID alloc] initWithComponents: $components(1,2,840,113549,1,1,1) count: 7] description],
|
jens@16
|
146 |
@"{1 2 840 113549 1 1 1}");
|
jens@16
|
147 |
|
jens@16
|
148 |
CAssertEqual([[[MYOID alloc] initWithComponents: $components(1,2,840,113549,1,1,1) count: 7] DEREncoding],
|
jens@16
|
149 |
$data(0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01));
|
jens@16
|
150 |
CAssertEqual([[[MYOID alloc] initWithComponents: $components(2,5,4,4) count: 4] DEREncoding],
|
jens@16
|
151 |
$data(0x55,0x04,0x04));
|
jens@16
|
152 |
}
|