utils.stringPBKDF2Hash()

Questions, tips and tricks and techniques for scripting in Servoy

utils.stringPBKDF2Hash()

Postby kwpsd » Sat Nov 23, 2013 2:52 am

Servoy 6.1.6

I am not at all familiar with the PBKDF2 hash, but Servoy recommends using it in lieu of the older MD5 algorithm, so I thought I would give it a try. Servoy's wiki gives the following usage:

Code: Select all
var hashed_password = utils.stringPBKDF2Hash(user_password)


When I tried encoding the same password multiple times, I noticed the hash value is different for each iteration (see examples below):

Code: Select all
utils.stringPBKDF2Hash( "PASSWORD" )   --->   "161B1BC242CE757B:2000:4FFBE76D36299AC9388696B8327609CB3F0B086D"
utils.stringPBKDF2Hash( "PASSWORD" )   --->   "83B0C847293F8FA6:2000:AEE6FCA55DA35280AB6477C95A2032DEB8D53DA9"
utils.stringPBKDF2Hash( "PASSWORD" )   --->   "69DD4FBB5C910459:2000:5C5F823EA5C9FB3DAAE08F8A1C54955A2E263C69"
utils.stringPBKDF2Hash( "PASSWORD" )   --->   "60A2C23E76FFC83F:2000:912CAC816F0D86C6C64AACD20B594374349B6325"


Most likely, I am not using Servoy's PBKDF2 hash function properly. Can someone explain to me how to properly use this function?
Kim W. Premuda
San Diego, CA USA
User avatar
kwpsd
 
Posts: 687
Joined: Sat Jul 28, 2007 6:59 pm
Location: San Diego, CA USA

Re: utils.stringPBKDF2Hash()

Postby patrick » Sat Nov 23, 2013 6:36 pm

The method returns the salt, the number of iterations and the hash separated by ":". So in this "161B1BC242CE757B:2000:4FFBE76D36299AC9388696B8327609CB3F0B086D", "161B1BC242CE757B" is the salt, 2000 is the number of iterations and "4FFBE76D36299AC9388696B8327609CB3F0B086D" is the hash. You could stored it as is or store the number of iterations in a variable and the salt in a separate column next to the hash. That the hash is different every time (because of the salt) is desired. When you use a MD5 hash, it will always be the same for a given password. That makes it possible to easily see where a user uses the same password and, of course, makes it easy to brute force compute all hashes for a given number of characters. There are tons of rainbow tables on the internet that will give you the password for a given MD5 hash. Some MD5 hashes can even be googled.
Patrick Ruhsert
Servoy DACH
patrick
 
Posts: 3703
Joined: Wed Jun 11, 2003 10:33 am
Location: Munich, Germany

Re: utils.stringPBKDF2Hash()

Postby jcompagner » Mon Nov 25, 2013 1:01 pm

Kim

Patrick already explained it quite nice, and yes you are using it correctly
The thing is if you then want to test a password if it is correctly against a stored string that you generated before you have to use the :

utils.validatePBKDF2Hash(password,hash)

Then that will check if that plaing text password would generate that same hash using the salt and the iterations that are stored in the hash.

So you can only check a password by checking it against the hash itself.

If your password table would become public knowledge then hackers can only brute force it one hash at the time. If they would succeed in 1 password then that doesn't have any effect on the next one because they have to start all over again.
Johan Compagner
Servoy
User avatar
jcompagner
 
Posts: 8829
Joined: Tue May 27, 2003 7:26 pm
Location: The Internet

Re: utils.stringPBKDF2Hash()

Postby kwpsd » Mon Nov 25, 2013 7:30 pm

Patrick and Johan,

Thank you both for your comments.

When I first created this post, I was expecting the utils.stringPBKDF2Hash( user_password ) to work like the MD5 method (I was wrong). Patrick's explanation, especially the term 'rainbow table', sent me scrambling to the Internet for more information. Most explanations there said to prefix the password with the salt and run it through the same hash algorithm, so I tried this:

Code: Select all
utils.stringPBKDF2Hash( salt + user_password )


which also didn't work. I later stumbled upon the utils.validatePBKDF2Hash( password, hash ) method Johan mentioned, and tried:

Code: Select all
utils.validatePBKDF2Hash( salt + password, hash )


which, again, did not work. Then, I decided to take the entire output of utils.stringPBKDF2Hash() which, as Patrick explained, is not really the hash, but a combination of salt:iterations:hash into the utils.validatePBKDF2Hash( password,hash ) method, and it worked!

So, I have several comments/recommendations:

    1. Update the documentation to include Patrick's explanation of the return value for utils.stringPBKDF2Hash( user_password ); that is, the salt:iterations:hash format plus description.

    2. Update the documentation for utils.validatePBKDF2Hash( password, hash ) to utils.validatePBKDF2Hash( password, salt:iterations:hash )

    3. Name like methods so that they appear next to each other in the documentation and the utils list in Developer: for example:

      utils.PBKDF2Hash( user_password )

      utils.PBKDF2Validate( password, salt:iterations:hash )

I think what you did with the PBKDF2 algorithm is very clever but needs to be better explained.

Again, thanks for all your help!
Kim W. Premuda
San Diego, CA USA
User avatar
kwpsd
 
Posts: 687
Joined: Sat Jul 28, 2007 6:59 pm
Location: San Diego, CA USA

Re: utils.stringPBKDF2Hash()

Postby jcompagner » Tue Nov 26, 2013 11:29 am

we can't name variables like that because those are illegal (a : in the name)
And it is really just a hash, what it really contains shouldn't really be important. Its just that you need to know how to use the return value of stringPBKDF2Hash
So i made the doc of stringPBKDF2Hash a bit more clear.
Johan Compagner
Servoy
User avatar
jcompagner
 
Posts: 8829
Joined: Tue May 27, 2003 7:26 pm
Location: The Internet

Re: utils.stringPBKDF2Hash()

Postby kwpsd » Tue Nov 26, 2013 7:29 pm

So i made the doc of stringPBKDF2Hash a bit more clear.


Very good, Johan!

I know that ':' is not allowed in variable names...I was just staying with Patrick's annotation for clarity of this thread (perhaps, I should have enclosed the salt:iterations:hash format in quotes to indicate a string value).
Kim W. Premuda
San Diego, CA USA
User avatar
kwpsd
 
Posts: 687
Joined: Sat Jul 28, 2007 6:59 pm
Location: San Diego, CA USA

Re: utils.stringPBKDF2Hash()

Postby patrick » Wed Nov 27, 2013 2:30 pm

I already filed a feature request that the hash method allows to provide your own salt. Right now, the salt is created in the code and returned as the first "block".
Patrick Ruhsert
Servoy DACH
patrick
 
Posts: 3703
Joined: Wed Jun 11, 2003 10:33 am
Location: Munich, Germany

Re: utils.stringPBKDF2Hash()

Postby jcompagner » Wed Nov 27, 2013 4:36 pm

why would you do that..
That means that people potentially could give us salts that are not really safe (for example just give always "1")
now the salt is generated by the SecureRandom class of java. That class has given a lot of thought how to generate a good and real (as possible) random number
Johan Compagner
Servoy
User avatar
jcompagner
 
Posts: 8829
Joined: Tue May 27, 2003 7:26 pm
Location: The Internet

Re: utils.stringPBKDF2Hash()

Postby patrick » Wed Nov 27, 2013 4:45 pm

because then I could, for example, use a uuid of the record where I am storing the hash and wouldn't need a salt column
Patrick Ruhsert
Servoy DACH
patrick
 
Posts: 3703
Joined: Wed Jun 11, 2003 10:33 am
Location: Munich, Germany

Re: utils.stringPBKDF2Hash()

Postby jcompagner » Wed Nov 27, 2013 5:11 pm

the tool/hash creator will generate that string in that format. And i guess that could potentially change at any time (or if we use suddenly a different hashing but that uses the same kind of hashing and validating, but stores it a bit different and it knows how to read/validate both variants)
What i want to say with this is that you shouldn't analyze the string, that's just a string, it doesn't matter at all how it is layout that's just some internal thing of the hash creator.

in your example we suddenly have an extra param in the hashing function and the validating function and we need to concat it, in the validating function, in a specific way so that the hash creator can do its stuff. That suddenly has then a dependency that we know exactly how it stores/works with it.

You should also just not store in over multiply columns, store it in 1 column, there is no need what so ever to extract/parse the hash
Johan Compagner
Servoy
User avatar
jcompagner
 
Posts: 8829
Joined: Tue May 27, 2003 7:26 pm
Location: The Internet

Re: utils.stringPBKDF2Hash()

Postby Harjo » Wed Nov 27, 2013 6:10 pm

jcompagner wrote:You should also just not store in over multiply columns, store it in 1 column, there is no need what so ever to extract/parse the hash

But what is the point of the hash than? You give the hacker the hash, when the db is compromised!
Harjo Kompagnie
ServoyCamp
Servoy Certified Developer
Servoy Valued Professional
SAN Developer
Harjo
 
Posts: 4321
Joined: Fri Apr 25, 2003 11:42 pm
Location: DEN HAM OV, The Netherlands

Re: utils.stringPBKDF2Hash()

Postby Yeroc » Wed Nov 27, 2013 6:31 pm

I agree with Johan on this. Treat the output from the PBKDF2Hash as an opaque string and store the whole thing in a single field. It's too easy to have someone mess this up by storing the salt separately and then not understanding what the salt is for and how it needs to be used so as not to compromise security. You're hardly saving anything by re-using another field as your salt and if you choose poorly you will have completely compromised your user's account security.

My 2 cents.

Corey
Yeroc
 
Posts: 109
Joined: Tue Aug 12, 2008 1:12 am
Location: Calgary, AB, Canada

Re: utils.stringPBKDF2Hash()

Postby jcompagner » Wed Nov 27, 2013 6:46 pm

what do you mean?
The whole point of this way of hashing is that a hacker could get access to "161B1BC242CE757B:2000:4FFBE76D36299AC9388696B8327609CB3F0B086D"
but still can't really in a normal amount of time extract the password from it

And even if it could calculate 1 hash from your db, then it has 1 password yes, but then the next it has to calculated completely from the start again.
A hacker can't get all the password of your compromised db at once, it has to completely calculate (brute force) hash by hash.

You can make it way more stronger to use up the iterations to for example 10000 that would increase the time to brute force it greatly
(for servoy i guess i can just already do that, just up the default iterations so that we are more secure)

Last year they already introduced another even more secure one: http://en.wikipedia.org/wiki/Scrypt

This one is invented and better then PBKDF2 because of ASIC's. So a hacker that does have quite a bit of resources and could buy a ASIC that is hardware programmed to crack PBKDF2 hashes it is i guess already possible (no idea what then really the time is...)
Johan Compagner
Servoy
User avatar
jcompagner
 
Posts: 8829
Joined: Tue May 27, 2003 7:26 pm
Location: The Internet

Re: utils.stringPBKDF2Hash()

Postby Yeroc » Wed Nov 27, 2013 6:53 pm

Harjo wrote:But what is the point of the hash than? You give the hacker the hash, when the db is compromised!


Harjo,

Not sure exactly what you're getting at here. The hacker has everything in your db when it's compromised. Is your concern that the hacker also has the salt? A salt is not intended to be secret. It's a random input added to the hash function to ensure rainbow tables can't be used to decode the user's password when the db is compromised. The important thing is to use an appropriate hashing algorithm that's designed to be slow (CPU intensive, memory intensive or both) so that dictionary attacks take a long time. Ideally, you want your hashing algorithm to be tunable so that as CPUs become more powerful you can adjust for that. That's where the number of iterations (also encoded in the hash above) comes in.

If anything, I'd suggest adding the number of iterations as an optional parameter so that it's more future-proof. Eg. Developers can increase the value without (presumably) having to upgrade Servoy.

Corey
Yeroc
 
Posts: 109
Joined: Tue Aug 12, 2008 1:12 am
Location: Calgary, AB, Canada


Return to Methods

Who is online

Users browsing this forum: No registered users and 11 guests