|
8 | 8 | // Licensed under CC Attribution Licence 3.0 <http://creativecommons.org/licenses/by/3.0/>
|
9 | 9 | //
|
10 | 10 |
|
| 11 | +#import "CFobLicGenerator.h" |
| 12 | + |
| 13 | +#import "CFobError.h" |
| 14 | + |
11 | 15 | #import "NSData+PECrypt.h"
|
12 | 16 | #import "NSString+PECrypt.h"
|
13 |
| -#import "CFobLicGenerator.h" |
| 17 | + |
14 | 18 | #import <openssl/evp.h>
|
15 | 19 | #import <openssl/err.h>
|
16 | 20 | #import <openssl/pem.h>
|
17 | 21 |
|
| 22 | +//*************************************************************************** |
18 | 23 |
|
19 | 24 | @interface CFobLicGenerator ()
|
| 25 | + |
| 26 | +@property (nonatomic, assign) DSA *dsa; |
| 27 | + |
20 | 28 | - (void)initOpenSSL;
|
21 | 29 | - (void)shutdownOpenSSL;
|
| 30 | + |
22 | 31 | @end
|
23 | 32 |
|
24 | 33 |
|
25 | 34 | @implementation CFobLicGenerator
|
26 | 35 |
|
27 |
| -@synthesize regName; |
28 |
| -@synthesize regCode; |
29 |
| -@synthesize lastError; |
30 |
| - |
31 |
| -#pragma mark - |
32 |
| -#pragma mark Class methods |
33 |
| - |
34 |
| -+ (id)generatorWithPrivateKey:(NSString *)privKey { |
35 |
| - return [[[CFobLicGenerator alloc] initWithPrivateKey:privKey] autorelease]; |
36 |
| -} |
| 36 | +@synthesize dsa = _dsa; |
37 | 37 |
|
38 | 38 | #pragma mark -
|
39 | 39 | #pragma mark Lifecycle
|
40 | 40 |
|
41 |
| -- (id)init { |
42 |
| - return [self initWithPrivateKey:nil]; |
43 |
| -} |
44 |
| - |
45 |
| -- (id)initWithPrivateKey:(NSString *)privKey { |
46 |
| - if (![super init]) |
| 41 | +- (id)init |
| 42 | +{ |
| 43 | + if ([super init] == nil) |
47 | 44 | return nil;
|
| 45 | + |
48 | 46 | [self initOpenSSL];
|
49 |
| - [self setPrivateKey:privKey]; |
| 47 | + |
50 | 48 | return self;
|
51 | 49 | }
|
52 | 50 |
|
53 | 51 | - (void)finalize
|
54 | 52 | {
|
55 |
| - if (dsa) |
56 |
| - DSA_free(dsa); |
| 53 | + if (self.dsa) |
| 54 | + DSA_free(self.dsa); |
| 55 | + |
57 | 56 | [self shutdownOpenSSL];
|
58 | 57 | [super finalize];
|
59 | 58 | }
|
60 | 59 |
|
61 |
| -- (void)dealloc { |
62 |
| - if (dsa) |
63 |
| - DSA_free(dsa); |
64 |
| - self.regCode = nil; |
65 |
| - self.regName = nil; |
66 |
| - self.lastError = nil; |
| 60 | +- (void)dealloc |
| 61 | +{ |
| 62 | + if (self.dsa) |
| 63 | + DSA_free(self.dsa); |
| 64 | + |
67 | 65 | [self shutdownOpenSSL];
|
68 | 66 | [super dealloc];
|
69 | 67 | }
|
70 | 68 |
|
71 | 69 | #pragma mark -
|
72 | 70 | #pragma mark API
|
73 | 71 |
|
74 |
| -- (BOOL)setPrivateKey:(NSString *)privKey { |
| 72 | +- (BOOL)setPrivateKey:(NSString *)privKey error:(NSError **)err |
| 73 | +{ |
75 | 74 | // Validate the argument.
|
76 |
| - if (!privKey || ![privKey length]) { |
77 |
| - self.lastError = @"Invalid key"; |
| 75 | + if (privKey == nil || [privKey length] < 1) { |
| 76 | + CFobAssignErrorWithDescriptionAndCode(err, @"Invalid private key.", CFobErrorCodeInvalidKey); |
78 | 77 | return NO;
|
79 | 78 | }
|
80 |
| - if (dsa) |
81 |
| - DSA_free(dsa); |
82 |
| - dsa = DSA_new(); |
| 79 | + |
| 80 | + if (self.dsa) |
| 81 | + DSA_free(self.dsa); |
| 82 | + self.dsa = DSA_new(); |
83 | 83 | // Prepare BIO to read PEM-encoded private key from memory.
|
84 | 84 | // Prepare buffer given NSString.
|
85 | 85 | const char *privkeyCString = [privKey UTF8String];
|
86 | 86 | BIO *bio = BIO_new_mem_buf((void *)privkeyCString, -1);
|
87 |
| - PEM_read_bio_DSAPrivateKey(bio, &dsa, NULL, NULL); |
| 87 | + PEM_read_bio_DSAPrivateKey(bio, &_dsa, NULL, NULL); |
88 | 88 | BOOL result = YES;
|
89 |
| - if (!dsa->priv_key) { |
90 |
| - self.lastError = @"Unable to decode key"; |
| 89 | + if (!self.dsa->priv_key) { |
| 90 | + CFobAssignErrorWithDescriptionAndCode(err, @"Unable to decode key.", CFobErrorCodeCouldNotDecode); |
91 | 91 | result = NO;
|
92 | 92 | }
|
93 | 93 | // Cleanup BIO
|
94 | 94 | BIO_vfree(bio);
|
95 | 95 | return result;
|
96 | 96 | }
|
97 | 97 |
|
98 |
| -- (BOOL)generate { |
99 |
| - if (![regName length] || !dsa || !dsa->priv_key) |
100 |
| - return NO; |
101 |
| - NSData *digest = [regName sha1]; |
| 98 | +- (NSString *)generateRegCodeForName:(NSString *)name error:(NSError **)err |
| 99 | +{ |
| 100 | + if (name == nil || [name length] < 1) { |
| 101 | + CFobAssignErrorWithDescriptionAndCode(err, @"No name provided.", CFobErrorCodeNoName); |
| 102 | + return nil; |
| 103 | + } |
| 104 | + |
| 105 | + if (!self.dsa || !self.dsa->priv_key) { |
| 106 | + CFobAssignErrorWithDescriptionAndCode(err, @"Invalid private key.", CFobErrorCodeInvalidKey); |
| 107 | + return nil; |
| 108 | + } |
| 109 | + |
| 110 | + NSData *digest = [name sha1]; |
102 | 111 | unsigned int siglen;
|
103 | 112 | unsigned char sig[100];
|
104 |
| - int check = DSA_sign(NID_sha1, [digest bytes], [digest length], sig, &siglen, dsa); |
| 113 | + int check = DSA_sign(NID_sha1, [digest bytes], [digest length], sig, &siglen, self.dsa); |
105 | 114 | if (!check) {
|
106 |
| - self.lastError = @"Signing failed"; |
| 115 | + CFobAssignErrorWithDescriptionAndCode(err, @"Signing failed.", CFobErrorCodeSigningFailed); |
107 | 116 | return NO;
|
108 | 117 | }
|
| 118 | + |
109 | 119 | // Encode signature in Base32
|
110 | 120 | NSData *signature = [NSData dataWithBytes:sig length:siglen];
|
111 | 121 | NSString *b32Orig = [signature base32];
|
112 | 122 | if (!b32Orig || ![b32Orig length]) {
|
113 |
| - self.lastError = @"Unable to encode in base32"; |
| 123 | + CFobAssignErrorWithDescriptionAndCode(err, @"Unable to encode in base32", CFobErrorCodeCouldNotEncode); |
114 | 124 | return NO;
|
115 | 125 | }
|
| 126 | + |
116 | 127 | // Replace Os with 8s and Is with 9s
|
117 | 128 | NSString *replacedOWith8 = [b32Orig stringByReplacingOccurrencesOfString:@"O" withString:@"8"];
|
118 | 129 | NSString *b32 = [replacedOWith8 stringByReplacingOccurrencesOfString:@"I" withString:@"9"];
|
| 130 | + |
119 | 131 | // Cut off the padding.
|
120 |
| - NSString *regKeyNoPadding = [b32 stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"="]]; |
| 132 | + NSString *regKeyNoPadding = [b32 stringByReplacingOccurrencesOfString:@"=" withString:@""]; |
| 133 | + |
121 | 134 | // Add dashes every 5 characters.
|
122 | 135 | NSMutableString *serial = [NSMutableString stringWithString:regKeyNoPadding];
|
123 | 136 | NSUInteger index = 5;
|
124 | 137 | while (index < [serial length]) {
|
125 | 138 | [serial insertString:@"-" atIndex:index];
|
126 | 139 | index += 6;
|
127 | 140 | }
|
128 |
| - self.regCode = serial; |
129 |
| - return YES; |
| 141 | + |
| 142 | + return serial; |
130 | 143 | }
|
131 | 144 |
|
132 | 145 | #pragma mark -
|
133 | 146 | #pragma mark OpenSSL Lifecycle
|
134 | 147 |
|
135 |
| -- (void)initOpenSSL { |
| 148 | +- (void)initOpenSSL |
| 149 | +{ |
136 | 150 | OpenSSL_add_all_algorithms();
|
137 | 151 | ERR_load_crypto_strings();
|
138 | 152 | }
|
139 | 153 |
|
140 |
| -- (void)shutdownOpenSSL { |
| 154 | +- (void)shutdownOpenSSL |
| 155 | +{ |
141 | 156 | EVP_cleanup();
|
142 | 157 | ERR_free_strings();
|
143 | 158 | }
|
|
0 commit comments