I've already shared this months ago but made a lots of modifications since then, Shhh is a Flask app to share encrypted secrets using secured links with passphrases and expiration dates. The goal is to keep secrets away from email or chat logs.
I understand that you can't trust anyone with your data, that's why it's mainly built for people or organisations to set it up on their own local/private server. There is also a one-click deploy button to Heroku 🙂
I know some great projects such as OnetimeSecret or PasswordPusher already exists, but it was actually really fun making my own!
If anyone wants to contribute you're more than welcome!
Here is the repo: [https://github.com/smallwat3r/shhh](https://github.com/smallwat3r/shhh)
Add it to awesome-selfhosted repo
Very cool!
You could make this query tory hunt’s pwned passwords API. It uses K-anonymity to avoid sending the actual password to the API when you query the range endpoint.
A client function would look like this:
“`
import hashlib
import requests
def pwned_password(passphrase):
hasher = hashlib.sha1()
hasher.update(passphrase.encode(‘UTF-8′))
digest = hasher.hexdigest().upper()
pw_list = requests.get(f’https://api.pwnedpasswords.com/range/{digest[:5]}’)
for line in pw_list.text.split(‘\n’):
info = line.split(‘:’)
if info[0] == digest[5:]:
return int(info[1])
# If we got this far the password wasn’t found
return False
“`
This returns the number of times the password was seen, or False if it wasn’t seen:
“`
>>> pwned_password(‘hunter2’)
17124
>>> pwned_password(‘password’)
3730471
>>> pwned_password(‘something-complex-9848fpcnp8c8py94cr8y9p4w3p89yrccr’)
False
>>> pwned_password(‘Password2015’) # Meets your requirements
128
“`
Implementation on your system could look something like:
“`
def strength(passphrase):
“””Passphrase strength validation handler.
Minimum 8 characters containing at least one number and one uppercase.
“””
if passphrase:
regex = re.compile(r”^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9]).{8,}$”)
if not regex.search(passphrase) is not None:
raise ValidationError(
“Passphrase too weak. Minimun 8 characters, including ”
“1 number and 1 uppercase.”)
times_pwned = pwned_password(passphrase)
if times_pwned:
raise ValidationError(
f”The pwned passwords API says this password was
pwned {times_pwned} times!”)
“`