﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
18144	MD5PasswordHasher: broken backwards compatibility with empty salt	apreobrazhensky@…	nobody	"In our project we stored unsalted MD5 passwords in format: ""md5$$<actual md5 hash>"".
In Django 1.3 django.contrib.auth.check_password(...) coped well with such format.

In Django 1.4 trying to check such password fails with assertion in django.contrib.auth.hashers.MD5PasswordHasher.encode(...)

{{{
Traceback (most recent call last):
  File ""/home/admin/sites/env/local/lib/python2.7/site-packages/django/core/handlers/base.py"", line 111, in get_response
    response = callback(request, *callback_args, **callback_kwargs)
  File ""/home/admin/sites/fxstart-production/source/apps/accounts/decorators.py"", line 17, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File ""/home/admin/sites/fxstart-production/source/apps/dashboard_personal/views.py"", line 57, in view_change_password
    if form.save():
  File ""/home/admin/sites/fxstart-production/source/apps/dashboard_personal/forms/change_password.py"", line 129, in save
    if not self.account.check_withdraw_password(current_password):
  File ""/home/admin/sites/fxstart-production/source/apps/accounts/models.py"", line 184, in check_withdraw_password
    return check_password(raw_password, self.withdraw_password)
  File ""/home/admin/sites/env/local/lib/python2.7/site-packages/django/contrib/auth/hashers.py"", line 45, in check_password
    is_correct = hasher.verify(password, encoded)
  File ""/home/admin/sites/env/local/lib/python2.7/site-packages/django/contrib/auth/hashers.py"", line 319, in verify
    encoded_2 = self.encode(password, salt)
  File ""/home/admin/sites/env/local/lib/python2.7/site-packages/django/contrib/auth/hashers.py"", line 312, in encode
    assert salt and '$' not in salt
AssertionError
}}}

As you can see from the code, salt variable is asserted, which means AssertionError is raised every time salt is empty string.

Is this intended behavior? (which means we have to regenerate our password's database or workaround it via replacing hashes like ""md5$$<actual md5 hash>"" to ""<actual md5 hash>"" before calling check_password)"	Bug	closed	contrib.auth	1.4	Release blocker	fixed	MD5PasswordHasher check_password salt	slav0nic0@… carsten.fuchs@…	Accepted	1	0	0	1	0	0
