ADDED LegacyPasswordGenerator.h Index: LegacyPasswordGenerator.h ================================================================== --- LegacyPasswordGenerator.h +++ LegacyPasswordGenerator.h @@ -0,0 +1,18 @@ +#import + +@interface LegacyPasswordGenerator: OFObject +{ + size_t _length; + OFString *_site; + const char *_passphrase; + unsigned char *_output; +} + +@property size_t length; +@property (copy) OFString *site; +@property const char *passphrase; +@property (readonly) unsigned char *output; + ++ (instancetype)generator; +- (void)derivePassword; +@end ADDED LegacyPasswordGenerator.m Index: LegacyPasswordGenerator.m ================================================================== --- LegacyPasswordGenerator.m +++ LegacyPasswordGenerator.m @@ -0,0 +1,51 @@ +#import "LegacyPasswordGenerator.h" + +@implementation LegacyPasswordGenerator +@synthesize length = _length, site = _site, passphrase = _passphrase; +@synthesize output = _output; + ++ (instancetype)generator +{ + return [[[self alloc] init] autorelease]; +} + +- init +{ + self = [super init]; + + _length = 16; + + return self; +} + +- (void)derivePassword +{ + OFSHA256Hash *siteHash = [OFSHA256Hash cryptoHash]; + [siteHash updateWithBuffer: [_site UTF8String] + length: [_site UTF8StringLength]]; + + if (_output != NULL) { + of_explicit_memset(_output, 0, _length); + [self freeMemory: _output]; + } + + _output = [self allocMemoryWithSize: _length + 1]; + + of_scrypt(8, 524288, 2, [siteHash digest], + [[siteHash class] digestSize], _passphrase, strlen(_passphrase), + _output, _length); + + /* + * This has a bias, however, this is what scrypt-genpass does and the + * legacy mode wants to be compatible to scrypt-genpass. + */ + _output[0] = "abcdefghijklmnopqrstuvwxyz"[_output[0] % 26]; + _output[1] = "0123456789"[_output[1] % 10]; + _output[2] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[_output[2] % 26]; + + for (size_t i = 3; i < _length; i++) + _output[i] = "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789"[_output[i] % (26 + 26 + 10)]; +} +@end Index: ScryptPWGen.m ================================================================== --- ScryptPWGen.m +++ ScryptPWGen.m @@ -1,10 +1,11 @@ #include #include #import "ScryptPWGen.h" +#import "LegacyPasswordGenerator.h" OF_APPLICATION_DELEGATE(ScryptPWGen) static void showHelp(OFStream *output, bool verbose) @@ -32,14 +33,13 @@ { '\0', nil, 0, NULL, NULL } }; OFOptionsParser *optionsParser = [OFOptionsParser parserWithOptions: options]; of_unichar_t option; - OFString *site, *prompt; + size_t length; char *passphrase; - OFSHA256Hash *siteHash; - unsigned char *output; + OFString *site, *prompt; while ((option = [optionsParser nextOption]) != '\0') { switch (option) { case 'h': showHelp(of_stdout, true); @@ -78,71 +78,54 @@ } } if (lengthStr != nil) { @try { - _length = (size_t)[lengthStr decimalValue]; + length = (size_t)[lengthStr decimalValue]; - if (_length < 3) + if (length < 3) @throw [OFInvalidFormatException exception]; } @catch (OFInvalidFormatException *e) { [of_stderr writeFormat: @"%@: Invalid length: %@\n", [OFApplication programName], lengthStr]; [OFApplication terminateWithStatus: 1]; } - } else - _length = 16; + } if ([[optionsParser remainingArguments] count] != 1) { showHelp(of_stderr, false); [OFApplication terminateWithStatus: 1]; } - site = [[optionsParser remainingArguments] firstObject]; - siteHash = [OFSHA256Hash cryptoHash]; - [siteHash updateWithBuffer: [site UTF8String] - length: [site UTF8StringLength]]; - prompt = [OFString stringWithFormat: @"Passphrase for site \"%@\": ", site]; - passphrase = getpass([prompt cStringWithEncoding: - [OFSystemInfo native8BitEncoding]]); - - output = [self allocMemoryWithSize: _length + 1]; - - of_scrypt(8, 524288, 2, [siteHash digest], - [[siteHash class] digestSize], passphrase, strlen(passphrase), - output, _length); - - of_explicit_memset(passphrase, 0, strlen(passphrase)); - - /* - * This has a bias, but is what scrypt-genpass does. This should be - * compatible to passwords generated by scrypt-genpass for now to allow - * an easy migration. - * - * This will be replaced with something better later on and the current - * code only available in legacy mode (which can be enabled using a - * flag). - */ - output[0] = "abcdefghijklmnopqrstuvwxyz"[output[0] % 26]; - output[1] = "0123456789"[output[1] % 10]; - output[2] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[output[2] % 26]; - - for (size_t i = 3; i < _length; i++) - output[i] = "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "0123456789"[output[i] % (26 + 26 + 10)]; - - output[_length] = '\n'; - - [of_stdout writeBuffer: output - length: _length + 1]; - - of_explicit_memset(output, 0, _length + 1); + + LegacyPasswordGenerator *generator = + [LegacyPasswordGenerator generator]; + generator.length = length; + generator.site = [[optionsParser remainingArguments] firstObject]; + + passphrase = getpass( + [prompt cStringWithEncoding: [OFSystemInfo native8BitEncoding]]); + @try { + generator.passphrase = passphrase; + + [generator derivePassword]; + @try { + [of_stdout writeBuffer: generator.output + length: generator.length]; + [of_stdout writeBuffer: "\n" + length: 1]; + } @finally { + of_explicit_memset(generator.output, 0, + generator.length); + } + } @finally { + of_explicit_memset(passphrase, 0, strlen(passphrase)); + } [OFApplication terminate]; } @end