Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥

Python Password Security: From Zero to Hero

Python Password Security: From Zero to Hero

Learn how password security works in Python -- what's good, what isn't, etc.

Randall Degges

March 21, 2014
Tweet

More Decks by Randall Degges

Other Decks in Programming

Transcript

  1. Stormpath User Management API for Developers • Authentication • User

    Profiles • Groups and Roles • Python/Flask SDK
  2. @app.route('/register', methods=['GET', 'POST']) def register(): if request.method == 'GET': return

    render_template('register.html') try: user = User( email = request.form.get('email'), password = request.form.get('password'), ) user.save() except: return render_template('register.html', error='Username and password required.') return redirect(url_for('dashboard'))
  3. from hashlib import md5 user = User( email = request.form.get('email'),

    password = md5( request.form.get('password') ).hexdigest(), )
  4. from hashlib import md5 from itertools import chain, product from

    string import printable from sys import argv def bruteforce(length): return ( ''.join(candidate) for candidate in chain.from_iterable( product( printable, repeat = i ) for i in range(1, length + 1) ) ) for pw in bruteforce(int(argv[2])): if md5(pw).hexdigest() == argv[1]: print 'Cracked hash: %s!' % argv[1] print 'Password is: %s' % pw break
  5. Also… brute! >>> from brute import brute >>> for s

    in brute(length=10): ... print s $ pip install brute
  6. from hashlib import sha512 from random import choice from string

    import printable salt = ''.join(choice(printable) for i in range (40)) user = User( email = request.form.get('email'), password = salt + '$' + sha512( salt + request.form.get('password') ).hexdigest(), )
  7. The Good • Rainbow tables won’t work! • Still easy

    to brute force. • Have to store your salt in the database. The Bad
  8. bcrypt is slow >>> from bcrypt import gensalt, hashpw >>>

    >>> hash = hashpw('omghi!', gensalt()) >>> if hashpw('omghi!', hash) == hash: ... print 'password valid!' ... 'password valid!'
  9. scrypt is slower! >>> from scrypt import hash >>> >>>

    myhash = hash('mypass', 'mysalt') >>> if hash('mypass', myhash) == myhash: ... print 'password valid!' ... 'password valid!'
  10. sqlite> create table users (email text, password text); sqlite> .tables

    users sqlite> .schema users CREATE TABLE users (email text, password text); sqlite> insert into users (email, password) values ( ...> '[email protected]', ...> 'mysalt$mypasswordhash' ...> ); sqlite> select * from users; [email protected]|mysalt$mypasswordhash ? ? ? ?
  11. Summary • Use bcrypt (or scrypt, if you live on

    the edge). • Lock your server(s) down. • Encrypt output if necessary. • Prevent human access.
  12. Flask-Stormpath @app.route('/register', methods=['GET', 'POST']) def register(): if request.method == 'GET':

    return render_template('register.html') try: someuser = User.create( email = request.form.get('email'), password = request.form.get('password'), ) except StormpathError, err: return render_template('register.html', error=err.message) login_user(someuser, remember=True) return redirect(url_for('dashboard'))
  13. So... • Don’t store passwords in plain text! • Check

    out Flask-Stormpath on Github: https://github.com/stormpath/stormpath- flask • If you liked this presentation, tweet me! @rdegges