2

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?
litepresence
  • 121
  • 3

1 Answers1

1

I will skip the usual don't roll your own speech. For a local password manager you typically need encryption not only password based key derivation. You want to encrypt your various passwords with a key derived from your master password. There are many methods for doing so, argon2 is one of the best. However iteratively applying a general purpose hash function is also acceptable. An example of how to use a general purpose hash function is: https://en.m.wikipedia.org/wiki/PBKDF2

Note it mixes the password again in it's iteration and xors the results these ensure the space of possible outcomes doesn't shrink with iteration count as it would with naive chaining. Also note the use of a Salt which prevents attacking multiple passwords together or use precomputed dictionaries/rainbow tables.

Argon2 is also memory hard and argon2i is also side channel resistant not sure these are a must.

With such a key derived from your master password you can encrypt the individual passwords with a symmetric cipher of your choice.

Note there are other things to watch out for when building your own password manager. For instance, be sure to ask lock the sensitive memory to never be swapped to disk. Or your master password and key may find themselves on disk so that anyone can read them.

Meir Maor
  • 12,053
  • 1
  • 24
  • 55