md5 na Devise - migracja haseł z php-fusion

Czesc,

Żeby mój projekt w ogóle wystartował potrzebuję przenieść użytkowników(a raczej ich hasła) z php-fusion7. Jest tam używany md5(md5()) tzw. podwójne szyfrowanie md5.

[code=ruby]module Devise
module Encryptors
class Md5 < Base
def self.digest(password, stretches, salt, pepper)
str = [password, salt].flatten.compact.join
Digest::MD5.hexdigest(str)
end
end
end
end

hasło php-fusion7 => 285bf5e5ac71fa7651f0311d443411a9
hasło devise(:md5) => 57b8eb3884083c5bb45029d77d0e392c[/code]
Udało mi się dzięki temu HowTo: https://github.com/plataformatec/devise/wiki/How-To:-Create-a-custom-encryptor użyć md5 jako encryptora haseł.

Nie jestem pewien jak te hasła są szyfrowane czy używana jest do tego nazwa użytkownika? bo na devise rejestruję się z emaila a na fusion z username.

Jeżeli to nie ma znaczenia to może devise nie ma podwójnej deszyfracji??

Ustaliłem, że Devise każdorazowo przy zakładaniu konta o tych samych parametrów zakłada inne hasło, może ma to coś wspólnego z salt?

na pierwszy rzut oka wygląda, że bez soli powinno być ok - ale mogę się mylić.

ja zrobiłem podobną rzecz, nie fusion ale stara werja strony w php, troche inaczej. wrzuciłem stare hasła uzytkowników do kolumny password_old i podczas logowania przez Devise najpierw próbowałem ich zalogowac po md5, jak poszło to kodowałem i zapisywałem jako devisowe password

Okej działa pięknie, oto co zmieniłem:

[code=ruby] module Devise
module Encryptors
class Md5 < Base
def self.digest(password, stretches, salt, pepper)
str = [password]
Digest::MD5.hexdigest(Digest::MD5.hexdigest(str))

    end
  end
end

end[/code]

Nie wiem za bardzo jak zrobić to tak jak ty. Myślisz, że nie wszystkie hasła mogą działać??

Na pewno ma to związek. Na tym cały bajer solenia polega, że dwa takie same hasła potraktowane innym saltem będą różnymi hashami, bo gdyby salta nie było, to byłyby identyczne.

Musisz odtworzyć w Twoim encryptorze dokładnie taki sam sposób tworzenia haseł jak w PHP fusion, czyli:

  • usunąć solenie, jeśli w PHP Fusion go nie ma (lamerstwo i security vulnerability swoją drogą)
  • sprawdzić gdzie wywoływany jest Twój encryptor i przeładuj to wywołanie, żeby trafiała do niego odpowiednia liczba argumentów: znajdź Devise::Encryptors::Base.digest(password, stretches, salt, pepper) i zmień odpowiednio (wywal salt)
  • wywal salt listy argumentów i z ciała funkcji (ta linia “str = …”), bo po co to przekazywać, skoro tego nie używasz

btw: podejście Artura jest całkiem interesujące.

Dzięki fidel udało się, teraz przynajmniej wiem jak to działa.

str = [password].flatten.compact.join

zobacz co robią metody flatten, compact, join - bo lekko bez sensu jest ten kod :wink:

[quote=krzyzak]str = [password].flatten.compact.join
zobacz co robią metody flatten, compact, join - bo lekko bez sensu jest ten kod ;)[/quote]
Ofkoz, myślałem, że to oczywiste jest :wink:

Ale nadal podtrzymuję, że nieposolone hasła to kiepski pomysł i lepiej byłoby je zmigrować na takie z soleniem i hashowane czymś lepszym, niż MD5…

Gdybym znalazł jakiś tutorial, z tym jak to zrobić tak jak napisał artur69, napewno bym się za to zabrał, narazie wystarczy bo to mały projekt dla 300 osób max.

Tutorial będzie ciężko znaleźć, trzeba by to rozpykać samemu. Na ten moment Tobie nie pomogę, ale jak starczy mi sił, to późnym wieczorem zrobię lekką rozkminę i może się coś urodzi.

Wrzucam kod, może się przyda a i może ktoś coś poprawi, testowane tylko na Devise 1.1.8, w nowszych wersjach mogło się coś zmienić w Devise::SessionsController, którego metode nadpisuje

[code=ruby]class Users::SessionsController < Devise::SessionsController

def create

resource = copy_old_password
resource = warden.authenticate!(:scope => resource_name, :recall => "new") unless resource

set_flash_message :notice, :signed_in
sign_in_and_redirect(resource_name, resource)

end

private

def copy_old_password
if u = User.find_by_email(params[:user][:email])
if u.encrypted_password.blank? and u.password_old.present?
md5 = Digest::MD5.hexdigest(params[:user][:password] + ‘tu stary site miał jakis swój salt’)
sha1 = Digest::SHA1.hexdigest(md5)
if sha1 == u.password_old
u.update_attribute :password, params[:user][:password]
u
end
end
end
end

end[/code]