From 914314b9275eca9984774ef83ccba7115beb0762 Mon Sep 17 00:00:00 2001 From: Jonathan Schleifer Date: Sat, 8 Oct 2016 14:08:36 +0200 Subject: [PATCH] Add new generation algorithm The scrypt-genpass compatible one is now the legacy algorithm (activated with -L or --legacy). --- LegacyPasswordGenerator.h | 12 ++----- LegacyPasswordGenerator.m | 16 ++++++++-- NewPasswordGenerator.h | 32 +++++++++++++++++++ NewPasswordGenerator.m | 67 +++++++++++++++++++++++++++++++++++++++ PasswordGenerator.h | 33 +++++++++++++++++++ ScryptPWGen.h | 2 +- ScryptPWGen.m | 49 ++++++++++++++++------------ 7 files changed, 178 insertions(+), 33 deletions(-) create mode 100644 NewPasswordGenerator.h create mode 100644 NewPasswordGenerator.m create mode 100644 PasswordGenerator.h diff --git a/LegacyPasswordGenerator.h b/LegacyPasswordGenerator.h index 268fb45..2209f9c 100644 --- a/LegacyPasswordGenerator.h +++ b/LegacyPasswordGenerator.h @@ -20,21 +20,13 @@ * 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 diff --git a/LegacyPasswordGenerator.m b/LegacyPasswordGenerator.m index 1ca18d5..d574709 100644 --- a/LegacyPasswordGenerator.m +++ b/LegacyPasswordGenerator.m @@ -23,8 +23,7 @@ #import "LegacyPasswordGenerator.h" @implementation LegacyPasswordGenerator -@synthesize length = _length, site = _site, passphrase = _passphrase; -@synthesize output = _output; +@synthesize site = _site, passphrase = _passphrase, output = _output; + (instancetype)generator { @@ -40,6 +39,19 @@ 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]; diff --git a/NewPasswordGenerator.h b/NewPasswordGenerator.h new file mode 100644 index 0000000..2e08886 --- /dev/null +++ b/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 diff --git a/NewPasswordGenerator.m b/NewPasswordGenerator.m new file mode 100644 index 0000000..efed591 --- /dev/null +++ b/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 diff --git a/PasswordGenerator.h b/PasswordGenerator.h new file mode 100644 index 0000000..78e8c3e --- /dev/null +++ b/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 diff --git a/ScryptPWGen.h b/ScryptPWGen.h index df06166..e30ab54 100644 --- a/ScryptPWGen.h +++ b/ScryptPWGen.h @@ -25,6 +25,6 @@ @interface ScryptPWGen: OFObject { size_t _length; - bool _repeat; + bool _legacy, _repeat; } @end diff --git a/ScryptPWGen.m b/ScryptPWGen.m index 3355c1c..c6f5953 100644 --- a/ScryptPWGen.m +++ b/ScryptPWGen.m @@ -23,6 +23,7 @@ #include #import "ScryptPWGen.h" +#import "NewPasswordGenerator.h" #import "LegacyPasswordGenerator.h" OF_APPLICATION_DELEGATE(ScryptPWGen) @@ -39,6 +40,8 @@ showHelp(OFStream *output, bool verbose) @"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"]; } @@ -49,13 +52,13 @@ showHelp(OFStream *output, bool verbose) 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; @@ -98,13 +101,33 @@ showHelp(OFStream *output, bool verbose) } } - if (lengthStr != nil) { - @try { - length = (size_t)[lengthStr decimalValue]; + if ([[optionsParser remainingArguments] count] != 1) { + showHelp(of_stderr, false); - if (length < 3) - @throw [OFInvalidFormatException exception]; + [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) { + bool invalid = false; + + @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]; @@ -113,20 +136,6 @@ showHelp(OFStream *output, bool verbose) } } - 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 {