...
 
Commits (5)
/* Copyright (c) 2018-2019, Thomas Fischer <[email protected]>
/* Copyright (c) 2018-2020, Thomas Fischer <[email protected]>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -34,9 +34,15 @@ static const size_t bits_for_binary = 1;
static const char *numbers = "0123456789";
static const unsigned int mod_for_numbers = 10;
static const size_t bits_for_numbers = 4;
static const char *luhn = "0123456789";
static const unsigned int mod_for_luhn = 10;
static const size_t bits_for_luhn = 4;
static const char *hex = "0123456789ABCDEF";
static const unsigned int mod_for_hex = 16;
static const size_t bits_for_hex = 4;
static const char *uuid = "0123456789abcdef";
static const unsigned int mod_for_uuid = 16;
static const size_t bits_for_uuid = 4;
static const char *alpha = "qaywsxedcrfvtgbzhnujmikolpQAYWSXEDCRFVTGBZHNUJMIKOLP";
static const unsigned int mod_for_alpha = 52;
static const size_t bits_for_alpha = 6;
......@@ -54,12 +60,14 @@ static const unsigned int ERROR_RANDOM_BITS = 0xffff;
int num_characters = 8, count_passwords = 1;
enum CharSet {Binary, Numbers, Hex, Alpha, AlphaNum, AlphaNumSpecial, KeyboardSafe};
enum CharSet {Binary, Numbers, Luhn, Hex, UUID, Alpha, AlphaNum, AlphaNumSpecial, KeyboardSafe};
enum CharSet charset = KeyboardSafe;
enum CaseChange {NoCaseChange, ToUpperCase, ToLowerCase};
enum CaseChange caseChange = NoCaseChange;
void print_version(FILE *output)
{
fprintf(output, "makepasswd v0.2\nCopyright 2018-2019 by Thomas Fischer <[email protected]>\n");
fprintf(output, "makepasswd v0.4\nCopyright 2018-2020 by Thomas Fischer <[email protected]>\n");
}
/**
......@@ -70,15 +78,20 @@ void print_version(FILE *output)
void print_help(FILE *output)
{
print_version(output);
fprintf(output, "\nUsage: makepasswd [--help] [--length N] [--binary|--num|--alpha|--alphanum|--special|--keyboard|--weak|--medium|--strong]\n");
fprintf(output, "\nUsage: makepasswd [--help] [--length N] [--binary|--num|--luhn|--alpha|\n");
fprintf(output, " --alphanum|--special|--keyboard|--weak|--medium|--strong]\n");
fprintf(output, " --help Print this help and exit without computing a password\n");
fprintf(output, " --version Print version and copyright information\n");
fprintf(output, " --length N Computed password shall be N characters long (default: N=%i)\n", num_characters);
fprintf(output, " --count N Number of passwords to be generated; one per line will be printed (default: N=%i)\n", count_passwords);
fprintf(output, " --count N Number of passwords to be generated; one per line will be\n");
fprintf(output, " printed (default: N=%i)\n", count_passwords);
fprintf(output, " --binary Computed password shall contain only digits 0 and 1\n");
fprintf(output, " --num Computed password shall contain only digits 0 to 9\n");
fprintf(output, " --luhn Computed a Luhn number, i.e. where last digit is the checksum\n");
fprintf(output, " --hex Computed password shall contain only digits 0 to 9\n");
fprintf(output, " and letters A to F (only upper case)\n");
fprintf(output, " --uuid Computed something that looks like an UUID, but is not\n");
fprintf(output, " conforming to RFC 4122\n");
fprintf(output, " --alpha Computed password shall contain only letters A to Z\n");
fprintf(output, " (both upper and lower case)\n");
fprintf(output, " --alphanum Computed password shall contain only digits 0 to 9\n");
......@@ -92,7 +105,10 @@ void print_help(FILE *output)
fprintf(output, " --weak Apply default settings to generate a weak password\n");
fprintf(output, " --medium Apply default settings to generate a medium password\n");
fprintf(output, " --strong Apply default settings to generate a strong password\n");
fprintf(output, "\nArguments --binary, --num, --hex, --alpha, --special, --keyboard, --weak, --medium, and --strong are mutually exclusive.\n");
fprintf(output, " --lc Make all letters lower case\n");
fprintf(output, " --uc Make all letters upper case\n");
fprintf(output, "\nArguments --binary, --num, --luhn, --hex, --uuid, --alpha, --special,\n");
fprintf(output, " --keyboard, --weak, --medium, and --strong are mutually exclusive.\n");
fprintf(output, "Default password mode is %s.\n", (charset == Binary ? "--binary" : (charset == Numbers ? "--num" : (charset == Hex ? "--hex" : (charset == Alpha ? "--alpha" : (charset == AlphaNum ? "--alphanum" : (charset == AlphaNumSpecial ? "--special" : (charset == KeyboardSafe ? "--keyboard" : "unset"))))))));
}
......@@ -156,9 +172,13 @@ int main(int argc, char *argv[])
charset = Binary;
else if (strncmp(argv[i], "--num", 5) == 0)
charset = Numbers;
else if (strncmp(argv[i], "--luhn", 6) == 0)
charset = Luhn;
else if (strncmp(argv[i], "--hex", 5) == 0)
charset = Hex;
else if (strncmp(argv[i], "--alpha", 7) == 0)
else if (strncmp(argv[i], "--uuid", 6) == 0)
charset = UUID;
else if (argv[i][7] == '\0' && strncmp(argv[i], "--alpha", 7) == 0) ///< need to test for zero byte at pos 7 to avoid matching '--alphanum'
charset = Alpha;
else if (strncmp(argv[i], "--alphanum", 10) == 0)
charset = AlphaNum;
......@@ -175,6 +195,10 @@ int main(int argc, char *argv[])
} else if (strncmp(argv[i], "--strong", 8) == 0) {
charset = AlphaNumSpecial;
num_characters = 16;
} else if (strncmp(argv[i], "--lc", 4) == 0) {
caseChange = ToLowerCase;
} else if (strncmp(argv[i], "--uc", 4) == 0) {
caseChange = ToUpperCase;
} else if (strncmp(argv[i], "--help", 6) == 0) {
print_help(stdout);
return 1;
......@@ -187,7 +211,9 @@ int main(int argc, char *argv[])
}
}
if (num_characters <= 0 || num_characters > 512) {
if (charset == UUID)
num_characters = 32; ///< UUIDs have fixed length
if (num_characters <= 0 || num_characters > 512 || (num_characters < 2 && charset == Luhn)) {
fprintf(stderr, "Invalid number of characters given\n");
return 1;
} else if (count_passwords <= 0 || count_passwords > 512) {
......@@ -195,15 +221,29 @@ int main(int argc, char *argv[])
return 1;
}
const size_t bits = charset == Binary ? bits_for_binary : (charset == Numbers ? bits_for_numbers : (charset == Hex ? bits_for_hex : (charset == Alpha ? bits_for_alpha : (charset == AlphaNum ? bits_for_alphanum : (charset == AlphaNumSpecial ? bits_for_alphanumspecial : bits_for_keyboardsafe)))));
const unsigned int mod = charset == Binary ? mod_for_binary : (charset == Numbers ? mod_for_numbers : (charset == Hex ? mod_for_hex : (charset == Alpha ? mod_for_alpha : (charset == AlphaNum ? mod_for_alphanum : (charset == AlphaNumSpecial ? mod_for_alphanumspecial : mod_for_keyboardsafe)))));
const char *chars = charset == Binary ? binary : (charset == Numbers ? numbers : (charset == Hex ? hex : (charset == Alpha ? alpha : (charset == AlphaNum ? alphanum : (charset == AlphaNumSpecial ? alphanumspecial : keyboardsafe)))));
const size_t bits = charset == Binary ? bits_for_binary : (charset == Numbers ? bits_for_numbers : (charset == Luhn ? bits_for_luhn : (charset == Hex ? bits_for_hex : (charset == UUID ? bits_for_uuid : (charset == Alpha ? bits_for_alpha : (charset == AlphaNum ? bits_for_alphanum : (charset == AlphaNumSpecial ? bits_for_alphanumspecial : bits_for_keyboardsafe)))))));
const unsigned int mod = charset == Binary ? mod_for_binary : (charset == Numbers ? mod_for_numbers : (charset == Luhn ? mod_for_luhn : (charset == Hex ? mod_for_hex : (charset == UUID ? mod_for_uuid : (charset == Alpha ? mod_for_alpha : (charset == AlphaNum ? mod_for_alphanum : (charset == AlphaNumSpecial ? mod_for_alphanumspecial : mod_for_keyboardsafe)))))));
const char *chars = charset == Binary ? binary : (charset == Numbers ? numbers : (charset == Luhn ? luhn : (charset == Hex ? hex : (charset == UUID ? uuid : (charset == Alpha ? alpha : (charset == AlphaNum ? alphanum : (charset == AlphaNumSpecial ? alphanumspecial : keyboardsafe)))))));
if (charset == Luhn) --num_characters; ///< because the last digit will be computed
for (int k = 0; k < count_passwords; ++k) {
int luhn_sum = 0;
for (int i = 0; i < num_characters; ++i) {
const unsigned int r = get_random_bits(bits);
if (r == ERROR_RANDOM_BITS) break;
printf("%c", chars[r % mod]);
char c = chars[r % mod];
if (caseChange == ToLowerCase && c >= 'A' && c <= 'Z') c += 0x20;
else if (caseChange == ToUpperCase && c >= 'a' && c <= 'z') c -= 0x20;
if (charset == Luhn) {
const int doubledigit = ((num_characters - i) % 2 + 1) * (c - '0');
luhn_sum += doubledigit % 10 + doubledigit / 10;
} else if (charset == UUID) {
if (i == 8 || i == 12 || i == 16 || i == 20)
putc('-', stdout);
}
printf("%c", c);
}
if (charset == Luhn)
printf("%c", ((luhn_sum * 9) % 10) + '0');
printf("\n");
}
......