django - Use sha256 hashes instead of plain text passwords -
my country's government has restricted https speed block access secure web services out side iran. clients in pain logging in accounts. know current account passwords encrypted , salted using pbkdf2_sha256
algorithm , there javascript/jquery libs digest sha256 hashes.
my question: there painless way (which not require rewriting/changing original django.contrib.auth
) use sha256 hashes sent ajax requests login password?
update: i'm planning host sites inside iran (which 5 times more expensive , of course controlled government) @ least https protocol not restricted. sending passwords either in plain text or digested way via http channel insecure anyway. while web developer (and not network expert) think can collect/sniff hashes/session ids/cookies anytime want, solving problem needs sophisticated knowledge , efforts , after site not require level of security. live in different planets.
you can write own authentication backend use raw passwords:
from django.contrib.auth import backends django.contrib.auth.models import user class rawpassworduser(user): class meta: proxy = true def set_password(self, raw_password): # default implementation made hash raw_password, # don't want self.password = raw_password def check_password(self, raw_password): # same here, don't make hash out of raw_password return self.password == raw_password class modelbackend(backends.modelbackend): def authenticate(self, username=none, password=none): try: user = rawpassworduser.objects.get(username=username) if user.check_password(password): return user except rawpassworduser.doesnotexist: return none def get_user(self, user_id): try: return rawpassworduser.objects.get(pk=user_id) except rawpassworduser.doesnotexist: return none
in settings file:
authentication_backends = ( # modelbackend project_root/auth/backends.py 'auth.backends.modelbackend', )
now when authenticate
users in views, rawpassworduser
instances. same applies login_required
decorator, request.user
point proxy class.
see documentation details.
for django 1.5+ there option replace default user model custom one, keep existing users have migrate them somehow, see this question.
actually won't able keep user passwords unchanged.
by default django stores passwords in following format:
algorithm$iterations$salt$hash
which means:
you can't regenerate passwords hashes of originals, since don't have originals.
you won't able generate same hash on client-side, without knowing salt. pass client-side, salt supposed secret, it's unwise via unencrypted channel.
the easiest solution see keep current django behaviour, suggested tadeck in comments, add hashing client-side , force users change passwords.
well, it's not solution, because attacker can intercept digested passwords , use them directly, mentioned question update. since don't care security much, checkout public key encryption in javascript.
another solution proposed tadeck use oauth-like service, might this:
def index(request): access_token = request.request.get('token', none) if not access_token: return redirect('login') # custom authentication backend accepts token # , searches user token in database. user = authenticate(access_token) if not user: return redirect('login') return render(...) def auth(request): ''' ajax-view has encrypted ssl.''' # normal django authentication. user = authenticate(request.post['username'], request.post['password']) # authentication failed if user none: return json.dumps({'error': '...'}) # generate, save , return token in json response token = usertoken(user=user, value=generate_token()) # token.expires_at = datetime.now() + timedelta(days=1) token.save() return json.dumps({'token': token.value})
an attacked can still intercept access token, it's bit better intercepting password hash.
Comments
Post a Comment