2
$\begingroup$

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?
$\endgroup$
  • $\begingroup$ As roll your own goes, I've seen worse. The advantage argon2 has is that it's designed by experts to do this - as you say; "I'm fairly entry level crypto; not a cryptographer by any stretch...". There are other KDFs as well - I'd recommend Scrypt. Pycryptodome and cryptography have that implemented. If you want a password manager, you also need to consider many other things. When you hash the passwords to store them, you make them almost unrecoverable. You need to encrypt them. And decrypt them later. $\endgroup$ – Legorooj Dec 23 '19 at 3:22
  • $\begingroup$ Thanks for quick response, re: recovering the messages... the procedure described just relates to the "master" password; I am using AES in mode CBC for the individual "site" password messages I wish to store. The final output structure will be a JSON dictonary text doc with human readable keys and AES encrypted passwords as values. $\endgroup$ – litepresence Dec 23 '19 at 4:37
  • 1
    $\begingroup$ CTR might be better; no padding. I'd suggest encrypting the file with AES and the master password as well. $\endgroup$ – Legorooj Dec 23 '19 at 4:39
  • $\begingroup$ Argon2 parameters Encrypt a file with AES using a secret key derived with Argon2 $\endgroup$ – kelalaka Dec 23 '19 at 7:57
1
$\begingroup$

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.

| improve this answer | |
$\endgroup$
  • $\begingroup$ If you are not sure, use argon2id. $\endgroup$ – kelalaka Dec 23 '19 at 7:43
  • 1
    $\begingroup$ I meant simpler approaches could be considered safe enough. I also like simple, and personally I use bcrypt mostly, because I have been for a while and it withstood the test of time, despite the advantages of the newer stuff like scrypt or argon2 $\endgroup$ – Meir Maor Dec 23 '19 at 8:09
  • $\begingroup$ @MeirMaor argon2 and Scrypt aren't exactly new. My opinion is Scrypt - probably because that was the first KDF recommended to me. Alot of peoples preferences will be because of some recommendation or another. $\endgroup$ – Legorooj Dec 24 '19 at 5:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.