Another security question

Chris Angelico rosuav at gmail.com
Fri Dec 23 20:31:52 EST 2016


On Sat, Dec 24, 2016 at 11:20 AM, Paul Rubin <no.email at nospam.invalid> wrote:
> The basic problem is those functions are fast enough to make dictionary
> attacks feasible.  The preferred password hashing function these days is
> Argon2, which has some tunable security parameters:

Solution: Don't use dictionary-attackable passwords. Here's a quick
and stupid password verifier that uses MD5:

import os, base64, hashlib, timeit

def encrypt_password(pw):
    salt = base64.b64encode(os.urandom(3))
    return salt + b":" + hashlib.md5(salt + pw).hexdigest().encode("ascii")

def verify_password(pw, enc):
    salt, hash = enc.split(b":")
    return hash == hashlib.md5(salt + pw).hexdigest().encode("ascii")

crackme = encrypt_password(b"elven-their-cure-planning")
assert not verify_password(b"figure-dagger-personal-excited", crackme)
assert verify_password(b"elven-their-cure-planning", crackme)

print(timeit.repeat('verify_password(b"figure-dagger-personal-excited",
crackme)', globals=globals()))
# [0.9219889058731496, 0.9255746062844992, 0.9231259850785136,
0.9204203351400793, 0.9239354520104825]


Okay, so that's about as insecure as salted hashes can get, right? I
brute-forced a million of them a second, one core. Now, suppose you
know for sure that I used that format of password (four words, all
lower-case, separated by hyphens), and you have a copy of my 2000-word
dictionary from which I select words. It'll still take you 185 days to
exhaustively try every possible password. So on average, it'll take
you a day of searching with 93 computers to crack this kind of
password. And that's just using four characters of salt and a single
iteration of MD5. That's borderline infeasible, without needing any
sort of top-notch hashing system. Switch to werkzeug's functions
and... well, I had to tweak timeit.repeat, because it did about two
*thousand* per second. And that's with default parameters. You're
going to need five hundred times as much processing to crack those
things.

Use XKCD 936 passwords. Even if someone has your entire password
generation system, they're still pretty secure. If anything, they'll
be even harder to crack, because of the many variations you could use
(capitalization, separators, precise list of words), not to mention
that you can easily add a fifth word to make them even more secure.
(But only if you're paranoid. Memorizing a fifth word is harder.) It
works.

ChrisA


More information about the Python-list mailing list