How to hash and encrypt password over the web? - mysql

I am working with a pet project and I come to a point where I want to add user sign up support. After some research I decide to go with saving hashed password and salt in my database and never the original password. However I am confused to what the steps are and in what order. Below is my assumption:
Signup
Client sends username and password to server (https)
Server grabs the password, generates a random salt
Base64 encode the salt
Hash the password with the stringify salt
Base64 encode the password
Save the password and salt into database
Login
Client sends username and password to server (https)
Server grabs username and password, look up hashed psw and salt from database
Hash password using the salt, base64 encode the result
Compare the password with hashed psw in database
If match, authenticate user
I am implementing my system as my assumption, and everything seems to work. However I am not sure about the base64 encoding part. What is the purpose of encoding the password and salt from binary to string, and can I skip this step? And if my assumed process is wrong, what are the correct steps?
P.S I am using express.js as the server, mysql as the database

The general idea is OK, but I've got some remarks:
Instead of using a hash, you should use a PBKDF, a Password Based Key Derivation Function. It is best to use a standardized version, that would be PBKDF2. Together with the salt, you should also choose a number of iterations to thwart attacks.
Make sure you always use the same character-encoding for the username and password.
The cryptographic algorithms should be based on binary input and output.
At the time you store or load binary data to a text presentation, you should use Base 64 encoding / decoding respectively.
So the scheme contains the following issues:
Using a hash instead of a PBKDF.
Using a base 64 encoded salt as input for the hash.

You need to understand what salts means. Its a way just to throw obstacles against possible brute force attack using rainbow table. Which means some bad guy will try with high computing power all possible hashes that can be generated. Then try to extract the plain text out of such hash.
Thus the salt is there to make sure even with such attack the returned plain text is not the correct one.
For example:
username: "Xavier_Ex"
password: "Ilovestackoverflow"
Such password will be hashed to "sfhj87s&^f". Now rainbow table can also say
"sfhj87s&^f" -> Ilovestackoverflow... bleh, your password is cracked.
But when salted it will be like "Ilovestackoverflow" -> "Io*ves5tacmkove3rflow".
when this is hashed "Io*ves5tacmkove3rflow" -> "dfgdfgdf"
With rainbow table that "dfgdfgdf" will return "Io*ves5tacmkove3rflow" .. your password is still secret.
In short.. you can skip this unless you do do need such protection.

Related

Need information on "Salt" parameter of Jmeter

Need to create hash token using SHA-512 Algorithm, So on using _digest function of jmeter, I am getting a different token.
What is "salt"? is it same as secret key ?
How to use it?
${__digest(SHA-512,{test_test_test},SXF,,)}
See documentation of function:
https://jmeter.apache.org/usermanual/functions.html#__digest
Regarding SALT, it is described here:
https://en.m.wikipedia.org/wiki/Salt_(cryptography)
It’s not a private key, a salt is random data that is used as an additional input to a one-way function that "hashes" data, a password or passphrase. Salts are used to safeguard passwords in storage.

How to submit blob data into MySQL from ruby without base64 encoding

I have searched without much success how to best submit binary data into a MySQL field of type BLOB, without doing a base64 encoding which increases the size of the data.
So far my Ruby code looks something like this:
require 'zlib'
require 'base64'
require 'mysql'
#Initialization of connection function
db = Mysql.init
db.options(Mysql::OPT_COMPRESS, true)
db.options(Mysql::SET_CHARSET_NAME, 'utf8')
dbh = db.real_connect('hostname','username','password','database') #replace with appropriate connection details
#Saving the data function
values=someVeryBigHash
values=JSON.dump(values)
values=Zlib::Deflate.deflate(values, Zlib::BEST_COMPRESSION)
values=Base64.encode64(values)
dbh.query("update `SomeTable` set Data='#{values}' where id=1")
dbh.close if dbh
#Retrieving the data function
res=dbh.query("select * from `SomeTable` where id=1")
data=res['Data']
data=Base64.decode64(data)
data=Zlib::inflate(data)
data=JSON.parse(data)
The issue is that using Base64 encoding/decoding is not very efficient and I was hopping for something a bit cleaner.
I also tried an alternative using Marhsal (which does not allow me to send the data without a base64 encoding, but is a bit more compact)
#In the saving function use Marshal.dump() instead of JSON.dump()
values=Marshal.dump(values)
#In Retrieve function use Marshal.load() (or Marshal.restore()) instead of JSON.parse(data)
data=Marshal.load(data)
However, I get some errors (perhaps someone spots what I do wrong, or has some ideas why this occurs):
incompatible marshal file format (can't be read) version 4.8 required; 34.92 given
I tried different flavor of this with/without Base64 encoding or decoding or with/without ZLib compression. But I seem to consistently get an error.
How would it be possible to send binary data using Ruby and mysql gem, without base64 encoding. Or is it simply a requirement to use base64 encoding for sending the data?
The issue is that using Base64 encoding/decoding is not very efficient and I was hopping for something a bit cleaner.
You're using JSON to convert a large hash to a string, then using ZLib compression on binary data, then Base64 encoding the resulting binary data, and you're worried about efficiency... I'm going to assume you mean spatial efficiency rather than temporal efficiency.
I guess I'm most curious about why you're Base64 encoding in the first place - a BLOB is a binary data format, and provided you pass an array of bytes to ZLib it should inflate it correctly regardless.
Have you tried writing binary data directly to the database? What issues did you experience.
Edit:
update SomeTable set Data='xڍ�]o�0��K$�k;�H��Z�*XATb�U,where id=1' resulted in an error... Obviously this has to do with the binary nature of the data. This captures the essence of my question. Hope you shine some light on this issue.
You can't just pass the binary string as a query value as you have here - I think you need to use a query with a bind variable.
I'm unsure whether the mysql gem you're using supports query bind parameters, but the format of query you'd use is something along the lines of:
#db.execute('update SomeTable set Data=? where id = 1', <binary data value>)
this will permit the mysql to properly escape or encapsulate the binary data that is to be inserted into the database table.
To sumarize mcfinningan answer. Transmitting the binary data is done via binding a parameter. In ruby this can be done with 'mysql' gem this can be done using prepared statments (cf. MySQL Ruby tutorial)
The code now looks like:
require 'zlib'
require 'mysql'
#Initialization of connection function
db = Mysql.init
db.options(Mysql::OPT_COMPRESS, true)
db.options(Mysql::SET_CHARSET_NAME, 'utf8')
dbh = db.real_connect('hostname','username','password','database') #replace with appropriate connection details
#Saving the data function (can skip Zlib compression if needed)
values=someVeryBigHash
values=Marshal.dump(values)
values=Zlib::Deflate.deflate(values, Zlib::BEST_COMPRESSION)
#Here is how to load the binary data into MySQL (assumes your schema has some tale with a Column Data of type BLOB
dbh.prepare("update `SomeTable` set Data=? where id=1")
dbh.execute(data)
#End of Data loading
dbh.close if dbh
#Retrieving the data function (can skip Zlib decompression if data is not compressed)
res=dbh.query("select * from `SomeTable` where id=1")
data=res['Data']
data=Zlib::inflate(data)
data=Marshal.restore(data)

Sql Server Storing SHA256 String as Question Marks

I have followed this article on how to implement password hashing and salting
http://www.codeproject.com/Articles/608860/A-Beginners-Tutorial-for-Understanding-and-Impleme
I have implemented all the code mentioned in the article into my MVC 5 web application, however, whenever I store the PasswordHash and Salt, both of these strings save in my User table as question marks, e.g, ????????????????
The database I'm using is Sql Server 2008 R2. The two fields within my database User table have both got a datatype of Nvarchar(100)
I should also mention the data is being persisted to the database using Entity Framework 5.
Has anyone seen this before? I'm thinking it might be a datatype problem, i.e., shouldn't be Nvarchar, however, I don't really know.
Any help with this would be great.
Thanks.
There's a problem in Utility.cs:
public static string GetString(byte[] bytes)
{
char[] chars = new char[bytes.Length / sizeof(char)];
System.Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length);
return new string(chars);
}
The function is fed random bytes. This is not how you create a random string. Characters are not meant to store binary data. Such strings will be hard to swallow for many components.
Use Convert.ToBase64String and don't trust random articles on the web. Validate what you find with your own understanding before using it.
SHA256 are not string, are byte arrays. Use byte[] in your client code, use VARBINARY on the server code.

how to define binary column in pas.plugin.sqlalchemy

I'm defining my custom model for pas.plugin.sqlalchemy.
Existing table of login details have binary field as password column. how should be define in model as binary. I tried to import _Binary class from SQLAlchemy after Googling but it doesn't import. Firstly I tried LargeBinary but when table been created its takes field type as Image which I dont want.
Any help would be appreciated.
Regards,
WEBBYFOX
I'm not surprised that _Binary doesn't work - even if it did, it's generally a very bad idea to use something that's intended as a private class. But "sqlalchemy.Binary" is a perfectly acceptable type.
That said, I doubt anybody's tested pas.plugins.sqlalchemy with Binary data for the password: PAS is a way to drop-in replacements for the existing Plone system, and out-of-the-box, Plone expects passwords to be strings.

Querying Chinese addresses in Googlemap API geocoding

I'm following the demo code from article of phpsqlgeocode.html
In the db, I inserted some Chinese addresses, which are utf-8 encoded. I
found after urlencode the Chinese address, the output of the address
would be wrong. Like this one:
http://maps.google.com.tw/maps/geo?output=csv&key=ABQIAAAAfG3KxFZXjEslq8VNxMBpKRR08snBovzCxLQZ9DWwpnzxH-ROPxSAS9Q36m-6OOy0qlwTL6Ht9qp87w&q=%3F%3F%3F%3F%3F%3F%3F%3F%3F132%3F
Then it outputs 200,5,59.3266963,18.2733433 (I can't query this through PHP, but through the browser instead).
This address is actually located in Taichung, Taiwan, but it turns out to be
in Sweden, Europe. But when I paste the Chinese address(such as 台中市西屯區智惠
街131巷56號58號60號) in the url, the result turns out to be fine!
How do I make sure it sends out the original Chinese
address? How do I avoid urlencode()? I found that removing urlencode() doesn't change anything.
(I've change the MAPS_HOST from maps.google.com to
maps.google.com.tw.)
(I'm sure my key is right, and other English address geocoding are
fine.)
q=%3F%3F%3F%3F%3F%3F%3F%3F%3F132%3F
decodes to:
?????????132?
so something has corrupted the string already before URL-encoding. This could happen if you try to convert the Chinese characters into an encoding that doesn't support Chinese characters, such as Latin-1.
You need to ensure that you're using UTF-8 consistently through your application. In particular you will need to ensure the tables in the database are stored using a UTF-8 character set; in MySQL terms, a UTF-8 collation. The default collation for MySQL otherwise is Latin-1. You'll also want to ensure your connection to the database uses UTF-8 by calling 1mysql_set_charset('utf-8')`.
(I am guessing from your question that you're using PHP.)