/* This file contains functions & definitions assiocated to players and players only. This includes hashing, player data, loading, saving etc. */ /* ** Hashing ** by Octet */ #define MAX_PASSWORD_LENGTH 64 #define MAX_SALT_LENGTH 32 #define MAX_ENCRYPTED_PASS_LENGTH 129 enum e_PassData { passEncrypt[MAX_ENCRYPTED_PASS_LENGTH], passSalt[MAX_SALT_LENGTH] } //temp vars for storing password new tempPassword[MAX_PLAYERS][65]; new tempHash[MAX_PLAYERS][65]; new tempSalt[MAX_PLAYERS][33]; /* Whirlpool: http://forum.sa-mp.com/showthread.php?t=570945 */ native WP_Hash(buffer[], len, const str[]); // Variables //Variables used when fetching the values from the table new NewPassword[MAX_PLAYERS][MAX_ENCRYPTED_PASS_LENGTH]; new NewSalt[MAX_PLAYERS][MAX_SALT_LENGTH]; // Prototypes forward HashPassword(password[], playerid); forward HashPasswordEx(password[], encrypted[], salt[]); forward CheckPassword(password[], hash[], salt[], playerid); // Functions //Updates the password in the DB, as well as hashing public HashPassword(password[], playerid) { printf("Hashing password for player %s (%d).", PlayerName(playerid), playerid); new string[MAX_ENCRYPTED_PASS_LENGTH]; new salt[MAX_SALT_LENGTH]; HashPasswordEx(password, string, salt); //save inside field NewPassword new query[300]; mysql_format(sqlGameConnection, query, sizeof query, "UPDATE `players` SET `NewPassword` = '%e', `NewSalt` = '%e' WHERE `Name` = '%s'", string, salt, PlayerName(playerid)); mysql_pquery(sqlGameConnection, query); return 1; } //Hashes the password referencing encrypted & salt & remember arrays are pointers so reference not required public HashPasswordEx(password[], encrypted[], salt[]) { new part1[33]; new part2[33]; strmid(part1, password, 0, floatround(strlen(password)/2, floatround_floor)); strmid(part2, password, floatround(strlen(password)/2, floatround_floor), strlen(password)); format(salt, MAX_SALT_LENGTH, "%s", generateRandomSalt()); format(encrypted, MAX_ENCRYPTED_PASS_LENGTH, "%s%s%s", part1, salt, part2); WP_Hash(encrypted, MAX_ENCRYPTED_PASS_LENGTH, encrypted); return; } public CheckPassword(password[], hash[], salt[], playerid) { new string[MAX_ENCRYPTED_PASS_LENGTH]; new part1[33]; new part2[33]; strmid(part1, password, 0, floatround(strlen(password)/2, floatround_floor)); strmid(part2, password, floatround(strlen(password)/2, floatround_floor), strlen(password)); format(string, sizeof(string), "%s%s%s", part1, salt, part2); WP_Hash(string, sizeof string, string); if(strcmp(hash, string, true) == 0) { printf("The account, %s (%d) has been authorized using password.", PlayerName(playerid), playerid); return true; } return false; } /* Salt generation by Smo (0ms) */ stock generateRandomSalt() { new salt[32 + 1]; for(new i; i < 32; i++) { salt[i] = random(79) + 47; if(salt[i] == 33 || salt[i] == 34 || salt[i] == 37 || salt[i] == 39 || salt[i] == 92) { //invalid SQL chars salt[i] = 33; //replace with ! } } salt[32] = 0; return salt; }