Add new generation algorithm

The scrypt-genpass compatible one is now the legacy algorithm
(activated with -L or --legacy).
This commit is contained in:
Jonathan Schleifer 2016-10-08 14:08:36 +02:00
parent cfb910164f
commit 914314b927
No known key found for this signature in database
GPG key ID: 338C3541DB54E169
7 changed files with 178 additions and 33 deletions

View file

@ -20,21 +20,13 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#import <ObjFW/ObjFW.h>
#import "PasswordGenerator.h"
@interface LegacyPasswordGenerator: OFObject
@interface LegacyPasswordGenerator: OFObject <PasswordGenerator>
{
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

View file

@ -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];

32
NewPasswordGenerator.h Normal file
View file

@ -0,0 +1,32 @@
/*
* Copyright (c) 2016, Jonathan Schleifer <js@heap.zone>
*
* 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 <PasswordGenerator>
{
size_t _length;
OFString *_site;
const char *_passphrase;
unsigned char *_output;
}
@end

67
NewPasswordGenerator.m Normal file
View file

@ -0,0 +1,67 @@
/*
* Copyright (c) 2016, Jonathan Schleifer <js@heap.zone>
*
* 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

33
PasswordGenerator.h Normal file
View file

@ -0,0 +1,33 @@
/*
* Copyright (c) 2016, Jonathan Schleifer <js@heap.zone>
*
* 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 <ObjFW/ObjFW.h>
@protocol PasswordGenerator
@property size_t length;
@property (copy) OFString *site;
@property const char *passphrase;
@property (readonly) unsigned char *output;
+ (instancetype)generator;
- (void)derivePassword;
@end

View file

@ -25,6 +25,6 @@
@interface ScryptPWGen: OFObject <OFApplicationDelegate>
{
size_t _length;
bool _repeat;
bool _legacy, _repeat;
}
@end

View file

@ -23,6 +23,7 @@
#include <unistd.h>
#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 <PasswordGenerator> 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 {