Last active
February 18, 2019 16:55
-
-
Save 166MMX/6b23d77567a5e0e9be42257b91e4e09b to your computer and use it in GitHub Desktop.
high entropy password generator tool with hashing capabilities
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# https://docs.python.org/3/tutorial/modules.html#packages |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env sh | |
set -x | |
pex pwtool \ | |
-r requirements.txt \ | |
-o pwtool.pex \ | |
-m pwtool:main \ | |
--python-shebang '#!/usr/bin/env python3' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import matplotlib.pyplot as plt | |
import numpy as np | |
import math | |
import itertools | |
charset_letters_upper = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' | |
charset_letters_lower = 'abcdefghijklmnopqrstuvwxyz' | |
charset_numbers = '0123456789' | |
charset_symbols = r''' !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~''' | |
def linear_diff_as_base(e): | |
f, l, n = e[0], e[-1], len(e) | |
avg = (l - f) / n | |
for i in range(n): | |
yield (e[i] - f) - (avg * i) | |
def contains_all_required(topology, source_set='luds'): | |
sorted_set = sorted(set(source_set)) | |
return sorted_set == sorted(set(topology)) | |
def exceeds_max_occurrence(topology, fall_off=0.65625, source_set='luds'): | |
source_set = set(source_set) | |
return True in set(topology.count(c) / len(topology) > fall_off for c in source_set) | |
def gen_topologies(length=100): | |
source_set = set('luds') | |
combinations = itertools.combinations_with_replacement(source_set, length) | |
for t in combinations: | |
# if not contains_all_required(t) or exceeds_max_occurrence(t): | |
# continue | |
yield ''.join(t) | |
def mark_max_occurrence(topologies, fall_off=0.65625): | |
for t in topologies: | |
yield t, exceeds_max_occurrence(t, fall_off) | |
def calc_entropy(topology): | |
return math.log2( | |
math.pow(len(charset_letters_lower), topology.count('l')) | |
* math.pow(len(charset_letters_upper), topology.count('u')) | |
* math.pow(len(charset_numbers), topology.count('d')) | |
* math.pow(len(charset_symbols), topology.count('s')) | |
) | |
def plot(topologies): | |
raw = list((calc_entropy(t), t) for t in topologies) | |
raw_sorted = sorted(raw, key=lambda tup: tup[0]) | |
e, t = zip(*raw_sorted) | |
d = np.diff(e) | |
a2l = list(linear_diff_as_base(e)) | |
line_style = '-' | |
fig, ax1 = plt.subplots() | |
ax2, ax3 = ax1.twinx(), ax1.twinx() | |
color = 'tab:blue' | |
ax1.set_ylabel('entroy', color=color) | |
ax1.tick_params(axis='y', labelcolor=color) | |
linear = ([0, len(e) - 1], [e[0], e[-1]]) | |
line1, = ax1.plot(linear[0], linear[1], '--', color=color, linewidth=1, label='lin') | |
line2, = ax1.plot(e, line_style, color=color, label='abs') | |
color = 'tab:orange' | |
ax2.tick_params(axis='y', labelcolor=color) | |
linear = ([0, len(e) - 1], [0, 0]) | |
line3, = ax2.plot(linear[0], linear[1], '--', color=color, linewidth=1, label='lin') | |
line4, = ax2.plot(a2l, line_style, color=color, label='abs:lin') | |
color = 'tab:green' | |
ax3.tick_params(axis='y', labelcolor=color) | |
# linear = ([0, len(e) - 1], [0, 0]) | |
# line5, = ax3.plot(linear[0], linear[1], '--', color=color, linewidth=1, label='lin') | |
line6, = ax3.plot(d, line_style, color=color, label='diff', alpha=0.25) | |
# annotated = list(mark_max_occurrence(t)) | |
# _, markers = zip(*annotated) | |
# plot_markers(plt, markers, facecolor='tab:red', alpha=0.5) | |
# https://matplotlib.org/gallery/ticks_and_spines/multiple_yaxis_with_spines.html#sphx-glr-gallery-ticks-and-spines-multiple-yaxis-with-spines-py | |
lines = [line2, line4, line6] | |
plt.legend(lines, [l.get_label() for l in lines], loc='right') | |
plt.savefig('entropy.pdf') | |
plt.show() | |
def plot_markers(plt, markers, **kwargs): | |
b, e = -1, -1 | |
for i in range(len(markers)): | |
if markers[i]: | |
if b == -1: | |
b = i | |
e = i | |
else: | |
if b != -1: | |
plt.axvspan(b, e, **kwargs) | |
print(b, e) | |
b, e = -1, -1 | |
def main(): | |
length = 16 | |
topologies = list(gen_topologies(length)) | |
plot(topologies) | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
"""Usage: | |
pwtool generate [LENGTH] | |
pwtool sha512_crypt [FILE] | |
Arguments: | |
LENGTH [default: 16] | |
FILE [default: stdin] | |
Example: | |
pwtool generate | tee plain.txt | pwtool sha512_crypt > hash.txt""" | |
# https://en.wikipedia.org/wiki/Random_password_generator#Stronger_methods | |
# http://www.passwordmeter.com/ | |
# https://keepass.info/help/base/pwgenerator.html | |
# https://i.imgur.com/e3mGIFY.png | |
# https://www.reddit.com/r/dataisbeautiful/comments/322lbk/time_required_to_bruteforce_crack_a_password/ | |
# https://blog.korelogic.com/blog/2014/04/04/pathwell_topologies | |
charset_letters_upper = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' | |
charset_letters_lower = 'abcdefghijklmnopqrstuvwxyz' | |
charset_numbers = '0123456789' | |
charset_symbols = ''' !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~''' | |
charset_space = ' ' | |
keyset_dead = '^`~' | |
class CharacterPool(object): | |
def __init__(self, dead_keys=False, space=False, lower=True, upper=True, | |
numbers=True, symbols=True): | |
super(__class__).__init__() | |
self.with_dead_keys = dead_keys | |
self.with_space = space | |
self.with_lower = lower | |
self.with_upper = upper | |
self.with_numbers = numbers | |
self.with_symbols = symbols | |
pass | |
@property | |
def letters_upper(self): | |
return charset_letters_upper | |
@property | |
def letters_lower(self): | |
return charset_letters_lower | |
@property | |
def numbers(self): | |
return charset_numbers | |
@property | |
def symbols(self): | |
blacklist = self.blacklist | |
symbols = charset_symbols | |
return ''.join(c for c in symbols if c not in blacklist) | |
@property | |
def blacklist(self): | |
result = '' | |
if not self.with_dead_keys: | |
result += keyset_dead | |
if not self.with_space: | |
result += charset_space | |
return result | |
@property | |
def chars(self): | |
return self.letters_upper + self.letters_lower + self.numbers + self.symbols | |
class Validator(object): | |
import re | |
consequtive_letters_upper_pattern = re.compile('[a-zA-Z]{2,}') | |
consequtive_letters_lower_pattern = re.compile('[a-zA-Z]{2,}') | |
consequtive_numbers_pattern = re.compile('[0-9]{2,}') | |
consequtive_symbols_pattern = re.compile(r'[\u0020-\u002F\u003A-\u0040\u005B-\u0060\u007B-\u007E]{2,}') | |
repeating_chars_pattern = re.compile(r'(.)\1') | |
keyboard_layout_us = [ | |
'`1234567890-=', 'qwertyuiop[]\\', 'asdfghjkl;\'', 'zxcvbnm,./', | |
'~!@#$%^&*()_+', 'QWERTYUIOP{}|', 'ASDFGHJKL:"', 'ZXCVBNM<>?', | |
] | |
keyboard_layout_de = [ | |
'^1234567890ß´', 'qwertzuiopü+', 'asdfghjklöä#', '<yxcvbnm,.-', | |
'°!"§$%&/()=?`', 'QWERTZUIOPÜ*', 'ASDFGHJKLÖÄ\'', '>YXCVBNM;:_', | |
] | |
keyboard_layouts = keyboard_layout_us + keyboard_layout_de | |
# https://github.com/KoreLogicSecurity/libpathwell/blob/master/data/topology_blacklist.default | |
topology_blacklist = '''?d?d?d?d?d?d?d?d | |
?d?d?d?d?d?d?d?d?d | |
?d?d?d?d?d?d?d?d?s?s?u | |
?d?d?d?d?d?d?d?d?u?l | |
?d?d?d?d?d?d?d?l | |
?d?d?d?d?d?d?d?u?l | |
?d?d?d?d?d?d?l?l | |
?d?d?d?d?d?d?u?l | |
?d?d?d?d?d?d?u?l?l | |
?d?d?d?d?d?u?l?l?l | |
?d?d?d?d?l?l?l?l | |
?d?d?d?d?l?l?l?l?d | |
?d?d?d?d?l?l?l?l?l | |
?d?d?d?d?l?l?l?l?s | |
?d?d?d?d?l?l?l?s | |
?d?d?d?d?s?l?l?l?l | |
?d?d?d?d?s?l?l?l?l?l | |
?d?d?d?d?s?l?l?l?l?l?l?l?d | |
?d?d?d?d?u?l?l?l | |
?d?d?d?d?u?l?l?l?l | |
?d?d?d?d?u?l?l?l?l?l | |
?d?d?d?d?u?l?l?l?l?l?l | |
?d?d?d?d?u?l?l?l?l?l?l?l | |
?d?d?d?d?u?l?l?l?l?l?l?l?l | |
?d?d?d?d?u?l?l?l?s | |
?d?d?d?d?u?l?l?s | |
?d?d?d?d?u?l?l?u?l?u?l?l?l | |
?d?d?d?d?u?u?l?l | |
?d?d?d?l?l?l?l?l | |
?d?d?d?l?l?l?l?l?l | |
?d?d?d?l?l?l?l?l?l?l | |
?d?d?d?s?l?l?l?l | |
?d?d?d?u?l?d?d?l | |
?d?d?d?u?l?l?l?l | |
?d?d?d?u?l?l?l?l?l | |
?d?d?d?u?l?l?l?l?l?l | |
?d?d?d?u?l?l?l?l?l?l?l | |
?d?d?l?l?l?l?l?l | |
?d?d?l?l?l?l?l?l?l | |
?d?d?l?l?l?l?l?l?l?l | |
?d?d?l?l?l?l?l?l?l?l?l | |
?d?d?l?l?l?l?u?l?l?l | |
?d?d?l?l?l?u?u?d?d | |
?d?d?l?u?l?d?d?d | |
?d?d?s?l?l?l?l?l | |
?d?d?s?l?l?l?u?u?u | |
?d?d?s?u?u?u?l?l?l | |
?d?d?u?l?l?l?d?d | |
?d?d?u?l?l?l?l?d | |
?d?d?u?l?l?l?l?d?d | |
?d?d?u?l?l?l?l?l | |
?d?d?u?l?l?l?l?l?d?d | |
?d?d?u?l?l?l?l?l?l | |
?d?d?u?l?l?l?l?l?l?l | |
?d?d?u?l?l?l?l?l?l?l?l | |
?d?d?u?l?l?l?l?l?l?l?l?l | |
?d?d?u?l?l?l?l?l?l?l?l?l?l | |
?d?d?u?l?l?l?l?l?s | |
?d?d?u?l?l?l?l?s | |
?d?d?u?l?l?l?l?u?l?d | |
?d?d?u?l?l?s?s?u?l?l?l?l?l?s | |
?d?d?u?s?s?l?s?l?d?d?d?d | |
?d?d?u?s?u?d?l?l | |
?d?d?u?s?u?d?l?u | |
?d?d?u?u?d?d?l?l?d?d?s?s | |
?d?l?d?d?d?l?d?d | |
?d?l?d?l?l?d?d?u | |
?d?l?d?l?l?d?s?s | |
?d?l?l?l?l?l?l?d | |
?d?l?l?l?l?l?l?l | |
?d?l?l?l?l?l?l?l?l | |
?d?l?l?l?l?l?l?l?l?l | |
?d?l?l?l?l?l?l?l?l?s | |
?d?l?l?l?l?l?l?l?s | |
?d?l?l?l?l?u?u?s?s?u?u?s?d?d | |
?d?l?l?l?s?l?l?l?l | |
?d?l?l?l?s?l?l?l?l?l?l?l | |
?d?l?u?d?u?u?l?s | |
?d?s?l?u?l?d?d?d | |
?d?s?l?u?l?d?d?l | |
?d?s?u?l?l?l?l?l | |
?d?u?l?l?l?l?d?d | |
?d?u?l?l?l?l?l?d | |
?d?u?l?l?l?l?l?d?d | |
?d?u?l?l?l?l?l?l | |
?d?u?l?l?l?l?l?l?d | |
?d?u?l?l?l?l?l?l?l | |
?d?u?l?l?l?l?l?l?l?d | |
?d?u?l?l?l?l?l?l?l?l | |
?d?u?l?l?l?l?l?l?l?l?l | |
?d?u?l?l?l?l?l?l?l?s | |
?d?u?l?l?l?l?l?l?s | |
?d?u?l?l?l?l?l?s | |
?d?u?l?l?s?l?l?l?l | |
?d?u?l?l?s?l?l?l?l?s | |
?d?u?l?u?u?u?u?l | |
?l?d?d?l?l?l?l?l?s | |
?l?d?d?l?l?s?l?l?d | |
?l?d?l?l?s?d?l?l | |
?l?d?l?l?u?l?d?u | |
?l?d?u?s?u?l?l?l | |
?l?d?u?s?u?l?l?u | |
?l?l?d?d?d?d?d?d | |
?l?l?d?d?d?d?d?d?d?d | |
?l?l?d?d?d?d?d?d?s | |
?l?l?d?l?l?l?s?l | |
?l?l?d?l?u?s?d?d?d?d | |
?l?l?d?u?u?u?d?d?d?d | |
?l?l?l?d?d?d?d?d | |
?l?l?l?d?d?d?d?d?d | |
?l?l?l?d?d?d?d?d?u?u | |
?l?l?l?d?d?d?d?s | |
?l?l?l?d?d?d?d?s?s | |
?l?l?l?d?d?d?s?s?s | |
?l?l?l?d?d?l?l?l | |
?l?l?l?d?d?l?l?l?s | |
?l?l?l?d?d?s?l?l?l | |
?l?l?l?d?d?s?u?u?u | |
?l?l?l?d?l?l?l?l | |
?l?l?l?d?l?l?l?l?l?s | |
?l?l?l?d?l?l?l?l?s | |
?l?l?l?d?l?l?l?s | |
?l?l?l?d?l?u?l?l | |
?l?l?l?d?s?d?d?d?d | |
?l?l?l?l?d?d?d?d | |
?l?l?l?l?d?d?d?d?d | |
?l?l?l?l?d?d?d?d?d?d | |
?l?l?l?l?d?d?d?d?l?s | |
?l?l?l?l?d?d?d?d?s | |
?l?l?l?l?d?d?d?s | |
?l?l?l?l?d?d?s?d?d | |
?l?l?l?l?d?l?l?l | |
?l?l?l?l?d?l?l?l?l | |
?l?l?l?l?d?s?d?d?d?d | |
?l?l?l?l?d?s?l?l?l?l | |
?l?l?l?l?l?d?d?d | |
?l?l?l?l?l?d?d?d?d | |
?l?l?l?l?l?d?d?d?d?d | |
?l?l?l?l?l?d?d?d?d?d?d | |
?l?l?l?l?l?d?d?d?d?d?d?s | |
?l?l?l?l?l?d?d?d?d?s | |
?l?l?l?l?l?d?d?d?s | |
?l?l?l?l?l?d?d?s | |
?l?l?l?l?l?d?d?s?l | |
?l?l?l?l?l?d?l?l | |
?l?l?l?l?l?d?l?l?l?l | |
?l?l?l?l?l?d?l?l?l?l?s | |
?l?l?l?l?l?d?s?d | |
?l?l?l?l?l?l?d?d | |
?l?l?l?l?l?l?d?d?d | |
?l?l?l?l?l?l?d?d?d?d | |
?l?l?l?l?l?l?d?d?d?d?d | |
?l?l?l?l?l?l?d?d?d?d?d?d | |
?l?l?l?l?l?l?d?d?d?d?s | |
?l?l?l?l?l?l?d?d?d?s | |
?l?l?l?l?l?l?d?d?l?l?l?s?s | |
?l?l?l?l?l?l?d?d?s | |
?l?l?l?l?l?l?d?d?u?s | |
?l?l?l?l?l?l?d?l | |
?l?l?l?l?l?l?d?s | |
?l?l?l?l?l?l?l?d | |
?l?l?l?l?l?l?l?d?d | |
?l?l?l?l?l?l?l?d?d?d | |
?l?l?l?l?l?l?l?d?d?d?d | |
?l?l?l?l?l?l?l?d?d?d?d?d | |
?l?l?l?l?l?l?l?d?d?d?d?s | |
?l?l?l?l?l?l?l?d?d?d?s | |
?l?l?l?l?l?l?l?d?d?s | |
?l?l?l?l?l?l?l?d?d?s?s | |
?l?l?l?l?l?l?l?d?s | |
?l?l?l?l?l?l?l?l | |
?l?l?l?l?l?l?l?l?d | |
?l?l?l?l?l?l?l?l?d?d | |
?l?l?l?l?l?l?l?l?d?d?d | |
?l?l?l?l?l?l?l?l?d?d?d?d | |
?l?l?l?l?l?l?l?l?d?d?d?s | |
?l?l?l?l?l?l?l?l?d?d?s | |
?l?l?l?l?l?l?l?l?d?s | |
?l?l?l?l?l?l?l?l?l | |
?l?l?l?l?l?l?l?l?l?d | |
?l?l?l?l?l?l?l?l?l?d?d | |
?l?l?l?l?l?l?l?l?l?d?d?d | |
?l?l?l?l?l?l?l?l?l?d?d?d?d | |
?l?l?l?l?l?l?l?l?l?d?d?s | |
?l?l?l?l?l?l?l?l?l?d?s | |
?l?l?l?l?l?l?l?l?l?l | |
?l?l?l?l?l?l?l?l?l?l?d | |
?l?l?l?l?l?l?l?l?l?l?d?d | |
?l?l?l?l?l?l?l?l?l?l?l | |
?l?l?l?l?l?l?l?l?l?l?l?d | |
?l?l?l?l?l?l?l?l?l?l?l?d?d | |
?l?l?l?l?l?l?l?l?l?l?l?l | |
?l?l?l?l?l?l?l?l?l?l?l?l?d | |
?l?l?l?l?l?l?l?l?l?l?l?l?d?d | |
?l?l?l?l?l?l?l?l?l?l?l?l?l | |
?l?l?l?l?l?l?l?l?l?l?l?l?l?d | |
?l?l?l?l?l?l?l?l?l?l?l?l?l?l | |
?l?l?l?l?l?l?l?l?l?l?l?l?l?l?s | |
?l?l?l?l?l?l?l?l?l?l?s?d | |
?l?l?l?l?l?l?l?l?l?s?d | |
?l?l?l?l?l?l?l?l?l?s?d?d?d | |
?l?l?l?l?l?l?l?l?s?d | |
?l?l?l?l?l?l?l?l?s?d?d | |
?l?l?l?l?l?l?l?l?s?d?d?d | |
?l?l?l?l?l?l?l?l?s?d?d?d?d | |
?l?l?l?l?l?l?l?s | |
?l?l?l?l?l?l?l?s?d | |
?l?l?l?l?l?l?l?s?d?d | |
?l?l?l?l?l?l?l?s?d?d?d | |
?l?l?l?l?l?l?l?s?d?d?d?d | |
?l?l?l?l?l?l?s?d | |
?l?l?l?l?l?l?s?d?d | |
?l?l?l?l?l?l?s?d?d?d | |
?l?l?l?l?l?l?s?d?d?d?d | |
?l?l?l?l?l?s?d?d | |
?l?l?l?l?l?s?d?d?d | |
?l?l?l?l?l?s?d?d?d?d | |
?l?l?l?l?l?s?s?d | |
?l?l?l?l?l?u?d?d | |
?l?l?l?l?l?u?d?d?d?d | |
?l?l?l?l?s?d?d?d | |
?l?l?l?l?s?d?d?d?d | |
?l?l?l?l?s?d?d?d?d?d | |
?l?l?l?l?s?d?s?s?s?s | |
?l?l?l?l?s?l?l?l?d?d | |
?l?l?l?l?s?l?l?l?l | |
?l?l?l?l?u?l?l?l?d | |
?l?l?l?l?u?l?l?l?d?d | |
?l?l?l?s?d?d?d?d | |
?l?l?l?s?d?d?d?d?d | |
?l?l?l?s?l?l?l?d | |
?l?l?l?s?l?l?l?d?d | |
?l?l?l?s?l?l?l?l?l | |
?l?l?l?s?s?d?d?d?d | |
?l?l?l?u?d?d?d?d | |
?l?l?l?u?l?l?d?d | |
?l?l?l?u?u?u?d?d?d | |
?l?l?l?u?u?u?d?d?s | |
?l?l?s?d?d?d?d?d | |
?l?l?s?d?d?d?d?d?d | |
?l?l?s?d?d?l?d?d?l | |
?l?l?s?d?s?l?u?s | |
?l?l?s?d?s?l?u?u | |
?l?l?s?l?d?d?l?d?d | |
?l?l?s?l?l?d?d?d?d | |
?l?l?s?l?l?l?d?d | |
?l?l?s?l?l?l?d?d?d | |
?l?l?s?l?l?l?d?d?d?d | |
?l?l?s?l?l?l?l?d | |
?l?l?s?l?l?l?l?d?d | |
?l?l?s?l?l?l?l?l?d | |
?l?l?s?l?l?l?l?l?d?d | |
?l?l?s?l?l?l?l?l?l?d?d | |
?l?l?s?u?l?l?d?d | |
?l?l?u?d?s?l?u?u | |
?l?l?u?l?d?d?d?d | |
?l?l?u?l?d?l?d?u | |
?l?l?u?l?l?l?l?l?l?l?d | |
?l?l?u?u?d?d?d?d | |
?l?s?l?l?d?l?d?d | |
?l?s?l?l?l?l?d?d | |
?l?s?l?l?l?l?l?l?d?d | |
?l?s?u?u?d?d?l?d?s?u?l?s | |
?l?u?l?l?l?d?l?l | |
?l?u?s?l?s?s?u?d | |
?l?u?u?d?d?d?s?s | |
?l?u?u?u?u?u?d?d | |
?s?d?d?d?l?l?l?l?l | |
?s?d?d?u?l?l?l?l?l?l?d?d?d | |
?s?d?l?d?l?d?l?d?l | |
?s?d?l?l?l?l?l?l | |
?s?d?l?l?l?l?l?l?l | |
?s?d?l?s?l?l?d?u | |
?s?d?u?l?l?l?l?l?d?d | |
?s?l?l?l?d?d?d?d | |
?s?l?l?l?d?d?l?d?d | |
?s?l?l?l?l?d?d?d?d | |
?s?l?l?l?l?l?d?d | |
?s?l?l?l?l?l?d?d?d | |
?s?l?l?l?l?l?l?d | |
?s?l?l?l?l?l?l?d?d | |
?s?l?l?l?l?l?l?l?d | |
?s?l?l?l?l?l?l?l?d?d | |
?s?l?l?l?l?l?l?l?l?d | |
?s?l?l?l?l?l?l?l?l?d?l?d | |
?s?l?l?l?l?l?l?l?l?l?l?l?d | |
?s?s?d?d?l?l?l?l?l?l?l | |
?s?s?d?d?l?l?l?l?l?l?l?l?l?l | |
?s?s?l?l?l?l?d?l | |
?s?s?l?u?l?s?d?d | |
?s?s?l?u?l?s?d?l | |
?s?s?u?l?l?l?d?d | |
?s?s?u?u?d?d?l?l | |
?s?u?d?l?d?s?s?d | |
?s?u?d?l?d?s?s?s | |
?s?u?l?d?d?d?d?s | |
?s?u?l?l?d?d?d?d | |
?s?u?l?l?l?d?d?d?d | |
?s?u?l?l?l?d?d?d?d?s | |
?s?u?l?l?l?l?d?d | |
?s?u?l?l?l?l?d?d?d | |
?s?u?l?l?l?l?d?d?d?d | |
?s?u?l?l?l?l?d?l?d | |
?s?u?l?l?l?l?l?d | |
?s?u?l?l?l?l?l?d?d | |
?s?u?l?l?l?l?l?d?d?d?d | |
?s?u?l?l?l?l?l?d?d?d?d?s | |
?s?u?l?l?l?l?l?l?d | |
?s?u?l?l?l?l?l?l?d?d | |
?s?u?l?l?l?l?l?l?l?d | |
?s?u?u?u?l?l?d?d?d?s | |
?u?d?d?d?l?s?s?d?d | |
?u?d?d?l?d?d?l?d | |
?u?d?d?l?l?l?d?d | |
?u?d?d?l?l?l?l?l | |
?u?d?d?l?l?l?l?l?l?l | |
?u?d?d?l?l?u?l?d | |
?u?d?d?u?l?l?u?d | |
?u?d?d?u?u?u?s?s | |
?u?d?l?d?l?l?d?l?d?l | |
?u?d?l?l?d?l?d?s | |
?u?d?l?l?d?l?l?l | |
?u?d?l?l?d?l?l?s | |
?u?d?l?l?d?l?s?l?d | |
?u?d?l?l?l?d?l?l?s | |
?u?d?l?l?l?l?d?d | |
?u?d?l?l?l?l?d?d?l?l | |
?u?d?l?l?l?l?d?d?s | |
?u?d?l?l?l?l?l?d | |
?u?d?l?l?l?l?l?l | |
?u?d?l?l?l?l?l?l?d | |
?u?d?l?l?l?l?l?l?l?d | |
?u?d?l?l?l?l?l?l?l?l | |
?u?d?l?l?l?l?l?l?s | |
?u?d?l?l?l?l?l?s | |
?u?d?l?l?l?l?l?s?u?l?l?l | |
?u?d?l?l?l?l?s?d | |
?u?d?l?l?l?l?s?d?d | |
?u?d?l?l?l?l?s?l?l | |
?u?d?l?s?l?l?l?d?d | |
?u?d?u?d?u?u?s?s | |
?u?d?u?l?d?s?l?d | |
?u?d?u?l?d?s?l?l | |
?u?d?u?l?d?s?l?u | |
?u?l?d?d?d?d?d?d | |
?u?l?d?d?d?d?d?d?d | |
?u?l?d?d?d?d?d?d?d?d | |
?u?l?d?d?d?d?d?d?d?d?s | |
?u?l?d?d?d?d?d?d?s | |
?u?l?d?d?d?d?l?l | |
?u?l?d?d?d?d?s?s | |
?u?l?d?d?l?d?l?l?l | |
?u?l?d?d?l?l?d?d | |
?u?l?d?d?l?l?l?l | |
?u?l?d?d?l?l?s?s | |
?u?l?d?l?d?d?d?d | |
?u?l?d?l?l?d?d?d | |
?u?l?d?l?l?d?l?l | |
?u?l?d?l?l?l?l?d | |
?u?l?d?l?l?l?l?l | |
?u?l?d?l?l?l?l?s | |
?u?l?d?u?l?l?l?d?d | |
?u?l?l?d?d?d?d?d | |
?u?l?l?d?d?d?d?d?d | |
?u?l?l?d?d?d?d?d?d?d | |
?u?l?l?d?d?d?d?d?d?d?d | |
?u?l?l?d?d?d?d?d?d?s | |
?u?l?l?d?d?d?d?d?s | |
?u?l?l?d?d?d?d?l | |
?u?l?l?d?d?d?d?l?l?s | |
?u?l?l?d?d?d?d?s | |
?u?l?l?d?d?d?d?s?s | |
?u?l?l?d?d?d?d?u?l?l | |
?u?l?l?d?d?d?s?s | |
?u?l?l?d?d?l?l?l | |
?u?l?l?d?d?l?l?l?s | |
?u?l?l?d?d?u?u?l?s | |
?u?l?l?d?l?l?l?d | |
?u?l?l?d?l?l?l?l | |
?u?l?l?d?l?l?l?l?d?d | |
?u?l?l?d?l?l?l?l?l | |
?u?l?l?d?l?l?l?s | |
?u?l?l?d?s?l?l?l | |
?u?l?l?d?u?l?l?l?l | |
?u?l?l?l?d?d?d?d | |
?u?l?l?l?d?d?d?d?d | |
?u?l?l?l?d?d?d?d?d?d | |
?u?l?l?l?d?d?d?d?s | |
?u?l?l?l?d?d?d?d?s?s | |
?u?l?l?l?d?d?d?s | |
?u?l?l?l?d?d?l?l | |
?u?l?l?l?d?d?l?l?l | |
?u?l?l?l?d?d?l?l?l?l | |
?u?l?l?l?d?d?l?l?l?l?l | |
?u?l?l?l?d?d?s?s | |
?u?l?l?l?d?l?l?d | |
?u?l?l?l?d?l?l?d?d | |
?u?l?l?l?d?l?l?d?d?d?d | |
?u?l?l?l?d?l?l?l | |
?u?l?l?l?d?l?l?l?d | |
?u?l?l?l?d?l?l?l?l | |
?u?l?l?l?d?l?l?s | |
?u?l?l?l?d?l?s?l?d?l?l?d?l | |
?u?l?l?l?d?u?l?l | |
?u?l?l?l?d?u?l?l?l | |
?u?l?l?l?l?d?d?d | |
?u?l?l?l?l?d?d?d?d | |
?u?l?l?l?l?d?d?d?d?d | |
?u?l?l?l?l?d?d?d?d?d?d | |
?u?l?l?l?l?d?d?d?d?s | |
?u?l?l?l?l?d?d?d?s | |
?u?l?l?l?l?d?d?d?s?s | |
?u?l?l?l?l?d?d?l | |
?u?l?l?l?l?d?d?l?d?l | |
?u?l?l?l?l?d?d?l?l | |
?u?l?l?l?l?d?d?s | |
?u?l?l?l?l?d?d?s?s | |
?u?l?l?l?l?d?l?d | |
?u?l?l?l?l?d?l?l | |
?u?l?l?l?l?d?l?l?d | |
?u?l?l?l?l?d?l?l?d?d?d | |
?u?l?l?l?l?d?l?l?l | |
?u?l?l?l?l?d?l?l?l?l | |
?u?l?l?l?l?d?l?l?s | |
?u?l?l?l?l?d?l?s | |
?u?l?l?l?l?d?s?s | |
?u?l?l?l?l?l?d?d | |
?u?l?l?l?l?l?d?d?d | |
?u?l?l?l?l?l?d?d?d?d | |
?u?l?l?l?l?l?d?d?d?d?d | |
?u?l?l?l?l?l?d?d?d?d?d?d | |
?u?l?l?l?l?l?d?d?d?d?s | |
?u?l?l?l?l?l?d?d?d?d?s?s | |
?u?l?l?l?l?l?d?d?d?s | |
?u?l?l?l?l?l?d?d?l | |
?u?l?l?l?l?l?d?d?s | |
?u?l?l?l?l?l?d?d?s?s | |
?u?l?l?l?l?l?d?l | |
?u?l?l?l?l?l?d?l?l | |
?u?l?l?l?l?l?d?l?s | |
?u?l?l?l?l?l?d?s | |
?u?l?l?l?l?l?l?d | |
?u?l?l?l?l?l?l?d?d | |
?u?l?l?l?l?l?l?d?d?d | |
?u?l?l?l?l?l?l?d?d?d?d | |
?u?l?l?l?l?l?l?d?d?d?d?d | |
?u?l?l?l?l?l?l?d?d?d?d?d?d | |
?u?l?l?l?l?l?l?d?d?d?d?s | |
?u?l?l?l?l?l?l?d?d?d?s | |
?u?l?l?l?l?l?l?d?d?l | |
?u?l?l?l?l?l?l?d?d?s | |
?u?l?l?l?l?l?l?d?d?s?s | |
?u?l?l?l?l?l?l?d?l?l | |
?u?l?l?l?l?l?l?d?l?l?s?l | |
?u?l?l?l?l?l?l?d?s | |
?u?l?l?l?l?l?l?d?s?s | |
?u?l?l?l?l?l?l?l | |
?u?l?l?l?l?l?l?l?d | |
?u?l?l?l?l?l?l?l?d?d | |
?u?l?l?l?l?l?l?l?d?d?d | |
?u?l?l?l?l?l?l?l?d?d?d?d | |
?u?l?l?l?l?l?l?l?d?d?d?d?d | |
?u?l?l?l?l?l?l?l?d?d?d?d?s | |
?u?l?l?l?l?l?l?l?d?d?d?s | |
?u?l?l?l?l?l?l?l?d?d?s | |
?u?l?l?l?l?l?l?l?d?s | |
?u?l?l?l?l?l?l?l?l | |
?u?l?l?l?l?l?l?l?l?d | |
?u?l?l?l?l?l?l?l?l?d?d | |
?u?l?l?l?l?l?l?l?l?d?d?d | |
?u?l?l?l?l?l?l?l?l?d?d?d?d | |
?u?l?l?l?l?l?l?l?l?d?d?d?d?s | |
?u?l?l?l?l?l?l?l?l?d?d?s | |
?u?l?l?l?l?l?l?l?l?d?s | |
?u?l?l?l?l?l?l?l?l?l | |
?u?l?l?l?l?l?l?l?l?l?d | |
?u?l?l?l?l?l?l?l?l?l?d?d | |
?u?l?l?l?l?l?l?l?l?l?d?d?d | |
?u?l?l?l?l?l?l?l?l?l?d?d?d?d | |
?u?l?l?l?l?l?l?l?l?l?d?d?s | |
?u?l?l?l?l?l?l?l?l?l?d?s | |
?u?l?l?l?l?l?l?l?l?l?l?d | |
?u?l?l?l?l?l?l?l?l?l?l?d?d | |
?u?l?l?l?l?l?l?l?l?l?l?d?d?d | |
?u?l?l?l?l?l?l?l?l?l?l?d?d?d?d | |
?u?l?l?l?l?l?l?l?l?l?l?d?s | |
?u?l?l?l?l?l?l?l?l?l?l?l?d | |
?u?l?l?l?l?l?l?l?l?l?l?l?d?d | |
?u?l?l?l?l?l?l?l?l?l?l?l?l?d | |
?u?l?l?l?l?l?l?l?l?l?l?l?s | |
?u?l?l?l?l?l?l?l?l?l?l?s | |
?u?l?l?l?l?l?l?l?l?l?s | |
?u?l?l?l?l?l?l?l?l?l?s?d | |
?u?l?l?l?l?l?l?l?l?l?s?d?d | |
?u?l?l?l?l?l?l?l?l?s | |
?u?l?l?l?l?l?l?l?l?s?d | |
?u?l?l?l?l?l?l?l?l?s?d?d | |
?u?l?l?l?l?l?l?l?s | |
?u?l?l?l?l?l?l?l?s?d | |
?u?l?l?l?l?l?l?l?s?d?d | |
?u?l?l?l?l?l?l?l?s?d?d?d | |
?u?l?l?l?l?l?l?l?s?d?d?d?d | |
?u?l?l?l?l?l?l?l?s?s | |
?u?l?l?l?l?l?l?s | |
?u?l?l?l?l?l?l?s?d | |
?u?l?l?l?l?l?l?s?d?d | |
?u?l?l?l?l?l?l?s?d?d?d | |
?u?l?l?l?l?l?l?s?d?d?d?d | |
?u?l?l?l?l?l?l?s?s | |
?u?l?l?l?l?l?l?u?s | |
?u?l?l?l?l?l?s?d | |
?u?l?l?l?l?l?s?d?d | |
?u?l?l?l?l?l?s?d?d?d | |
?u?l?l?l?l?l?s?d?d?d?d | |
?u?l?l?l?l?l?s?s | |
?u?l?l?l?l?l?s?s?d?d | |
?u?l?l?l?l?l?u?d?d | |
?u?l?l?l?l?l?u?l?l?d?d | |
?u?l?l?l?l?s?d?d | |
?u?l?l?l?l?s?d?d?d | |
?u?l?l?l?l?s?d?d?d?d | |
?u?l?l?l?l?s?l?l | |
?u?l?l?l?l?u?d?d | |
?u?l?l?l?l?u?d?d?d | |
?u?l?l?l?l?u?d?d?l?l | |
?u?l?l?l?l?u?l?l?d | |
?u?l?l?l?l?u?l?l?l?d | |
?u?l?l?l?l?u?l?l?l?d?d | |
?u?l?l?l?l?u?l?l?l?l?d?d | |
?u?l?l?l?l?u?l?l?l?l?l?d?d | |
?u?l?l?l?s?d?d?d | |
?u?l?l?l?s?d?d?d?d | |
?u?l?l?l?s?d?d?d?d?d?d | |
?u?l?l?l?s?d?d?l?l?l | |
?u?l?l?l?s?d?l?l | |
?u?l?l?l?s?l?l?l?d | |
?u?l?l?l?s?l?l?l?l | |
?u?l?l?l?s?s?d?d | |
?u?l?l?l?s?s?s?s | |
?u?l?l?l?u?l?d?d | |
?u?l?l?l?u?l?l?d | |
?u?l?l?l?u?l?l?d?d | |
?u?l?l?l?u?l?l?l?d | |
?u?l?l?l?u?l?l?l?d?d | |
?u?l?l?l?u?l?l?l?d?d?d?d | |
?u?l?l?l?u?l?l?l?d?s | |
?u?l?l?l?u?l?l?l?l?d | |
?u?l?l?l?u?l?l?l?l?d?d | |
?u?l?l?s?d?d?d?d | |
?u?l?l?s?d?d?d?d?d | |
?u?l?l?s?d?d?d?d?d?d | |
?u?l?l?s?l?l?l?d | |
?u?l?l?s?l?l?l?d?d | |
?u?l?l?u?l?l?d?d | |
?u?l?l?u?l?l?d?d?d?d | |
?u?l?l?u?l?l?l?d | |
?u?l?l?u?l?l?l?d?d | |
?u?l?l?u?l?l?l?d?d?d?d | |
?u?l?l?u?l?l?l?l?d?d | |
?u?l?l?u?l?l?u?d?d?d?d?d?d | |
?u?l?s?d?d?d?d?d?d | |
?u?l?s?d?s?u?u?s | |
?u?l?s?d?s?u?u?u | |
?u?l?s?l?l?l?d?d | |
?u?l?s?l?l?l?l?d | |
?u?l?s?l?l?l?l?l | |
?u?l?s?s?l?l?l?l | |
?u?l?s?s?l?l?l?l?d | |
?u?l?s?s?l?l?l?l?d?d | |
?u?l?s?u?l?s?d?d?d?d?d?d | |
?u?l?u?l?d?d?d?d | |
?u?l?u?l?d?s?l?d | |
?u?l?u?l?d?s?l?l | |
?u?l?u?l?d?s?l?u | |
?u?l?u?l?l?l?d?d | |
?u?l?u?l?s?d?d?d?d | |
?u?l?u?u?d?d?s?s | |
?u?s?d?l?l?l?l?d?d | |
?u?s?d?u?d?d?s?l | |
?u?s?l?l?d?d?d?d | |
?u?s?l?l?d?l?l?l | |
?u?s?l?l?l?d?d?d | |
?u?s?l?l?l?d?d?d?d | |
?u?s?l?l?l?d?l?l | |
?u?s?l?l?l?l?d?d | |
?u?s?l?l?l?l?d?d?d | |
?u?s?l?l?l?l?d?d?d?d | |
?u?s?l?l?l?l?l?d?d | |
?u?s?l?l?l?l?l?l | |
?u?s?l?l?l?l?l?l?d | |
?u?s?l?l?l?l?l?l?d?d | |
?u?s?l?l?l?l?l?l?d?d?d?d | |
?u?s?l?l?l?l?l?l?l?l | |
?u?s?l?l?s?l?d?l | |
?u?s?u?l?l?d?l?s?u?u | |
?u?u?d?d?d?d?l?l | |
?u?u?d?d?d?d?s?s | |
?u?u?d?l?d?u?s?d | |
?u?u?d?l?d?u?s?s | |
?u?u?d?l?l?l?d?d?d?d | |
?u?u?d?l?l?l?d?d?d?u | |
?u?u?d?s?l?l?l?l | |
?u?u?l?d?d?d?s?s | |
?u?u?l?l?d?d?d?d | |
?u?u?l?l?d?d?d?d?s | |
?u?u?l?l?d?d?s?s | |
?u?u?l?l?l?d?d?d?d | |
?u?u?l?l?l?d?l?s?l?d?d | |
?u?u?l?l?l?l?d?d | |
?u?u?l?l?l?l?d?d?d?d | |
?u?u?l?l?l?l?d?d?s | |
?u?u?l?l?l?l?l?d | |
?u?u?l?l?l?l?l?d?d | |
?u?u?l?l?l?l?l?l?d?d | |
?u?u?l?l?l?l?s?d?d | |
?u?u?l?l?l?s?d?d | |
?u?u?s?d?d?l?d?d?l | |
?u?u?s?l?l?l?d?d | |
?u?u?s?u?u?u?d?d | |
?u?u?u?d?d?d?d?d?d?s | |
?u?u?u?d?d?d?d?s | |
?u?u?u?d?d?d?s?s | |
?u?u?u?d?d?l?l?l | |
?u?u?u?d?d?s?l?l?l | |
?u?u?u?d?d?u?s?s | |
?u?u?u?d?l?l?l?d | |
?u?u?u?d?l?l?l?d?d?d?d | |
?u?u?u?l?d?d?d?d | |
?u?u?u?l?d?s?l?d | |
?u?u?u?l?d?s?l?l | |
?u?u?u?l?d?s?l?u | |
?u?u?u?l?l?d?d?d | |
?u?u?u?l?l?d?d?d?d | |
?u?u?u?l?l?l?d?d | |
?u?u?u?l?l?l?d?d?d | |
?u?u?u?l?l?l?d?d?d?d | |
?u?u?u?l?l?l?d?d?s | |
?u?u?u?l?l?l?d?s | |
?u?u?u?l?l?l?l?d | |
?u?u?u?l?l?l?l?d?d | |
?u?u?u?l?l?l?l?d?d?d?d | |
?u?u?u?l?l?l?l?l?d | |
?u?u?u?l?l?l?l?l?d?d | |
?u?u?u?s?d?d?d?d | |
?u?u?u?s?d?l?l?l | |
?u?u?u?s?l?l?l?d | |
?u?u?u?s?l?l?l?d?d?d?d?d | |
?u?u?u?s?l?l?s?l | |
?u?u?u?u?d?d?d?d | |
?u?u?u?u?d?d?d?d?s | |
?u?u?u?u?d?d?s?s | |
?u?u?u?u?l?l?d?d | |
?u?u?u?u?l?l?l?d?d?d?d | |
?u?u?u?u?l?l?l?l?d | |
?u?u?u?u?l?l?l?l?d?d | |
?u?u?u?u?l?l?l?l?l?s | |
?u?u?u?u?s?d?s?d | |
?u?u?u?u?u?d?d?d?d | |
?u?u?u?u?u?u?d?d | |
?u?u?u?u?u?u?d?l | |
?u?u?u?u?u?u?d?s | |
?u?u?u?u?u?u?u?d | |
?u?u?u?u?u?u?u?d?d | |
?u?u?u?u?u?u?u?u | |
?u?u?u?u?u?u?u?u?d | |
?u?u?u?u?u?u?u?u?u'''.split('\n') | |
@staticmethod | |
def has_consequtive_upper_letters(subject): | |
# type: (str) -> bool | |
return __class__.consequtive_letters_upper_pattern.search(subject) is not None | |
@staticmethod | |
def has_consequtive_lower_letters(subject): | |
# type: (str) -> bool | |
return __class__.consequtive_letters_lower_pattern.search(subject) is not None | |
@staticmethod | |
def has_consequtive_numbers(subject): | |
# type: (str) -> bool | |
return __class__.consequtive_numbers_pattern.search(subject) is not None | |
@staticmethod | |
def has_consequtive_symbols(subject): | |
# type: (str) -> bool | |
return __class__.consequtive_symbols_pattern.search(subject) is not None | |
@staticmethod | |
def has_repeating_chars(subject): | |
# type: (str) -> bool | |
return __class__.repeating_chars_pattern.search(subject) is not None | |
@staticmethod | |
def has_sequentional_letters(subject): | |
# type: (str) -> bool | |
return __class__.has_sequentional_chars(subject, charset_letters_upper) | |
@staticmethod | |
def has_sequentional_numbers(subject): | |
# type: (str) -> bool | |
return __class__.has_sequentional_chars(subject, charset_numbers) | |
@staticmethod | |
def has_sequentional_symbols(subject): | |
# type: (str) -> bool | |
return __class__.has_sequentional_chars(subject, charset_symbols) | |
@staticmethod | |
def has_sequentional_key_strokes(subject): | |
# type: (str) -> bool | |
for row in __class__.keyboard_layouts: | |
if __class__.has_sequentional_chars(subject, row): | |
return True | |
return False | |
@staticmethod | |
def has_sequentional_chars(haystack, needle): | |
# type: (str, str) -> bool | |
haystack = haystack.upper() | |
needle = needle.upper() | |
for s in range(len(needle) - 2): | |
fwd = needle[s: s + 3] | |
rev = ''.join(reversed(fwd)) | |
if fwd in haystack or rev in haystack: | |
return True | |
return False | |
@staticmethod | |
def valid_char(prev, cur): | |
# type: (str, str) -> bool | |
subject = ''.join([prev, cur]) | |
if __class__.has_consequtive_lower_letters(subject) \ | |
or __class__.has_consequtive_upper_letters(subject) \ | |
or __class__.has_consequtive_numbers(subject) \ | |
or __class__.has_consequtive_symbols(subject) \ | |
or __class__.has_sequentional_letters(subject) \ | |
or __class__.has_sequentional_numbers(subject) \ | |
or __class__.has_sequentional_symbols(subject) \ | |
or __class__.has_sequentional_key_strokes(subject) \ | |
or __class__.has_repeating_chars(subject): | |
return False | |
return True | |
@staticmethod | |
def topology_id(char): | |
# type: (str) -> str | |
if char in charset_letters_upper: | |
return '?u' | |
elif char in charset_letters_lower: | |
return '?l' | |
elif char in charset_numbers: | |
return '?d' | |
elif char in charset_symbols: | |
return '?s' | |
@staticmethod | |
def topology(secret): | |
# type: (str) -> str | |
return ''.join(__class__.topology_id(c) for c in secret) | |
@staticmethod | |
def blacklisted_by_topology(secret): | |
# type: (str) -> bool | |
return __class__.topology(secret) in __class__.topology_blacklist | |
class Generator(object): | |
def __init__(self) -> None: | |
from random import SystemRandom | |
import sys | |
super(__class__).__init__() | |
self.random = SystemRandom() | |
self.msg_file = sys.stderr | |
self.pool = CharacterPool() | |
@staticmethod | |
def obtain_char(random, chars, result): | |
while True: | |
char = random.choice(chars) | |
if Validator.valid_char(result[-1:], char) and char not in result: | |
return char | |
def create_secret(self, length): | |
# type: (int) -> str | |
chars = self.pool.chars | |
print('pool size: %i' % len(chars), file=self.msg_file) | |
print(' length: %i' % length, file=self.msg_file) | |
print(' entropy: %f' % __class__.entropy(chars, length), file=self.msg_file) | |
while True: | |
result = self.obtain_secret(length, chars) | |
if not Validator.blacklisted_by_topology(result): | |
return result | |
def obtain_secret(self, length, chars): | |
result = '' | |
for _ in range(length): | |
char = __class__.obtain_char(self.random, chars, result) | |
result += char | |
return result | |
@staticmethod | |
def entropy(chars, length): | |
# type: (str, int) -> float | |
import math | |
return math.log2(math.pow(len(chars), length)) | |
class Hasher(object): | |
@staticmethod | |
def sha512_crypt(message): | |
# type: (str) -> str | |
from passlib.hash import sha512_crypt # https://pypi.org/project/passlib/ | |
return sha512_crypt.using(rounds=5000).hash(message) | |
def main(args): | |
import sys | |
if args['generate']: | |
length = int(args['LENGTH']) if args['LENGTH'] else 16 | |
secret = Generator().create_secret(length) | |
print(secret, end='') | |
elif args['sha512_crypt']: | |
file = open(args['FILE'], 'r') if args['FILE'] and args['FILE'] != '-' else sys.stdin | |
message = file.read() | |
digest = Hasher.sha512_crypt(message) | |
print(digest, end='') | |
if __name__ == '__main__': | |
from docopt import docopt # https://pypi.org/project/docopt/ | |
main(docopt(__doc__)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
docopt>=0.6.2 | |
passlib>=1.7.1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from distutils.core import setup | |
setup(name='pwtool', version='1.0.0', py_modules=['pwtool']) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment