Using new SHA-256 function -
dominik523 - 12.07.2015
Introduction
Hey there! This will be a small tutorial about how to create salted passwords which will be hashed with the new SHA-256 hashing function.
First of, what is hashing?
Hash algorithms are one way functions. They turn any amount of data into a fixed-length "fingerprint" that cannot be reversed. They also have the property that if the input changes by even a tiny bit, the resulting hash is completely different (see the example below). This is great for protecting passwords, because we want to store passwords in a form that protects them even if the password file itself is compromised, but at the same time, we need to be able to verify that a user's password is correct.
Example of a hash:
pawn Code:
hash("hello") = 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
hash("hbllo") = 58756879c05c68dfac9866712fad6a93f8146f337a69afe7dd238f3364946366
hash("waltz") = c0e81794384491161f1777c232bc6bd9ec38f616560b120fda8e90f383853542
Good way is to use a hash functions that can't be decrypted. But that's a naive way of storing passwords.
Better way is to add a salt to a password. A salt is an array of characters which is added to the password before the hash so it gets harder for people to crack the password by using brute force or dictionary attacks.
If you ever wondered how those attacks look like, here's a small example:
Code:
Dictionary Attack
Trying apple : failed
Trying blueberry : failed
Trying justinbeiber : failed
...
Trying letmein : failed
Trying s3cr3t : success!
Code:
Brute Force Attack
Trying aaaa : failed
Trying aaab : failed
Trying aaac : failed
...
Trying acdb : failed
Trying acdc : success!
Sorry if this is too long, but I think everyone who is dealing with passwords should know these things.
SHA-256
SHA-256 is a hash function that comes from SHA-2, set of hash functions designed by the NSA. It's a widely used in the Linux systems and some other security applications and protocols like TSL and SSL.
Let's write some code
In this tutorial, I'll show you how to make a code which will generate a random salt which will be added to our passwords later on. I'll show examples of storing the data in MySQL but you can use y_ini or some othes data saving system. It really doesn't matter.
So to start our code, I'm going to show you how to create a salt which will be inserted in our database along with password and other data.
pawn Code:
enum pInfo
{
pName[MAX_PLAYER_NAME],
pPassword[65] // SHA-256 creates a hash of 64 characters,
pSalt[11]
};
new PlayerInfo[MAX_PLAYERS][pInfo];
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
if(dialogid == REGISTER_USER)
{
new salt[11];
// generating random string of characters which is 10 character long
for(new i; i < 10; i++)
{
// storing random character in every slot of our salt array
salt[i] = random(79) + 47;
}
salt[10] = 0;
SHA256_PassHash(inputtext, salt, PlayerInfo[playerid][pPassword], 65);
// inputtext - text that we've entered in the dialog
// query to save our name, password and salt
new query[256];
mysql_format(mysql, query, sizeof(query), "INSERT INTO `users` (`Name`, `Password`, `Salt`) VALUES ('%e', '%e', '%e')", PlayerInfo[playerid][pName], PlayerInfo[playerid][pPassword], salt);
mysql_tquery(mysql, query, "", "");
}
return 1;
}
This code will give us random generated salt which will be saved into the database as a plain-text, next to the password field.
salt[i] = random(79) + 47; - we are getting a random value from the ASCII table from 33 to 126, our you could say, we are getting one by one random generated character. After the salt is generated, we are adding a null value to the end of it.
Our users can now register at our server but they can't login yet. Here's the code for it:
pawn Code:
public OnPlayerConnect(playerid)
{
// checking for user in the database
new query[128];
mysql_format(mysql, query, sizeof(query),"SELECT `Password`, `Salt` FROM `users` WHERE `Name` = '%e'", PlayerInfo[playerid][pName]);
mysql_tquery(mysql, query, "OnAccountCheck", "i", playerid);
return 1;
}
forward public OnAccountCheck(playerid);
public OnAccountCheck(playerid)
{
// if the users exists
if(cache_get_row_count(mysql))
{
// saving password and salt from the database
cache_get_field_content(0, "Password", PlayerInfo[playerid][pPassword], mysql, 65);
cache_get_field_content(0, "Salt", PlayerInfo[playerid][pSalt], mysql, 11);
// login dialog
ShowDialog(playerid, LOGIN_USER);
}
else
{
// user doesn't exist, show the register dialog
ShowDialog(playerid, REGISTER_USER);
}
return 1;
}
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
// ...
else if(dialogid == LOGIN_USER)
{
new hash[65];
// hashing the text that user entered and salt that was loaded
SHA256_PassHash(inputtext, PlayerInfo[playerid][pSalt], hash, 64);
// if the hash is same as the loaded password
if(!strcmp(hash, PlayerInfo[playerid][pPassword]))
{
// load user
}
else
{
// wrong password, show the dialog again etc.
}
}
return 1;
}
That's it! You should now have a more secure password saving system.
This is how it looks like in my database:
Some of the wrong ways of salting
- Do not reuse salts (using same salt over multiple passwords)
Code:
A common mistake is to use same salt for hashing your passwords. This is ineffective because
if two users have the same password, they'll still have the same hash. A new random salt must be
generated each time a user creates an account or changes their password.
Oh, and don't use user's name for the salt since it's predictable and often reused for accounts
on other services.
- Do not create short salts
Code:
If the salt is only three ASCII characters, there are only 95x95x95 = 857,375 possible salts.
To make it impossible for an attacker to create a lookup table for every possible salt, the salt
must be long. A good rule of thumb is to use a salt that is the same size as the output of the hash
function.
- Do not do double hashing
Code:
It's easy to get carried away and try to combine different hash functions, hoping that the result
will be more secure. In practice, though, there is very little benefit to doing it. All it does is
create interoperability problems, and can sometimes even make the hashes less secure.
- Do not use wacky hash functions
Code:
Never try to invent your own crypto, always use a standard that has been designed by experts.
Thank you for reading this tutorial. If you have some advices for better password managing, feel free to write them here.
Thanks to:
-CrackStation for making awesome article on secure salted password. You can find it here:
https://crackstation.net/hashing-sec...#normalhashing
- SA:MP team for adding SHA-256 hashing function alongside with many other useful stuf.
Re: Using new SHA-256 function -
lukewid - 12.07.2015
Very nice!
Re: Using new SHA-256 function -
lexjusto - 13.07.2015
good job.
Re: Using new SHA-256 function -
dominik523 - 13.07.2015
Thank you guys.
Re: Using new SHA-256 function -
zT KiNgKoNg - 13.07.2015
Its Ironic really; I was talking to someone when the update came out how SHA-256 can still be cracked, and anyone's best bet is to 'SALT' it, so Dominik, you sir have got yourself some rep just for doing this. GJ.
Re: Using new SHA-256 function -
dominik523 - 13.07.2015
Quote:
Originally Posted by zT KiNgKoNg
Its Ironic really; I was talking to someone when the update came out how SHA-256 can still be cracked, and anyone's best bet is to 'SALT' it, so Dominik, you sir have got yourself some rep just for doing this. GJ.
|
Thank you very much.
I think it's a good thing that we got a new function so we don't have to use other plugins just for password security. I'm also glad to see that salting is supported by the function so we don't have to go and concatenate strings and do other stuff.
Re: Using new SHA-256 function -
Lordzy - 13.07.2015
It's good to see someone post a decent hashing tutorial with salting method. I suggest you to also note about updating salts at a particular time. In case if MySQL is used,
event scheduler method can be handy!
Re: Using new SHA-256 function -
dominik523 - 13.07.2015
Thanks for sharing that tutorial. It's nice to see some new cool stuff.
I haven't seen any tips on updating the salt over time but it might be useful.
Re: Using new SHA-256 function -
Youssef221 - 13.07.2015
Wish you could explain it in Yini, but good job.
Re: Using new SHA-256 function -
zT KiNgKoNg - 14.07.2015
Quote:
Originally Posted by Youssef221
Wish you could explain it in Yini, but good job.
|
Pretty much the same to be honest, just INI functions.
Re: Using new SHA-256 function -
yugecin - 14.07.2015
Nice tutorial
Quote:
Originally Posted by dominik523
random(79) + 47; - we are getting a random value from the ASCII table from 33 to 126
|
Wouldn't the result be 47 - 125?
Re: Using new SHA-256 function -
scaunel - 14.07.2015
a bit like Whirlpool complicated but is very good and also useful
Re: Using new SHA-256 function -
dominik523 - 14.07.2015
Quote:
Originally Posted by yugecin
Nice tutorial
Wouldn't the result be 47 - 125?
|
Random(79) will give anything from 0 to 79, and we don't want our characters to start from 0 which is null in ASCII. Because of that, we are adding 47 to it so we'll get anything from / to ~.
Thank you all for your kind replies.
EDIT: @Youssef221 - You can do the same thing. Just like saving password in INI, save the salt and load it when the user joins the server. If you really want it, I could add a small part to the tutorial which will be in y_ini.
Re: Using new SHA-256 function -
Hiddos - 14.07.2015
Quote:
Originally Posted by dominik523
Random(79) will give anything from 0 to 79, and we don't want our characters to start from 0 which is null in ASCII. Because of that, we are adding 47 to it so we'll get anything from / to ~.
|
It will give a value from [0,max), meaning that the highest value you will ever get is max-1, or in the case of random(79) it's 78.
Otherwise it's a decent tutorial, anyone dealing with passwords should be aware of hashing.
Re: Using new SHA-256 function -
dominik523 - 14.07.2015
Quote:
Originally Posted by Hiddos
It will give a value from [0,max), meaning that the highest value you will ever get is max-1, or in the case of random(79) it's 78.
Otherwise it's a decent tutorial, anyone dealing with passwords should be aware of hashing.
|
Yeah, that's what I meant but I have no idea why did I write 79. Oh well.
I totally agree. Hashing isn't that hard and it should be always done. Thanks!
Re: Using new SHA-256 function -
Youssef221 - 14.07.2015
Nevermind, it was a mistake in some code.
Re: Using new SHA-256 function -
Youssef221 - 14.07.2015
there is a problem, I can't log in my account, it always say invalid pass
EDIT: codes:
http://pastebin.com/teJcJnHB
Re: Using new SHA-256 function -
dominik523 - 14.07.2015
Can you please check if you are saving correct salt and password (print it out when user registers) and then check if you are loading the correct values.
EDIT: There is now 0.3.7 R2-1 version of SA:MP which fixes SHA256 function. Be sure to update your server files.
Re: Using new SHA-256 function -
Cyber123 - 14.07.2015
This is good way to hash passwords .. thanks for tutorial broo
Re: Using new SHA-256 function -
RaeF - 16.07.2015
Why do we must hash a password ? there is any chance someone trying to hack player account??
Edit:
Is it possible to attack password inside .ini .json files?