├── .gitignore ├── BasicEncodingRules.h ├── BasicEncodingRules.m ├── NSData+Base64.h ├── NSData+Base64.m ├── README.md ├── SCZ-BasicEncodingRules-iOS.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata └── Unit Tests ├── Unit Tests-Info.plist ├── Unit Tests-Prefix.pch ├── Unit_Tests.h ├── Unit_Tests.m └── en.lproj └── InfoPlist.strings /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | build/* 3 | *.pbxuser 4 | !default.pbxuser 5 | *.mode1v3 6 | !default.mode1v3 7 | *.mode2v3 8 | !default.mode2v3 9 | *.perspectivev3 10 | !default.perspectivev3 11 | *.xcworkspace 12 | !default.xcworkspace 13 | xcuserdata 14 | profile 15 | *.moved-aside 16 | 17 | *UserInterfaceState.xcuserstate 18 | -------------------------------------------------------------------------------- /BasicEncodingRules.h: -------------------------------------------------------------------------------- 1 | // 2 | // BasicEncodingRules.h 3 | // 4 | // Created by Peter Suk on 5/16/12. 5 | // Copyright (c) Ooghamist LLC 2012. All rights reserved. 6 | // 7 | // Distributed under the permissive zlib License 8 | // Get the latest version from here: 9 | // 10 | // https://github.com/StCredZero/SCZ-BasicEncodingRules-iOS 11 | // 12 | // This software is provided 'as-is', without any express or implied 13 | // warranty. In no event will the authors be held liable for any damages 14 | // arising from the use of this software. 15 | // 16 | // Permission is granted to anyone to use this software for any purpose, 17 | // including commercial applications, and to alter it and redistribute it 18 | // freely, subject to the following restrictions: 19 | // 20 | // 1. The origin of this software must not be misrepresented; you must not 21 | // claim that you wrote the original software. If you use this software 22 | // in a product, an acknowledgment in the product documentation would be 23 | // appreciated but is not required. 24 | // 25 | // 2. Altered source versions must be plainly marked as such, and must not be 26 | // misrepresented as being the original software. 27 | // 28 | // 3. This notice may not be removed or altered from any source distribution. 29 | // 30 | 31 | #import 32 | #include 33 | 34 | // Bits 7 and 8 35 | // 8 7 6 5 4 3 2 1 36 | // --------------- 37 | // X X 0 0 0 0 0 0 38 | 39 | #define kBerClassUniversal 0x00 40 | #define kBerClassApplication 0x40 41 | #define kBerClassContextSpecific 0x80 42 | #define kBerClassPrivate 0xC0 43 | 44 | // Bit 6 is primitive or constructed 45 | // 8 7 6 5 4 3 2 1 46 | // --------------- 47 | // 0 0 1 0 0 0 0 0 48 | 49 | #define kBerTypeConstructed 0x20 50 | 51 | // Bits 1 through 5 52 | // 8 7 6 5 4 3 2 1 53 | // --------------- 54 | // 0 0 0 X X X X X 55 | 56 | #define BER_EOC 0x00 57 | #define BER_BOOLEAN 0x01 58 | #define BER_INTEGER 0x02 59 | #define BER_BIT_STRING 0x03 60 | #define BER_OCTET_STRING 0x04 61 | #define BER_NULL 0x05 62 | #define BER_OBJECT_IDENTIFIER 0x06 63 | #define BER_OBJECT_DESCRIPTOR 0x07 64 | #define BER_EXTERNAL 0x08 65 | #define BER_REAL 0x09 66 | #define BER_ENUMERATED 0x0A 67 | #define BER_EMBEDDED_PDV 0x0B 68 | #define BER_UTF8STRING 0x0C 69 | #define BER_RELATIVE_OID 0x0D 70 | #define BER_RESERVED0X0E 0x0E 71 | #define BER_RESERVED0X0F 0x0F 72 | #define BER_SEQUENCE 0x10 73 | #define BER_SET 0x11 74 | #define BER_NUMERICSTRING 0x12 75 | #define BER_PRINTABLESTRING 0x13 76 | #define BER_T61STRING 0x14 77 | #define BER_VIDEOTEXSTRING 0x15 78 | #define BER_IA5STRING 0x16 79 | #define BER_UTCTIME 0x17 80 | #define BER_GENERALIZEDTIME 0x18 81 | #define BER_GRAPHICSTRING 0x19 82 | #define BER_VISIBLESTRING 0x1A 83 | #define BER_GENERALSTRING 0x1B 84 | #define BER_UNIVERSALSTRING 0x1C 85 | #define BER_CHARACTER_STRING 0x1D 86 | #define BER_BMPSTRING 0x1E 87 | #define BER_USE_LONG_FORM 0x1F 88 | 89 | #define BER_A0 (kBerClassContextSpecific | kBerTypeConstructed) 90 | #define BER_SEQUENCE_CONSTRUCTED (BER_SEQUENCE | kBerTypeConstructed) 91 | #define BER_SET_CONSTRUCTED (BER_SET | kBerTypeConstructed) 92 | 93 | @interface BERVisitor : NSObject 94 | - (id)visitBERLeafNode:(id)leaf; 95 | - (id)visitBERInteriorNode:(id)node; 96 | @end 97 | 98 | @interface BERPrintVisitor : BERVisitor 99 | { 100 | NSUInteger indentLevel; 101 | BOOL isIndenting; 102 | NSMutableString * string; 103 | } 104 | @property (nonatomic, assign) NSUInteger indentLevel; 105 | @property (nonatomic, assign) BOOL isIndenting; 106 | @property (nonatomic, strong) NSMutableString * string; 107 | @end 108 | 109 | @interface NSObject (BasicEncodingRules) 110 | 111 | - (NSData*)berData; 112 | - (uint8_t*)berTag; 113 | - (NSData*)berHeader; 114 | - (NSUInteger)berLengthBytes; 115 | - (NSUInteger)berContentsLengthBytes; 116 | - (NSData*)berContents; 117 | 118 | - (id)berDecode; 119 | - (id)berParse; 120 | 121 | //Utility Methods 122 | - (void)raiseUnimplemented; 123 | - (NSData*)zeroByteData; 124 | 125 | - (NSString*)berTagDescription; 126 | - (NSString*)berContentsDescription; 127 | 128 | - (void)acceptBERVisitor:(BERVisitor*)visitor; 129 | @end 130 | 131 | @interface NSString (BasicEncodingRules) 132 | - (NSData*)berDataUsingEncoding:(NSStringEncoding)encoding; 133 | - (NSUInteger)berContentsLengthBytesUsingEncoding:(NSStringEncoding)encoding; 134 | @end 135 | 136 | @interface NSData (BasicEncodingRules) 137 | @end 138 | 139 | @interface NSArray (BasicEncodingRules) 140 | @end 141 | 142 | @interface NSNull (BasicEncodingRules) 143 | @end 144 | 145 | @interface BerTaggedObject : NSObject { 146 | uint8_t berTag[1]; 147 | id obj; 148 | NSUInteger start; 149 | NSUInteger end; 150 | } 151 | @property (nonatomic, assign) uint8_t berTagValue; 152 | @property (nonatomic, strong) id obj; 153 | @property (nonatomic, assign) NSUInteger start; 154 | @property (nonatomic, assign) NSUInteger end; 155 | - (void)beMutable; 156 | - (id)unwrapped; 157 | - (NSString*)descriptionFormat; 158 | @end 159 | 160 | @interface BerTaggedCollection : BerTaggedObject {} 161 | @property (nonatomic, strong) NSMutableArray *collection; 162 | - (void)addObject:(id)anObject; 163 | -(id)objectAtIndex:(NSUInteger)index; 164 | @end 165 | 166 | @interface BerTaggedData : BerTaggedObject {} 167 | @property (nonatomic, strong) NSData *data; 168 | @end 169 | 170 | @interface BerTaggedString : BerTaggedObject {} 171 | @property (nonatomic, strong) NSString *string; 172 | @end 173 | 174 | -------------------------------------------------------------------------------- /BasicEncodingRules.m: -------------------------------------------------------------------------------- 1 | // 2 | // BasicEncodingRules.m 3 | // 4 | // Created by Peter Kwangjun Suk on 5/16/12. 5 | // Copyright (c) Ooghamist LLC 2012. All rights reserved. 6 | // 7 | // Distributed under the permissive zlib License 8 | // Get the latest version from here: 9 | // 10 | // https://github.com/StCredZero/SCZ-BasicEncodingRules-iOS 11 | // 12 | // This software is provided 'as-is', without any express or implied 13 | // warranty. In no event will the authors be held liable for any damages 14 | // arising from the use of this software. 15 | // 16 | // Permission is granted to anyone to use this software for any purpose, 17 | // including commercial applications, and to alter it and redistribute it 18 | // freely, subject to the following restrictions: 19 | // 20 | // 1. The origin of this software must not be misrepresented; you must not 21 | // claim that you wrote the original software. If you use this software 22 | // in a product, an acknowledgment in the product documentation would be 23 | // appreciated but is not required. 24 | // 25 | // 2. Altered source versions must be plainly marked as such, and must not be 26 | // misrepresented as being the original software. 27 | // 28 | // 3. This notice may not be removed or altered from any source distribution. 29 | // 30 | 31 | #import "BasicEncodingRules.h" 32 | 33 | @implementation BERVisitor : NSObject 34 | - (id)visitBERLeafNode:(id)leaf 35 | { 36 | [self raiseUnimplemented]; 37 | return nil; 38 | } 39 | - (id)visitBERInteriorNode:(id)node 40 | { 41 | [self raiseUnimplemented]; 42 | return nil; 43 | } 44 | @end 45 | 46 | 47 | @implementation BERPrintVisitor : BERVisitor 48 | @synthesize indentLevel; 49 | @synthesize isIndenting; 50 | @synthesize string; 51 | - (id) init 52 | { 53 | if (self = [super init]) 54 | { 55 | self.indentLevel = 0; 56 | self.isIndenting = YES; 57 | self.string = [[NSMutableString alloc] init]; 58 | } 59 | return self; 60 | } 61 | - (id)visitBERLeafNode:(id)leaf 62 | { 63 | NSString *tempString = [leaf berContentsDescription]; 64 | 65 | [self berIndent]; 66 | [self.string appendFormat:@"%@ ", [leaf berTagDescription]]; 67 | if([tempString length] > 80) 68 | { 69 | [self.string appendFormat:@"\n"]; 70 | [self increaseIndent]; 71 | [self berIndent]; 72 | } 73 | for (NSUInteger i = 0; i < [tempString length]; i++) 74 | { 75 | [self.string appendFormat:@"%c", [tempString characterAtIndex:i]]; 76 | if ((i > 0) && (i % 80 == 0)) 77 | { 78 | [self.string appendFormat:@"\n"]; 79 | [self berIndent]; 80 | } 81 | } 82 | if([tempString length] > 80) 83 | { 84 | [self decreaseIndent]; 85 | } 86 | 87 | return nil; 88 | } 89 | - (id)visitBERInteriorNode:(id)node 90 | { 91 | NSString *initialDelimiter = @"\n"; 92 | NSString *middleDelimiter = @"\n"; 93 | BOOL indentDelimiter = YES; 94 | BOOL indentState = self.isIndenting; 95 | if ([node berContentsLengthBytes] <= 20) 96 | { 97 | initialDelimiter = @""; 98 | middleDelimiter = @", "; 99 | indentDelimiter = NO; 100 | } 101 | [self berIndent]; 102 | if ( ! indentDelimiter) self.isIndenting = NO; 103 | 104 | [self.string appendFormat:@"%@ ( %@", 105 | [node berTagDescription], 106 | initialDelimiter]; 107 | [self increaseIndent]; 108 | NSUInteger count = [[node collection] count]; 109 | for (NSUInteger i = 0; i < count; i++) 110 | { 111 | id childNode = [[node collection] objectAtIndex:i]; 112 | [childNode acceptBERVisitor:self]; 113 | if (i < count - 1) [self.string appendFormat:middleDelimiter]; 114 | } 115 | [self decreaseIndent]; 116 | [self.string appendFormat:@" )"]; 117 | self.isIndenting = indentState; 118 | 119 | return nil; 120 | } 121 | - (void)berIndent 122 | { 123 | if (self.isIndenting) 124 | { 125 | for (NSUInteger i = 0; i < self.indentLevel; i++) 126 | { 127 | [self.string appendFormat:@"%@", @" "]; 128 | } 129 | } 130 | } 131 | - (void)increaseIndent 132 | { 133 | self.indentLevel = self.indentLevel + 1; 134 | } 135 | - (void)decreaseIndent 136 | { 137 | self.indentLevel = self.indentLevel - 1; 138 | 139 | } 140 | @end 141 | 142 | 143 | 144 | @implementation NSObject (BasicEncodingRules) 145 | 146 | #pragma mark - NSObject Encoding 147 | 148 | - (NSData*)berData 149 | { 150 | NSMutableData *berData = [[NSMutableData alloc] init]; 151 | [berData appendData:[self berHeader]]; 152 | [berData appendData:[self berContents]]; 153 | return berData; 154 | } 155 | 156 | - (uint8_t*)berTag { 157 | [self raiseUnimplemented]; 158 | return nil; 159 | } 160 | 161 | - (NSData*)berHeader 162 | { 163 | NSMutableData *berHeader = [[NSMutableData alloc] init]; 164 | [berHeader appendBytes:[self berTag] length:1]; 165 | [berHeader appendData:[self lengthStorageData]]; 166 | return berHeader; 167 | } 168 | 169 | - (NSData*)berContents { 170 | [self raiseUnimplemented]; 171 | return nil; 172 | } 173 | 174 | - (NSUInteger)berLengthBytes 175 | { 176 | NSUInteger berContentsLengthBytes = [self berContentsLengthBytes]; 177 | if (berContentsLengthBytes <= 0x7F) { 178 | return 2 + berContentsLengthBytes; 179 | } 180 | return 2 + [self lengthBytesLog8] + berContentsLengthBytes; 181 | } 182 | 183 | - (NSUInteger)berContentsLengthBytes 184 | { 185 | [self raiseUnimplemented]; 186 | return 0; 187 | } 188 | 189 | - (NSUInteger)lengthBytesLog8 190 | { 191 | NSUInteger lengthBytes = 0; 192 | NSUInteger myLength = [self berContentsLengthBytes]; 193 | for (NSUInteger tempLength = myLength; tempLength > 0; lengthBytes++) { 194 | tempLength >>= 8; 195 | } 196 | return lengthBytes; 197 | } 198 | 199 | - (NSData*)lengthStorageData 200 | { 201 | NSMutableData *lengthStorageData = [[NSMutableData alloc] init]; 202 | uint8_t lengthBytesTag[1]; 203 | NSUInteger contentsLength = [self berContentsLengthBytes]; 204 | if (contentsLength > 0x7F) { 205 | NSUInteger lengthStorageBytes = [self lengthBytesLog8]; 206 | if (lengthStorageBytes > sizeof(NSUInteger)) 207 | [NSException 208 | raise:@"Invalid length value" 209 | format:@"length storage greater than %d bytes is invalid", lengthStorageBytes]; 210 | lengthBytesTag[0] = 0x80 + lengthStorageBytes; 211 | [lengthStorageData appendBytes:lengthBytesTag length:1]; 212 | uint8_t temp[sizeof(NSUInteger)]; 213 | NSInteger bitOffset; 214 | for (NSInteger i = 0; i < lengthStorageBytes; i++) { 215 | bitOffset = (lengthStorageBytes - i - 1)*8; 216 | temp[i] = (contentsLength & (0xFF << bitOffset)) >> bitOffset; 217 | } 218 | [lengthStorageData appendBytes:temp length:lengthStorageBytes]; 219 | } 220 | else { 221 | lengthBytesTag[0] = contentsLength; 222 | [lengthStorageData appendBytes:lengthBytesTag length:1]; 223 | } 224 | return lengthStorageData; 225 | } 226 | 227 | #pragma mark - NSObject Decoding 228 | 229 | - (id)berDecode { 230 | [self raiseUnimplemented]; 231 | return nil; 232 | } 233 | 234 | - (id)berParse { 235 | [self raiseUnimplemented]; 236 | return nil; 237 | } 238 | 239 | #pragma mark - BERVisitor 240 | 241 | - (void)acceptBERVisitor:(BERVisitor*)visitor 242 | { 243 | [visitor visitBERLeafNode:(id)self]; 244 | } 245 | 246 | #pragma mark - NSObject Printing 247 | 248 | - (NSString*)berContentsDescription 249 | { 250 | return [NSString string]; 251 | } 252 | 253 | #pragma mark - NSObject Utility 254 | 255 | - (NSData*)zeroByteData 256 | { 257 | static uint8_t zero[] = { 0x00 }; 258 | NSMutableData *zeroByteData = [[NSMutableData alloc] init]; 259 | [zeroByteData appendBytes:zero length:1]; 260 | return zeroByteData; 261 | } 262 | 263 | - (void)raiseUnimplemented { 264 | [NSException 265 | raise:@"Invalid BER translation" 266 | format:@"unimplemented for this type"]; 267 | } 268 | 269 | - (NSString*)berTagDescription 270 | { 271 | uint8_t *tagBytes = [self berTag]; 272 | NSString *desc; 273 | switch (tagBytes[0]) { 274 | case BER_A0: 275 | desc = @"A0"; 276 | break; 277 | case BER_EOC: 278 | desc = @"EOC"; 279 | break; 280 | case BER_BOOLEAN: 281 | desc = @"BOOL"; 282 | break; 283 | case BER_INTEGER: 284 | desc = @"INTEGER"; 285 | break; 286 | case BER_BIT_STRING: 287 | desc = @"BIT_STR"; 288 | break; 289 | case BER_OCTET_STRING: 290 | desc = @"OCTET_STR"; 291 | break; 292 | case BER_NULL: 293 | desc = @"NULL"; 294 | break; 295 | case BER_OBJECT_IDENTIFIER: 296 | desc = @"OID"; 297 | break; 298 | case BER_OBJECT_DESCRIPTOR: 299 | desc = @"OBJ_DESC"; 300 | break; 301 | case BER_EXTERNAL: 302 | desc = @"EXTERNAL"; 303 | break; 304 | case BER_REAL: 305 | desc = @"REAL"; 306 | break; 307 | case BER_ENUMERATED: 308 | desc = @"ENUM"; 309 | break; 310 | case BER_EMBEDDED_PDV: 311 | desc = @"EMBED_PDV"; 312 | break; 313 | case BER_UTF8STRING: 314 | desc = @"UTF8_STR"; 315 | break; 316 | case BER_RELATIVE_OID: 317 | desc = @"RELATIVE_OID"; 318 | break; 319 | case BER_RESERVED0X0E: 320 | desc = @"RESERVED0x0E"; 321 | break; 322 | case BER_RESERVED0X0F: 323 | desc = @"RESERVED0x0F"; 324 | break; 325 | case BER_SEQUENCE: 326 | desc = @"SEQ"; 327 | break; 328 | case BER_SET: 329 | desc = @"SET"; 330 | break; 331 | case BER_NUMERICSTRING: 332 | desc = @"NUM_STR"; 333 | break; 334 | case BER_PRINTABLESTRING: 335 | desc = @"PRINTABLE_STR"; 336 | break; 337 | case BER_T61STRING: 338 | desc = @"T61_STR"; 339 | break; 340 | case BER_VIDEOTEXSTRING: 341 | desc = @"VIDTEX_STR"; 342 | break; 343 | case BER_IA5STRING: 344 | desc = @"IA5_STR"; 345 | break; 346 | case BER_UTCTIME: 347 | desc = @"UTCTIME"; 348 | break; 349 | case BER_GENERALIZEDTIME: 350 | desc = @"GEN_TIME"; 351 | break; 352 | case BER_GRAPHICSTRING: 353 | desc = @"GRAPHIC_STR"; 354 | break; 355 | case BER_VISIBLESTRING: 356 | desc = @"VIS_STR"; 357 | break; 358 | case BER_GENERALSTRING: 359 | desc = @"GEN_STR"; 360 | break; 361 | case BER_UNIVERSALSTRING: 362 | desc = @"UNIV_STR"; 363 | break; 364 | case BER_CHARACTER_STRING: 365 | desc = @"CHAR_STR"; 366 | break; 367 | case BER_BMPSTRING: 368 | desc = @"BMP_STR"; 369 | break; 370 | case BER_USE_LONG_FORM: 371 | desc = @"USE_LONG_FORM"; 372 | break; 373 | case BER_SEQUENCE_CONSTRUCTED: 374 | desc = @"SEQ_CONSTR"; 375 | break; 376 | case BER_SET_CONSTRUCTED: 377 | desc = @"SET_CONSTR"; 378 | break; 379 | default: 380 | desc = @"UNKNOWN"; 381 | } 382 | return [NSString stringWithString:desc]; 383 | } 384 | 385 | @end 386 | 387 | #pragma mark - BER Subclasses 388 | @implementation BerTaggedObject : NSObject 389 | @synthesize obj; 390 | @synthesize start; 391 | @synthesize end; 392 | - (void)beMutable 393 | { 394 | 395 | } 396 | - (id)unwrapped 397 | { 398 | return self.obj; 399 | } 400 | - (uint8_t*)berTag 401 | { 402 | return berTag; 403 | } 404 | - (void)setBerTagValue:(uint8_t)newValue 405 | { 406 | berTag[0] = newValue; 407 | } 408 | - (uint8_t)berTagValue 409 | { 410 | return berTag[0]; 411 | } 412 | - (BOOL)isEqual:(id)other 413 | { 414 | if ([other isKindOfClass:[BerTaggedObject class]]) 415 | { 416 | BerTaggedObject *taggedObj = other; 417 | return (self.berTagValue == taggedObj.berTagValue 418 | && [self.obj isEqual:taggedObj.obj]); 419 | } 420 | return NO; 421 | } 422 | - (NSUInteger)berContentsLengthBytes 423 | { 424 | if (self.obj) 425 | { 426 | return [self.obj berContentsLengthBytes]; 427 | } 428 | return [super berContentsLengthBytes]; 429 | } 430 | - (NSUInteger)berLengthBytes 431 | { 432 | if (self.obj) 433 | { 434 | return [self.obj berLengthBytes]; 435 | } 436 | return [super berLengthBytes]; 437 | } 438 | - (NSString*)descriptionFormat 439 | { 440 | return [NSString stringWithString:@"<%@ %@>"]; 441 | } 442 | - (NSString*)description 443 | { 444 | if (self.obj) 445 | { 446 | return [NSString stringWithFormat:[self descriptionFormat], 447 | [self berTagDescription], 448 | [self.obj description]]; 449 | } 450 | return [self berTagDescription]; 451 | } 452 | - (NSData*)berContents 453 | { 454 | [self raiseUnimplemented]; 455 | return nil; 456 | } 457 | - (NSData*)lengthStorageData 458 | { 459 | if (self.obj) 460 | { 461 | return [self.obj lengthStorageData]; 462 | } 463 | return [self zeroByteData]; 464 | } 465 | - (NSString*)berContentsDescription 466 | { 467 | return [self.obj berContentsDescription]; 468 | } 469 | @end 470 | 471 | @implementation BerTaggedCollection : BerTaggedObject 472 | - (void)beMutable 473 | { 474 | NSMutableArray *newArray = [[NSMutableArray alloc] initWithCapacity:[self.collection count]]; 475 | [newArray addObjectsFromArray:self.collection]; 476 | self.collection = newArray; 477 | for (NSUInteger i = 0; i < [self.collection count]; i++) { 478 | [[self.collection objectAtIndex:i] beMutable]; 479 | } 480 | } 481 | - (id)unwrapped 482 | { 483 | for (NSUInteger i = 0; i < [self.collection count]; i++) { 484 | BerTaggedObject *item = [self.collection objectAtIndex:i]; 485 | id unwrapped = [item unwrapped]; 486 | [self.collection replaceObjectAtIndex:i withObject:unwrapped]; 487 | } 488 | return self.obj; 489 | } 490 | - (NSData*)berContents 491 | { 492 | NSMutableData *berContents = [[NSMutableData alloc] init]; 493 | for (NSUInteger i = 0; i < [self.collection count]; i++) { 494 | [berContents appendData:[[self.collection objectAtIndex:i] berData]]; 495 | } 496 | return berContents; 497 | } 498 | - (void)setCollection:(NSMutableArray*)aCollection 499 | { 500 | self.obj = aCollection; 501 | } 502 | - (NSArray*)collection 503 | { 504 | return self.obj; 505 | } 506 | - (void)addObject:(id)anObject 507 | { 508 | [self.obj addObject:anObject]; 509 | } 510 | -(id)objectAtIndex:(NSUInteger)index 511 | { 512 | return [self.collection objectAtIndex:index]; 513 | } 514 | 515 | #pragma mark - BERVisitor 516 | 517 | - (void)acceptBERVisitor:(BERVisitor*)visitor 518 | { 519 | [visitor visitBERInteriorNode:(id)self]; 520 | } 521 | 522 | @end 523 | 524 | 525 | @implementation BerTaggedData : BerTaggedObject 526 | - (void)setData:(NSData*)newData 527 | { 528 | self.obj = newData; 529 | } 530 | - (NSData*)data 531 | { 532 | return self.obj; 533 | } 534 | - (NSData*)berContents 535 | { 536 | return self.data; 537 | } 538 | @end 539 | 540 | @implementation BerTaggedString : BerTaggedObject 541 | - (void)setString:(NSString*)newData 542 | { 543 | self.obj = (id)newData; 544 | } 545 | - (NSString*)string 546 | { 547 | return (NSString*)self.obj; 548 | } 549 | - (NSString*)descriptionFormat 550 | { 551 | return [NSString stringWithString:@"%@\"%@\""]; 552 | } 553 | - (NSStringEncoding)berStringEncoding 554 | { 555 | NSStringEncoding encoding = NSUTF8StringEncoding; 556 | if (self.berTagValue == BER_IA5STRING) 557 | { 558 | encoding = NSASCIIStringEncoding; 559 | } 560 | return encoding; 561 | } 562 | - (NSData*)berData 563 | { 564 | NSMutableData *berData = [[NSMutableData alloc] init]; 565 | [berData setData:[self.string berDataUsingEncoding:[self berStringEncoding]]]; 566 | [berData replaceBytesInRange:NSMakeRange(0,1) withBytes:[self berTag]]; 567 | return berData; 568 | } 569 | - (NSUInteger)berContentsLengthBytes 570 | { 571 | return [self.string berContentsLengthBytesUsingEncoding:[self berStringEncoding]]; 572 | } 573 | 574 | @end 575 | 576 | @implementation NSString (BasicEncodingRules) 577 | - (NSUInteger)berContentsLengthBytesUsingEncoding:(NSStringEncoding)encoding 578 | { 579 | NSUInteger myLength = [self lengthOfBytesUsingEncoding:encoding]; 580 | return myLength; 581 | } 582 | 583 | - (NSUInteger)berContentsLengthBytes 584 | { 585 | return [self berContentsLengthBytesUsingEncoding:NSUTF8StringEncoding]; 586 | } 587 | 588 | - (uint8_t*)berTag 589 | { 590 | static uint8_t myTag[] = { BER_UTF8STRING }; 591 | return myTag; 592 | } 593 | 594 | - (NSData*)berDataUsingEncoding:(NSStringEncoding)encoding 595 | { 596 | NSMutableData *berData = [[NSMutableData alloc] init]; 597 | [berData appendData:[self berHeader]]; 598 | [berData appendData:[self dataUsingEncoding:encoding]]; 599 | return berData; 600 | } 601 | 602 | - (NSData*)berData 603 | { 604 | return [self berDataUsingEncoding:NSUTF8StringEncoding]; 605 | } 606 | 607 | #pragma mark - NSData Printing 608 | - (NSString*)berContentsDescription 609 | { 610 | return self; 611 | } 612 | @end 613 | 614 | @implementation NSData (BasicEncodingRules) 615 | 616 | #pragma mark - NSData Encoding 617 | 618 | - (NSUInteger)berContentsLengthBytes 619 | { 620 | NSUInteger myLength = [self length]; 621 | return myLength; 622 | } 623 | 624 | - (uint8_t*)berTag 625 | { 626 | static uint8_t integerTag[] = { BER_INTEGER }; 627 | return integerTag; 628 | } 629 | 630 | - (NSData*)berContents 631 | { 632 | return self; 633 | } 634 | 635 | #pragma mark - NSData Decoding 636 | 637 | - (id)berParse 638 | { 639 | NSUInteger iterator = 0; 640 | return [self berDecodeFromStart:0 641 | to:[self length] - 1 642 | iterator:&iterator]; 643 | } 644 | 645 | - (id)berDecode 646 | { 647 | id decoded = [self berParse]; 648 | [decoded beMutable]; 649 | return [decoded unwrapped]; 650 | } 651 | 652 | - (id)berDecodeFromStart:(NSUInteger)start to:(NSUInteger)end iterator:(NSUInteger*)iterator 653 | { 654 | uint8_t *bytes = (uint8_t*)[self bytes]; 655 | uint8_t currentTag = bytes[start]; 656 | 657 | switch (currentTag) 658 | { 659 | case BER_A0: 660 | case BER_SEQUENCE_CONSTRUCTED: 661 | case BER_SET_CONSTRUCTED: 662 | case BER_SEQUENCE: 663 | case BER_SET: 664 | return [self berDecodeAsCollectionTagged:currentTag 665 | from:start 666 | to:end]; 667 | break; 668 | case BER_EOC: 669 | case BER_BOOLEAN: 670 | case BER_INTEGER: 671 | case BER_BIT_STRING: 672 | case BER_OCTET_STRING: 673 | case BER_NULL: 674 | case BER_OBJECT_IDENTIFIER: 675 | case BER_OBJECT_DESCRIPTOR: 676 | case BER_RELATIVE_OID: 677 | return [self berDecodeAsDataTagged:currentTag 678 | from:start 679 | to:end]; 680 | break; 681 | case BER_UTF8STRING: 682 | case BER_NUMERICSTRING: 683 | case BER_PRINTABLESTRING: 684 | case BER_T61STRING: 685 | case BER_VIDEOTEXSTRING: 686 | case BER_IA5STRING: 687 | case BER_UTCTIME: 688 | case BER_GENERALIZEDTIME: 689 | case BER_GRAPHICSTRING: 690 | case BER_VISIBLESTRING: 691 | case BER_GENERALSTRING: 692 | case BER_UNIVERSALSTRING: 693 | case BER_CHARACTER_STRING: 694 | case BER_BMPSTRING: 695 | return [self berDecodeAsStringTagged:currentTag 696 | from:start 697 | to:end]; 698 | break; 699 | default: 700 | [self raiseUnimplemented]; 701 | } 702 | return nil; 703 | } 704 | 705 | - (NSUInteger)berDecodeSizeAt:(NSUInteger*)iterator 706 | { 707 | uint8_t *bytes = (uint8_t*)[self bytes]; 708 | NSUInteger iter = *iterator; 709 | NSUInteger container_length = 0, num_bytes = 1; 710 | 711 | iter++; // Skip the tag byte 712 | if (bytes[iter] > 0x80) 713 | { 714 | num_bytes = bytes[iter] - 0x80; 715 | iter++; 716 | } 717 | for (NSUInteger i = 0; i < num_bytes; i++) 718 | { 719 | container_length = (container_length * 0x100) + bytes[iter + i]; 720 | } 721 | *iterator = iter + num_bytes; 722 | return container_length; 723 | } 724 | 725 | - (id)berDecodeAsCollection:(id)collection from:(NSUInteger)start to:(NSUInteger)end 726 | { 727 | NSUInteger iterator = start; 728 | NSUInteger container_length, container_end; 729 | 730 | container_length = [self berDecodeSizeAt:&iterator]; 731 | container_end = iterator + container_length; 732 | 733 | while (iterator < container_end) 734 | { 735 | NSUInteger item_start = iterator; 736 | NSUInteger item_length = [self berDecodeSizeAt:&iterator]; 737 | NSUInteger next_item_start = iterator + item_length; 738 | 739 | id item = [self berDecodeFromStart:item_start 740 | to:(next_item_start - 1) 741 | iterator:&iterator]; 742 | [collection addObject: item]; 743 | 744 | iterator = next_item_start; 745 | } 746 | return collection; 747 | } 748 | 749 | - (NSMutableSet*)berDecodeAsCollectionTagged:(uint8_t)tagValue from:(NSUInteger)start to:(NSUInteger)end 750 | { 751 | BerTaggedCollection *newSet = [[BerTaggedCollection alloc] init]; 752 | newSet.berTagValue = tagValue; 753 | newSet.collection = [[NSMutableArray alloc] init]; 754 | newSet.start = start; 755 | newSet.end = end; 756 | return [self berDecodeAsCollection:newSet from:start to:end]; 757 | } 758 | 759 | - (NSData*)berDecodeAsDataFrom:(NSUInteger)start to:(NSUInteger)end 760 | { 761 | NSUInteger iterator = start; 762 | NSUInteger item_length = [self berDecodeSizeAt:&iterator]; 763 | NSUInteger item_start = iterator; 764 | return [self subdataWithRange:NSMakeRange(item_start, item_length)]; 765 | } 766 | 767 | - (BerTaggedData*)berDecodeAsDataTagged:(uint8_t)tagValue from:(NSUInteger)start to:(NSUInteger)end 768 | { 769 | BerTaggedData *newData = [[BerTaggedData alloc] init]; 770 | newData.data = [self berDecodeAsDataFrom:start to:end]; 771 | newData.berTagValue = tagValue; 772 | newData.start = start; 773 | newData.end = end; 774 | return newData; 775 | } 776 | 777 | - (NSString*)berDecodeAsStringFrom:(NSUInteger)start to:(NSUInteger)end 778 | { 779 | NSUInteger iterator = start; 780 | NSUInteger item_length = [self berDecodeSizeAt:&iterator]; 781 | NSUInteger item_start = iterator; 782 | NSData *rawData = [self subdataWithRange:NSMakeRange(item_start, item_length)]; 783 | return [[NSString alloc] initWithData:rawData encoding:NSUTF8StringEncoding ]; 784 | } 785 | 786 | - (BerTaggedString*)berDecodeAsStringTagged:(uint8_t)tagValue from:(NSUInteger)start to:(NSUInteger)end 787 | { 788 | BerTaggedString *newString = [[BerTaggedString alloc] init]; 789 | newString.string = [self berDecodeAsStringFrom:start to:end]; 790 | newString.berTagValue = tagValue; 791 | newString.start = start; 792 | newString.end = end; 793 | return newString; 794 | } 795 | 796 | #pragma mark - NSData Printing 797 | - (NSString*)berContentsDescription 798 | { 799 | uint8_t *bytes = (uint8_t*)[self bytes]; 800 | NSMutableString *aString = [[NSMutableString alloc] init]; 801 | for (NSUInteger i = 0; i < [self length]; i++) 802 | { 803 | [aString appendFormat:@"%02X", bytes[i]]; 804 | } 805 | return aString; 806 | } 807 | @end 808 | 809 | 810 | @implementation NSArray (BasicEncodingRules) 811 | 812 | #pragma mark - NSArray Encoding 813 | 814 | - (NSUInteger)berContentsLengthBytes 815 | { 816 | NSUInteger subTotalLength = 0; 817 | for (NSUInteger i = 0; i < [self count]; i++) { 818 | subTotalLength += [[self objectAtIndex:i] berLengthBytes]; 819 | } 820 | return subTotalLength; 821 | } 822 | 823 | - (uint8_t*)berTag 824 | { 825 | static uint8_t bitfieldTag[] = { (kBerTypeConstructed | BER_SEQUENCE) }; 826 | return bitfieldTag; 827 | } 828 | 829 | - (NSData*)berContents 830 | { 831 | NSMutableData *berContents = [[NSMutableData alloc] init]; 832 | for (NSUInteger i = 0; i < [self count]; i++) { 833 | // A BER_SEQUENCE's berContents data is the sum of 834 | // all contained item's represented data. 835 | // Basically, it does not include the length data 836 | // That's why we're invoking berData below 837 | NSData *itemData = [[self objectAtIndex:i] berData]; 838 | [berContents appendData:itemData]; 839 | } 840 | return berContents; 841 | } 842 | 843 | #pragma mark - BERVisitor 844 | 845 | - (void)acceptBERVisitor:(BERVisitor*)visitor 846 | { 847 | [visitor visitBERInteriorNode:(id)self]; 848 | } 849 | 850 | - (NSArray*)collection 851 | { 852 | return self; 853 | } 854 | 855 | @end 856 | 857 | @implementation NSNull (BasicEncodingRules) 858 | 859 | #pragma mark - NSNull Encoding 860 | 861 | - (NSUInteger)berContentsLengthBytes 862 | { 863 | return 0; 864 | } 865 | 866 | - (NSUInteger)berLengthBytes 867 | { 868 | return 2; 869 | } 870 | 871 | - (uint8_t*)berTag 872 | { 873 | static uint8_t bitfieldTag[] = { BER_NULL }; 874 | return bitfieldTag; 875 | } 876 | 877 | - (NSData*)lengthStorageData 878 | { 879 | return [self zeroByteData]; 880 | } 881 | 882 | - (NSData*)berData 883 | { 884 | return [self berHeader]; 885 | } 886 | 887 | @end 888 | -------------------------------------------------------------------------------- /NSData+Base64.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSData+Base64.h 3 | // 4 | // Version 1.0.2 5 | // 6 | // Created by Nick Lockwood on 12/01/2012. 7 | // Copyright (C) 2012 Charcoal Design 8 | // 9 | // Distributed under the permissive zlib License 10 | // Get the latest version from here: 11 | // 12 | // https://github.com/nicklockwood/Base64 13 | // 14 | // This software is provided 'as-is', without any express or implied 15 | // warranty. In no event will the authors be held liable for any damages 16 | // arising from the use of this software. 17 | // 18 | // Permission is granted to anyone to use this software for any purpose, 19 | // including commercial applications, and to alter it and redistribute it 20 | // freely, subject to the following restrictions: 21 | // 22 | // 1. The origin of this software must not be misrepresented; you must not 23 | // claim that you wrote the original software. If you use this software 24 | // in a product, an acknowledgment in the product documentation would be 25 | // appreciated but is not required. 26 | // 27 | // 2. Altered source versions must be plainly marked as such, and must not be 28 | // misrepresented as being the original software. 29 | // 30 | // 3. This notice may not be removed or altered from any source distribution. 31 | // 32 | 33 | #import 34 | 35 | @interface NSData (Base64) 36 | 37 | + (NSData *)dataWithBase64EncodedString:(NSString *)string; 38 | - (NSString *)base64EncodedStringWithWrapWidth:(NSUInteger)wrapWidth; 39 | - (NSString *)base64EncodedString; 40 | 41 | @end -------------------------------------------------------------------------------- /NSData+Base64.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSData+Base64.m 3 | // 4 | // Version 1.0.2 5 | // 6 | // Created by Nick Lockwood on 12/01/2012. 7 | // Copyright (C) 2012 Charcoal Design 8 | // 9 | // Distributed under the permissive zlib License 10 | // Get the latest version from here: 11 | // 12 | // https://github.com/nicklockwood/Base64 13 | // 14 | // This software is provided 'as-is', without any express or implied 15 | // warranty. In no event will the authors be held liable for any damages 16 | // arising from the use of this software. 17 | // 18 | // Permission is granted to anyone to use this software for any purpose, 19 | // including commercial applications, and to alter it and redistribute it 20 | // freely, subject to the following restrictions: 21 | // 22 | // 1. The origin of this software must not be misrepresented; you must not 23 | // claim that you wrote the original software. If you use this software 24 | // in a product, an acknowledgment in the product documentation would be 25 | // appreciated but is not required. 26 | // 27 | // 2. Altered source versions must be plainly marked as such, and must not be 28 | // misrepresented as being the original software. 29 | // 30 | // 3. This notice may not be removed or altered from any source distribution. 31 | // 32 | 33 | #import "NSData+Base64.h" 34 | 35 | @implementation NSData (Base64) 36 | 37 | + (NSData *)dataWithBase64EncodedString:(NSString *)string 38 | { 39 | const char lookup[] = 40 | { 41 | 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 42 | 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 43 | 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 62, 99, 99, 99, 63, 44 | 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 99, 99, 99, 99, 99, 99, 45 | 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 46 | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 99, 99, 99, 99, 99, 47 | 99, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 48 | 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 99, 99, 99, 99, 99 49 | }; 50 | 51 | NSData *inputData = [string dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES]; 52 | long long inputLength = [inputData length]; 53 | const unsigned char *inputBytes = [inputData bytes]; 54 | 55 | long long maxOutputLength = (inputLength / 4 + 1) * 3; 56 | NSMutableData *outputData = [NSMutableData dataWithLength:maxOutputLength]; 57 | unsigned char *outputBytes = (unsigned char *)[outputData mutableBytes]; 58 | 59 | int accumulator = 0; 60 | long long outputLength = 0; 61 | unsigned char accumulated[] = {0, 0, 0, 0}; 62 | for (long long i = 0; i < inputLength; i++) 63 | { 64 | unsigned char decoded = lookup[inputBytes[i] & 0x7F]; 65 | if (decoded != 99) 66 | { 67 | accumulated[accumulator] = decoded; 68 | if (accumulator == 3) 69 | { 70 | outputBytes[outputLength++] = (accumulated[0] << 2) | (accumulated[1] >> 4); 71 | outputBytes[outputLength++] = (accumulated[1] << 4) | (accumulated[2] >> 2); 72 | outputBytes[outputLength++] = (accumulated[2] << 6) | accumulated[3]; 73 | } 74 | accumulator = (accumulator + 1) % 4; 75 | } 76 | } 77 | 78 | //handle left-over data 79 | if (accumulator > 0) outputBytes[outputLength] = (accumulated[0] << 2) | (accumulated[1] >> 4); 80 | if (accumulator > 1) outputBytes[++outputLength] = (accumulated[1] << 4) | (accumulated[2] >> 2); 81 | if (accumulator > 2) outputLength++; 82 | 83 | //truncate data to match actual output length 84 | outputData.length = outputLength; 85 | return outputLength? outputData: nil; 86 | } 87 | 88 | - (NSString *)base64EncodedStringWithWrapWidth:(NSUInteger)wrapWidth 89 | { 90 | //ensure wrapWidth is a multiple of 4 91 | wrapWidth = (wrapWidth / 4) * 4; 92 | 93 | const char lookup[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 94 | 95 | long long inputLength = [self length]; 96 | const unsigned char *inputBytes = [self bytes]; 97 | 98 | long long maxOutputLength = (inputLength / 3 + 1) * 4; 99 | maxOutputLength += wrapWidth? (maxOutputLength / wrapWidth) * 2: 0; 100 | unsigned char *outputBytes = (unsigned char *)malloc(maxOutputLength); 101 | 102 | long long i; 103 | long long outputLength = 0; 104 | for (i = 0; i < inputLength - 2; i += 3) 105 | { 106 | outputBytes[outputLength++] = lookup[(inputBytes[i] & 0xFC) >> 2]; 107 | outputBytes[outputLength++] = lookup[((inputBytes[i] & 0x03) << 4) | ((inputBytes[i + 1] & 0xF0) >> 4)]; 108 | outputBytes[outputLength++] = lookup[((inputBytes[i + 1] & 0x0F) << 2) | ((inputBytes[i + 2] & 0xC0) >> 6)]; 109 | outputBytes[outputLength++] = lookup[inputBytes[i + 2] & 0x3F]; 110 | 111 | //add line break 112 | if (wrapWidth && (outputLength + 2) % (wrapWidth + 2) == 0) 113 | { 114 | outputBytes[outputLength++] = '\r'; 115 | outputBytes[outputLength++] = '\n'; 116 | } 117 | } 118 | 119 | //handle left-over data 120 | if (i == inputLength - 2) 121 | { 122 | // = terminator 123 | outputBytes[outputLength++] = lookup[(inputBytes[i] & 0xFC) >> 2]; 124 | outputBytes[outputLength++] = lookup[((inputBytes[i] & 0x03) << 4) | ((inputBytes[i + 1] & 0xF0) >> 4)]; 125 | outputBytes[outputLength++] = lookup[(inputBytes[i + 1] & 0x0F) << 2]; 126 | outputBytes[outputLength++] = '='; 127 | } 128 | else if (i == inputLength - 1) 129 | { 130 | // == terminator 131 | outputBytes[outputLength++] = lookup[(inputBytes[i] & 0xFC) >> 2]; 132 | outputBytes[outputLength++] = lookup[(inputBytes[i] & 0x03) << 4]; 133 | outputBytes[outputLength++] = '='; 134 | outputBytes[outputLength++] = '='; 135 | } 136 | 137 | //truncate data to match actual output length 138 | outputBytes = realloc(outputBytes, outputLength); 139 | NSString *result = [[NSString alloc] initWithBytesNoCopy:outputBytes length:outputLength encoding:NSASCIIStringEncoding freeWhenDone:YES]; 140 | 141 | #if !__has_feature(objc_arc) 142 | [result autorelease]; 143 | #endif 144 | 145 | return (outputLength >= 4)? result: nil; 146 | } 147 | 148 | - (NSString *)base64EncodedString 149 | { 150 | return [self base64EncodedStringWithWrapWidth:0]; 151 | } 152 | 153 | @end 154 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SCZ-BasicEncodingRules-iOS 2 | ========================== 3 | 4 | Implementation of Basic Encoding Rules to enable import of RSA keys to iOS 5 | KeyChain using exponent. Code targets iOS 5 with ARC. 6 | 7 | Let's say you already have a modulus and exponent from 8 | an RSA public key as an NSData in variables named pubKeyModData and 9 | pubKeyModData. Then the following code will create an NSData containing that RSA 10 | public key, which you can then insert into the iOS or OS X Keychain. 11 | 12 | NSMutableArray *testArray = [[NSMutableArray alloc] init]; 13 | [testArray addObject:pubKeyModData]; 14 | [testArray addObject:pubKeyExpData]; 15 | NSData *testPubKey = [testArray berData]; 16 | 17 | This would allow you to store the key using the addPeerPublicKey:keyBits: method from SecKeyWrapper in the Apple CryptoExercise example. Or, from the perspective of the low-level API, you can use SecItemAdd(). 18 | 19 | NSString * peerName = @"Test Public Key"; 20 | 21 | NSData * peerTag = 22 | [[NSData alloc] 23 | initWithBytes:(const void *)[peerName UTF8String] 24 | length:[peerName length]]; 25 | 26 | NSMutableDictionary * peerPublicKeyAttr = [[NSMutableDictionary alloc] init]; 27 | 28 | [peerPublicKeyAttr 29 | setObject:(__bridge id)kSecClassKey 30 | forKey:(__bridge id)kSecClass]; 31 | [peerPublicKeyAttr 32 | setObject:(__bridge id)kSecAttrKeyTypeRSA 33 | forKey:(__bridge id)kSecAttrKeyType]; 34 | [peerPublicKeyAttr 35 | setObject:peerTag 36 | forKey:(__bridge id)kSecAttrApplicationTag]; 37 | [peerPublicKeyAttr 38 | setObject:testPubKey 39 | forKey:(__bridge id)kSecValueData]; 40 | [peerPublicKeyAttr 41 | setObject:[NSNumber numberWithBool:YES] 42 | forKey:(__bridge id)kSecReturnPersistentRef]; 43 | 44 | sanityCheck = SecItemAdd((__bridge CFDictionaryRef) peerPublicKeyAttr, (CFTypeRef *)&persistPeer); 45 | -------------------------------------------------------------------------------- /SCZ-BasicEncodingRules-iOS.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 18664EEA156DAD8000E29E64 /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18664EE9156DAD8000E29E64 /* SenTestingKit.framework */; }; 11 | 18664EEC156DAD8000E29E64 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18664EEB156DAD8000E29E64 /* UIKit.framework */; }; 12 | 18664EEE156DAD8000E29E64 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18664EED156DAD8000E29E64 /* Foundation.framework */; }; 13 | 18664EF4156DAD8000E29E64 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 18664EF2156DAD8000E29E64 /* InfoPlist.strings */; }; 14 | 18664EF7156DAD8000E29E64 /* Unit_Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 18664EF6156DAD8000E29E64 /* Unit_Tests.m */; }; 15 | 18664EFC156DB54100E29E64 /* BasicEncodingRules.m in Sources */ = {isa = PBXBuildFile; fileRef = 18664EDE156D773D00E29E64 /* BasicEncodingRules.m */; }; 16 | 18A0CEAF156F76940064F0CB /* NSData+Base64.m in Sources */ = {isa = PBXBuildFile; fileRef = 18A0CEAE156F76940064F0CB /* NSData+Base64.m */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXFileReference section */ 20 | 18664EDD156D773D00E29E64 /* BasicEncodingRules.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BasicEncodingRules.h; sourceTree = ""; }; 21 | 18664EDE156D773D00E29E64 /* BasicEncodingRules.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BasicEncodingRules.m; sourceTree = ""; }; 22 | 18664EDF156D773D00E29E64 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = text; path = README.md; sourceTree = ""; }; 23 | 18664EE6156DAD8000E29E64 /* Unit Tests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Unit Tests.octest"; sourceTree = BUILT_PRODUCTS_DIR; }; 24 | 18664EE9156DAD8000E29E64 /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; }; 25 | 18664EEB156DAD8000E29E64 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; 26 | 18664EED156DAD8000E29E64 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; 27 | 18664EF1156DAD8000E29E64 /* Unit Tests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Unit Tests-Info.plist"; sourceTree = ""; }; 28 | 18664EF3156DAD8000E29E64 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 29 | 18664EF5156DAD8000E29E64 /* Unit_Tests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Unit_Tests.h; sourceTree = ""; }; 30 | 18664EF6156DAD8000E29E64 /* Unit_Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Unit_Tests.m; sourceTree = ""; }; 31 | 18664EF8156DAD8000E29E64 /* Unit Tests-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Unit Tests-Prefix.pch"; sourceTree = ""; }; 32 | 18A0CEAD156F76940064F0CB /* NSData+Base64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+Base64.h"; sourceTree = ""; }; 33 | 18A0CEAE156F76940064F0CB /* NSData+Base64.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+Base64.m"; sourceTree = ""; }; 34 | /* End PBXFileReference section */ 35 | 36 | /* Begin PBXFrameworksBuildPhase section */ 37 | 18664EE2156DAD8000E29E64 /* Frameworks */ = { 38 | isa = PBXFrameworksBuildPhase; 39 | buildActionMask = 2147483647; 40 | files = ( 41 | 18664EEA156DAD8000E29E64 /* SenTestingKit.framework in Frameworks */, 42 | 18664EEC156DAD8000E29E64 /* UIKit.framework in Frameworks */, 43 | 18664EEE156DAD8000E29E64 /* Foundation.framework in Frameworks */, 44 | ); 45 | runOnlyForDeploymentPostprocessing = 0; 46 | }; 47 | /* End PBXFrameworksBuildPhase section */ 48 | 49 | /* Begin PBXGroup section */ 50 | 18664ED1156D741100E29E64 = { 51 | isa = PBXGroup; 52 | children = ( 53 | 18A0CEAD156F76940064F0CB /* NSData+Base64.h */, 54 | 18A0CEAE156F76940064F0CB /* NSData+Base64.m */, 55 | 18664EDD156D773D00E29E64 /* BasicEncodingRules.h */, 56 | 18664EDE156D773D00E29E64 /* BasicEncodingRules.m */, 57 | 18664EDF156D773D00E29E64 /* README.md */, 58 | 18664EEF156DAD8000E29E64 /* Unit Tests */, 59 | 18664EE8156DAD8000E29E64 /* Frameworks */, 60 | 18664EE7156DAD8000E29E64 /* Products */, 61 | ); 62 | sourceTree = ""; 63 | }; 64 | 18664EE7156DAD8000E29E64 /* Products */ = { 65 | isa = PBXGroup; 66 | children = ( 67 | 18664EE6156DAD8000E29E64 /* Unit Tests.octest */, 68 | ); 69 | name = Products; 70 | sourceTree = ""; 71 | }; 72 | 18664EE8156DAD8000E29E64 /* Frameworks */ = { 73 | isa = PBXGroup; 74 | children = ( 75 | 18664EE9156DAD8000E29E64 /* SenTestingKit.framework */, 76 | 18664EEB156DAD8000E29E64 /* UIKit.framework */, 77 | 18664EED156DAD8000E29E64 /* Foundation.framework */, 78 | ); 79 | name = Frameworks; 80 | sourceTree = ""; 81 | }; 82 | 18664EEF156DAD8000E29E64 /* Unit Tests */ = { 83 | isa = PBXGroup; 84 | children = ( 85 | 18664EF5156DAD8000E29E64 /* Unit_Tests.h */, 86 | 18664EF6156DAD8000E29E64 /* Unit_Tests.m */, 87 | 18664EF0156DAD8000E29E64 /* Supporting Files */, 88 | ); 89 | path = "Unit Tests"; 90 | sourceTree = ""; 91 | }; 92 | 18664EF0156DAD8000E29E64 /* Supporting Files */ = { 93 | isa = PBXGroup; 94 | children = ( 95 | 18664EF1156DAD8000E29E64 /* Unit Tests-Info.plist */, 96 | 18664EF2156DAD8000E29E64 /* InfoPlist.strings */, 97 | 18664EF8156DAD8000E29E64 /* Unit Tests-Prefix.pch */, 98 | ); 99 | name = "Supporting Files"; 100 | sourceTree = ""; 101 | }; 102 | /* End PBXGroup section */ 103 | 104 | /* Begin PBXNativeTarget section */ 105 | 18664EE5156DAD8000E29E64 /* Unit Tests */ = { 106 | isa = PBXNativeTarget; 107 | buildConfigurationList = 18664EF9156DAD8000E29E64 /* Build configuration list for PBXNativeTarget "Unit Tests" */; 108 | buildPhases = ( 109 | 18664EE1156DAD8000E29E64 /* Sources */, 110 | 18664EE2156DAD8000E29E64 /* Frameworks */, 111 | 18664EE3156DAD8000E29E64 /* Resources */, 112 | 18664EE4156DAD8000E29E64 /* ShellScript */, 113 | ); 114 | buildRules = ( 115 | ); 116 | dependencies = ( 117 | ); 118 | name = "Unit Tests"; 119 | productName = "Unit Tests"; 120 | productReference = 18664EE6156DAD8000E29E64 /* Unit Tests.octest */; 121 | productType = "com.apple.product-type.bundle"; 122 | }; 123 | /* End PBXNativeTarget section */ 124 | 125 | /* Begin PBXProject section */ 126 | 18664ED3156D741100E29E64 /* Project object */ = { 127 | isa = PBXProject; 128 | attributes = { 129 | LastUpgradeCheck = 0430; 130 | ORGANIZATIONNAME = "Ooghamist LLC"; 131 | }; 132 | buildConfigurationList = 18664ED6156D741100E29E64 /* Build configuration list for PBXProject "SCZ-BasicEncodingRules-iOS" */; 133 | compatibilityVersion = "Xcode 3.2"; 134 | developmentRegion = English; 135 | hasScannedForEncodings = 0; 136 | knownRegions = ( 137 | en, 138 | ); 139 | mainGroup = 18664ED1156D741100E29E64; 140 | productRefGroup = 18664EE7156DAD8000E29E64 /* Products */; 141 | projectDirPath = ""; 142 | projectRoot = ""; 143 | targets = ( 144 | 18664EE5156DAD8000E29E64 /* Unit Tests */, 145 | ); 146 | }; 147 | /* End PBXProject section */ 148 | 149 | /* Begin PBXResourcesBuildPhase section */ 150 | 18664EE3156DAD8000E29E64 /* Resources */ = { 151 | isa = PBXResourcesBuildPhase; 152 | buildActionMask = 2147483647; 153 | files = ( 154 | 18664EF4156DAD8000E29E64 /* InfoPlist.strings in Resources */, 155 | ); 156 | runOnlyForDeploymentPostprocessing = 0; 157 | }; 158 | /* End PBXResourcesBuildPhase section */ 159 | 160 | /* Begin PBXShellScriptBuildPhase section */ 161 | 18664EE4156DAD8000E29E64 /* ShellScript */ = { 162 | isa = PBXShellScriptBuildPhase; 163 | buildActionMask = 2147483647; 164 | files = ( 165 | ); 166 | inputPaths = ( 167 | ); 168 | outputPaths = ( 169 | ); 170 | runOnlyForDeploymentPostprocessing = 0; 171 | shellPath = /bin/sh; 172 | shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n"; 173 | }; 174 | /* End PBXShellScriptBuildPhase section */ 175 | 176 | /* Begin PBXSourcesBuildPhase section */ 177 | 18664EE1156DAD8000E29E64 /* Sources */ = { 178 | isa = PBXSourcesBuildPhase; 179 | buildActionMask = 2147483647; 180 | files = ( 181 | 18664EFC156DB54100E29E64 /* BasicEncodingRules.m in Sources */, 182 | 18664EF7156DAD8000E29E64 /* Unit_Tests.m in Sources */, 183 | 18A0CEAF156F76940064F0CB /* NSData+Base64.m in Sources */, 184 | ); 185 | runOnlyForDeploymentPostprocessing = 0; 186 | }; 187 | /* End PBXSourcesBuildPhase section */ 188 | 189 | /* Begin PBXVariantGroup section */ 190 | 18664EF2156DAD8000E29E64 /* InfoPlist.strings */ = { 191 | isa = PBXVariantGroup; 192 | children = ( 193 | 18664EF3156DAD8000E29E64 /* en */, 194 | ); 195 | name = InfoPlist.strings; 196 | sourceTree = ""; 197 | }; 198 | /* End PBXVariantGroup section */ 199 | 200 | /* Begin XCBuildConfiguration section */ 201 | 18664ED8156D741100E29E64 /* Debug */ = { 202 | isa = XCBuildConfiguration; 203 | buildSettings = { 204 | }; 205 | name = Debug; 206 | }; 207 | 18664ED9156D741100E29E64 /* Release */ = { 208 | isa = XCBuildConfiguration; 209 | buildSettings = { 210 | }; 211 | name = Release; 212 | }; 213 | 18664EFA156DAD8000E29E64 /* Debug */ = { 214 | isa = XCBuildConfiguration; 215 | buildSettings = { 216 | ALWAYS_SEARCH_USER_PATHS = NO; 217 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 218 | CLANG_ENABLE_OBJC_ARC = YES; 219 | COPY_PHASE_STRIP = NO; 220 | FRAMEWORK_SEARCH_PATHS = ( 221 | "$(SDKROOT)/Developer/Library/Frameworks", 222 | "$(DEVELOPER_LIBRARY_DIR)/Frameworks", 223 | ); 224 | GCC_C_LANGUAGE_STANDARD = gnu99; 225 | GCC_DYNAMIC_NO_PIC = NO; 226 | GCC_OPTIMIZATION_LEVEL = 0; 227 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 228 | GCC_PREFIX_HEADER = "Unit Tests/Unit Tests-Prefix.pch"; 229 | GCC_PREPROCESSOR_DEFINITIONS = ( 230 | "DEBUG=1", 231 | "$(inherited)", 232 | ); 233 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 234 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 235 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 236 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 237 | GCC_WARN_UNUSED_VARIABLE = YES; 238 | INFOPLIST_FILE = "Unit Tests/Unit Tests-Info.plist"; 239 | IPHONEOS_DEPLOYMENT_TARGET = 5.1; 240 | PRODUCT_NAME = "$(TARGET_NAME)"; 241 | SDKROOT = iphoneos; 242 | WRAPPER_EXTENSION = octest; 243 | }; 244 | name = Debug; 245 | }; 246 | 18664EFB156DAD8000E29E64 /* Release */ = { 247 | isa = XCBuildConfiguration; 248 | buildSettings = { 249 | ALWAYS_SEARCH_USER_PATHS = NO; 250 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 251 | CLANG_ENABLE_OBJC_ARC = YES; 252 | COPY_PHASE_STRIP = YES; 253 | FRAMEWORK_SEARCH_PATHS = ( 254 | "$(SDKROOT)/Developer/Library/Frameworks", 255 | "$(DEVELOPER_LIBRARY_DIR)/Frameworks", 256 | ); 257 | GCC_C_LANGUAGE_STANDARD = gnu99; 258 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 259 | GCC_PREFIX_HEADER = "Unit Tests/Unit Tests-Prefix.pch"; 260 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 261 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 262 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 263 | GCC_WARN_UNUSED_VARIABLE = YES; 264 | INFOPLIST_FILE = "Unit Tests/Unit Tests-Info.plist"; 265 | IPHONEOS_DEPLOYMENT_TARGET = 5.1; 266 | PRODUCT_NAME = "$(TARGET_NAME)"; 267 | SDKROOT = iphoneos; 268 | VALIDATE_PRODUCT = YES; 269 | WRAPPER_EXTENSION = octest; 270 | }; 271 | name = Release; 272 | }; 273 | /* End XCBuildConfiguration section */ 274 | 275 | /* Begin XCConfigurationList section */ 276 | 18664ED6156D741100E29E64 /* Build configuration list for PBXProject "SCZ-BasicEncodingRules-iOS" */ = { 277 | isa = XCConfigurationList; 278 | buildConfigurations = ( 279 | 18664ED8156D741100E29E64 /* Debug */, 280 | 18664ED9156D741100E29E64 /* Release */, 281 | ); 282 | defaultConfigurationIsVisible = 0; 283 | defaultConfigurationName = Release; 284 | }; 285 | 18664EF9156DAD8000E29E64 /* Build configuration list for PBXNativeTarget "Unit Tests" */ = { 286 | isa = XCConfigurationList; 287 | buildConfigurations = ( 288 | 18664EFA156DAD8000E29E64 /* Debug */, 289 | 18664EFB156DAD8000E29E64 /* Release */, 290 | ); 291 | defaultConfigurationIsVisible = 0; 292 | defaultConfigurationName = Release; 293 | }; 294 | /* End XCConfigurationList section */ 295 | }; 296 | rootObject = 18664ED3156D741100E29E64 /* Project object */; 297 | } 298 | -------------------------------------------------------------------------------- /SCZ-BasicEncodingRules-iOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Unit Tests/Unit Tests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | SCZ.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Unit Tests/Unit Tests-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'Unit Tests' target in the 'Unit Tests' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #import 8 | #endif 9 | -------------------------------------------------------------------------------- /Unit Tests/Unit_Tests.h: -------------------------------------------------------------------------------- 1 | // 2 | // Unit_Tests.h 3 | // Unit Tests 4 | // 5 | // Created by Peter Suk on 5/23/12. 6 | // Copyright (c) 2012 Ooghamist LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "BasicEncodingRules.h" 11 | #import "NSData+Base64.h" 12 | 13 | @interface Unit_Tests : SenTestCase 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Unit Tests/Unit_Tests.m: -------------------------------------------------------------------------------- 1 | // 2 | // Unit_Tests.m 3 | // Unit Tests 4 | // 5 | // Created by Peter Suk on 5/23/12. 6 | // Copyright (c) 2012 Ooghamist LLC. All rights reserved. 7 | // 8 | 9 | #import "Unit_Tests.h" 10 | 11 | @implementation Unit_Tests 12 | 13 | - (void)setUp 14 | { 15 | [super setUp]; 16 | 17 | // Set-up code here. 18 | } 19 | 20 | - (void)tearDown 21 | { 22 | // Tear-down code here. 23 | 24 | [super tearDown]; 25 | } 26 | 27 | - (NSData*)dataWithDEADBEEFLength:(NSUInteger)length 28 | { 29 | uint8_t item_bytes[] = { 0xDE, 0xAD, 0xBE, 0xEF }; 30 | NSMutableData *returnValue = [[NSMutableData alloc] initWithLength:length]; 31 | uint8_t *bytes = [returnValue mutableBytes]; 32 | for (NSUInteger i = 0; i < length; i++) 33 | { 34 | bytes[i] = item_bytes[i % 4]; 35 | } 36 | return returnValue; 37 | } 38 | 39 | - (NSData*)dataWithCAFEBABELength:(NSUInteger)length 40 | { 41 | uint8_t item_bytes[] = { 0xCA, 0xFE, 0xBA, 0xBE }; 42 | NSMutableData *returnValue = [[NSMutableData alloc] initWithLength:length]; 43 | uint8_t *bytes = [returnValue mutableBytes]; 44 | for (NSUInteger i = 0; i < length; i++) 45 | { 46 | bytes[i] = item_bytes[i % 4]; 47 | } 48 | return returnValue; 49 | } 50 | 51 | - (NSString*)hexadecimalFor:(NSData*)data 52 | { 53 | NSMutableString *result = [[NSMutableString alloc] init]; 54 | uint8_t *resultBytes = (uint8_t*)[data bytes]; 55 | for (NSUInteger i = 0; i < [data length]; i++) 56 | { 57 | [result appendFormat:@"%02X", resultBytes[i]]; 58 | } 59 | return result; 60 | } 61 | 62 | - (void)testSmallItems 63 | { 64 | 65 | NSData *item1 = [self dataWithDEADBEEFLength:4]; 66 | NSData *item2 = [self dataWithCAFEBABELength:4]; 67 | 68 | NSMutableArray *testArray = [[NSMutableArray alloc] init]; 69 | [testArray addObject:item1]; 70 | [testArray addObject:item2]; 71 | NSData *testData = [testArray berData]; 72 | 73 | 74 | NSLog(@"testData: %@", [self hexadecimalFor:testData]); 75 | 76 | NSMutableArray *testArray2 = [testData berDecode]; 77 | 78 | STAssertEqualObjects(testArray, testArray2, 79 | @"Small items failed"); 80 | 81 | NSData *testData2 = [testArray2 berData]; 82 | 83 | NSLog(@"testData: %@", [self hexadecimalFor:testData2]); 84 | 85 | } 86 | 87 | - (void)testBigItems 88 | { 89 | 90 | NSData *item1 = [self dataWithDEADBEEFLength:0x7F]; 91 | NSData *item2 = [self dataWithCAFEBABELength:500]; 92 | 93 | NSMutableArray *testArray = [[NSMutableArray alloc] init]; 94 | [testArray addObject:item1]; 95 | [testArray addObject:item2]; 96 | NSData *testData = [testArray berData]; 97 | 98 | NSMutableArray *testArray2 = [testData berDecode]; 99 | 100 | STAssertEqualObjects(testArray, testArray2, 101 | @"Big items decode failed"); 102 | 103 | NSData *testData2 = [testArray2 berData]; 104 | 105 | STAssertEqualObjects(testData, testData2, 106 | @"Big items failed"); 107 | } 108 | 109 | - (void)testNestedArrays 110 | { 111 | 112 | NSData *item1 = [self dataWithDEADBEEFLength:0x7F]; 113 | NSData *item2 = [self dataWithCAFEBABELength:500]; 114 | 115 | NSMutableArray *testArray = [[NSMutableArray alloc] init]; 116 | NSMutableArray *nestedArray = [[NSMutableArray alloc] init]; 117 | [nestedArray addObject:item1]; 118 | [testArray addObject:nestedArray]; 119 | [testArray addObject:item2]; 120 | NSData *testData = [testArray berData]; 121 | 122 | NSMutableArray *testArray2 = [testData berDecode]; 123 | 124 | STAssertEqualObjects(testArray, testArray2, 125 | @"Nested arrays failed"); 126 | 127 | NSData *testData2 = [testArray2 berData]; 128 | 129 | STAssertEqualObjects(testData, testData2, 130 | @"Nested arrays data failed"); 131 | } 132 | 133 | - (void)testCert 134 | { 135 | char *certBytes = "\x30\x82\x01\xd3\x30\x82\x01\x3c\xa0\x03\x02\x01\x02\x02\x01\x03\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x04\x05\x00\x30\x19\x31\x17\x30\x15\x06\x0a\x09\x92\x26\x89\x93\xf2\x2c\x64\x01\x19\x16\x07\x73\x64\x6d\x64\x65\x6d\x6f\x30\x1e\x17\x0d\x31\x32\x30\x35\x32\x31\x31\x36\x33\x31\x33\x34\x5a\x17\x0d\x31\x37\x30\x35\x32\x31\x31\x36\x33\x31\x33\x34\x5a\x30\x46\x31\x17\x30\x15\x06\x0a\x09\x92\x26\x89\x93\xf2\x2c\x64\x01\x19\x16\x07\x73\x64\x6d\x64\x65\x6d\x6f\x31\x2b\x30\x13\x06\x0a\x09\x92\x26\x89\x93\xf2\x2c\x64\x01\x01\x0c\x05\x61\x64\x6d\x69\x6e\x30\x14\x06\x03\x55\x04\x03\x0c\x0d\x41\x64\x6d\x69\x6e\x69\x73\x74\x72\x61\x74\x6f\x72\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xd2\xa2\x25\x1e\x78\x68\x14\xa8\xb4\xcc\xa1\x33\xae\xcd\xfb\xd1\xdf\x22\x5d\xbe\x87\xbc\x4b\x7f\x86\xff\x26\x91\xe3\xee\x74\x13\x98\x85\x73\x05\x24\x81\x03\xa1\x05\x19\x5f\x20\x7e\x16\x0f\xbd\x9f\x35\x82\xfb\x08\x8d\x53\x5d\x91\x99\xe7\xd9\xd7\x8e\x49\xef\xa2\x6f\x14\x63\x81\x6b\xcd\x6a\xdf\x56\x24\x27\xba\xfb\x76\x91\x19\xfa\x74\x41\x34\xad\x23\xee\xd8\xd6\x4a\x40\x69\x88\x67\x1e\xa4\x34\x11\x97\xd7\xc3\x9b\x42\xbd\x15\x69\x29\xf8\x8c\x7e\xd9\x70\xe7\xcd\x40\xc4\x18\x47\x09\x1e\x4d\x35\x73\x49\x95\xd6\xd1\x02\x03\x01\x00\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x04\x05\x00\x03\x81\x81\x00\x79\x18\xab\xf1\xb1\x51\x3b\xb3\x22\xbe\x03\x69\x3e\xc7\x17\x91\xf9\x4d\x79\x0c\xc5\x91\x7e\xc9\xc9\xd9\xd0\x29\x31\x99\x93\x05\x2b\xa2\x74\x5e\x58\xc4\x70\xd3\x36\xa8\xfd\x48\x8e\x4b\xb3\xe3\x5b\xc1\x46\x2e\x54\x08\xd3\xdb\xd4\xa8\x4e\xa7\x5c\xfc\x81\xec\x85\xe1\x0e\xfb\xf4\x0b\xa9\x87\xaa\xb7\x3e\xa5\x88\x3d\x9c\x3e\xe7\x60\xff\xc0\x1c\x36\xa0\xe5\x5a\xa7\x8b\xfe\x0b\x21\xda\xc0\x20\x72\x97\x08\xca\x9e\xd3\x20\x68\xa4\xf1\x0c\x29\xc8\x2e\x92\xff\x8b\x3c\x89\xb2\x78\x23\xf0\xb0\x81\xa3\x9f\x87\x14\x38\xb4"; 136 | //length 471 137 | NSData *testData = [NSData dataWithBytes:certBytes length:471]; 138 | NSString *testDataBase64 = [testData base64EncodedString]; 139 | NSLog(@"base64: %@", testDataBase64); 140 | BerTaggedObject *parsed = [testData berParse]; 141 | NSData *testData2 = [parsed berData]; 142 | 143 | BERPrintVisitor *printer = [[BERPrintVisitor alloc] init]; 144 | [printer visitBERInteriorNode:parsed]; 145 | NSLog(@"result: %@", printer.string); 146 | STAssertEqualObjects(testData, testData2, 147 | @"Cert binaries are not the same"); 148 | } 149 | 150 | @end 151 | -------------------------------------------------------------------------------- /Unit Tests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | --------------------------------------------------------------------------------