I'm fairly entry-level crypto; not a cryptographer by any stretch... I am at the level of ability to implement most of the traditional packages in python; the hashlib hashes and EAS, ECDSA implementations, etc. And generally logically grasp what they're doing under the hood and when they're appropriate. I've come here to learn a bit more about this new breed of PHC 2015 candidates.
I'm working on a "password manager" to manage my logins to social media, email accts and the like. I tend not to like GUI's, nor did I like any of the implementations I found... so I thought I'd have a go at it myself. Of course, as I get down the rabbit hole I gain a clearer picture of my own naivety. Initially... I was just thinking very simplistically... hash the master password w/ sha256... AES-CBC for each site pass... copy to clipboard, ctrl+v and auto remove from the clipboard. Then I was like... no, we need stronger master pass! so:
key = sha256(blake(pbkdf(key)))
I was proud for a moment of my implementation... that faded quickly.
I got to thinking about the whole "hash the master password" concept and I realized that it was really meant for server/client situations, with brute being restricted by websocket communications response time and API limits. With enough time by some malware running in the background and near-unlimited speed on my beast desktop this was still plausibly brute prone? Not sure to be honest; concerned enough to ponder on... At this point, I was unaware of "password hacking competition" and the likes of argon2 and friends. But I saw a problem and of course headed down the ill-advised path of "roll my own".
Two things immediately came to mind.
1) increase ram requirement
2) increase time requirement.
My first attempt was to up the iteration count of pbdfk, which did indeed increase the cost by about 1 second before the python implementation denied me any further iterations. But I wanted more...
So I devised two simple solutions:
# 1) make the key really big
key *= int(10 ** 8.5 / len(key))
# 2) sha256 it millions of times
for i in range (10 ** 7):
key = sha256(key)
First gives me about a gig of ram requirement and second slows the response down to 8 seconds. The ram gives multicore resistance, the time... increases brute time, surely the iterative sha256 makes rainbow tables less likely. And of course, I could still do something more salty on the way into my iterative big sha256... ala:
blake(pbkdf()).
I did a little happy dance, but it was at this point that I delved deeper into the rabbit hole and "read the docs" eventually stumbling upon blake2.net:
You shouldn't use any general-purpose hash function for user passwords. Instead you should use a password hashing function such as the PHC winner Argon2 with appropriate time and memory cost parameters, to mitigate the risk of bruteforce attacks.
At first, I was vilified! I was right!
Then... the "don't roll your own" came over me... and the fact that I was 4 years behind the times in my own awareness. I've since learned argon2 is using blake under the hood.
So I have come here to ask:
- Is my method as strong as I expect?
- What does argon2 achieve beyond what I'm doing?