24
loading...
This website collects cookies to deliver better user experience
input()
, but that would show the password in terminal, to avoid that you should use getpass
instead:import getpass
user = getpass.getuser()
password = getpass.getpass()
# Do Stuff...
getpass
is a very simple package that allows you to prompt user for password as well as get their username by extracting current user's login name. Be aware though that not every system supports hiding of passwords. Python will try to warn you about that, so just read warnings in command line.import string
import secrets
length = 15
# Choose wide set of characters, but consider what your system can handle
alphabet = string.ascii_letters + string.digits + string.punctuation
password = ''.join(secrets.choice(alphabet) for i in range(length))
xkcdpass
after famous XKCD about password strength, and it does exactly what the comic describes - generates strong passphrase made of words:# pip install xkcdpass
from xkcdpass import xkcd_password as xp
word_file = xp.locate_wordfile()
words = xp.generate_wordlist(wordfile=word_file, min_length=5, max_length=10)
for i in range(4):
print(xp.generate_xkcdpassword(words, acrostic="python", numwords=6, delimiter="*"))
# punch*yesterday*throwback*heaviness*overnight*numbing
# plethora*yesterday*thigh*handlebar*outmost*natural
# pyromania*yearly*twisty*hyphen*overstuff*nuzzle
# pandemic*yearly*theology*hatching*overlaid*neurosis
/usr/dict/words
and picks all the words of the specified length, from which it then generates a word list used for generating the passphrase. The generator itself has a few arguments which we can use to customize the passphrase. Apart from obvious ones like number of words and length, it also has acrostic parameter, which is a word whose characters will be used as first letters of words in the passphrase (sounds complicated? well, see the example passphrases above). passlib
as it provides proper algorithms, as well as high-level interface usable even by people who aren't well-versed with cryptography.# pip install passlib
from passlib.hash import bcrypt
from getpass import getpass
print(bcrypt.setting_kwds)
# ('salt', 'rounds', 'ident', 'truncate_error')
print(bcrypt.default_rounds)
# 12
hasher = bcrypt.using(rounds=13) # Make it slower
password = getpass()
hashed_password = hasher.hash(password)
print(hashed_password)
# $2b$13$H9.qdcodBFCYOWDVMrjx/uT.fbKzYloMYD7Hj2ItDmEOnX5lw.BX.
# \__/\/ \____________________/\_____________________________/
# Alg Rounds Salt (22 char) Hash (31 char)
print(hasher.verify(password, hashed_password))
# True
print(hasher.verify("not-the-password", hashed_password))
# False
bcrypt
as our algorithm of choice, as it's one of the most popular and well tested hashing algorithms. First we inspect its possible settings and check what is the default number of rounds used by the algorithm. We then modify the hasher to use higher number of rounds (cost factor) making the hashing slower and therefore, hashes harder to crack. This number should be the largest possible that doesn't cause intolerable delay for your users (~300ms). passlib
updates default rounds value periodically, so your don't necessarily need to change this value.passlib
boils down to hash
and modify
methods of our algorithm of choice. If you however wanted more control over schemes, rounds, etc., then you can use CryptContext
class:from passlib.context import CryptContext
ctx = CryptContext(schemes=["bcrypt", "argon2", "scrypt"],
default="bcrypt",
bcrypt__rounds=14)
password = getpass()
hashed_password = ctx.hash(password)
print(hashed_password)
# $2b$14$pFTXqnHjn91C8k8ehbuM.uSJM.H5S0l7vkxE8NxgAiS2LiMWMziAe
print(ctx.verify(password, hashed_password))
print(ctx.verify("not-the-password", hashed_password))
CryptContext
integration tutorial.CryptContext
is if you need to deal with operating system passwords such as the ones in /etc/shadow
. For that you can use preconfigured contexts available in passlib.hosts
, for more details see example here.passlib
and there's not really a reason to use this low-level library.hashlib.scrypt
for hashing your passwords..env
file, add it to .gitignore
, populate it with credentials needed for current project. You can then use dotenv
package to get all these variables into your application like so:# pip install python-dotenv
import os
from os.path import join, dirname
from dotenv import load_dotenv
dotenv_path = join(dirname(__file__), ".env")
load_dotenv(dotenv_path)
API_KEY = os.environ.get("API_KEY", "default")
print(API_KEY)
# a3491fb2-000f-4d9f-943e-127cfe29c39c
.env
file using os.path
functions, which is then used to load the environment variables using load_dotenv()
. If your .env
file is in current directory like in the example above, then you can simplify the code and just call load_dotenv(find_dotenv())
which automatically finds the environment file. When the file is loaded, all that's left is to retrieve individual variables using os.environ.get
.from dotenv import dotenv_values
config = dotenv_values(".env")
print(config)
# OrderedDict([('API_KEY', 'a3491fb2-000f-4d9f-943e-127cfe29c39c')])
keyring
:# pip install keyring
import keyring
import keyring.util.platform_ as keyring_platform
print(keyring_platform.config_root())
# /home/username/.config/python_keyring # Might be different for you
print(keyring.get_keyring())
# keyring.backends.SecretService.Keyring (priority: 5)
NAMESPACE = "my-app"
ENTRY = "API_KEY"
keyring.set_password(NAMESPACE, ENTRY, "a3491fb2-000f-4d9f-943e-127cfe29c39c")
print(keyring.get_password(NAMESPACE, ENTRY))
# a3491fb2-000f-4d9f-943e-127cfe29c39c
cred = keyring.get_credential(NAMESPACE, ENTRY)
print(f"Password for username {cred.username} in namespace {NAMESPACE} is {cred.password}")
# Password for username API_KEY in namespace my-app is a3491fb2-000f-4d9f-943e-127cfe29c39c
set_password
and get_password
respectively. In addition to that, also get_credential
can be used - it returns a credential object which has an attribute for username and password.