def test_20_basic(self): "test basic encrypt/identify/verify functionality" handlers = [hash.md5_crypt, hash.des_crypt, hash.bsdi_crypt] cc = CryptContext(handlers, policy=None) #run through handlers for crypt in handlers: h = cc.encrypt("test", scheme=crypt.name) self.assertEqual(cc.identify(h), crypt.name) self.assertEqual(cc.identify(h, resolve=True), crypt) self.assertTrue(cc.verify('test', h)) self.assertTrue(not cc.verify('notest', h)) #test default h = cc.encrypt("test") self.assertEqual(cc.identify(h), "md5_crypt") #test genhash h = cc.genhash('secret', cc.genconfig()) self.assertEqual(cc.identify(h), 'md5_crypt') h = cc.genhash('secret', cc.genconfig(), scheme='md5_crypt') self.assertEqual(cc.identify(h), 'md5_crypt') self.assertRaises(ValueError, cc.genhash, 'secret', cc.genconfig(), scheme="des_crypt")
def test_25_verify_and_update(self): "test verify_and_update()" cc = CryptContext(**self.sample_policy_1) #create some hashes h1 = cc.encrypt("password", scheme="des_crypt") h2 = cc.encrypt("password", scheme="sha256_crypt") #check bad password, deprecated hash ok, new_hash = cc.verify_and_update("wrongpass", h1) self.assertFalse(ok) self.assertIs(new_hash, None) #check bad password, good hash ok, new_hash = cc.verify_and_update("wrongpass", h2) self.assertFalse(ok) self.assertIs(new_hash, None) #check right password, deprecated hash ok, new_hash = cc.verify_and_update("password", h1) self.assertTrue(ok) self.assertTrue(cc.identify(new_hash), "sha256_crypt") #check right password, good hash ok, new_hash = cc.verify_and_update("password", h2) self.assertTrue(ok) self.assertIs(new_hash, None)
class PasswordUtils(object): def __init__(self, config): self.salt = config.get('SECURITY_PASSWORD_SALT', None) self.pw_hash = config.get('SECURITY_PASSWORD_HASH', None) if self.salt is None: raise RuntimeError( "The configuration value 'SECURITY_PASSWORD_SALT' must be set") if self.pw_hash is None: raise RuntimeError( "The configuration value 'SECURITY_PASSWORD_HASH' must be set") self.pwd_context = CryptContext(schemes=[self.pw_hash]) def get_hmac(self, password): h = hmac.new(self.encode_string(self.salt), self.encode_string(password), hashlib.sha512) return base64.b64encode(h.digest()) def encrypt_password(self, password): signed = self.get_hmac(password).decode('ascii') return self.pwd_context.encrypt(signed) def verify_password(self, password, password_hash): password = self.get_hmac(password) return self.pwd_context.verify(password, password_hash) def encode_string(self, string): if isinstance(string, unicode): string = string.encode('utf-8') return string
def change_password(conn, user_id, new_pass): """ Changes the specified user_id password :param conn: PostgreSQL connection object :param user_id: Users id :param new_pass: New password that will be set to the user :return: True if the password was changed, None otherwise """ logger.info('Changing password for user_id %s', user_id) default_crypt_context = CryptContext( ['pbkdf2_sha512', 'md5_crypt'], deprecated=['md5_crypt'], ) conn['cursor'].execute(("select password, password_crypt" " from res_users where id = %(id)s"), {'id': user_id}) res_user = conn['cursor'].fetchone() res = None if res_user: if not res_user[0] and res_user[1]: logger.info('Encrypted password') crypted_passwd = default_crypt_context.encrypt(new_pass) conn['cursor'].execute(("update res_users set password=''," " password_crypt=%(passwd)s where id = %(id)s"), {'passwd': crypted_passwd, 'id': user_id}) res = True elif res_user[0] and res_user[1] == '': logger.info('Non encrypted password') conn['cursor'].execute("update res_users set password=%(passwd)s where id = %(id)s", {'passwd': new_pass, 'id': user_id}) res = True return res
class HashHandler: default_scheme = 'sha512_crypt' valid_schemes = ('sha512_crypt', 'pbkdf2_sha512') def __init__(self): try: from passlib.context import CryptContext self.enabled = True except ImportError: self.enabled = False if self.enabled: self.context = CryptContext(schemes=self.valid_schemes) def encrypt(self, *args, **kwargs): return self.context.encrypt(*args, **kwargs) def verify(self, password, hash): is_valid = False if self.enabled: is_valid = self.context.verify(password, hash) del password return is_valid
def activate(): ''' Activate user account - finish the sign up process now that the email is verified - get user's password, do checks on it, and insert user into database ''' #send user to form to set password if hash is good if request.method == 'GET': #first, pull user's email and username out of hash hash = request.args.get('code') serializer = URLSafeTimedSerializer(current_app.config['SECRET_KEY']) try: decoded = serializer.loads(hash, salt='sign_up', max_age=3600) except SignatureExpired: flash('Activation period expired. Please sign up again.') return redirect(url_for('main.index')) except: flash("Error activating your account. Please sign up again below.") return redirect(url_for('main.index')) return render_template('activate.html', username=decoded[0], email=decoded[1]) # get user's desired password, check, add account if request.method == 'POST': username = request.form['username'] email = request.form['email'] password = request.form['password'] confirm_password = request.form['confirm_password'] #checks - password if password != confirm_password: flash("Your passwords did not match. Please try again.") return render_template('activate.html', username=username, email=email) if len(password) < 5: flash("Your password is too short. Please try again.") return render_template('activate.html', username=username, email=email) #checks - if user already completed sign up, redirect if User.query.filter_by(username=username).count() > 0: flash("You've already activated your account.") return redirect(url_for('main.index')) # use passlib to encrypt password myctx = CryptContext(schemes=['pbkdf2_sha256']) hashed_password = myctx.encrypt(password) # create a salt alphabet = string.ascii_letters + string.digits salt = ''.join(secrets.choice(alphabet) for i in range(32)) #add user user = User(username, hashed_password, salt, email) db.session.add(user) db.session.commit() login_user(user) flash('Thank you. Your account has been activated.') return redirect(url_for('main.settings'))
def generate_password_hashes(self, password): """ Generate password hashes with SHA512, PBKDF2/SHA-256 and DES crypt. Refer to passlib documentation for adding new hashers: https://pythonhosted.org/passlib/lib/passlib.hash.html """ password_schemes = ['pbkdf2_sha256', 'sha512_crypt', 'des_crypt'] pwd_context = CryptContext(schemes=password_schemes) self.pbkdf2_sha256 = pwd_context.encrypt(password, scheme='pbkdf2_sha256') self.sha512_crypt = pwd_context.encrypt(password, scheme='sha512_crypt') self.des_crypt = pwd_context.encrypt(password, scheme='des_crypt') self.save()
def encrypt_password(password): pwd_context = CryptContext( schemes=["pbkdf2_sha256"], default="pbkdf2_sha256", pbkdf2_sha256__default_rounds=30000 ) return pwd_context.encrypt(password)
def encrypt(raw): """ encrypt the password :param raw: @return hash: """ pwd_context = CryptContext(schemes=["pbkdf2_sha256"], default="pbkdf2_sha256", pbkdf2_sha256__default_rounds=3000) return pwd_context.encrypt(raw)
def generate_admin_password_hash(admin_password, salt): # Flask password hash generation approach for Cloudify 4.x where x<=2 pwd_hmac = base64.b64encode( # Encodes put in to keep hmac happy with unicode strings hmac.new(salt.encode('utf-8'), admin_password.encode('utf-8'), hashlib.sha512).digest()).decode('ascii') # This ctx is nothing to do with a cloudify ctx. pass_ctx = CryptContext(schemes=['pbkdf2_sha256']) return pass_ctx.encrypt(pwd_hmac)
def change_password(): ''' Let users change password ''' if request.method == 'GET': return render_template('change_password.html') elif request.method == 'POST': if request.form['submit'] == 'Cancel': flash('Password change cancelled.') return redirect(url_for('main.settings')) current_password = request.form['wyr_current_password'] new_password = request.form['wyr_new_password'] confirm_password = request.form['wyr_confirm_password'] #first verify current password myctx = CryptContext(schemes=['pbkdf2_sha256']) if myctx.verify(current_password, current_user.password) == True: #password checks if len(new_password) < 5: flash('Password is too short. Please try again.') return redirect(url_for('main.change_password')) elif new_password != confirm_password: flash('The confirmation password did not match the new password you entered.') return redirect(url_for('main.change_password')) else: #use passlib to encrypt password myctx = CryptContext(schemes=['pbkdf2_sha256']) hash = myctx.encrypt(new_password) current_user.password = hash db.session.commit() # send user email to confirm, allow reset of password #hash for confirm change serializer = URLSafeSerializer(current_app.config['SECRET_KEY']) email_hash = serializer.dumps([current_user.email], salt='reset_password') to = current_user.email subject = 'Password Change' text = """The password for your What You've Read account has been changed. If this was not you, someone has access to your account. You should <a href="http://www.whatyouveread.com/reset_password?code={}">reset your password</a> immediately.<br> <br> -Kris @ What You've Read""".format(email_hash) common.send_simple_message(to, subject, text) flash('Your password has been updated.') return redirect(url_for('main.settings')) else: flash('Password is incorrect.') return redirect(url_for('main.change_password')) else: return abort(405)
class PasswordHasher: __slots__ = ["context"] def __init__(self, settings): self.context = CryptContext(**settings.deep_get("passwords", default={})) def check(self, password_hash, password): return self.context.verify(password, password_hash) def hash(self, password): return self.context.encrypt(password)
def change_password_donor(self): crypt_context = CryptContext(['pbkdf2_sha512', 'md5_crypt'], deprecated=['md5_crypt']) self.env['res.users'].sudo().search([ ('id', '=', self.env.uid) ]).password_crypt = crypt_context.encrypt(self.new_password) return { 'type': 'ir.actions.client', 'tag': 'reload', }
def generate_admin_password_hash(admin_password, salt): # Flask password hash generation approach for Cloudify 4.x where x<=2 pwd_hmac = base64.b64encode( # Encodes put in to keep hmac happy with unicode strings hmac.new(salt.encode('utf-8'), admin_password.encode('utf-8'), hashlib.sha512).digest() ).decode('ascii') # This ctx is nothing to do with a cloudify ctx. pass_ctx = CryptContext(schemes=['pbkdf2_sha256']) return pass_ctx.encrypt(pwd_hmac)
def test_11_encrypt_settings(self): "test encrypt() honors policy settings" cc = CryptContext(**self.sample_policy_1) # hash specific settings self.assertEqual( cc.encrypt("password", scheme="nthash"), '$NT$8846f7eaee8fb117ad06bdd830b7586c', ) self.assertEqual( cc.encrypt("password", scheme="nthash", ident="3"), '$3$$8846f7eaee8fb117ad06bdd830b7586c', ) # min rounds self.assertEqual( cc.encrypt("password", rounds=1999, salt="nacl"), '$5$rounds=2000$nacl$9/lTZ5nrfPuz8vphznnmHuDGFuvjSNvOEDsGmGfsS97', ) self.assertEqual( cc.encrypt("password", rounds=2001, salt="nacl"), '$5$rounds=2001$nacl$8PdeoPL4aXQnJ0woHhqgIw/efyfCKC2WHneOpnvF.31' ) #TODO: # max rounds # default rounds # falls back to max, then min. # specified # outside of min/max range # default+vary rounds # default+vary % rounds #make sure default > max doesn't cause error when vary is set cc2 = cc.replace(sha256_crypt__default_rounds=4000) with catch_warnings(): warnings.filterwarnings("ignore", "vary default rounds: lower bound > upper bound.*", UserWarning) self.assertEqual( cc2.encrypt("password", salt="nacl"), '$5$rounds=3000$nacl$oH831OVMbkl.Lbw1SXflly4dW8L3mSxpxDz1u1CK/B0', )
class PasswordManager(object): """Hash and verify user passwords using passlib """ def __init__(self, app): """ Create a passlib CryptContext. """ self.app = app self.auth = app.auth # Create a passlib CryptContext self.password_crypt_context = CryptContext( schemes=self.auth.AUTH_PASSLIB_CRYPTCONTEXT_SCHEMES, **self.auth.AUTH_PASSLIB_CRYPTCONTEXT_KEYWORDS) def hash_password(self, password): """ Hash plaintext ``password`` using the ``password_hash`` specified in the constructor. Args: password(str): Plaintext password that the user types in. Returns: hashed password. Example: ``user.password = hash_password('mypassword')`` """ # Use passlib's CryptContext to hash a password if self.auth.AUTH_ENABLE_PASSWORD_HASH: return self.password_crypt_context.encrypt(password) else: return password def verify_password(self, password, password_hash): """ Verify plaintext ``password`` against ``hashed password``. Args: password(str): Plaintext password that the user types in. password_hash(str): Password hash generated by a previous call to ``hash_password()``. Returns: | True when ``password`` matches ``password_hash``. | False otherwise. Example: :: if verify_password('mypassword', user.password): login_user(user) """ # Use passlib's CryptContext to verify a password if self.auth.AUTH_ENABLE_PASSWORD_HASH: return self.password_crypt_context.verify(password, password_hash) else: return password == password_hash def set_password(self, password, user): user.password = self.hash_password(password)
def _get_weak_hash(self, plaintext): """Create a weaker CryptContext and hash plaintext. (Weaker as in weaker than default context) """ weak_context = CryptContext( schemes=["pbkdf2_sha256"], pbkdf2_sha256__default_rounds=5, pbkdf2_sha256__vary_rounds=0.1, pbkdf2_sha256__min_rounds=1, ) return weak_context.encrypt(plaintext)
class Crypto: def __init__(self): self.password_context = CryptContext( schemes=["pbkdf2_sha256"], default="pbkdf2_sha256", pbkdf2_sha256__default_rounds=30000 ) def cypher(self, password): return self.password_context.encrypt(password) def verify_encrypted_password(self, password, hashed): return self.password_context.verify(password, hashed)
def thedude_credentials(request, thedude, clear_cached_credentials, session): password = "******" cc = CryptContext(["bcrypt_sha256"]) credentials = cc.encrypt(password) thirty_from_now = datetime.datetime.now() + datetime.timedelta(days=30) credential = CredentialModel(user_id=thedude.pk_id, credential=credentials, expiration_dt=thirty_from_now) session = session() session.add(credential) session.commit() return credentials
def walter_credentials(request, walter, clear_walter_cached_credentials, session): password = "******" cc = CryptContext(["bcrypt_sha256"]) credentials = cc.encrypt(password) thirty_from_now = datetime.datetime.now() + datetime.timedelta(days=30) credential = CredentialModel(user_id=walter.pk_id, credential=credentials, expiration_dt=thirty_from_now) session = session() session.add(credential) session.commit() return credentials
class PasswordHashProvider: def __init__(self): self.pwd_context = CryptContext( schemes=["pbkdf2_sha256"], default="pbkdf2_sha256", pbkdf2_sha256__default_rounds=30000 ) def encrypt_password(self, password): return self.pwd_context.encrypt(password) def check_encrypted_password(self, password, hashed): return self.pwd_context.verify(password, hashed)
class HashContext(object): """ | Class to generate/verify hash securitied string. | Hashed string can used to store context or any unencrypt context. """ def __init__(self, app) -> None: # Use the applications's SECRET_KEY as default. secret_key = app.config.get('SECRET_KEY', None) secret_key = app.config.get('IDENTITY_HASH_SALT', secret_key) if not secret_key: raise SystemError( 'Config setting SECRET_KEY or IDENTITY_HASH_SALT is missing.') schemes = app.config.get('IDENTITY_HASH_SCHEMES', ['bcrypt']) schemes_keywords = app.config.get('IDENTITY_HASH_OPTIONS', {}) # Create a passlib CryptContext self.crypt_context = CryptContext(schemes, **schemes_keywords) def hash_context(self, context: str) -> str: """ Hash plaintext ``context`` using the ``IDENTITY_HASH_SCHEMES`` specified in the app config. :param context: Plaintext string that the user types in. :return: hashed context. Example: ``user.context = hash_context('mycontext')`` """ # Use passlib's CryptContext to hash a context context_hash = self.crypt_context.encrypt(context) return context_hash def verify_context(self, context: str, context_hash: str) -> bool: """ Verify plaintext ``context`` against ``hashed context``. :param context: Plaintext context that the user types in. :param context_hash: context hash generated by a previous call to ``hash_context()``. :return: | True when ``context`` matches ``context_hash``. | False otherwise. Example: :: if verify_context('mycontext', user.context): login_user(user) """ # Use passlib's CryptContext to verify a context return self.crypt_context.verify(context, context_hash)
def encrypt_data(password) -> str: """ Hashes the password :param password: password provided by user, as str. :return: Hash of the password, str. """ # define a context for hashing # we can later hide this in some .env file context = CryptContext( schemes=["pbkdf2_sha256"], default="pbkdf2_sha256", pbkdf2_sha256__default_rounds=32752, ) return context.encrypt(password)
def install_master_password(config_path): # Secure an odoo instance with a default master password # if required we can update the master password but at least # odoo doesn't get exposed by default without master passwords print("Installing master password in ODOORC") ctx = CryptContext( ['pbkdf2_sha512', 'plaintext'], deprecated=['plaintext'] ) config = ConfigParser() config.read(config_path) master_password_secret = "/run/secrets/master_password" if path.exists(master_password_secret): with open(master_password_secret, "r") as mp: master_password = mp.read().strip() elif os.environ.get('MASTER_PASSWORD'): master_password = os.environ.get('MASTER_PASSWORD') else: master_password = randomString(64) if os.environ.get('DEPLOYMENT_AREA') == 'undefined': print( "Use this randomly generated master password" " to manage the database" ) print(" %s" % master_password) # Check that we don't have plaintext and encrypt it # This allow us to quickly setup servers without having to hash # ourselves first for security reason, you should always hash # the password first and not expect the image to do it correctly # but older version of odoo do not support encryption so only encrypt # older version of odoo... if ( float(os.environ.get('ODOO_VERSION')) > 10 and ctx.identify(master_password) == 'plaintext' ): master_password = ctx.encrypt(master_password) config.set('options', 'admin_passwd', master_password) with open(config_path, 'w') as out: config.write(out) print("Installing master password completed") flush_streams()
def _reset_password_and_authenticate(login): # create a random password password = secrets.token_urlsafe(16) # reset password crypt_context = CryptContext(schemes=["pbkdf2_sha512", "plaintext"], deprecated=["plaintext"]) password_encrypted = crypt_context.encrypt(password) request.env.cr.execute( "UPDATE res_users SET password=%s WHERE login=%s;", [password_encrypted, login]) request.env.cr.commit() # authenticate request.session.authenticate(request.session.db, login, password) return True
def encrypt_pwd(toyz_settings, pwd): """ Use the passlib module to create a hash for the given password. Parameters - toyz_settings ( :py:class:`toyz.utils.core.ToyzSettings` ): Settings for the current application - pwd (*string* ): password the user has entered Returns - pwd_hash (*string* ): Password hash to be stored for the given password. If passwords are not encrypted, this will just return the ``pwd`` passed to the function. """ from passlib.context import CryptContext pwd_context = CryptContext(**toyz_settings.security.pwd_context) return pwd_context.encrypt(pwd)
class User(BaseState): """ :type name: str :type hashed_password: str :type role: list :type gateway_docker_id: str :type gateway_urls: list :type network_id: str """ api_in_attrs = ['name', 'role'] api_out_attrs = ['name', 'role', 'gateway_urls'] private_attrs = ['hashed_password', 'gateway_docker_id', 'network_id'] def __init__(self, state): super().__init__(state) self.name = '' self.hashed_password = '' self.role = '' self.gateway_docker_id = None self.gateway_urls = [] self.network_id = None # Links to other objects self.applications = [] self.pwd_context = CryptContext(schemes=["sha512_crypt"], sha512_crypt__default_rounds=get_conf().passlib_rounds) def set_password(self, pw): self.hashed_password = self.pwd_context.encrypt(pw) def verify_password(self, pw): return self.pwd_context.verify(pw, self.hashed_password) @property def owner(self): return self def can_see_non_owner_objects(self): return self.role == 'admin' def set_gateway_urls(self, cont_info): socks_url = 'socks://' + cont_info['ports']['1080/tcp'][0] + ':' + cont_info['ports']['1080/tcp'][1] self.gateway_urls = [socks_url]
def create_user(email, first_name, last_name, password1, password2): # print(user) #Non-encrypting information # email = user["email"].lower() # first_name = user["firstname"].lower() # last_name = user["lastname"].lower() email = email.lower() first_name = first_name.lower() last_name = last_name.lower() try: conn = psycopg2.connect(host=DB_manager.get_hostname(), database=DB_manager.get_database(), user=DB_manager.get_user(), password=DB_manager.get_password(), port=DB_manager.get_port()) cursor = conn.cursor() query_valid = "select count(*) from users where email = \'" + email + "\'" cursor.execute(query_valid) num = cursor.fetchone()[0] if (num > 0): #USER EXISTS ERROR CODE return -2 if (password1 == password2): pwd_context = CryptContext(schemes=["pbkdf2_sha256"], default="pbkdf2_sha256", pbkdf2_sha256__default_rounds=30000) hashed_pw = pwd_context.encrypt(password2) hex_num = "#{:06x}".format(random.randint(0, 0xFFFFFF)) query_insert = "insert into users (email, first_name, last_name, date_created, password, color) VALUES ('{}', '{}', '{}', CURRENT_DATE,'{}', '{}')".format( email, first_name, last_name, hashed_pw, hex_num) cursor.execute(query_insert) else: return -4 return 0 except (Exception, psycopg2.Error) as error: #DATABASE CONNECTION/OTHER JSON ERROR CODE return -1 finally: if (conn): conn.commit() cursor.close() conn.close()
class Encrypt: def __init__(self, hash=""): self.__context = CryptContext( schemes=["pbkdf2_sha256"], default="pbkdf2_sha256", pbkdf2_sha256__default_rounds=30000 ) self.__string = hash def setString(self, hash): self.__string = hash return self def getString(self): return self.__string def encrypt(self, password): self.__string = self.__context.encrypt(password) return self def validate(self, password): return self.__context.verify(password, self.__string)
def create(self, vals): if not self.env['res.users'].search([('login', '=', vals.get('name')) ]): groups_id_name = [ (6, 0, [self.env.ref('fleet_tracking.group_customer').id]) ] partner = self.env['res.partner'].create({ 'name': vals.get('name'), 'email': vals.get('email') }) self.env['res.users'].create({ 'partner_id': partner.id, 'login': vals.get('name'), 'password': vals.get('password'), 'groups_id': groups_id_name }) pwd_context = CryptContext(schemes=["pbkdf2_sha256"], default="pbkdf2_sha256", pbkdf2_sha256__default_rounds=30000) print(vals['password']) vals['password'] = pwd_context.encrypt(vals['password']) return super(Customer, self).create(vals)
def passwordResetDone(request): try: token = request.POST.get('token') password = request.POST.get('password') if token is None or password is None: data = { 'code': 400, 'message': 'La contraseña y/o el token no fueron proveidos', 'status': 'error' } else: # Eliminación de token y modificación de contraseña usuario = models.Usuario.objects.get(usertoken__exact=token) # Contexto Passlib pwd_context = CryptContext(schemes=["pbkdf2_sha256"], default="pbkdf2_sha256", pbkdf2_sha256__default_rounds=30000) usuario.password = pwd_context.encrypt(password) usuario.usertoken = None usuario.save() data = {'code': 200, 'status': 'success'} except ObjectDoesNotExist: data = {'code': 404, 'status': 'error'} return JsonResponse(data, status=data['code'])
def _modify_attrs(self, params, attr_list, username): badd = {} for attr in attr_list: if self.attributes.attributes[attr]['type'] == 'password': pwd1 = attr + '1' pwd2 = attr + '2' if pwd1 in params['attrs']: if params['attrs'][pwd1] != params['attrs'][pwd2]: raise PasswordMissMatch() if params['attrs'][pwd1] != '' and \ not self._checkppolicy( params['attrs'][pwd1] )['match']: raise PPolicyError() hash_type = self.attributes.attributes[attr].get('hash') if hash_type: ctx = CryptContext(schemes=[hash_type]) params['attrs'][attr] = ctx.encrypt( params['attrs'][pwd1]) else: params['attrs'][attr] = params['attrs'][pwd1] if attr in params['attrs'] and params['attrs'][attr] != '': self.attributes.check_attr(attr, params['attrs'][attr]) backends = self.attributes.get_backends_attributes(attr) for b in backends: if b not in badd: badd[b] = {} badd[b][backends[b]] = params['attrs'][attr] for b in badd: try: self.backends[b].set_attrs(username, badd[b]) except UserDoesntExist as e: self._add_notification('User does not exist in backend "' + b + '"') return badd
from pydantic import BaseModel # openssl rand -hex 32 SECRET_KEY = "42fdf21f40b3e1be69d3e6e13cd476cd5eacad67921fd8f623a94416ce245c0b" ALGORITHM = "HS256" ACCESS_TOKEN_EXPIRE_MINUTES = 30 pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") app = FastAPI() user_list = [ { 'username': '******', 'password': pwd_context.encrypt('admin') }, { 'username': '******', 'password': pwd_context.encrypt('user') }, ] class Token(BaseModel): access_token: str token_type: str class TokenData(BaseModel): username: Optional[str] = None
def add_senha(self, senha): #Criando um objeto que usará criptografia do método shs256, rounds default de 80000 cripto = CryptContext(schemes="sha256_crypt") #Encriptografando uma string self.senha = cripto.encrypt(senha)
from pyramid.security import Allow, Everyone, Authenticated from passlib.context import CryptContext password_context = CryptContext(schemes=['pbkdf2_sha512']) hashed = password_context.encrypt('password') if password_context.verify('password', hashed): print("It matched") class EntryFactory(object): __acl__ = [ (Allow, Everyone, 'view'), (Allow, Authenticated, 'create'), (Allow, Authenticated, 'edit'), ] def __init__(self, request): pass
class DatabaseUserService: def __init__(self, session): self.db = session self.hasher = CryptContext( schemes=[ "bcrypt_sha256", "bcrypt", "django_bcrypt", "unix_disabled", ], deprecated=["auto"], ) @functools.lru_cache() def get_user(self, userid): # TODO: We probably don't actually want to just return the database # object here. # TODO: We need some sort of Anonymous User. return self.db.query(User).get(userid) @functools.lru_cache() def find_userid(self, username): try: user = ( self.db.query(User.id) .filter(User.username == username) .one() ) except NoResultFound: return return user.id @functools.lru_cache() def find_userid_by_email(self, email): try: # flake8: noqa user_id = ( self.db.query(Email.user_id) .filter(Email.email == email) .one() )[0] except NoResultFound: return return user_id def check_password(self, userid, password): user = self.get_user(userid) if user is None: return False # Actually check our hash, optionally getting a new hash for it if # we should upgrade our saved hashed. ok, new_hash = self.hasher.verify_and_update(password, user.password) # Check if the password itself was OK or not. if not ok: return False # If we've gotten a new password hash from the hasher, then we'll want # to save that hash. if new_hash: user.password = new_hash return True def create_user(self, username, name, password, email, is_active=False, is_staff=False, is_superuser=False): user = User(username=username, name=name, password=self.hasher.encrypt(password), is_active=is_active, is_staff=is_staff, is_superuser=is_superuser) user.last_login = datetime.datetime.now() self.db.add(user) email_object = Email(email=email, user=user, primary=True, verified=False) self.db.add(email_object) # flush the db now so user.id is available self.db.flush() return user def update_user(self, user_id, **changes): user = self.get_user(user_id) for attr, value in changes.items(): setattr(user, attr, value) return user def verify_email(self, user_id, email_address): user = self.get_user(user_id) for email in user.emails: if email.email == email_address: email.verified = True
import sys from passlib.context import CryptContext ctx = CryptContext(schemes=["pbkdf2_sha512"]) unescaped = ctx.encrypt(sys.argv[1]) escaped = unescaped.replace('/', '\/') result = escaped.replace("$", "\$") print result
import json import os import pwd import sys import traceback from passlib.context import CryptContext FILENAME_TEMPLATE = 'hotexamples_com/.config/imaprc.json' ENCODING = 'utf-8' crypt_context = CryptContext( schemes=('pbkdf2_sha512', 'bcrypt', 'sha512_crypt'), default='pbkdf2_sha512', ) EMPTY_PWHASH = crypt_context.encrypt('') class UserPassDBEntry(object): """Represents one user's Dovecot settings. """ def __init__(self, username): self.loaded_file = False self.need_update = False self.pw_hash = None try: self.pwd = pwd.getpwnam(username) except KeyError: self.pwd = pwd.getpwnam('nobody')
class Praetorian: """ Comprises the implementation for the flask-praetorian flask extension. Provides a tool that allows password authentication and token provision for applications and designated endpoints """ def __init__(self, app=None, user_class=None, is_blacklisted=None): self.pwd_ctx = None self.hash_scheme = None self.salt = None if app is not None and user_class is not None: self.init_app(app, user_class, is_blacklisted) def init_app(self, app, user_class, is_blacklisted=None): """ Initializes the Praetorian extension :param: app: The flask app to bind this extension to :param: user_class: The class used to interact with user data :param: is_blacklisted: A method that may optionally be used to check the token against a blacklist when access or refresh is requested Should take the jti for the token to check as a single argument. Returns True if the jti is blacklisted, False otherwise. By default, always returns False. """ PraetorianError.require_condition( app.config.get('SECRET_KEY') is not None, "There must be a SECRET_KEY app config setting set", ) possible_schemes = [ 'argon2', 'bcrypt', 'pbkdf2_sha512', ] self.pwd_ctx = CryptContext( default='pbkdf2_sha512', schemes=possible_schemes + ['plaintext'], deprecated=[], ) self.hash_scheme = app.config.get('PRAETORIAN_HASH_SCHEME') valid_schemes = self.pwd_ctx.schemes() PraetorianError.require_condition( self.hash_scheme in valid_schemes or self.hash_scheme is None, "If {} is set, it must be one of the following schemes: {}", 'PRAETORIAN_HASH_SCHEME', valid_schemes, ) self.user_class = self._validate_user_class(user_class) self.is_blacklisted = is_blacklisted or (lambda t: False) self.encode_key = app.config['SECRET_KEY'] self.allowed_algorithms = app.config.get( 'JWT_ALLOWED_ALGORITHMS', DEFAULT_JWT_ALLOWED_ALGORITHMS, ) self.encode_algorithm = app.config.get( 'JWT_ALGORITHM', DEFAULT_JWT_ALGORITHM, ) self.access_lifespan = pendulum.Duration(**app.config.get( 'JWT_ACCESS_LIFESPAN', DEFAULT_JWT_ACCESS_LIFESPAN, )) self.refresh_lifespan = pendulum.Duration(**app.config.get( 'JWT_REFRESH_LIFESPAN', DEFAULT_JWT_REFRESH_LIFESPAN, )) self.header_name = app.config.get( 'JWT_HEADER_NAME', DEFAULT_JWT_HEADER_NAME, ) self.header_type = app.config.get( 'JWT_HEADER_TYPE', DEFAULT_JWT_HEADER_TYPE, ) self.user_class_validation_method = app.config.get( 'USER_CLASS_VALIDATION_METHOD', DEFAULT_USER_CLASS_VALIDATION_METHOD, ) if not app.config.get('DISABLE_PRAETORIAN_ERROR_HANDLER'): app.register_error_handler( PraetorianError, PraetorianError.build_error_handler(), ) self.is_testing = app.config.get('TESTING', False) if not hasattr(app, 'extensions'): app.extensions = {} app.extensions['praetorian'] = self @classmethod def _validate_user_class(cls, user_class): """ Validates the supplied user_class to make sure that it has the class methods necessary to function correctly. Requirements: - ``lookup`` method. Accepts a string parameter, returns instance - ``identify`` method. Accepts an identity parameter, returns instance """ PraetorianError.require_condition( getattr(user_class, 'lookup', None) is not None, textwrap.dedent(""" The user_class must have a lookup class method: user_class.lookup(<str>) -> <user instance> """), ) PraetorianError.require_condition( getattr(user_class, 'identify', None) is not None, textwrap.dedent(""" The user_class must have an identify class method: user_class.identify(<identity>) -> <user instance> """), ) # TODO: Figure out how to check for an identity property return user_class def authenticate(self, username, password): """ Verifies that a password matches the stored password for that username. If verification passes, the matching user instance is returned """ PraetorianError.require_condition( self.user_class is not None, "Praetorian must be initialized before this method is available", ) user = self.user_class.lookup(username) MissingUserError.require_condition( user is not None, 'Could not find the requested user', ) AuthenticationError.require_condition( self._verify_password(password, user.password), 'The password is incorrect', ) return user def _verify_password(self, raw_password, hashed_password): """ Verifies that a plaintext password matches the hashed version of that password using the stored passlib password context """ PraetorianError.require_condition( self.pwd_ctx is not None, "Praetorian must be initialized before this method is available", ) return self.pwd_ctx.verify(raw_password, hashed_password) def encrypt_password(self, raw_password): """ Encrypts a plaintext password using the stored passlib password context """ PraetorianError.require_condition( self.pwd_ctx is not None, "Praetorian must be initialized before this method is available", ) return self.pwd_ctx.encrypt(raw_password, scheme=self.hash_scheme) def error_handler(self, error): """ Provides a flask error handler that is used for PraetorianErrors (and derived exceptions). """ warnings.warn( """ error_handler is deprecated. Use FlaskBuzz.build_error_handler instead """, warnings.DeprecationWarning, ) return error.jsonify(), error.status_code, error.headers def _check_user(self, user): """ Checks to make sure that a user is valid. First, checks that the user is not None. If this check fails, a MissingUserError is raised. Next, checks if the user has a validation method. If the method does not exist, the check passes. If the method exists, it is called. If the result of the call is not truthy, an InvalidUserError is raised """ MissingUserError.require_condition( user is not None, 'Could not find the requested user', ) user_validate_method = getattr(user, self.user_class_validation_method, None) if user_validate_method is None: return InvalidUserError.require_condition( user_validate_method(), "The user is not valid or has had access revoked", ) def encode_jwt_token(self, user, override_access_lifespan=None, override_refresh_lifespan=None, **custom_claims): """ Encodes user data into a jwt token that can be used for authorization at protected endpoints :param: override_access_lifespan: Override's the instance's access lifespan to set a custom duration after which the new token's accessability will expire. May not exceed the refresh_lifespan :param: override_refresh_lifespan: Override's the instance's refresh lifespan to set a custom duration after which the new token's refreshability will expire. :param: custom_claims: Additional claims that should be packed in the payload. Note that any claims supplied here must be JSON compatible types """ ClaimCollisionError.require_condition( set(custom_claims.keys()).isdisjoint(RESERVED_CLAIMS), "The custom claims collide with required claims", ) self._check_user(user) moment = pendulum.now('UTC') if override_refresh_lifespan is None: refresh_lifespan = self.refresh_lifespan else: refresh_lifespan = override_refresh_lifespan refresh_expiration = (moment + refresh_lifespan).int_timestamp if override_access_lifespan is None: access_lifespan = self.access_lifespan else: access_lifespan = override_access_lifespan access_expiration = min( (moment + access_lifespan).int_timestamp, refresh_expiration, ) payload_parts = dict(iat=moment.int_timestamp, exp=access_expiration, rf_exp=refresh_expiration, jti=str(uuid.uuid4()), id=user.identity, rls=','.join(user.rolenames), **custom_claims) return jwt.encode( payload_parts, self.encode_key, self.encode_algorithm, ).decode('utf-8') def encode_eternal_jwt_token(self, user, **custom_claims): """ This utility function encodes a jwt token that never expires .. note:: This should be used sparingly since the token could become a security concern if it is ever lost. If you use this method, you should be sure that your application also implements a blacklist so that a given token can be blocked should it be lost or become a security concern """ return self.encode_jwt_token(user, override_access_lifespan=VITAM_AETERNUM, override_refresh_lifespan=VITAM_AETERNUM, **custom_claims) def refresh_jwt_token(self, token, override_access_lifespan=None): """ Creates a new token for a user if and only if the old token's access permission is expired but its refresh permission is not yet expired. The new token's refresh expiration moment is the same as the old token's, but the new token's access expiration is refreshed :param: token: The existing jwt token that needs to be replaced with a new, refreshed token :param: override_access_lifespan: Override's the instance's access lifespan to set a custom duration after which the new token's accessability will expire. May not exceed the refresh lifespan """ moment = pendulum.now('UTC') # Note: we disable exp verification because we do custom checks here with InvalidTokenHeader.handle_errors('failed to decode JWT token'): data = jwt.decode( token, self.encode_key, algorithms=self.allowed_algorithms, options={'verify_exp': False}, ) self._validate_jwt_data(data, access_type=AccessType.refresh) user = self.user_class.identify(data['id']) self._check_user(user) if override_access_lifespan is None: access_lifespan = self.access_lifespan else: access_lifespan = override_access_lifespan refresh_expiration = data['rf_exp'] access_expiration = min( (moment + access_lifespan).int_timestamp, refresh_expiration, ) custom_claims = { k: v for (k, v) in data.items() if k not in RESERVED_CLAIMS } payload_parts = dict(iat=moment.int_timestamp, exp=access_expiration, rf_exp=refresh_expiration, jti=data['jti'], id=data['id'], rls=','.join(user.rolenames), **custom_claims) return jwt.encode( payload_parts, self.encode_key, self.encode_algorithm, ).decode('utf-8') def extract_jwt_token(self, token): """ Extracts a data dictionary from a jwt token """ # Note: we disable exp verification because we will do it ourselves with InvalidTokenHeader.handle_errors('failed to decode JWT token'): data = jwt.decode( token, self.encode_key, algorithms=self.allowed_algorithms, options={'verify_exp': False}, ) self._validate_jwt_data(data, access_type=AccessType.access) return data def _validate_jwt_data(self, data, access_type): """ Validates that the data for a jwt token is valid """ MissingClaimError.require_condition( 'jti' in data, 'Token is missing jti claim', ) BlacklistedError.require_condition( not self.is_blacklisted(data['jti']), 'Token has a blacklisted jti', ) MissingClaimError.require_condition( 'id' in data, 'Token is missing id field', ) MissingClaimError.require_condition( 'exp' in data, 'Token is missing exp claim', ) MissingClaimError.require_condition( 'rf_exp' in data, 'Token is missing rf_exp claim', ) moment = pendulum.now('UTC').int_timestamp if access_type == AccessType.access: ExpiredAccessError.require_condition( moment <= data['exp'], 'access permission has expired', ) elif access_type == AccessType.refresh: EarlyRefreshError.require_condition( moment > data['exp'], 'access permission for token has not expired. may not refresh', ) ExpiredRefreshError.require_condition( moment <= data['rf_exp'], 'refresh permission for token has expired', ) def _unpack_header(self, headers): """ Unpacks a jwt token from a request header """ jwt_header = headers.get(self.header_name) MissingTokenHeader.require_condition( jwt_header is not None, "JWT token not found in headers under '{}'", self.header_name, ) match = re.match(self.header_type + r'\s*([\w\.-]+)', jwt_header) InvalidTokenHeader.require_condition( match is not None, "JWT header structure is invalid", ) token = match.group(1) return token def read_token_from_header(self): """ Unpacks a jwt token from the current flask request """ return self._unpack_header(flask.request.headers) def pack_header_for_user(self, user, override_access_lifespan=None, override_refresh_lifespan=None, **custom_claims): """ Encodes a jwt token and packages it into a header dict for a given user :param: user: The user to package the header for :param: override_access_lifespan: Override's the instance's access lifespan to set a custom duration after which the new token's accessability will expire. May not exceed the refresh_lifespan :param: override_refresh_lifespan: Override's the instance's refresh lifespan to set a custom duration after which the new token's refreshability will expire. :param: custom_claims: Additional claims that should be packed in the payload. Note that any claims supplied here must be JSON compatible types """ token = self.encode_jwt_token( user, override_access_lifespan=override_access_lifespan, override_refresh_lifespan=override_refresh_lifespan, **custom_claims) return {self.header_name: self.header_type + ' ' + token}
def main(): engine = init_engine() Base.metadata.create_all(engine) session_factory = get_session_factory(engine) with transaction.manager: dbsession = get_tm_session(session_factory, transaction.manager) # yes, the user model is redundant but I ran out of time making this users = [UserModel(first_name='Bubzy', last_name='Monster', identifier='bubzy'), UserModel(first_name='Moozy', last_name='Monster', identifier='drmoozy'), UserModel(first_name='Maxter', last_name='Monster', identifier='nursemax')] domains = [DomainModel(name='prescription'), DomainModel(name='medicine'), DomainModel(name='rx_request')] actions = [ActionModel(name='create'), ActionModel(name='write'), ActionModel(name='approve'), ActionModel(name='view')] resources = [ResourceModel(name='1')] # the first medicine pk_id (cinammon jb) -- this is a hack roles = [RoleModel(title='patient'), RoleModel(title='physician'), RoleModel(title='nurse_practitioner')] dbsession.add_all(users + roles + domains + actions + resources) users = dict((user.identifier, user) for user in dbsession.query(UserModel).all()) domains = dict((domain.name, domain) for domain in dbsession.query(DomainModel).all()) actions = dict((action.name, action) for action in dbsession.query(ActionModel).all()) resources = dict((resource.name, resource) for resource in dbsession.query(ResourceModel).all()) roles = dict((role.title, role) for role in dbsession.query(RoleModel).all()) thirty_from_now = datetime.now() + timedelta(days=30) cc = CryptContext(schemes=['bcrypt_sha256']) password = cc.encrypt('monster_rx') credentials = [CredentialModel(user_id=user.pk_id, credential=password, expiration_dt=thirty_from_now) for user in users.values()] dbsession.add_all(credentials) perm1 = PermissionModel(domain=domains['prescription'], action=actions['view']) perm2 = PermissionModel(domain=domains['rx_request'], action=actions['create']) perm3 = PermissionModel(domain=domains['rx_request'], action=actions['approve']) perm5 = PermissionModel(domain=domains['rx_request'], action=actions['view']) perm6 = PermissionModel(domain=domains['prescription'], action=actions['write'], resource=resources['1']) # resource-level perm for first medicine perm7 = PermissionModel(domain=domains['prescription'], action=actions['write']) dbsession.add_all([perm1, perm2, perm3, perm5, perm6, perm7]) patient = roles['patient'] physician = roles['physician'] nurse_practitioner = roles['nurse_practitioner'] # associate permissions with roles patient.permissions.append(perm2) # a patient can create an rx_request physician.permissions.extend([perm1, perm3, perm5, perm7]) nurse_practitioner.permissions.append(perm6) # assign the users to roles drmoozy = users['drmoozy'] drmoozy.roles.extend([physician, patient]) bubzy = users['bubzy'] bubzy.roles.append(patient) drmax = users['nursemax'] drmax.roles.extend([nurse_practitioner, patient])
import binascii import json from passlib.context import CryptContext from webob import Response, exc from cornice import Service pwd_context = CryptContext(schemes=["sha256_crypt", "ldap_salted_md5"], sha256_crypt__default_rounds=91234, ldap_salted_md5__salt_size=16) # TODO - users, tokens need to be persisted in a database somewhere _USERS = { "testuser": { "password": pwd_context.encrypt("testpassword") } } class _401(exc.HTTPError): def __init__(self, msg='Unauthorized'): body = {'status': 401, 'message': msg} Response.__init__(self, json.dumps(body)) self.status = 401 self.content_type = 'application/json' def _generate_token(): return binascii.b2a_hex(os.urandom(20)) def valid_token(request): header = 'Authorization'
class PasswordManager(object): """Hash and verify user passwords using passlib """ def __init__(self, app): """ Create a passlib CryptContext. Args: password_hash(str): The name of a valid passlib password hash. Examples: ``'bcrypt', 'pbkdf2_sha512', 'sha512_crypt' or 'argon2'``. Example: ``password_manager = PasswordManager('bcrypt')`` """ self.app = app self.user_manager = app.user_manager # Create a passlib CryptContext self.password_crypt_context = CryptContext( schemes=self.user_manager.USER_PASSLIB_CRYPTCONTEXT_SCHEMES, **self.user_manager.USER_PASSLIB_CRYPTCONTEXT_KEYWORDS) def hash_password(self, password): """Hash plaintext ``password`` using the ``password_hash`` specified in the constructor. Args: password(str): Plaintext password that the user types in. Returns: hashed password. Example: ``user.password = hash_password('mypassword')`` """ # Use passlib's CryptContext to hash a password password_hash = self.password_crypt_context.encrypt(password) return password_hash def verify_password(self, password, password_hash): """Verify plaintext ``password`` against ``hashed password``. Args: password(str): Plaintext password that the user types in. password_hash(str): Password hash generated by a previous call to ``hash_password()``. Returns: | True when ``password`` matches ``password_hash``. | False otherwise. Example: :: if verify_password('mypassword', user.password): login_user(user) """ # Print deprecation warning if called with (password, user) instead of (password, user.password) if isinstance(password_hash, self.user_manager.db_manager.UserClass): print( 'Deprecation warning: verify_password(password, user) has been changed'\ ' to: verify_password(password, password_hash). The user param will be deprecated.'\ ' Please change your call with verify_password(password, user) into'\ ' a call with verify_password(password, user.password)' ' as soon as possible.') password_hash = password_hash.password # effectively user.password # Use passlib's CryptContext to verify a password try: res = self.password_crypt_context.verify(password, password_hash) except: res = False return res
class PasswordType(types.TypeDecorator): """ Hashes passwords as they come into the database and allows verifying them using a pythonic interface :: >>> target = Model() >>> target.password = '******' '$5$rounds=80000$H.............' >>> target.password == 'b' True """ impl = types.BINARY(60) python_type = Password def __init__(self, **kwargs): """ All keyword arguments are forwarded to the construction of a `passlib.context.CryptContext` object. The following usage will create a password column that will automatically hash new passwords as `pbkdf2_sha512` but still compare passwords against pre-existing `md5_crypt` hashes. As passwords are compared; the password hash in the database will be updated to be `pbkdf2_sha512`. :: class Model(Base): password = sa.Column(PasswordType( schemes=[ 'pbkdf2_sha512', 'md5_crypt' ], deprecated=['md5_crypt'] )) """ # Bail if passlib is not found. if passlib is None: raise ImproperlyConfigured( "'passlib' is required to use 'PasswordType'") # Construct the passlib crypt context. self.context = CryptContext(**kwargs) def process_bind_param(self, value, dialect): if isinstance(value, Password): # Value has already been hashed. return value.hash if isinstance(value, six.string_types): # Assume value has not been hashed. return self.context.encrypt(value).encode('utf8') def process_result_value(self, value, dialect): if value is not None: return Password(value, self.context) def coercion_listener(self, target, value, oldvalue, initiator): if not isinstance(value, Password): # Hash the password using the default scheme. value = self.context.encrypt(value).encode('utf8') return Password(value, context=self.context) else: # If were given a password object; ensure the context is right. value.context = weakref.proxy(self.context) return value
class PasswordType(types.TypeDecorator, ScalarCoercible): """ PasswordType hashes passwords as they come into the database and allows verifying them using a pythonic interface. All keyword arguments (aside from max_length) are forwarded to the construction of a `passlib.context.CryptContext` object. The following usage will create a password column that will automatically hash new passwords as `pbkdf2_sha512` but still compare passwords against pre-existing `md5_crypt` hashes. As passwords are compared; the password hash in the database will be updated to be `pbkdf2_sha512`. :: class Model(Base): password = sa.Column(PasswordType( schemes=[ 'pbkdf2_sha512', 'md5_crypt' ], deprecated=['md5_crypt'] )) Verifying password is as easy as: :: target = Model() target.password = '******' # '$5$rounds=80000$H.............' target.password == 'b' # True """ impl = types.VARBINARY(1024) python_type = Password def __init__(self, max_length=None, **kwargs): # Fail if passlib is not found. if passlib is None: raise ImproperlyConfigured( "'passlib' is required to use 'PasswordType'" ) # Construct the passlib crypt context. self.context = CryptContext(**kwargs) if max_length is None: max_length = self.calculate_max_length() # Set the length to the now-calculated max length. self.length = max_length def calculate_max_length(self): # Calculate the largest possible encoded password. # name + rounds + salt + hash + ($ * 4) of largest hash max_lengths = [1024] for name in self.context.schemes(): scheme = getattr(__import__('passlib.hash').hash, name) length = 4 + len(scheme.name) length += len(str(getattr(scheme, 'max_rounds', ''))) length += (getattr(scheme, 'max_salt_size', 0) or 0) length += getattr( scheme, 'encoded_checksum_size', scheme.checksum_size ) max_lengths.append(length) # Return the maximum calculated max length. return max(max_lengths) def load_dialect_impl(self, dialect): if dialect.name == 'postgresql': # Use a BYTEA type for postgresql. impl = postgresql.BYTEA(self.length) return dialect.type_descriptor(impl) if dialect.name == 'oracle': # Use a RAW type for oracle. impl = oracle.RAW(self.length) return dialect.type_descriptor(impl) # Use a VARBINARY for all other dialects. impl = types.VARBINARY(self.length) return dialect.type_descriptor(impl) def process_bind_param(self, value, dialect): if isinstance(value, Password): # If were given a password secret; encrypt it. if value.secret is not None: return self.context.encrypt(value.secret).encode('utf8') # Value has already been hashed. return value.hash if isinstance(value, six.string_types): # Assume value has not been hashed. return self.context.encrypt(value).encode('utf8') def process_result_value(self, value, dialect): if value is not None: return Password(value, self.context) def _coerce(self, value): if value is None: return if not isinstance(value, Password): # Hash the password using the default scheme. value = self.context.encrypt(value).encode('utf8') return Password(value, context=self.context) else: # If were given a password object; ensure the context is right. value.context = weakref.proxy(self.context) # If were given a password secret; encrypt it. if value.secret is not None: value.hash = self.context.encrypt(value.secret).encode('utf8') value.secret = None return value
if silent == 0: progress = str(cnt),chr(47),str(TotalPass) pcnt = "(",str(round(float(float(cnt) / float(TotalPass))*100,2)),"%)" duration = str(round(TotalTime,2)),"s" print "Elapsed:",''.join(duration),"Progess:",''.join(progress),''.join(pcnt),"Speed:", round((cnt / TotalTime),2),"Hash/s" ETime = CurrTime for linep in passwd: lines += 1 CurrPass = linep CurrHash = CurrHash.strip(chr(13)) CurrHash = CurrHash.strip(chr(10)) CurrHash = CurrHash.strip(chr(34)) CurrPass = CurrPass.strip(chr(13)) CurrPass = CurrPass.strip(chr(10)) CurrPass = CurrPass.strip(chr(34)) md51x = md5.encrypt(CurrPass) md52x = md5.encrypt(md51x) md53x = md5.encrypt(md52x) md54x = md5.encrypt(md53x) md55x = md5.encrypt(md54x) md56x = md5.encrypt(md55x) md5sha1 = md5.encrypt(md5sha_hash.encrypt(CurrPass)) md41x = md4.encrypt(CurrPass) md42x = md4.encrypt(md41x) md43x = md4.encrypt(md42x) md44x = md4.encrypt(md43x) md45x = md4.encrypt(md44x) md46x = md4.encrypt(md45x) CurrPass2 = str(CurrPass + str((chr(0) * 100))) radmin = md5.encrypt(CurrPass2[0:100]) md5umd5 = md5.encrypt(md51x.upper())
class PasswordType(types.TypeDecorator, ScalarCoercible): """ PasswordType hashes passwords as they come into the database and allows verifying them using a pythonic interface. All keyword arguments (aside from max_length) are forwarded to the construction of a `passlib.context.CryptContext` object. The following usage will create a password column that will automatically hash new passwords as `pbkdf2_sha512` but still compare passwords against pre-existing `md5_crypt` hashes. As passwords are compared; the password hash in the database will be updated to be `pbkdf2_sha512`. :: class Model(Base): password = sa.Column(PasswordType( schemes=[ 'pbkdf2_sha512', 'md5_crypt' ], deprecated=['md5_crypt'] )) Verifying password is as easy as: :: target = Model() target.password = '******' # '$5$rounds=80000$H.............' target.password == 'b' # True """ impl = types.VARBINARY(1024) python_type = Password def __init__(self, max_length=None, **kwargs): # Fail if passlib is not found. if passlib is None: raise ImproperlyConfigured( "'passlib' is required to use 'PasswordType'") # Construct the passlib crypt context. self.context = CryptContext(**kwargs) if max_length is None: max_length = self.calculate_max_length() # Set the length to the now-calculated max length. self.length = max_length def calculate_max_length(self): # Calculate the largest possible encoded password. # name + rounds + salt + hash + ($ * 4) of largest hash max_lengths = [1024] for name in self.context.schemes(): scheme = getattr(__import__('passlib.hash').hash, name) length = 4 + len(scheme.name) length += len(str(getattr(scheme, 'max_rounds', ''))) length += (getattr(scheme, 'max_salt_size', 0) or 0) length += getattr(scheme, 'encoded_checksum_size', scheme.checksum_size) max_lengths.append(length) # Return the maximum calculated max length. return max(max_lengths) def load_dialect_impl(self, dialect): if dialect.name == 'postgresql': # Use a BYTEA type for postgresql. impl = postgresql.BYTEA(self.length) return dialect.type_descriptor(impl) if dialect.name == 'oracle': # Use a RAW type for oracle. impl = oracle.RAW(self.length) return dialect.type_descriptor(impl) # Use a VARBINARY for all other dialects. impl = types.VARBINARY(self.length) return dialect.type_descriptor(impl) def process_bind_param(self, value, dialect): if isinstance(value, Password): # If were given a password secret; encrypt it. if value.secret is not None: return self.context.encrypt(value.secret).encode('utf8') # Value has already been hashed. return value.hash if isinstance(value, six.string_types): # Assume value has not been hashed. return self.context.encrypt(value).encode('utf8') def process_result_value(self, value, dialect): if value is not None: return Password(value, self.context) def _coerce(self, value): if value is None: return if not isinstance(value, Password): # Hash the password using the default scheme. value = self.context.encrypt(value).encode('utf8') return Password(value, context=self.context) else: # If were given a password object; ensure the context is right. value.context = weakref.proxy(self.context) # If were given a password secret; encrypt it. if value.secret is not None: value.hash = self.context.encrypt(value.secret).encode('utf8') value.secret = None return value @property def python_type(self): return self.impl.type.python_type
class HashEntity(object): """ Represents a primary key (owner? owner+key? @todo ????) and an associated digest (aka hash, which is a reserved word in Python). Also stores data for convenience, though it's not ever saved. @todo needs work on what inconsistent (is_verified = False) states it can and can't exist in, etc. """ key = None data = None digest_str = None cryptcontext = None def __init__(self, key, data=None, digest=None, cryptcontext=None): if cryptcontext is None: # @todo make the CryptContext schemes not hard-coded self.cryptcontext = CryptContext(schemes=['ldap_pbkdf2_sha512'], default='ldap_pbkdf2_sha512', all__vary_rounds=0.1) else: self.cryptcontext = cryptcontext if data is not None and digest is not None: self.data = data # okay, first verify the digest we got to check for a mismatch -- # we have to use the passlib verify, in case an older scheme was # used, instead of just calculating the new digest and comparing # strings if not self.cryptcontext.verify(data, digest): raise SaltboxException("Given data doesn't verify with given digest") # if self.digest_str isn't our default hash scheme, recalculate it # and save it as default hash scheme # @todo this always recalculates; wasteful self.digest() elif data is not None: self.data = data self.digest() elif digest is not None: self.digest_str = digest def __str__(self): my_data = self.data or '' my_digest = self.digest_str or '' return "HashEntity: data length %d, digest '%s'" % (len(my_data), my_digest) def digest(self, data=None): """ Calculates the digest of self.data and sets self.digest_str. @param data If set, replaces self.data before calculating digest. @return None """ self.data = data or self.data if self.data is None: raise SaltboxException('Cannot calculate digest with no data.') self.digest_str = self._calculate_digest() def verify(self, data=None): """ Calculates the digest of some data and compares to self.digest_str. If the data argument is None, self.data will be verified against self.digest_str. @param data If set, replaces self.data before verifying digest. @return boolean True if the digest of self.data matches self.digest_str, else False. """ check_data = data or self.data if check_data is None: raise SaltboxException('Cannot verify digest with no data.') if self.digest_str is None: raise SaltboxException('Cannot verify an empty digest.') return self._verify_digest(check_data) @property def is_verified(self): return self.verify() def clear(self): """ Clears all data variables, but not the cryptcontext. """ self.key = None self.data = None self.digest_str = None def save(self): assert self.is_verified, "Cannot save HashEntity which doesn't verify." raise NotImplementedError # @todo def _calculate_digest(self, data=None): data = data or self.data return self.cryptcontext.encrypt(data) def _verify_digest(self, data=None): data = data or self.data return self.cryptcontext.verify(data, self.digest_str)
'pyramid_debugtoolbar', 'pyramid_tm', 'SQLAlchemy', 'transaction', 'zope.sqlalchemy', 'waitress', 'wtforms', 'passlib', 'markdown', 'pygments', ] #Added from class notes from passlib.context import CryptContext password_context = CryptContext(schemes=['pbkdf2_sha512']) hashed = password_context.encrypt('password') if password_context.verify('password', hashed): print ("It matched") setup(name='learning_journal', version='0.0', description='learning_journal', long_description=README + '\n\n' + CHANGES, classifiers=[ "Programming Language :: Python", "Framework :: Pyramid", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: WSGI :: Application", ], author='', author_email='',
if silent == 0: progress = str(cnt),chr(47),str(TotalPass) pcnt = "(",str(round(float(float(cnt) / float(TotalPass))*100,2)),"%)" duration = str(round(TotalTime,2)),"s" print "Elapsed:",''.join(duration),"Progess:",''.join(progress),''.join(pcnt),"Speed:", round((cnt / TotalTime),2),"Hash/s" ETime = CurrTime for linep in passwd: lines += 1 CurrPass = linep CurrHash = CurrHash.strip(chr(13)) CurrHash = CurrHash.strip(chr(10)) CurrHash = CurrHash.strip(chr(34)) CurrPass = CurrPass.strip(chr(13)) CurrPass = CurrPass.strip(chr(10)) CurrPass = CurrPass.strip(chr(34)) sha1 = sha.encrypt(CurrPass) sha12x = sha.encrypt(sha1) sha13x = sha.encrypt(sha12x) sha14x = sha.encrypt(sha13x) sha15x = sha.encrypt(sha14x) sha16x = sha.encrypt(sha15x) shamd5 = sha.encrypt(md5.encrypt(CurrPass)) shamd4 = sha.encrypt(md4.encrypt(CurrPass)) cnt = (lines * 8) CurrTime = time.time() TotalTime = CurrTime - StartTime if sha1 == CurrHash: Algo = "SHA1" Cracked = sha1,":",CurrPass if LastAlgo == Algo: print ''.join(Cracked)
def reset_password(): ''' allow user to reset password hash: variable emailed in link to user to confirm resetting ''' # user has clicked on reset password link in an email sent to them about # changing their email address if request.method == 'GET': if request.args.get('code'): return render_template('reset_password.html', hash=request.args.get('code'), untimed='true') return redirect(url_for('main.index')) # process the password reset request elif request.method == 'POST': if request.form['submit'] == 'cancel': flash("Password reset canceled.") return redirect(url_for('main.index')) hash = request.form['hash'] untimed = '' # use untimed version of URL serializer - user has noticed attempt to change # their email and is resetting password if request.form['untimed'] == 'true': untimed = request.form['untimed'] serializer = URLSafeSerializer(current_app.config['SECRET_KEY']) try: decoded = serializer.loads(hash, salt='reset_password') except: flash("Sorry, there was an error. Please try again.") return redirect(url_for('main.index')) #use timed version - user forgot password and was sent link to reset else: serializer = URLSafeTimedSerializer(current_app.config['SECRET_KEY']) try: decoded = serializer.loads(hash, salt='forgot_password', max_age=3600) except SignatureExpired: flash('The link has expired; password not reset.') return redirect(url_for('main.index')) except: flash("Sorry, there was an error. Please try again.") return redirect(url_for('main.index')) #try to update password try: user = User.query.filter_by(email=decoded[0]).one() except NoResultFound: flash('Could not find an account associated with that email address.') return redirect(url_for('main.index')) else: password = request.form['password'] confirm_password = request.form['confirm_password'] if len(password) < 5: flash('Password is too short. Please try again.') return render_template('reset_password.html', hash=hash, untimed=untimed) elif password != confirm_password: flash('The confirmation password did not match the new password you entered.') return render_template('reset_password.html', hash=hash, untimed=untimed) else: #use passlib to encrypt password and then update it myctx = CryptContext(schemes=['pbkdf2_sha256']) hashed_password = myctx.encrypt(password) user.password = hashed_password db.session.commit() flash('Your password has been updated. Please use it to login.') return redirect(url_for('main.login')) else: return abort(405)
# This script is just to save me having to go out and find a hash generator every time I want to test something. # It takes in a string from the command line and outputs a hash for each algorithm in the python hashlib. import hashlib from passlib.context import CryptContext schemes = ["sha1_crypt", "sha256_crypt", "sha512_crypt", "md5_crypt", "des_crypt", 'ldap_salted_sha1', 'ldap_salted_md5', 'ldap_sha1', 'ldap_md5', 'ldap_plaintext', "mysql323"] myctx = CryptContext(schemes) key = raw_input("enter key: ") print "hashlib hashes:\n" for algorithm in hashlib.algorithms: print "The %s hash representation of %s is: " % (algorithm, key) print hashlib.new(algorithm, key).hexdigest() print "\npasslib hashes:\n" for algorithm in schemes: print "The %s hash representation of %s is: " % (algorithm, key) print myctx.encrypt(key, algorithm) hash1 = myctx.encrypt(key, 'ldap_md5') if myctx.verify(key, hash1): print "true" else: print "false"