Inscription php/mysql ==> Compte ruby..

Therand
Invité n'ayant pas de compte PHPfrance

04 nov. 2012, 00:16

Bonjour,

Pardonnez-moi pour le titre peu explicite, mais je n'ai pas trouvé mieux.

Je vous explique mon problème,
J'ai d'un coté un jeu en ruby et de l'autre un site simple php/mysql avec espace membre.

Mon but ==> Le client arrive sur le site, s'inscrit, ses informations se stockent dans la table "user", il peut dès lors accéder à toutes les pages du site et au jeu..
Pour le moment, je suis au stade ou le client peut s'inscrire sur le site, ou sur le jeu, mais je peux utiliser le compte du site pour le jeu et vice-versa...

Bon, la fonction permettant de s'inscrire via le jeu sera retiré (pas vraiment compliqué..), pour le moment il m'est pratique de la laisser pour les tests.
Le problème, je pense l'avoir détecté ==> la methode utiliser pour le cryptage du mot de passe n'est pas la même..

Ma question est, comment dans php utiliser un algorithme "unsigned 32-bit hash value".. C'est du moins la seule piste que j'ai trouvé.
Dans le code ruby (qui n'est pas de moi à la base) voila les seuls commentaires que je retrouve:

#--------------------------------------------------------------------------
# Encrypts the password into an unsigned 32-bit hash value as string.
# password - original password
# Returns: Unsigned 32-bit hash of the given password as string.
#--------------------------------------------------------------------------

Tout le reste devrait plus ou moins bien se passer, mais sans cette aide, je pense ne jamais trouver ><
Voici un exemple de mot de passe crypté avec ruby ==> yWa55/Met5w donc je pense déjà que ce n'est pas très courant..
Inutile de dire que j'ai déjà essayé $mdp = MD5('mdp'); dans ma requête de création de compte, mais aucuns caractères ne corresponds...

Merci d'avance pour l'aide précieuse!
Très cdt.

Therand
Invité n'ayant pas de compte PHPfrance

04 nov. 2012, 00:19

mais je peux utiliser le compte du site pour le jeu et vice-versa...
====>
mais ne peux utiliser le compte du site pour le jeu et vice-versa...

Pardon pour le double poste mais c'est pas cohérent sinon...

Invité
Invité n'ayant pas de compte PHPfrance

04 nov. 2012, 12:32

Aussi, voici la seule "définition" de la methode utilisée dans mon ruby:

Code : Tout sélectionner

def encrypt_password(password) # encrypting password encrypted = password.crypt(RMXOS::Options::ENCRYPTION_SALT) # removing first two characters which actually are the salt for safety return encrypted[2, encrypted.size - 2] end

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

06 nov. 2012, 21:54

salut

as tu regarder les infos que la classe Digest(ruby) fournit ?
par exemple pour MD5 http://rubyscube.blogspot.fr/2008/03/md5-en-ruby.html

sinon tu peux simplement utiliser une fonction ou procédure stockée sur le sgbd qui fait la comparaison, comme ça aucun problème quelque soit la techno choisie pour l'accès.

Seul bémol transit du mot de passe sur le réseau.

@+
Il en faut peu pour être heureux ......

Therand
Invité n'ayant pas de compte PHPfrance

07 nov. 2012, 15:06

Un grand merci pour ta réponse!
J'ai au moins une grosse piste :)

Mon petit problème est que je ne sais pas trop ou placer la définition, pour le code en lui même je pense avoir trouvé.
Si tu accepte de m'aider encore une fois, voici mes deux codes, qui je pense, servent à encrypter le password.

Coté client, j'ai ça:

Code : Tout sélectionner

#-------------------------------------------------------------------------- # Requests a login. The server responds with whether the login has # succeeded or failed. # username - username of the player # password - password of the player #-------------------------------------------------------------------------- def try_login(username, password) self.send("LIN#{username}\t#{encrypt_password(password)}") end #-------------------------------------------------------------------------- # Requests the registering of an acocunt. The server responds with whether # the login has succeeded or failed. # username - username of the player # password - password of the player #-------------------------------------------------------------------------- def try_register(username, password) self.send("REG#{username}\t#{encrypt_password(password)}") end
Ici, je pense que c'est au niveau des 3 lignes du haut, du fait que j’interdis la création de compte via le client du jeu.

Et coté serveur, j'ai ceci:

Code : Tout sélectionner

#====================================================================== # Action_Handler #---------------------------------------------------------------------- # Handles all basic actions. #====================================================================== class Action_Handler # setting all accessible variables attr_reader :current #---------------------------------------------------------------------- # Initialization. #---------------------------------------------------------------------- def initialize(client) @client = client @current = Action.new end #---------------------------------------------------------------------- # Tries to register this client. # username - username # password - password's hash value # Returns: Success result of the register try. #---------------------------------------------------------------------- def try_register(username, password) # try to find user check = RMXOS.server.sql.query("SELECT COUNT(*) AS count FROM users WHERE username = '#{RMXOS.fix_string(username)}'") hash = check.fetch_hash # user already exists return RMXOS::RESULT_FAIL if hash['count'].to_i > 0 # get user count check = RMXOS.server.sql.query("SELECT COUNT(*) AS count FROM users") hash = check.fetch_hash RMXOS.server.sql.query("START TRANSACTION") # first registered user becomes admin group = (hash['count'].to_i == 0 ? RMXOS::GROUP_ADMIN : RMXOS::GROUP_PLAYER) # register new user RMXOS.server.sql.query("INSERT INTO users (username, password, usergroup) VALUES ('#{RMXOS.fix_string(username)}', '#{password}', #{group})") # get new user ID check = RMXOS.server.sql.query("SELECT user_id FROM users WHERE username = '#{RMXOS.fix_string(username)}'") hash = check.fetch_hash user_id = hash['user_id'].to_i RMXOS.server.sql.query("INSERT INTO user_data (user_id, lastlogin) VALUES (#{user_id}, '#{RMXOS.get_sqltime(Time.now.getutc)}')") # get client's IP address ip = @client.socket.peeraddr[3] # record IP RMXOS.server.sql.query("REPLACE INTO ips(user_id, ip) VALUES (#{user_id}, '#{ip}')") RMXOS.server.sql.query("COMMIT") return RMXOS::RESULT_SUCCESS end #---------------------------------------------------------------------- # Tries to log in this client. # username - username # password - password's hash value # Returns: Success result. #---------------------------------------------------------------------- def try_login(username, password) # find this user check = RMXOS.server.sql.query("SELECT user_id, usergroup, banned FROM users WHERE username = " + "'#{RMXOS.fix_string(username)}' AND password = '#{password}'") # either username or password is incorrect return RMXOS::RESULT_FAIL if check.num_rows == 0 hash = check.fetch_hash # this user is banned return RMXOS::RESULT_DENIED if hash['banned'] != '0' user_id = hash['user_id'].to_i # get client's IP address ip = @client.socket.peeraddr[3] # if using IP banning if USE_IP_BANNING # match against recorded IPs check = RMXOS.server.sql.query("SELECT DISTINCT users.user_id FROM users JOIN ips ON users.user_id = ips.user_id " + "WHERE banned = 1 AND ips.ip = '#{ip}'") # IP matches with IP of a banned user return RMXOS::RESULT_DENIED if check.num_rows > 0 end # this user is already logged in return RMXOS::RESULT_ALTFAIL if $clients.any? {|client| client.player.user_id == user_id} # get user main data @client.player.user_id = user_id @client.player.username = username @client.player.usergroup = hash['usergroup'].to_i # log last login time RMXOS.server.sql.query("UPDATE user_data SET lastlogin = '#{RMXOS.get_sqltime(Time.now.getutc)}' WHERE user_id = #{@client.player.user_id}") # record IP RMXOS.server.sql.query("REPLACE INTO ips(user_id, ip) VALUES (#{user_id}, '#{ip}')") # find all buddies self.setup_buddies # get other user data check = RMXOS.server.sql.query("SELECT guild_id FROM user_data WHERE user_id = #{user_id}") hash = check.fetch_hash # set all guild related data if player is in a guild self.setup_guild_data(hash['guild_id'].to_i) if hash['guild_id'] != nil # notify if new PMs in the inbox check = RMXOS.server.sql.query("SELECT COUNT(*) AS count FROM inbox WHERE recipient_id = #{@client.player.user_id} AND unread = 1") hash = check.fetch_hash @client.send("CHT#{RMXOS::Data::ColorInfo}\t0\t#{RMXOS::Data::NewPMs}") if hash['count'].to_i > 0 # notify if inbox is full check = RMXOS.server.sql.query("SELECT COUNT(*) AS count FROM inbox WHERE recipient_id = #{@client.player.user_id}") hash = check.fetch_hash if hash['count'].to_i >= INBOX_SIZE @client.send("CHT#{RMXOS::Data::ColorInfo}\t0\t#{RMXOS::Data::InboxFull}") end return RMXOS::RESULT_SUCCESS end #---------------------------------------------------------------------- # Changes the user password. # oldpass - old encrypted password # newpass - new encrypted password # Returns: Action result of this action. #---------------------------------------------------------------------- def try_password_change(oldpass, newpass) check = RMXOS.server.sql.query("SELECT password FROM users WHERE user_id = #{@client.player.user_id}") hash = check.fetch_hash # password check return RMXOS::RESULT_FAIL if oldpass != hash['password'] # prepare yes/no action @current.type = Action::TYPE_PASSWORD_CHANGE @current.data = [@client.player.user_id, newpass, @client.player.username] return RMXOS::RESULT_SUCCESS end #---------------------------------------------------------------------- # Executes YES on the last action. #---------------------------------------------------------------------- def execute_yes # check action type case @current.type when Action::TYPE_PASSWORD_CHANGE then self.execute_password_change when Action::TYPE_GUILD_PASSWORD_CHANGE then self.execute_guild_password_change when Action::TYPE_GUILD_DISBAND then self.execute_guild_disband when Action::TYPE_GUILD_TRANSFER then self.execute_guild_transfer when Action::TYPE_GUILD_JOIN then self.execute_guild_join when Action::TYPE_GUILD_LEAVE then self.execute_guild_leave when Action::TYPE_TRADE_REQUEST then self.execute_trade_request when Action::TYPE_BUDDY_ADD then self.execute_buddy_add when Action::TYPE_BUDDY_REMOVE then self.execute_buddy_remove when Action::TYPE_PM_DELETE then self.execute_pm_delete when Action::TYPE_PM_DELETE_ALL then self.execute_pm_delete_all else # no request message @client.send("CHT#{RMXOS::Data::ColorInfo}\t0\t#{RMXOS::Data::NoRequest}") end # clear current @current.clear end #---------------------------------------------------------------------- # Executes NO on the last action. #---------------------------------------------------------------------- def execute_no name = nil # check action type case @current.type when Action::TYPE_PASSWORD_CHANGE, Action::TYPE_GUILD_PASSWORD_CHANGE # player confirmation message message1 = RMXOS::Data::PasswordNoChange when Action::TYPE_GUILD_DISBAND # player confirmation message message1 = RMXOS::Data::GuildNoDisband.sub('GUILD') {@client.player.guildname} when Action::TYPE_GUILD_TRANSFER # player confirmation message message1 = RMXOS::Data::GuildNoTransfer # answer to requester message2 = RMXOS::Data::GuildNoTransferPlayer.sub('PLAYER') {@client.player.username} name = @client.player.guildleader when Action::TYPE_GUILD_JOIN # player confirmation message message1 = RMXOS::Data::GuildNoJoin # answer to requester message2 = RMXOS::Data::GuildNoJoinPlayer.sub('PLAYER') {@client.player.username} name = @current.data[1] when Action::TYPE_GUILD_LEAVE if @current.data[1] == @client.player.username # player confirmation message message1 = RMXOS::Data::GuildNoLeave.sub('GUILD') {@client.player.guildname} else # confirmation message for no removal from guild message1 = RMXOS::Data::GuildNoRemove.sub('PLAYER') {@current.data[1]} end when Action::TYPE_TRADE_REQUEST # player confirmation message message1 = RMXOS::Data::TradeNoRequest # answer to requester message2 = RMXOS::Data::TradeNoRequestPlayer.sub('PLAYER') {@client.player.username} name = @current.data[0] when Action::TYPE_BUDDY_ADD # player confirmation message message1 = RMXOS::Data::BuddyNoAdd # answer to requester message2 = RMXOS::Data::BuddyNoAddPlayer.sub('PLAYER') {@client.player.username} name = @current.data[0] when Action::TYPE_BUDDY_REMOVE # player confirmation message message1 = RMXOS::Data::BuddyNoRemovePlayer.sub('PLAYER') {@current.data[0]} when Action::TYPE_PM_DELETE, Action::TYPE_PM_DELETE_ALL # player confirmation message message1 = RMXOS::Data::PMNoDeletion else # no request message message1 = RMXOS::Data::NoRequest end # send player confirmation message @client.send("CHT#{RMXOS::Data::ColorInfo}\t0\t#{message1}") # send answer to requester if requester exists @client.sender.send_to_name(name, "CHT#{RMXOS::Data::ColorInfo}\t0\t#{message2}") if name != nil # clear action @current.clear end #---------------------------------------------------------------------- # Executes a password change. #---------------------------------------------------------------------- def execute_password_change # change password user_id, newpass, username = @current.data RMXOS.server.sql.query("UPDATE users SET password = '#{newpass}' WHERE user_id = #{user_id}") @client.send("CHT#{RMXOS::Data::ColorOK}\t0\t#{RMXOS::Data::PasswordChanged}") # log this action if action log is turned on if RMXOS.server.options.log_actions RMXOS.log(@client.player, 'Action', "user password change: #{user_id} (#{username})") end end #---------------------------------------------------------------------- # Broadcasts disconnection of this client by kicking. #---------------------------------------------------------------------- def execute_kick @client.send('KCK') @client.terminate $clients.delete(@client) end #---------------------------------------------------------------------- # Sets up buddies. #---------------------------------------------------------------------- def setup_buddies @client.player.buddies = [] # get all buddy IDs check = RMXOS.server.sql.query("SELECT * FROM buddy_list WHERE user1_id = #{@client.player.user_id} OR user2_id = #{@client.player.user_id}") check.num_rows.times { hash = check.fetch_hash if hash['user1_id'].to_i == @client.player.user_id @client.player.buddies.push(hash['user2_id'].to_i) else @client.player.buddies.push(hash['user1_id'].to_i) end } # convert buddy IDs @client.player.buddies.each_index {|i| check = RMXOS.server.sql.query("SELECT username FROM users WHERE user_id = #{@client.player.buddies[i]}") hash = check.fetch_hash @client.player.buddies[i] = hash['username'] } end #---------------------------------------------------------------------- # Sets up all guild related data. # guild_id - ID of the guild #---------------------------------------------------------------------- def setup_guild_data(guild_id) # get guild data check = RMXOS.server.sql.query("SELECT guildname, leader_id FROM guilds WHERE guild_id = #{guild_id}") hash = check.fetch_hash @client.player.guildname = hash['guildname'] # get guild leader name if hash['leader_id'].to_i != @client.player.user_id check = RMXOS.server.sql.query("SELECT username FROM users WHERE user_id = #{hash['leader_id']}") hash = check.fetch_hash @client.player.guildleader = hash['username'] else # this player is the guild leader @client.player.guildleader = @client.player.username end # get guild member count check = RMXOS.server.sql.query("SELECT username FROM users JOIN user_data ON users.user_id = " + "user_data.user_id WHERE guild_id = #{guild_id}") @client.player.guildmembers = [] check.num_rows.times { hash = check.fetch_hash @client.player.guildmembers.push(hash['username']) } end #---------------------------------------------------------------------- # Checks if this client has trades enabled. # user_id - user ID of the other client # Returns: True or False. #---------------------------------------------------------------------- def can_trade?(user_id) check = RMXOS.server.sql.query("SELECT notrade FROM user_data WHERE user_id = #{user_id}") # user does not exist, can't trade return false if check.num_rows == 0 hash = check.fetch_hash return (hash['notrade'] == '0') end end
Il s'agit du action_handler1 (4 composant ce dossier), d'après moi, le code à changer pour du md5 est ici.. entre les lignes 25 et 105


Merci encore pour l'aide apportée.
Dans l'attente d'une réponse.
Cdt

Therand
Invité n'ayant pas de compte PHPfrance

09 nov. 2012, 00:13

Résolu!

J'ai mis du temps, mais j'ai fini pas trouver!
Pour information, dans mon ruby, le mdp était simplement crypt($mdp)...
Donc au lieux de changer de methode pour du md5, j'ai plutôt chercher à faire correspondre les deux "crypt" (ruby et php)

Se qui a pour avantage de juste ajouter :
$salt = 'XS';
$mdp = crypt($mdp, $salt);
$mdp = substr($mdp,2);
Au dessus de l'insert sql...

XS étant le salt de mon mdp
et le substr car la "methode" XS était bonne mais affichait "XS" devant le mdp encrypté alors que mon client ruby non...
Du coup hop >> substr 2 et fini le XS devant :p

Merci pour l'aide,
Cdt

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

09 nov. 2012, 00:55

Salut,

enregistrement d'un utilisateur
[ruby]
def try_register(username, password)
# try to find user
check = RMXOS.server.sql.query("SELECT COUNT(*) AS count FROM users WHERE username = '#{RMXOS.fix_string(username)}'")
hash = check.fetch_hash
# user already exists
return RMXOS::RESULT_FAIL if hash['count'].to_i > 0
# get user count
check = RMXOS.server.sql.query("SELECT COUNT(*) AS count FROM users")
hash = check.fetch_hash
RMXOS.server.sql.query("START TRANSACTION")
# first registered user becomes admin
group = (hash['count'].to_i == 0 ? RMXOS::GROUP_ADMIN : RMXOS::GROUP_PLAYER)
# register new user
# Insertion dans la base du nouvel utilisateur
RMXOS.server.sql.query("INSERT INTO users (username, password, usergroup) VALUES ('#{RMXOS.fix_string(username)}', '#{password}', #{group})")
# get new user ID
check = RMXOS.server.sql.query("SELECT user_id FROM users WHERE username = '#{RMXOS.fix_string(username)}'")
hash = check.fetch_hash
user_id = hash['user_id'].to_i
# Log de la dernière connexion
RMXOS.server.sql.query("INSERT INTO user_data (user_id, lastlogin) VALUES (#{user_id}, '#{RMXOS.get_sqltime(Time.now.getutc)}')")
# get client's IP address
ip = @client.socket.peeraddr[3]
# record IP
# Log de l'ip : Attention avec ça il s'agit d'une donnée perso il y a des règles qui encadre ce stockage
RMXOS.server.sql.query("REPLACE INTO ips(user_id, ip) VALUES (#{user_id}, '#{ip}')")
RMXOS.server.sql.query("COMMIT")
return RMXOS::RESULT_SUCCESS
end[/ruby]

Code de connexion

[ruby]def try_login(username, password)
# find this user
#Selection de l'utilisateur : username avec le mot de passe : password
check = RMXOS.server.sql.query("SELECT user_id, usergroup, banned FROM users WHERE username = " +
"'#{RMXOS.fix_string(username)}' AND password = '#{password}'")
# either username or password is incorrect
return RMXOS::RESULT_FAIL if check.num_rows == 0
hash = check.fetch_hash
# this user is banned
return RMXOS::RESULT_DENIED if hash['banned'] != '0'
user_id = hash['user_id'].to_i
# get client's IP address
ip = @client.socket.peeraddr[3]
# if using IP banning
if USE_IP_BANNING
# match against recorded IPs
check = RMXOS.server.sql.query("SELECT DISTINCT users.user_id FROM users JOIN ips ON users.user_id = ips.user_id " +
"WHERE banned = 1 AND ips.ip = '#{ip}'")
# IP matches with IP of a banned user
return RMXOS::RESULT_DENIED if check.num_rows > 0
end
# this user is already logged in
return RMXOS::RESULT_ALTFAIL if $clients.any? {|client| client.player.user_id == user_id}
# get user main data
@client.player.user_id = user_id
@client.player.username = username
@client.player.usergroup = hash['usergroup'].to_i
# log last login time
RMXOS.server.sql.query("UPDATE user_data SET lastlogin = '#{RMXOS.get_sqltime(Time.now.getutc)}' WHERE user_id = #{@client.player.user_id}")
# record IP
RMXOS.server.sql.query("REPLACE INTO ips(user_id, ip) VALUES (#{user_id}, '#{ip}')")
# find all buddies
self.setup_buddies
# get other user data
check = RMXOS.server.sql.query("SELECT guild_id FROM user_data WHERE user_id = #{user_id}")
hash = check.fetch_hash
# set all guild related data if player is in a guild
self.setup_guild_data(hash['guild_id'].to_i) if hash['guild_id'] != nil
# notify if new PMs in the inbox
check = RMXOS.server.sql.query("SELECT COUNT(*) AS count FROM inbox WHERE recipient_id = #{@client.player.user_id} AND unread = 1")
hash = check.fetch_hash
@client.send("CHT#{RMXOS::Data::ColorInfo}\t0\t#{RMXOS::Data::NewPMs}") if hash['count'].to_i > 0
# notify if inbox is full
check = RMXOS.server.sql.query("SELECT COUNT(*) AS count FROM inbox WHERE recipient_id = #{@client.player.user_id}")
hash = check.fetch_hash
if hash['count'].to_i >= INBOX_SIZE
@client.send("CHT#{RMXOS::Data::ColorInfo}\t0\t#{RMXOS::Data::InboxFull}")
end
return RMXOS::RESULT_SUCCESS
end
[/ruby]
Le code modification du mot de passe

[ruby]
def execute_password_change
# change password
user_id, newpass, username = @current.data
RMXOS.server.sql.query("UPDATE users SET password = '#{newpass}' WHERE user_id = #{user_id}")
@client.send("CHT#{RMXOS::Data::ColorOK}\t0\t#{RMXOS::Data::PasswordChanged}")
# log this action if action log is turned on
if RMXOS.server.options.log_actions
RMXOS.log(@client.player, 'Action', "user password change: #{user_id} (#{username})")
end
end
[/ruby]

Dans ces 3 cas il n'y a nul part l''utilisation d'un quelconque hash, donc c'est fait avant soit dans le SGBD, mais les trigger ce n'est pas sur un select, donc j'ai l'impression que les mots de passe sont en clair dans la base (sauf si l'encodage est fait avant cette classe, celle qui l'utilise).


Donc deux solutions :
- Utilisation des possibilités indiquées dans mon 1er message
- Utilisation des possibilités offertes par MySQL, a savoir un trigger before insert / update qui fait le hash avant ajout / modification (histoire de pas l'oublier), et utiliser une procédure stockée pour le select afin de masquer le comportement, d'ailleurs tu peux utiliser des procédure stockée pour tout si tu le souhaite.

PS : si tu met ruby au lieu de code dans le bbcode tu auras la colorisation de la syntaxe :)

@+

edit : arf trop lent ^^
donc encodage fait avant XD
Il en faut peu pour être heureux ......

Therand
Invité n'ayant pas de compte PHPfrance

09 nov. 2012, 02:19

Hooo!!

Merci beaucoup pour tes explications!
Et ne t'en fais pas, tu n'a pas perdu ton temps! J'ai trouvé une solution qui, dans l'immédiat me convient, certes, mais dans un futur proche je vais opter pour ta méthode plus... propre :)
(merci pour tes commentaires in-code, je vais régler quelques soucis disons de.. légalité ^^)

Sinon pour le hash, je pense l'avoir localisé dans un autre code...

Code : Tout sélectionner

ENCRYPTION_SALT = 'XS'
Enfin, je savais qu'il y avait bel et bien un "hash" ou autre, car dans ma bdd >> password, j'avais des résultats genre: 84Dpm-Ssiet en 11 caractères maj, min, chiffre,..
après, j'ai découvert les supers clé de salage..
puis en cherchant par ci par la bha j'suis arrivé à un résultat pas trop mal quoi :p
Mais dans mon bonheur j'avais encore un souci avec XS qui avait décidé de se foutre devant chaque hash de password (XS84Dpm-Ssiet, ...)
d'où mon "$mdp = substr($mdp,2);"

Et voila, 3 jours de vie perdus ><