Index: LegacyPasswordGenerator.h ================================================================== --- LegacyPasswordGenerator.h +++ LegacyPasswordGenerator.h @@ -18,23 +18,15 @@ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -#import +#import "PasswordGenerator.h" -@interface LegacyPasswordGenerator: OFObject +@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 Index: LegacyPasswordGenerator.m ================================================================== --- LegacyPasswordGenerator.m +++ LegacyPasswordGenerator.m @@ -21,12 +21,11 @@ */ #import "LegacyPasswordGenerator.h" @implementation LegacyPasswordGenerator -@synthesize length = _length, site = _site, passphrase = _passphrase; -@synthesize output = _output; +@synthesize site = _site, passphrase = _passphrase, output = _output; + (instancetype)generator { return [[[self alloc] init] autorelease]; } @@ -37,10 +36,23 @@ _length = 16; return self; } + +- (void)setLength: (size_t)length +{ + if (length < 3) + @throw [OFInvalidArgumentException exception]; + + _length = length; +} + +- (size_t)length +{ + return _length; +} - (void)derivePassword { OFSHA256Hash *siteHash = [OFSHA256Hash cryptoHash]; [siteHash updateWithBuffer: [_site UTF8String] ADDED NewPasswordGenerator.h Index: NewPasswordGenerator.h ================================================================== --- /dev/null +++ NewPasswordGenerator.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2016, Jonathan Schleifer + * + * https://heap.zone/git/?p=scrypt-pwgen.git + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#import "PasswordGenerator.h" + +@interface NewPasswordGenerator: OFObject +{ + size_t _length; + OFString *_site; + const char *_passphrase; + unsigned char *_output; +} +@end ADDED NewPasswordGenerator.m Index: NewPasswordGenerator.m ================================================================== --- /dev/null +++ NewPasswordGenerator.m @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2016, Jonathan Schleifer + * + * https://heap.zone/git/?p=scrypt-pwgen.git + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#import "NewPasswordGenerator.h" + +@implementation NewPasswordGenerator +@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 +{ + OFSHA384Hash *siteHash = [OFSHA384Hash 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); + + for (size_t i = 0; i < _length; i++) + _output[i] = + "0123456789" + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + ".!"[_output[i] & 0x3F]; +} +@end ADDED PasswordGenerator.h Index: PasswordGenerator.h ================================================================== --- /dev/null +++ PasswordGenerator.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2016, Jonathan Schleifer + * + * https://heap.zone/git/?p=scrypt-pwgen.git + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#import + +@protocol PasswordGenerator +@property size_t length; +@property (copy) OFString *site; +@property const char *passphrase; +@property (readonly) unsigned char *output; + ++ (instancetype)generator; +- (void)derivePassword; +@end Index: ScryptPWGen.h ================================================================== --- ScryptPWGen.h +++ ScryptPWGen.h @@ -23,8 +23,8 @@ #import @interface ScryptPWGen: OFObject { size_t _length; - bool _repeat; + bool _legacy, _repeat; } @end Index: ScryptPWGen.m ================================================================== --- ScryptPWGen.m +++ ScryptPWGen.m @@ -21,10 +21,11 @@ */ #include #import "ScryptPWGen.h" +#import "NewPasswordGenerator.h" #import "LegacyPasswordGenerator.h" OF_APPLICATION_DELEGATE(ScryptPWGen) static void @@ -37,10 +38,12 @@ [output writeString: @"\n" @"Options:\n" @" -h --help Show this help\n" @" -l --length Length for the derived password\n" + @" -L --legacy Use the legacy algorithm " + @"(compatible with scrypt-genpass)\n" @" -r --repeat Repeat input\n"]; } @implementation ScryptPWGen - (void)applicationDidFinishLaunching @@ -47,17 +50,17 @@ { OFString *lengthStr; const of_options_parser_option_t options[] = { { 'h', @"help", 0, NULL, NULL }, { 'l', @"length", 1, NULL, &lengthStr }, + { 'L', @"legacy", 0, &_legacy, NULL }, { 'r', @"repeat", 0, &_repeat, NULL }, { '\0', nil, 0, NULL, NULL } }; OFOptionsParser *optionsParser = [OFOptionsParser parserWithOptions: options]; of_unichar_t option; - size_t length; char *passphrase; OFString *site, *prompt; while ((option = [optionsParser nextOption]) != '\0') { switch (option) { @@ -96,39 +99,45 @@ [OFApplication terminateWithStatus: 1]; break; } } + if ([[optionsParser remainingArguments] count] != 1) { + showHelp(of_stderr, false); + + [OFApplication terminateWithStatus: 1]; + } + + site = [[optionsParser remainingArguments] firstObject]; + prompt = [OFString stringWithFormat: @"Passphrase for site \"%@\": ", + site]; + + id generator = (_legacy + ? [LegacyPasswordGenerator generator] + : [NewPasswordGenerator generator]); + generator.site = [[optionsParser remainingArguments] firstObject]; + if (lengthStr != nil) { - @try { - length = (size_t)[lengthStr decimalValue]; + bool invalid = false; - if (length < 3) - @throw [OFInvalidFormatException exception]; + @try { + generator.length = (size_t)[lengthStr decimalValue]; + } @catch (OFInvalidArgumentException *e) { + invalid = true; } @catch (OFInvalidFormatException *e) { + invalid = true; + } + + if (invalid) { [of_stderr writeFormat: @"%@: Invalid length: %@\n", [OFApplication programName], lengthStr]; [OFApplication terminateWithStatus: 1]; } } - if ([[optionsParser remainingArguments] count] != 1) { - showHelp(of_stderr, false); - - [OFApplication terminateWithStatus: 1]; - } - - prompt = [OFString stringWithFormat: @"Passphrase for site \"%@\": ", - site]; - - LegacyPasswordGenerator *generator = - [LegacyPasswordGenerator generator]; - generator.length = length; - generator.site = [[optionsParser remainingArguments] firstObject]; - passphrase = getpass( [prompt cStringWithEncoding: [OFSystemInfo native8BitEncoding]]); @try { generator.passphrase = passphrase;