Permalink
Browse files

Merge branch 'develop'

  • Loading branch information...
2 parents 989ddf4 + e019fe5 commit 6848b5825a2d042296b4f45e7b38ba3f078f04f2 Danny Greg committed Aug 24, 2010
View
@@ -0,0 +1,20 @@
+//
+// CFobError.h
+// cocoafob
+//
+// Created by Danny Greg on 24/08/2010.
+// Copyright 2010 Realmac Software. All rights reserved.
+// Licensed under CC Attribution Licence 3.0 <http://creativecommons.org/licenses/by/3.0/>
+//
+
+#import <Foundation/Foundation.h>
+
+enum _CFobErrorCode {
+ CFobErrorCodeInvalidKey = -1,
+ CFobErrorCodeCouldNotDecode = -2,
+ CFobErrorCodeSigningFailed = -3,
+ CFobErrorCodeCouldNotEncode = -4,
+ CFobErrorCodeNoName = -5,
+};
+
+void CFobAssignErrorWithDescriptionAndCode(NSError **err, NSString *description, NSInteger code);
View
@@ -0,0 +1,18 @@
+//
+// CFobError.h
+// cocoafob
+//
+// Created by Danny Greg on 24/08/2010.
+// Copyright 2010 Realmac Software. All rights reserved.
+// Licensed under CC Attribution Licence 3.0 <http://creativecommons.org/licenses/by/3.0/>
+//
+
+#import "CFobError.h"
+
+#import "CFobLicVerifier.h"
+
+void CFobAssignErrorWithDescriptionAndCode(NSError **err, NSString *description, NSInteger code)
+{
+ if (err != NULL)
+ *err = [NSError errorWithDomain:[[NSBundle bundleForClass:[CFobLicVerifier class]] bundleIdentifier] code:code userInfo:[NSDictionary dictionaryWithObject:NSLocalizedStringFromTableInBundle(description, nil, [NSBundle bundleForClass:[CFobLicVerifier class]], nil) forKey:NSLocalizedDescriptionKey]];
+}
View
@@ -18,49 +18,25 @@
@discussion Given user name and DSA private key, generates a human-readable registration code.
*/
@interface CFobLicGenerator : NSObject {
- DSA *dsa;
- NSString *regName;
- NSString *regCode;
- NSString *lastError;
+ DSA *_dsa;
}
-@property (nonatomic, copy) NSString *regName;
-@property (nonatomic, copy) NSString *regCode;
-@property (nonatomic, copy) NSString *lastError;
-
-/*!
- @method generatorWithPrivateKey:
- @abstract Creates a new registration code generator given DSA private key.
- @discussion Use this class method to create an autoreleased registration code generator.
- @param privKey PEM-encoded non-encrypted DSA private key.
- @result A new autoreleased registration code generator object.
-*/
-+ (id)generatorWithPrivateKey:(NSString *)privKey;
-
-/*!
- @method initWithPrivateKey:
- @abstract Designated initializer that takes a DSA private key.
- @discussion Initializes registration code generator using a DSA private key.
- @param privKey PEM-encoded non-encrypted DSA private key.
- @result An initialized registration code generator object.
-*/
-- (id)initWithPrivateKey:(NSString *)privKey;
-
/*!
@method setPrivateKey:
@abstract Sets a new DSA private key.
@discussion Sets a new DSA private key to be used for subsequent generated registration codes.
@param privKey PEM-encoded non-encrypted DSA private key.
@result YES on success, NO on error.
*/
-- (BOOL)setPrivateKey:(NSString *)privKey;
+- (BOOL)setPrivateKey:(NSString *)privKey error:(NSError **)err;
/*!
@method generate
@abstract Generates a registration code from regName property.
@discussion Takes regName property and DSA private key and generates a new registration code that is placed in regCode property.
- @result YES on success, NO on error.
+ @param The name or registration string to generate a serial number for.
+ @result The serial number as a string, nil on failure.
*/
-- (BOOL)generate;
+- (NSString *)generateRegCodeForName:(NSString *)name error:(NSError **)err;
@end
View
@@ -8,136 +8,151 @@
// Licensed under CC Attribution Licence 3.0 <http://creativecommons.org/licenses/by/3.0/>
//
+#import "CFobLicGenerator.h"
+
+#import "CFobError.h"
+
#import "NSData+PECrypt.h"
#import "NSString+PECrypt.h"
-#import "CFobLicGenerator.h"
+
#import <openssl/evp.h>
#import <openssl/err.h>
#import <openssl/pem.h>
+//***************************************************************************
@interface CFobLicGenerator ()
+
+@property (nonatomic, assign) DSA *dsa;
+
- (void)initOpenSSL;
- (void)shutdownOpenSSL;
+
@end
@implementation CFobLicGenerator
-@synthesize regName;
-@synthesize regCode;
-@synthesize lastError;
-
-#pragma mark -
-#pragma mark Class methods
-
-+ (id)generatorWithPrivateKey:(NSString *)privKey {
- return [[[CFobLicGenerator alloc] initWithPrivateKey:privKey] autorelease];
-}
+@synthesize dsa = _dsa;
#pragma mark -
#pragma mark Lifecycle
-- (id)init {
- return [self initWithPrivateKey:nil];
-}
-
-- (id)initWithPrivateKey:(NSString *)privKey {
- if (![super init])
+- (id)init
+{
+ if ([super init] == nil)
return nil;
+
[self initOpenSSL];
- [self setPrivateKey:privKey];
+
return self;
}
- (void)finalize
{
- if (dsa)
- DSA_free(dsa);
+ if (self.dsa)
+ DSA_free(self.dsa);
+
[self shutdownOpenSSL];
[super finalize];
}
-- (void)dealloc {
- if (dsa)
- DSA_free(dsa);
- self.regCode = nil;
- self.regName = nil;
- self.lastError = nil;
+- (void)dealloc
+{
+ if (self.dsa)
+ DSA_free(self.dsa);
+
[self shutdownOpenSSL];
[super dealloc];
}
#pragma mark -
#pragma mark API
-- (BOOL)setPrivateKey:(NSString *)privKey {
+- (BOOL)setPrivateKey:(NSString *)privKey error:(NSError **)err
+{
// Validate the argument.
- if (!privKey || ![privKey length]) {
- self.lastError = @"Invalid key";
+ if (privKey == nil || [privKey length] < 1) {
+ CFobAssignErrorWithDescriptionAndCode(err, @"Invalid private key.", CFobErrorCodeInvalidKey);
return NO;
}
- if (dsa)
- DSA_free(dsa);
- dsa = DSA_new();
+
+ if (self.dsa)
+ DSA_free(self.dsa);
+ self.dsa = DSA_new();
// Prepare BIO to read PEM-encoded private key from memory.
// Prepare buffer given NSString.
const char *privkeyCString = [privKey UTF8String];
BIO *bio = BIO_new_mem_buf((void *)privkeyCString, -1);
- PEM_read_bio_DSAPrivateKey(bio, &dsa, NULL, NULL);
+ PEM_read_bio_DSAPrivateKey(bio, &_dsa, NULL, NULL);
BOOL result = YES;
- if (!dsa->priv_key) {
- self.lastError = @"Unable to decode key";
+ if (!self.dsa->priv_key) {
+ CFobAssignErrorWithDescriptionAndCode(err, @"Unable to decode key.", CFobErrorCodeCouldNotDecode);
result = NO;
}
// Cleanup BIO
BIO_vfree(bio);
return result;
}
-- (BOOL)generate {
- if (![regName length] || !dsa || !dsa->priv_key)
- return NO;
- NSData *digest = [regName sha1];
+- (NSString *)generateRegCodeForName:(NSString *)name error:(NSError **)err
+{
+ if (name == nil || [name length] < 1) {
+ CFobAssignErrorWithDescriptionAndCode(err, @"No name provided.", CFobErrorCodeNoName);
+ return nil;
+ }
+
+ if (!self.dsa || !self.dsa->priv_key) {
+ CFobAssignErrorWithDescriptionAndCode(err, @"Invalid private key.", CFobErrorCodeInvalidKey);
+ return nil;
+ }
+
+ NSData *digest = [name sha1];
unsigned int siglen;
unsigned char sig[100];
- int check = DSA_sign(NID_sha1, [digest bytes], [digest length], sig, &siglen, dsa);
+ int check = DSA_sign(NID_sha1, [digest bytes], [digest length], sig, &siglen, self.dsa);
if (!check) {
- self.lastError = @"Signing failed";
+ CFobAssignErrorWithDescriptionAndCode(err, @"Signing failed.", CFobErrorCodeSigningFailed);
return NO;
}
+
// Encode signature in Base32
NSData *signature = [NSData dataWithBytes:sig length:siglen];
NSString *b32Orig = [signature base32];
if (!b32Orig || ![b32Orig length]) {
- self.lastError = @"Unable to encode in base32";
+ CFobAssignErrorWithDescriptionAndCode(err, @"Unable to encode in base32", CFobErrorCodeCouldNotEncode);
return NO;
}
+
// 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 stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"="]];
+ 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;
}
- self.regCode = serial;
- return YES;
+
+ return serial;
}
#pragma mark -
#pragma mark OpenSSL Lifecycle
-- (void)initOpenSSL {
+- (void)initOpenSSL
+{
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
}
-- (void)shutdownOpenSSL {
+- (void)shutdownOpenSSL
+{
EVP_cleanup();
ERR_free_strings();
}
View
@@ -18,26 +18,11 @@
@discussion Verifies CocoaFob-style registration key given licensing information (for example, application name, user name, and number of copies as suggested in Potion Store) and signature in human-readable format. A signature is a base32-encoded bignum with padding removed and dashes inserted.
*/
@interface CFobLicVerifier : NSObject {
- DSA *dsa;
- NSString *regName;
- NSString *regCode;
- NSArray *blacklist;
- NSString *lastError;
+ DSA *_dsa;
+ NSArray *_blacklist;
}
-@property (nonatomic, copy) NSString *regName;
-@property (nonatomic, copy) NSString *regCode;
-@property (nonatomic, retain) NSArray *blacklist;
-@property (nonatomic, copy) NSString *lastError;
-
-/*!
- @method verifierWithPublicKey:
- @abstract Creates a new registration code verifier object given a DSA public key.
- @discussion Creates a new registration code verifier object. Use setRegName: and setRegKey: on it, then call verify to verify registration key.
- @param pubKey A DSA public key in PEM encoding. See completePublicKeyPEM: for help on how to construct a PEM-encoded DSA public key.
- @result A new autoreleased registration code verifier object.
-*/
-+ (id)verifierWithPublicKey:(NSString *)pubKey;
+@property (nonatomic, copy) NSArray *blacklist;
/*!
@method completePublicKeyPEM:
@@ -49,29 +34,20 @@
+ (NSString *)completePublicKeyPEM:(NSString *)partialPEM;
/*!
- @method initWithPublicKey:
- @abstract Designated initialiser.
- @discussion Initialises a newly allocated registration code verifier object with a PEM-encoded DSA public key.
- @param pubKey A PEM-encoded DSA public key. See completePublicKeyPEM: for help on how to constuct a PEM-encoded DSA key string from base64-encoded lines.
- @result An initialised registration code verifier object.
-*/
-- (id)initWithPublicKey:(NSString *)pubKey;
-
-/*!
@method setPubKey:
@abstract Sets DSA public key to the passed key in PEM format.
@discussion Sets DSA public key in the verifier object to the argument which is a PEM-encoded DSA public key.
@param pubKey PEM-encoded DSA public key.
- @result YES on success, NO on error (check lastError property).
+ @result YES on success, NO on error (err may or may not be populated).
*/
-- (BOOL)setPublicKey:(NSString *)pubKey;
+- (BOOL)setPublicKey:(NSString *)pubKey error:(NSError **)err;
/*!
@method verify
@abstract Verifies registration code in the regName property using public DSA key.
@discussion Takes regName and regCode properties and verifies regCode against regName using public DSA certificate.
- @result YES if regCode is valid, NO if not.
+ @result YES if regCode is valid, NO if not. If an error was recovered it will be set in the err paramater
*/
-- (BOOL)verify;
+- (BOOL)verifyRegCode:(NSString *)regCode forName:(NSString *)name error:(NSError **)err;
@end
Oops, something went wrong.

0 comments on commit 6848b58

Please sign in to comment.