MYASN1Object.m
author Jens Alfke <jens@mooseyard.com>
Sat Jun 06 15:01:28 2009 -0700 (2009-06-06)
changeset 21 2c300b15b381
parent 20 df9da0f6b358
permissions -rw-r--r--
* Created class MYCertificateRequest, factored out of MYCertificateInfo.
* Added method to create a MYIdentity directly from a MYCertificateRequest.
* Added raw modulus+exponent accessor and initializer for MYPublicKey.
* Removed obsolete MYCertGen code, and the MYPrivateKey identity-creation method that used it.
jens@16
     1
//
jens@16
     2
//  MYASN1Object.m
jens@16
     3
//  MYCrypto-iPhone
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@20
     9
// Reference:
jens@20
    10
// <http://www.columbia.edu/~ariel/ssleay/layman.html> "Layman's Guide To ASN.1/BER/DER"
jens@20
    11
jens@16
    12
#import "MYASN1Object.h"
jens@16
    13
jens@16
    14
jens@16
    15
@implementation MYASN1Object
jens@16
    16
jens@16
    17
jens@16
    18
- (id) initWithTag: (uint32_t)tag
jens@16
    19
           ofClass: (uint8_t)tagClass 
jens@16
    20
       constructed: (BOOL)constructed
jens@16
    21
             value: (NSData*)value
jens@16
    22
{
jens@16
    23
    Assert(value);
jens@16
    24
    self = [super init];
jens@16
    25
    if (self != nil) {
jens@16
    26
        _tag = tag;
jens@16
    27
        _tagClass = tagClass;
jens@16
    28
        _constructed = constructed;
jens@16
    29
        _value = [value copy];
jens@16
    30
    }
jens@16
    31
    return self;
jens@16
    32
}
jens@16
    33
jens@16
    34
- (id) initWithTag: (uint32_t)tag
jens@16
    35
           ofClass: (uint8_t)tagClass 
jens@16
    36
        components: (NSArray*)components
jens@16
    37
{
jens@16
    38
    Assert(components);
jens@16
    39
    self = [super init];
jens@16
    40
    if (self != nil) {
jens@16
    41
        _tag = tag;
jens@16
    42
        _tagClass = tagClass;
jens@16
    43
        _constructed = YES;
jens@16
    44
        _components = [components copy];
jens@16
    45
    }
jens@16
    46
    return self;
jens@16
    47
}
jens@16
    48
jens@16
    49
- (void) dealloc
jens@16
    50
{
jens@16
    51
    [_value release];
jens@16
    52
    [_components release];
jens@16
    53
    [super dealloc];
jens@16
    54
}
jens@16
    55
jens@16
    56
jens@16
    57
@synthesize tag=_tag, tagClass=_tagClass, constructed=_constructed, value=_value, components=_components;
jens@16
    58
jens@16
    59
jens@16
    60
- (NSString*)description {
jens@16
    61
    if (_components)
jens@16
    62
        return $sprintf(@"%@[%hhu/%u/%u]%@", self.class, _tagClass,(unsigned)_constructed,_tag, _components);
jens@16
    63
    else
jens@16
    64
        return $sprintf(@"%@[%hhu/%u/%u, %u bytes]", self.class, _tagClass,(unsigned)_constructed,_tag, _value.length);
jens@16
    65
}
jens@16
    66
jens@19
    67
- (BOOL) isEqual: (id)object {
jens@19
    68
    return [object isKindOfClass: [MYASN1Object class]] 
jens@19
    69
        && _tag==[object tag] 
jens@19
    70
        && _tagClass==[object tagClass] 
jens@19
    71
        && _constructed==[object constructed] 
jens@19
    72
        && $equal(_value,[object value])
jens@19
    73
        && $equal(_components,[object components]);
jens@19
    74
}
jens@19
    75
jens@16
    76
static void dump(id object, NSMutableString *output, NSString *indent) {
jens@16
    77
    if ([object isKindOfClass: [MYASN1Object class]]) {
jens@16
    78
        MYASN1Object *asn1Obj = object;
jens@16
    79
        [output appendFormat: @"%@%@[%hhu/%u]", indent, asn1Obj.class, asn1Obj.tagClass,asn1Obj.tag];
jens@16
    80
        if (asn1Obj.components) {
jens@16
    81
            [output appendString: @":\n"];
jens@16
    82
            NSString *subindent = [indent stringByAppendingString: @"    "];
jens@16
    83
            for (id o in asn1Obj.components)
jens@16
    84
                dump(o,output, subindent);
jens@16
    85
        } else
jens@16
    86
            [output appendFormat: @" %@\n", asn1Obj.value];
jens@16
    87
    } else if([object respondsToSelector: @selector(objectEnumerator)]) {
jens@16
    88
        [output appendString: indent];
jens@16
    89
        if ([object isKindOfClass: [NSArray class]])
jens@16
    90
            [output appendString: @"Sequence:\n"];
jens@16
    91
        else if ([object isKindOfClass: [NSSet class]])
jens@16
    92
            [output appendString: @"Set:\n"];
jens@16
    93
        else
jens@16
    94
            [output appendFormat: @"%@:\n", [object class]];
jens@16
    95
        NSString *subindent = [indent stringByAppendingString: @"    "];
jens@16
    96
        for (id o in object)
jens@16
    97
            dump(o,output, subindent);
jens@16
    98
    } else {
jens@16
    99
        [output appendFormat: @"%@%@\n", indent, object];
jens@16
   100
    }
jens@16
   101
}
jens@16
   102
jens@16
   103
+ (NSString*) dump: (id)object {
jens@16
   104
    NSMutableString *output = [NSMutableString stringWithCapacity: 512];
jens@16
   105
    dump(object,output,@"");
jens@16
   106
    return output;
jens@16
   107
}
jens@16
   108
jens@16
   109
jens@16
   110
@end
jens@16
   111
jens@16
   112
jens@16
   113
jens@16
   114
@implementation MYASN1BigInteger
jens@16
   115
jens@21
   116
- (id) initWithSignedData: (NSData*)signedData {
jens@21
   117
    // Skip unnecessary leading 00 (if positive) or FF (if negative) bytes:
jens@21
   118
    const SInt8 *start = signedData.bytes, *last = start + signedData.length - 1;
jens@21
   119
    const SInt8 *pos = start;
jens@21
   120
    while (pos<last && ((pos[0]==0 && pos[1]>=0) || (pos[0]==-1 && pos[1]<0)))
jens@21
   121
        pos++;
jens@21
   122
    if (pos > start)
jens@21
   123
        signedData = [NSData dataWithBytes: pos length: last-pos+1];
jens@21
   124
    return [self initWithTag: 2 ofClass: 0 constructed: NO value: signedData];
jens@21
   125
}
jens@21
   126
jens@21
   127
- (id) initWithUnsignedData: (NSData*) unsignedData {
jens@21
   128
    const UInt8 *start = unsignedData.bytes;
jens@21
   129
    if (*start >= 0x80) {
jens@21
   130
        // Prefix with 00 byte so high bit isn't misinterpreted as a sign bit:
jens@21
   131
        NSMutableData *fixedData = [NSMutableData dataWithCapacity: unsignedData.length + 1];
jens@21
   132
        UInt8 zero = 0;
jens@21
   133
        [fixedData appendBytes: &zero length: 1];
jens@21
   134
        [fixedData appendData: unsignedData];
jens@21
   135
        unsignedData = fixedData;
jens@21
   136
    }
jens@21
   137
    return [self initWithSignedData: unsignedData];
jens@21
   138
}
jens@21
   139
jens@21
   140
- (NSData*) signedData {
jens@21
   141
    return self.value;
jens@21
   142
}
jens@21
   143
jens@21
   144
- (NSData*) unsignedData {
jens@21
   145
    // Strip any leading zero bytes that were inserted for sign-bit padding:
jens@21
   146
    NSData *data = self.value;
jens@21
   147
    const UInt8 *start = data.bytes, *last = start + data.length - 1;
jens@21
   148
    const UInt8 *pos = start;
jens@21
   149
    while (pos<last && *pos==0)
jens@21
   150
        pos++;
jens@21
   151
    if (pos > start)
jens@21
   152
        data = [NSData dataWithBytes: pos length: last-pos+1];
jens@21
   153
    return data;
jens@21
   154
}
jens@21
   155
jens@16
   156
@end
jens@16
   157
jens@16
   158
jens@16
   159
jens@16
   160
@implementation MYBitString
jens@16
   161
jens@16
   162
jens@19
   163
- (id)initWithBits: (NSData*)bits count: (unsigned)bitCount {
jens@16
   164
    Assert(bits);
jens@16
   165
    Assert(bitCount <= 8*bits.length);
jens@16
   166
    self = [super init];
jens@16
   167
    if (self != nil) {
jens@16
   168
        _bits = [bits copy];
jens@16
   169
        _bitCount = bitCount;
jens@16
   170
    }
jens@16
   171
    return self;
jens@16
   172
}
jens@16
   173
jens@19
   174
+ (MYBitString*) bitStringWithData: (NSData*)bits {
jens@19
   175
    return [[[self alloc] initWithBits: bits count: 8*bits.length] autorelease];
jens@19
   176
}
jens@19
   177
jens@16
   178
- (void) dealloc
jens@16
   179
{
jens@16
   180
    [_bits release];
jens@16
   181
    [super dealloc];
jens@16
   182
}
jens@16
   183
jens@16
   184
@synthesize bits=_bits, bitCount=_bitCount;
jens@16
   185
jens@17
   186
- (NSString*) description {
jens@17
   187
    return $sprintf(@"%@%@", [self class], _bits);
jens@17
   188
}
jens@17
   189
jens@19
   190
- (unsigned) hash {
jens@19
   191
    return _bits.hash ^ _bitCount;
jens@19
   192
}
jens@19
   193
jens@19
   194
- (BOOL) isEqual: (id)object {
jens@19
   195
    return [object isKindOfClass: [MYBitString class]] 
jens@19
   196
        && _bitCount==[object bitCount] 
jens@19
   197
        && [_bits isEqual: [object bits]];
jens@19
   198
}
jens@19
   199
jens@16
   200
@end
jens@21
   201
jens@21
   202
jens@21
   203
jens@21
   204
/*
jens@21
   205
 Copyright (c) 2009, Jens Alfke <jens@mooseyard.com>. All rights reserved.
jens@21
   206
 
jens@21
   207
 Redistribution and use in source and binary forms, with or without modification, are permitted
jens@21
   208
 provided that the following conditions are met:
jens@21
   209
 
jens@21
   210
 * Redistributions of source code must retain the above copyright notice, this list of conditions
jens@21
   211
 and the following disclaimer.
jens@21
   212
 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
jens@21
   213
 and the following disclaimer in the documentation and/or other materials provided with the
jens@21
   214
 distribution.
jens@21
   215
 
jens@21
   216
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
jens@21
   217
 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
jens@21
   218
 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
jens@21
   219
 BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
jens@21
   220
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
jens@21
   221
  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
jens@21
   222
 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
jens@21
   223
 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
jens@21
   224
 */