Skip to content
Snippets Groups Projects
Commit aef7621f authored by David Huss's avatar David Huss :speech_balloon:
Browse files

Initial commit

parents
No related branches found
No related tags found
No related merge requests found
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
__version__ = '0.1.0'
#!/usr/bin/env python
#-*- coding: utf-8 -*-
import secrets
import itertools
import hashlib
from words import EMOJIS, DE_ADJEKTIVE, EN_COMMON_WORDS, DE_ARTWORDS, EN_ARTWORDS, EN_ADJECTIVES
lenemoji = len(EMOJIS)
def emojihash(s, n=1):
number = str(int(hashlib.sha1(s.encode("utf-8")).hexdigest(), 16))
if n == 1:
index = int(number) % lenemoji
return EMOJIS[index]
strlen = len(number)
stepsize = strlen//n
h = []
for i in range(0, strlen-1, stepsize):
index = int(number[i:i+stepsize]) % lenemoji
h.append(EMOJIS[index])
return "".join(h)
print(emojihash("testpasswort-mit-einer-gewissen-Länge?", 2))
DELIMITERS = ["-"]
SPECIAL_CHARACTERS = ["!","!", "!", "?", "?", "?", "!1", "!!", "!?", "?!"]
STRATEGIES = [
[DE_ADJEKTIVE, DE_ARTWORDS, EN_ADJECTIVES, EN_ARTWORDS],
[DE_ADJEKTIVE, DE_ADJEKTIVE, DE_ARTWORDS, EN_ADJECTIVES, EN_ARTWORDS],
[EN_ADJECTIVES, EN_ARTWORDS, EN_ADJECTIVES, EN_ARTWORDS],
[EN_COMMON_WORDS, EN_ADJECTIVES, DE_ARTWORDS],
[DE_ARTWORDS, DE_ARTWORDS, DE_ADJEKTIVE, DE_ARTWORDS],
[DE_ARTWORDS, EN_ARTWORDS, DE_ARTWORDS, EN_ARTWORDS],
[DE_ADJEKTIVE+EMOJIS, DE_ARTWORDS, EMOJIS]
]
CAPITALIZATION_STRATEGIES = [
# ["upper"],
["lower"],
["lower"],
# ["lower"],
# ["lower"],
# ["title"],
# ["title"],
# ["title"],
# ["title"],
# ["title", "lower", "lower", "lower"],
# ["upper", "lower", "lower", "lower"],
# ["lower", "lower", "upper", "upper"],
]
def apply_capital(word, strategy) -> str:
if strategy == "upper":
return word.upper()
elif strategy == "lower":
return word.lower()
elif strategy == "title":
return word.title()
else:
return word
def assemble_passphrase(length_guide=24):
words = []
tally = 0
rounds = 0
strategy = secrets.choice(STRATEGIES)
capitalization = secrets.choice(CAPITALIZATION_STRATEGIES)
delimiter = secrets.choice(DELIMITERS)
while tally < length_guide:
word = secrets.choice(strategy[rounds%len(strategy)])
rounds += 1
tally += len(word)+len(delimiter)
words.append(word)
# Randomly add numbers either at the beginning or the end
if secrets.randbelow(1000) > 850:
num = secrets.randbelow(99)
if not num in [88, 0]:
words = [str(num)] + words
elif secrets.randbelow(1000) > 650:
num = secrets.randbelow(99)
if not num in [88, 0]:
words.append(str(num))
# Randomly add punktuation in the end
if secrets.randbelow(1000) > 750:
words[-1] += secrets.choice(SPECIAL_CHARACTERS)
# Make sure words don't have spaces in beginning or end
words = [w.strip() for w in words]
# Apply capitalization strategy
words = [apply_capital(w, capitalization[i%len(capitalization)]) for i, w in enumerate(words)]
return delimiter.join(words)
def generate_passphrase(min_length=20, max_length=28):
passphrase = ""
while min_length > len(passphrase) or len(passphrase) > max_length:
passphrase = assemble_passphrase(length_guide=min_length)
return passphrase
# # USAGE - like this:
for i in range(10):
print(generate_passphrase(min_length=22, max_length=25))
\ No newline at end of file
This diff is collapsed.
[tool.poetry]
name = "passphrase-generator"
version = "0.1.0"
description = ""
authors = ["David Huss <dh@atoav.com>"]
[tool.poetry.dependencies]
python = "^3.8"
[tool.poetry.dev-dependencies]
pytest = "^5.2"
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
from hfbk_passphrase import __version__
def test_version():
assert __version__ == '0.1.0'
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment