forked from billymeltdown/cocoafob
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCFobLicGenerator.m
145 lines (119 loc) · 3.96 KB
/
CFobLicGenerator.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
//
// CFobLicGenerator.m
// CocoaFob
//
// Created by Gleb Dolgich on 09/02/2009.
// Follow me on Twitter @glebd.
// Copyright (C) 2009-2015 PixelEspresso. All rights reserved.
// BSD License
//
#import "CFobLicGenerator.h"
#import "CFobError.h"
@interface CFobLicGenerator ()
@property (retain) __attribute__((NSObject)) SecKeyRef privateKey;
@end
@implementation CFobLicGenerator
@synthesize privateKey = _privateKey;
#pragma mark -
#pragma mark Lifecycle
#if !__has_feature(objc_arc)
- (void)finalize
{
self.privateKey = nil;
[super finalize];
}
- (void)dealloc
{
[super dealloc];
}
#endif
#pragma mark -
#pragma mark API
- (BOOL)setPrivateKey:(NSString *)privKey error:(NSError **)err
{
self.privateKey = nil;
// Validate the argument.
if (privKey == nil || [privKey length] < 1) {
CFobAssignErrorWithDescriptionAndCode(err, @"Invalid private key.", CFobErrorCodeInvalidKey);
return NO;
}
SecItemImportExportKeyParameters params = {};
SecExternalItemType keyType = kSecItemTypePrivateKey;
SecExternalFormat keyFormat = kSecFormatPEMSequence;
CFArrayRef importArray = NULL;
NSData *privKeyData = [privKey dataUsingEncoding:NSUTF8StringEncoding];
#if __has_feature(objc_arc)
CFDataRef privKeyDataRef = (__bridge CFDataRef)privKeyData;
#else
CFDataRef privKeyDataRef = (CFDataRef)privKeyData;
#endif
OSStatus importError = SecItemImport(privKeyDataRef, NULL, &keyFormat, &keyType, 0, ¶ms, NULL, &importArray);
if (importError) {
CFobAssignErrorWithDescriptionAndCode(err, @"Unable to decode key.", CFobErrorCodeCouldNotDecode);
if (importArray) {
CFRelease(importArray);
}
return NO;
}
self.privateKey = (SecKeyRef)CFArrayGetValueAtIndex(importArray, 0);
CFRelease(importArray);
return YES;
}
- (NSString *)generateRegCodeForName:(NSString *)name error:(NSError **)err
{
if (name == nil || [name length] < 1) {
CFobAssignErrorWithDescriptionAndCode(err, @"No name provided.", CFobErrorCodeNoName);
return nil;
}
if (!self.privateKey) {
CFobAssignErrorWithDescriptionAndCode(err, @"Invalid private key.", CFobErrorCodeInvalidKey);
return nil;
}
NSData *keyData = nil;
NSData *nameData = [name dataUsingEncoding:NSUTF8StringEncoding];
#if __has_feature(objc_arc)
CFDataRef nameDataRef = (__bridge CFDataRef)nameData;
#else
CFDataRef nameDataRef = (CFDataRef)nameData;
#endif
SecGroupTransformRef group = SecTransformCreateGroupTransform();
SecTransformRef signer = SecSignTransformCreate(self.privateKey, NULL);
if (signer) {
SecTransformSetAttribute(signer, kSecTransformInputAttributeName, nameDataRef, NULL);
SecTransformSetAttribute(signer, kSecDigestTypeAttribute, kSecDigestSHA1, NULL);
SecTransformRef encoder = SecEncodeTransformCreate(kSecBase32Encoding, NULL);
if (encoder) {
SecTransformConnectTransforms(signer, kSecTransformOutputAttributeName, encoder, kSecTransformInputAttributeName, group, NULL);
#if __has_feature(objc_arc)
keyData = (NSData *)CFBridgingRelease(SecTransformExecute(group, NULL));
#else
keyData = [(NSData *)SecTransformExecute(group, NULL) autorelease];
#endif
CFRelease(encoder);
}
CFRelease(signer);
}
CFRelease(group);
if (!keyData) {
CFobAssignErrorWithDescriptionAndCode(err, @"Signing failed.", CFobErrorCodeSigningFailed);
return nil;
}
NSString *b32Orig = [[NSString alloc] initWithData:keyData encoding:NSUTF8StringEncoding];
#if !__has_feature(objc_arc)
[b32Orig autorelease];
#endif
// Replace Os with 8s and Is with 9s
NSString *replacedOWith8 = [b32Orig stringByReplacingOccurrencesOfString:@"O" withString:@"8"];
NSString *b32 = [replacedOWith8 stringByReplacingOccurrencesOfString:@"I" withString:@"9"];
// Cut off the padding.
NSString *regKeyNoPadding = [b32 stringByReplacingOccurrencesOfString:@"=" withString:@""];
// Add dashes every 5 characters.
NSMutableString *serial = [NSMutableString stringWithString:regKeyNoPadding];
NSUInteger index = 5;
while (index < [serial length]) {
[serial insertString:@"-" atIndex:index];
index += 6;
}
return serial;
}
@end