
How to Safely Store Your Users' Passwords in 2016 - antitamper
https://paragonie.com/blog/2016/02/how-safely-store-password-in-2016
======
jordonias
I called my bank the other day and they asked over the phone for my password.
This isn't a bank I often use, I only currently have a loan through them so
I've never used the login on the website. I said I don't remember setting a
password. They gave me a hint about the characters in the password and I was
able to remember the password based on their hint. I verbally said the
password character by character and they confirmed it. This is an example of
how to not handle passwords in 2016.

~~~
darkstar999
Same thing happened to me, my local credit union emailed me my password. They
ensured me that they use "bank-level encryption". Of course I didn't get into
the difference between one- and two-way encryption with the teller, or that
email isn't secure.

We live in an age where this should be unacceptable. Why aren't there
financial security laws yet?

~~~
CydeWeys
It's so infuriating because I've worked at companies doing digital commerce
before, and PCI compliance and certification is quite onerous. But at the end
of the day credit card numbers still aren't as sensitive as bank logins, yet
there are no security standards on bank logins! It's crazy.

~~~
scruple
PCI compliance is pretty interesting. It's been many years since I worked in
an e-commerce shop but I seem to remember that it even described physical
security layers i.e., dictating the placement of door hinges to server rooms.

~~~
rtpg
Goes to show that when money is at stake for the stakeholders then things get
done.

I don't think banks actually care about individual user login security too
much. Credit Cards reallllly suffer from security breaches though

~~~
JadeNB
> I don't think banks actually care about individual user login security too
> much. Credit Cards reallllly suffer from security breaches though

But the only reason that banks care so much about credit-card security
breaches is that the law forces them to do so. If the law didn't make credit
card fraud the bank's responsibility, then they'd be just as lackluster about
preventing it as they currently are about securing login credentials.

~~~
Domenic_S
I don't know if that's true. Say we lived in a world where those regulations
didn't exist and the fraud risk was on par with what it is today. If _one_
bank introduced their own fraud protection program, wouldn't they basically
capture 90% of the market overnight?

~~~
JadeNB
This is a good argument, but I'm not sure that I buy this. There are plenty of
industries (I think of the cable and cell-phone industries, but I'm sure there
are others) where it's just a given that the service will be crappy, even
though one company that started to respect its customers could seemingly
corner the market. (I'm not sure what are the results of T-Mobile's exercises
in respecting its customers. Their unfortunate net-neutrality stance with
Binge On means that it's not an unalloyed win to go with them.)

~~~
Domenic_S
I get what you're saying, but credit cards are unique: the advantage credit
card companies have over those other industries is that there is essentially
no lock-in, and your old cards continue to work while you're in the process of
switching eg your autopays over. It's a very switch-friendly industry.

Remember when you couldn't take your cell phone number with you and so pretty
much nobody switched carriers? It was a massive pain. Now it's easier than
ever to switch, except most people are locked into multi-year contracts.
Switching friction = high, but not impossible. As you said, TMO is trying to
compete here.

Cable has monopolies on towns, so there's 0 incentive. People couldn't switch
even if they wanted to. I suppose there's satellite, but you'll still be
paying the cable company for internet -- they get their pound of flesh no
matter what. Switching friction = impossible.

~~~
JadeNB
These are good points. My remark was off the cuff; it's clear that you've
thought (or at least are thinking) about it much more deeply.

------
jtwebman
Bad idea to use bcrypt.hashSync in Node.js. I hate that so many tutorials use
that one instead of the correct bcrypt.hash with a callback. This is Node.js
for that 200 ms where you are hashing that password nothing else runs, no
requests, everything stops. Here is the correct way to use bcrypt in Node.js:

bcrypt.genSalt(10, function(err, salt) {

    
    
      if (err) return; //handle error
    
      bcrypt.hash(clearPassword, salt, function(err, hash) {
    
        if (err) return; //handle error
    
        // Store hash in your password DB.
    
      });
    

});

~~~
dsp1234
Note that bcrypt.hash just calls bcrypt.hashSync anyways[0]. So there it's
still going to stall exactly the same amount.

edit: Looks like it depends on which version you use.

'npm install bcrypt'[1] gives a version which supports true async usage (via
V8 async callbacks in native code)

'npm install bcrypt-nodejs'[2] gives a pure JS version which I linked to.
Which is the top search result for 'nodejs bcrypt'

[0] - [https://github.com/shaneGirish/bcrypt-
nodejs/blob/master/bCr...](https://github.com/shaneGirish/bcrypt-
nodejs/blob/master/bCrypt.js#L630)

[1] -
[https://www.npmjs.com/package/bcrypt](https://www.npmjs.com/package/bcrypt)

[2] - [https://www.npmjs.com/package/bcrypt-
node](https://www.npmjs.com/package/bcrypt-node)

[3] -
[https://www.google.com/search?q=nodejs+bcrypt](https://www.google.com/search?q=nodejs+bcrypt)

~~~
__abc
BUT NODE.JS IS NON BLOCKING?!?@?!?!?!

Kidding.

~~~
EGreg
It's IO-bound. I guess they could make a version that yields and resumes
several times though!

------
jayeshsalvi
By not storing them [https://medium.com/the-story/signing-in-to-medium-by-
email-a...](https://medium.com/the-story/signing-in-to-medium-by-email-
aacc21134fcd#.fkttu9kdh)

~~~
alextgordon
So there's no password option? That's horrible, means you can't use it with
incognito mode (because you'd have to receive an email each time)

~~~
Kiro
You can use the link in incognito. Why wouldn't you?

~~~
alextgordon
Because every time you open the site you'd have to receive an email. vs just
letting 1password, browser, etc enter the password.

------
VincentEvans
Serious question: What about using a Public/Private key encryption to store
the password?

\- Private key is stored in a secure place. Offline for all i care; printed on
a piece of paper; memorized and swallowed.

\- When user creates the account - password is padded with salt, then a public
key is used to encrypt it. The resulting encrypted form is stored, along with
the salt.

\- When user attempts to authenticate - the password that is provided is
padded with the stored salt, encrypted with the public key and compared to the
stored password.

Private key is never used when comparing passwords. Never available to the
system doing authentication, etc.

The only purpose of using a reversible encryption - is to be able to switch to
a different authentication provider completely transparently to the user.

I've implemented this functionality considering that we may need to switch
over to active directory (or some other directory) in place of storing
passwords in the database - but never used it, fearful that i would be
committing some cardinal crime against proper security practices

Thoughts?

~~~
zaroth
This only works for deterministic encryption like "textbook RSA", not for any
semantically secure encryption, which would produce different ciphertext each
time you run it.

I would worry about trying to dual-purpose the encryption like this. If you
feel like you must have a way to get the plaintext password back, which BTW
you really really do NOT want that liability, but anyway, the safer choice
would be to use a semantically secure encryption of the password, and then
ALSO hash the password using the current best practices. Use the hash for now
to authenticate users, keep the ciphertext if you must, but you'll probably
regret it.

~~~
VincentEvans
Thanks for you reply. It is indeed RSA that I used (from .NET framework).

There's no argument from me regarding undesirability of keeping the passwords.
But we also have a different concern - we don't want to be in the business of
authentication _at all_ \- our goal is to have a third party service or
appliance performing authentication and forwarding us already authenticated
sessions with the user name as a header, for instance. Our desired end-state -
is when we do not have any knowledge of or access to credentials used by the
end-user.

To enable us to make this transition possible - for the time being we store
the passwords, since as i explained in another reply, we must make this
transition transparent to the users and we have legitimate users that login
once a year (think credit report, just an example, not our business), so we
can't intercept the credentials within a reasonable time period.

What i try to get out of the replies - is whether there's nothing immediately
broken about using asymmetric encryption that endangers us aside from the
understandable but not immediate concern about liability.

P.S: Earlier i mentioned "intercepting credentials" in our code - and wanted
to highlight that the ease of doing that is precisely the reason why we really
want to separate ourselves from handling credentials in any form.

------
rcconf
If you're using node.js and you use these hashing methods, your entire server
is going to pause for 0.5 seconds on a login because it runs on a single
thread. Goodbye to all of your server performance.

You can create a worker system, or use a child process to solve this problem,
but most of these articles never mention it

~~~
lukev
I think this says more about node.js than it does about the proper way to
secure a password.

~~~
ARussell
Wasn't Node's big draw early on (aside from the fact that it's JavaScript) the
fact that everything is supposed to be asynchronous? I'm actually surprised
this is a problem.

~~~
mobiuscog
asynchronous doesn't magically make CPU-intensive tasks faster.

~~~
corobo
It does mean other tasks (e.g. serving pages to visitors) can still be run at
the same time as the CPU-intensive task though, like most languages do when it
comes to hashing passwords and logging people in

------
Freaky
> base64_encode(hash('sha384', $password, true))

> ...

> The above construction may invite theoretical concerns about entropy
> reduction (i.e. 72 characters of raw binary without any NUL bytes comes out
> to about 573 bits of possible entropy, but a SHA-384 hash outputs are
> clearly limited to 384 bits).

Given BCrypt hashes are a mere 184 bits, I don't see how this is a meaningful
concern even in principle. If you're brute-forcing search spaces this big
you're no longer looking to recover a password, but find a collision.

~~~
sarciszewski
> Given BCrypt hashes are a mere 184 bits, I don't see how this is a
> meaningful concern even in principle.

This was added in response to a point that a couple people (or perhaps a
convincing sockpuppeteer) raised and tried to use to decry the entire article.
You're lucky to get 60 bits of information entropy in any given user's
password, as is. The "theoretical weakening" here isn't a practical concern:
"2^192 security" is still boring crypto.

------
AdmiralAsshat
I had no idea that PBKDF2 had fallen so much in recent years. I still remember
the 1Password team extolling its virtues five years ago:

[https://blog.agilebits.com/2011/05/05/defending-against-
crac...](https://blog.agilebits.com/2011/05/05/defending-against-crackers-
peanut-butter-keeps-dogs-friendly-too/)

~~~
sarciszewski
Correction: Scrypt actually uses PBKDF2 internally. (Previously said "scrypt
is based on PBKDF2" but that's a loaded statment.)

PBKDF2 is an improvement over PBKDF1 (and other naive iterated hash
constructions), but attacks got better and better defenses are called for.

~~~
cperciva
_Scrypt is based on PBKDF2._

No, it really isn't.

~~~
sarciszewski
I could have sworn it used PBKDF2-SHA256 and Salsa20/8 internally, which is
what I meant by "based on".

~~~
cperciva
It also uses xor internally, but I wouldn't say that scrypt is based on xor.
scrypt does not use PBKDF2 for any PBKDF properties; it's just a convenient
arbitrary-length-output hash function. I would have used a sponge if they had
been widely available when I created scrypt.

~~~
sarciszewski
Okay, thanks for the clarification.

------
hellofunk
It would be great if, in 2020, or sooner, but probably later, the answer is
"don't use passwords any more. They are deprecated components of society."

~~~
jobigoud
Can you expand on this idea? What type of authentication method would replace
it? (One that can't be directly linked to the person obviously).

~~~
jcrawfordor
I'm optimistic for the use of physical tokens instead of passwords. In my work
environment, a lot of authentication is based on physical token possession
plus a password just as a guard against lost devices (password validated by
the token, not by the service).

These kinds of systems aren't technically very complex but there hasn't been a
lot of traction for them outside of corporate environments. The result is that
they tend to be hyper-expensive, unfortunately. Standards like FIDO and the
Yubikey are good first steps at pushing this into the consumer space, although
they don't offer on-device PIN validation yet.

~~~
herbst
I would love a replacement for passwords, but i dont think hardware based
solutions are practical enough yet. It is a Gadget more i need to take with
me, and even more make sure that it connects with any device i have.

The worst part for me would be loosing that thing, in the end i would need
alternative login methods anyway to be sure i dont lock myself out.

Classic Authy on a Smartwatch would be the simplest method i could live with
that comes to my mind.

~~~
nickik
Its not one more Gadget that you have to carry around. New Lenovo Laptops and
Samsung Phones already have UAF enabled Fingerprint Sensors that could be used
for all your Web Authentification needs. The Yubikey is either the size of a
USB slot or the size of a key on your keychain, so even your second factor is
pretty minimal in size.

Alternative Login is always a problem, their is always a tradeoff between
security and useability. You could easly print out some backup access codes.
You can continue to use your E-Mail as a anker, you get an E-Mail and then
your allowed to register a new token. That leaves the question of how does
your E-Mail provider secure its login? I think Google is a good example of the
options that are possible.

------
oliwarner
Disappointed that the first solution isn't: Let somebody else do it.

I know this doesn't apply to banking, etc but 99% of the websites that
"require" me to create an account and log in don't need to store primary
credentials for me. Please pick a secure implementation of oAuth2 and let
people store their credentials wherever the hell they want to.

I'm bored of getting hits from "Have I been pwned?"

~~~
sarciszewski
This requires your users to trust whichever OAuth providers you decide to
integrate with. Sometimes, the set of "trusted OAuth providers" for your users
is {}. What then?

> 99% of the websites that "require" me to create an account and log in don't
> need to store primary credentials for me

Why are you giving them valuable credentials? Give them a throw-away password
(password managers are great for this).

~~~
oliwarner
You don't integrate with _a_ provider. You implement the protocol and let your
users supply a URL. Layering on popular alternatives (Facebook, Google, etc)
help, but use the Stack Exchange model. Let users do what they want to do.

That way users can be their own oAuth providers if they want.

~~~
sarciszewski
My question was: "What if your users don't trust any of the existing providers
on Earth?"

It's hard to make a blanked recommendation like that, even for "only 99%" of
websites. Neither you, nor the person building the website, has any insight
into who the website's users trust.

Offer OAuth2 as an alternative to passwords: Great move.

Only offer OAuth2 and don't let people create an account: Questionable.

~~~
oliwarner
I did answer.

They can host their own.

I don't understand why they would trust <crappy forum owner> over a dedicated
authentication storage place but that's their choice. And yes, there is also
every possibility to offer direct credentials, per the Stack Exchange model
(they host their own oAuth server and allow simple registrations).

~~~
sarciszewski
> I don't understand why they would trust <crappy forum owner> over a
> dedicated authentication storage place but that's their choice.

What if <crappy forum owner> happens to be a security engineer, and <crappy
forum> happens to be Silk Road 13?

The trust decisions people make are situational and nuanced. OAuth is great if
that's where people invest their trust. Otherwise, you're outsourcing it for
the user to a company they might fear.

~~~
oliwarner
Again. The _user_ picks who they authenticate with. You (the site owner) get
no say in the matter. You aren't outsourcing it to any one company.

~~~
sarciszewski
No, you're saying "which of this limited set of companies are you going to
authenticate with" instead. If you don't want to be guilty of taking users'
agency away from their own trust decisions, you need to do one of two things:

1\. Let every website on the Internet potentially be an OAuth provider.

2\. Make OAuth optional.

If you follow option #2, then this article is still relevant because you need
to handle passwords securely.

~~~
oliwarner
Your first paragraph is like saying using email is forcing somebody to use one
of a "limited set of companies". It's nonsense. Again, if they don't like
what's on offer they can host their own, just like email!. They can hire a
company like yours to host their credentials with as many layers of security
as they want. The user has ultimate choice.

Secondly, every website on the Internet _is_ potentially an OAuth provider.

Not to mention that I have —on multiple occasions here— suggested that
websites that consume OAuth should also provide it (like Stack Exchange).

------
josefdlange
Anyone have a good explanation of why, in the Python example, they recommend
`hmac.compare_digest` instead of `==` for comparison?

Is there something obvious I'm missing here?

~~~
herge
== in python will stop comparing after the first character mismatch. You can
use that fact to test byte by byte your password knowing that the more good
characters you have, the longer the comparison will take, which is called a
timing attack.

hmac.compare_digest is a constant time compare, in that no matter if there is
a match or not, it will take the same amount of time.

~~~
tptacek
Timing attacks aren't useful against password hashes, but avoiding them is a
good habit to be in.

~~~
Someone1234
This is "mostly true" but with an edge case...

If the attacker knows which algorithm and work factor you're utilising and
your system doesn't use randomly generated per user salts (or an unknown
pepper) then theoretically an attacker could use a hash timing attack,
combined with a rainbow table, to massively reduce the scope of a user's
potential password.

For example, let's say your rainbow table has 20 million password-hash
combinations and your hash length is 33 letters, for every letter I know I
could drop literally millions of hashes I know it ISN'T. With just the first
four letters I could drop it by almost 60% (although my maths here might be
completely wrong, it is actually pretty complicated to determine). But there's
no real limit on how many letters you could drop from the hash with a timing
attack, you could turn someone's password into a 1 in 62 chance.

The TL;DR: Use a per user salt. But a timing immune comparison definitely is
"defense in depth" in case there is a bug elsewhere that breaks salts.

~~~
tptacek
I chose the words "password hash" carefully. If you're using a secure password
hash, you're not worrying about salts, because they take care of randomization
for you. If you are worrying about salts, you probably have bigger problems
than memcmp timing.

~~~
Someone1234
I literally don't understand what it is you're getting at.

Password hashing has existed since at least the 1970s and until the 2000s
salting wasn't common. While some hashing libraries do insist on you supplying
a salt, it is still ultimately up to the application developer to generate and
store the salt for later usage.

Therefore it is still common for an application developer to "worry about
salts" even if just for storage and generation reasons.

Anyone using 3DES, MD5, or similar is likely vulnerable to timing attacks, and
they're definitely still in the realm of a "password hash." Plus some
wonderful developers hard code the salt (salt = "secret") which too could
leave them vulnerable to timing attacks if an attacker knew what hashing
algorithm and workfactor (e.g. the default) was in usage.

~~~
sarciszewski
> I literally don't understand what it is you're getting at.

I truly hope this will help then: [https://paragonie.com/blog/2015/08/you-
wouldnt-base64-a-pass...](https://paragonie.com/blog/2015/08/you-wouldnt-
base64-a-password-cryptography-decoded)

"Password hashing" is its own compound noun. The acceptable algorithms (as
defined in the blog post this HN thread is about) take care of this for you.

> Anyone using 3DES, MD5, or similar is likely vulnerable to timing attacks,
> and they're definitely still in the realm of a "password hash."

3DES is a block cipher. MD5 is a crytographic hash. Neither of them are
password hashes.

> Plus some wonderful developers hard code the salt (salt = "secret") which
> too could leave them vulnerable to timing attacks if an attacker knew what
> hashing algorithm and workfactor (e.g. the default) was in usage.

What you're describing is closer to a "pepper".

[http://blog.ircmaxell.com/2012/04/properly-salting-
passwords...](http://blog.ircmaxell.com/2012/04/properly-salting-passwords-
case-against.html)

~~~
Someone1234
> 3DES is a block cipher. MD5 is a crytographic hash.

3DES is both a block cipher and a cryptographic hash. At least UNIX thought so
in the 1990s as many MANY people were storing UNIX passwords in 3DES, DES,
MD5, and similar.

> Neither of them are password hashes.

25 years of computing history would disagree with you. MD5 was the defacto
standard for password hashing for almost fifteen years.

But no doubt you'd playing silly word games, and are going with your own
definition of "password hash" that includes or excludes different hashing
algorithms as it is convenient for you. I won't get drawn into that.

> What you're describing is closer to a "pepper".

What you're doing is called being "condescending." You know full well from my
posts above that I am familiar with salt/peppering/hashing, and the different
technologies involved. So linking to 101 tutorials and definitions of basic
terms is only intended to aggravate.

~~~
brazzledazzle
To be honest I'd probably interpret them as being antagonistic if the same
statements were directed at me (and quoting never helps either) but I think if
you take a charitable interpretation it doesn't read that way. I think it's
just a direct/technical challenge/debate sort of reply and it's really easy to
read into those when you're on the receiving end of them.

------
TorKlingberg
For some reason the article completely fails to link to libsodium:
[https://download.libsodium.org/doc/](https://download.libsodium.org/doc/)

~~~
sarciszewski
> For some reason the article completely fails to link to libsodium:
> [https://download.libsodium.org/doc/](https://download.libsodium.org/doc/)

The "bindings for most programming languages" link goes to the libsodium
documentation, but I'll add a link in more contexts.

~~~
daveloyall
The article offers specific advice for Java-without-libsodium, but it offers
no such specific advice for Java-with-libsodium.

There would appear to be three distinct Java bindings of libsodium.

~~~
sarciszewski
(I'm not ignoring your comment, I'm currently debating whether to update it to
include libsodium example code or to write a separate post for that.)

~~~
obelisk_
Write a separate post and then link to that from your current post. Best of
both worlds :D

------
damon_c
I have always been impressed by the way django does it.

[https://docs.djangoproject.com/en/1.9/topics/auth/passwords/](https://docs.djangoproject.com/en/1.9/topics/auth/passwords/)

------
pbreit
Assuming this is legit (seems like it), mega bonus points for walking through
examples on the various platforms/languages.

------
sinatra
From previous discussions about this topic, I had noted down the following
best practices:

Passwords should be scrypt'ed on client, and then, the server should generate
a SHA256 hash of the scrypt'ed hash and store that in DB.

\- Running CPU & memory heavy scrypt hashing on the client side will allow us
to use bigger hashing work-loads.

\- EDIT: Removing the MITM point, because as many said, that's the job of TLS
anyway.

\- External brute force attackers will have to take the burden of heavy
hashing. No DOSing through scrypt.

\- Storing SHA256 hash instead of scrypt hash on DB means even if DB is
stolen, attackers can't use stolen scrypt hashes to authenticate any client.

I would love to get others' feedback on this. EDIT: Found the reference:
[https://news.ycombinator.com/item?id=9305504](https://news.ycombinator.com/item?id=9305504)

~~~
sarciszewski
How are you going to calculate the scrypt hash, client-side?

Doesn't that scrypt hash then become the password, from the server-side
application's perspective?

How are you storing the salt for the user if your server only knows about a
SHA-256 hash.

> MITM attacks won't get access to unencrypted fields.

That's TLS's job. If you, for example, are building a web app and you're
delivering Javascript to perform the scrypt calculation, a MitM can replace
the code to exfiltrate the user's plaintext password. It doesn't make sense
for the threat model.

~~~
Strilanc
I think the idea is that the scrypt hash does become the password, but it's a
_better_ password. A password with a lot more entropy (kinda). The increased
kinda-sorta entropy makes the use of a slow key derivation function on the
server side unnecessary, so SHA-256 becomes sufficient.

Not sure how I feel about it.

~~~
sarciszewski
I feel that this is needlessly dangerous, personally.

How are the salts managed? This detail is important. SHA256(scrypt(password,
constant_value_instead_of_salt)) is going to produce collisions in the stored
hash.

~~~
owenmarshall
I think he's going for SHA256(scrypt(password, salt, work_factor)) and saying
the bare SHA256 is sufficient. As opposed to SHA256(salt+scrypt(password,
salt, work_factor)).

I think it's dangerous because of the dependence on the client, and useless
because scrypt(password,salt,work_factor) on the server is plenty hard to
attack.

~~~
timv
> scrypt(password,salt,work_factor) on the server is plenty hard to attack

For a large enough work_factor. In practice "large enough" is usually
interpreted to mean "something that seems safe without being so large that I
need to buy lots more servers"

The argument (which I'm interested in, but not yet sold on) is that moving the
scrypt to the client allows you to pump up the work_factor even higher than
you would have been willing to do on the server.

~~~
owenmarshall
After thinking about it more the concept is interesting, but the main fear I
have is that doing it in a web browser with JS is next to impossible to
secure. Maybe if vendors got on board...

In general though, pushing auth down to clients in Javascript makes my skin
crawl. You're one XSS away from having an attacker no-op your scrypt and
return SHA256("secret-attacker-password") on registration. The logical follow-
up to that: 'have the server run scrypt the first time' \-- but then you've
just moved the tough work to user registration, which seems just as
exploitable.

I dunno. Safe crypto is hard enough already; I'm not sure pushing it into
Javascript on the browser makes it any easier.

~~~
timv
The proposals I've see have always had the initial scrypt be done on the
server.

The DOS risk on registration can be mitigated more easily than the login one.
e.g. Rate limiting new registrations will often be more palatable than
limiting logins, or you can require "email validation" before you set the
first password. And, not every application allows self registration.

------
Justsignedup
Wish there was a site where it lists algorithms and gives a table, and an
ability to compare it to x years ago:

algorith | fairly safe difficulty (all variables) | very safe difficulty
without incurring too much performance cost.

pbkdf + sha1 | completely unsafe | completely unsafe

pbkdf + sha2 | 100000 | ...

pbkdf + sha256

bcrypt

scrypt

argon2

~~~
tptacek
PBKDF2-SHA1 is safe.

That's the problem with a chart like this. The gradation will go from
"completely unsafe" salted hashes to "very much safe enough" with only
marginal changes after that.

Another problem is that these functions are all parameterized, so the chart
needs to capture the safety level at specific parameters.

~~~
Justsignedup
My goal was to create a chart of:

algorith | a safe set of parameters | a VERY safe set of parameters but needs
strong hardware

Maybe a 4th column of "unsafe if difficulty is below"

This could be something updated yearly or whatever to help people figure out
what things they need to move towards. If they see that their currently used
settings are below the unsafe line, they will know it's time to upgrade.

Example: I use PBKDF2-SHA1 at difficulty of 11k iterations. Is that number
still within the "probably okay" list, or is that in the "I can hack any
password on your list in 15 minutes"

------
sarciszewski
I'm part of the Paragon Initiative Enterprises team and have access to edit
the blog. If you have any questions (AMA) or would like to suggest any
additions, please let me know.

~~~
warrentr
We really appreciate the post, thanks! Not a suggestion for this topic, but
would love a future post on request signing in 2016 (think HMAC). In
particular there are so many JSON REST APIs these days going over HTTPS that
it's hard to determine best practices and what's overkill.

~~~
sarciszewski
Thanks for the suggestion, I'll put it on the list. :)

------
latenightcoding
Perl programmers should try this module: Crypt::ScryptKDF I have been using it
for a while now

~~~
eCa
And with DBIx::Class it is almost easier to do it right[1] than wrong.

[1] [https://blog.afoolishmanifesto.com/posts/do-passwords-
right/](https://blog.afoolishmanifesto.com/posts/do-passwords-right/)

------
cm2187
What I find frustrating is the lack of availability of most of these
algorithms for the most common platforms (.net, php, java). The author
recommendation seems to be driven by availability, not the algorithms own
merits.

~~~
sarciszewski
If you're using any of: PBKDF2, Bcrypt, Scrypt, Argon2, then you're fine. Our
recommendation is:

    
    
        1. Use the best option available, but
        2. We provided example code in multiple languages for the
           best one that's widely available

------
astockwell
I believe the Ruby example is incorrect: When checking a password's validity,
you must use a constant-time comparison or else you are exposing a
vulnerability to side-channel timing attacks.

There is an open issue in Coda Hale's bcrypt repo about this:
[https://github.com/codahale/bcrypt-
ruby/pull/119](https://github.com/codahale/bcrypt-ruby/pull/119)

My stance on posting "best practice" articles is: you must follow _all_ best
practices in them.

<Edited for clarity>

~~~
sarciszewski
> I believe the Ruby example is incorrect

Unfortunately, there's nothing I can do about that, unless someone can point
me to an alternative that uses a constant-time comparison.

I've left a comment on the pull request so that, hopefully, it can be merged.

> (and likely others)

Which others?

~~~
astockwell
After re-reading the others in depth, all other examples appear to use
appropriate comparison methods (knowing nothing of the underlying
implementations). I've updated my comment to clarify.

I see your team is actively posting on the bcrypt-ruby issue #119 as we speak,
so I guess I'd say wait for the PR to merge, or manually implement the
approach they've outlined to secure compare:
[https://github.com/codahale/bcrypt-
ruby/pull/119/files](https://github.com/codahale/bcrypt-ruby/pull/119/files)

------
movedx
Hashicorp's Vault (vaultproject.io) is also an excellent way of controlling
access to secrets and back ends, such as PostgreSQL.

It's worth spending the time to learn, implement, and integrate into the
security best practices you should already be deploying.

------
carlesfe
Here's yesterday's discussion for the exact same post (maybe the duplicate
search failed this time?)

[https://news.ycombinator.com/item?id=11108481](https://news.ycombinator.com/item?id=11108481)

------
serge2k
> PBKDF2 (nearly everyone except FIPS agrees this is the worst of the
> acceptable options)

is that true?

~~~
tptacek
Only in the most technical sense: cycle for cycle, PBKDF2 gets you the
smallest amount of protection from that group of password hashes. PBKDF2 is
still vastly better than non- password hashes like salted SHA.

~~~
joshreesjones
You say that "PBKDF2 is still vastly better than non-password hashes like
salted SHA", but is PBKDF2 (with >10,000 iterations using SHA512 and a random
salt, for example) secure enough?

------
jimktrains2
Or, we could move to not storing passwords at all, viz client certs and SRP.

~~~
tptacek
SRP still stores crackable password verifiers, and is tricky to implement
safely.

~~~
jimktrains2
Crackable in what way?

Of course the core of it could be upgraded, but the idea is sound. Sounds like
you could say the same thing about using a DES-based hash. "Don't Hash! It's
weak!" is throwing the baby out with the bath water.

~~~
tptacek
In exactly the same way as any other password hash is cracked.

~~~
jimktrains2
By iterating over all passwords? That seems like the definition of a good
password storage if that's the only way! I mean, you can make the same
complaint against anything; it's meaningless by definition.

Sure, public-private pairs are more difficult (to impossible) to brute force
once they're so long, but srp, bcrypt, pbkdf2 &c are pretty good when you
want/need a password. Srp being superior in that your secret never leaves your
computer.

~~~
tptacek
I'm not following you. The whole point of a password hash is to (1) admit only
that one brute-force attack, and then (2) to slow that attack down as much as
possible.

SRP gets you (1), but is inferior to every other modern password hash on (2).
SRP is better on (2) than other PAKEs (it's an "augmented" PAKE because it
tries to slow down brute force), but password hashes have (2) as their whole
objective, and total design freedom.

You can combine PAKEs and password hash concepts. But for the purposes of
_password storage_ , SRP isn't buying you anything (except for a bunch of
possible crypto bugs that will gameover your project).

SRP is a bad call for virtually all projects. Or, maybe a better way to say
that is, "if you have to ask, don't use SRP."

~~~
jimktrains2
> but password hashes have (2) as their whole objective,

Only until that was what people cared about. How long, and how many still, use
single-round md5 and sha for password storage?

SRP is an old algorithm -- it could be strengthened significantly with little
love. (Similar as to how took a little care from the community for bcrypt,
pbkdf2, &c have become the "norm" over md5.)

> SRP isn't buying you anything

SRP is buying you the ability for the server to never have the password, a
secret value you're handing someone else!

> SRP is a bad call for virtually all projects. Or, maybe a better way to say
> that is, "if you have to ask, don't use SRP."

I still feel like you're throwing the baby out with the bathwater. Just
because something can be updated and hasn't (like using a weak hash like md5),
doesn't mean the core concept is bad (using a 1-way hash function).

~~~
tptacek
No, it isn't. It's storing verifiers with the same power for attackers as
scrypt, except that scrypt's verifiers are harder to crack.

------
firelink
I kind of don't like this article. I think we should be teaching people best
practice for securing and storing a password, not simply giving them a
library.

------
dogweather
I believe that the safest way is not to save them. Instead, outsource this to
a few select OAuth providers which you and your customers are willing to
trust.

~~~
CM30
What do you do about sites where the users don't particularly likely said
providers? Not everyone uses Facebook or Google or Twitter after all, and a
lot more would rather use an anonymous disposable account than one tied to an
existing identity.

There's also the fact said systems seem to be a nice target for spammers.
They're popular, so they're often attacked. And because they're often
attacked, their anti spam defences don't usually last very long. So any
spammer now has a nice way to get an account on near enough any site they
like, while with a standalone system, they'd at least have to tailor their
attacks to the site in question.

There's also the fact it silos much of the internet (or at least user
information) within the systems of a few large providers, which gives a
significant amount of control to said providers.

~~~
dogweather
> Not everyone uses Facebook or Google or Twitter after all

Yep, I do tailor the selection of oauth providers to my audience. E.g., an app
for devs = google, github, and gitlab.

------
xjlin0
Ruby's argon2 gem is pretty good!

------
balls187
"How to Safely Store a Password in 2016"

Don't. Unless it's 100% absolutely necessary.

If you must, continue reading on.

~~~
rehevkor5
The article inaccurately describes generating a password hash & using it as
"storing a password".

~~~
balls187
My point is simply if you can avoid storing user credentials, avoid storing
their credentials.

For many services, the most valuable data they contain happens to be the user
credentials that the service uses to authenticate the identity of the user. If
you assume that users share their credentials across multiple services, if
your system is attacked, and you improperly stored their credentials, you've
caused way more damage, than the data you were trying to secure.

For example, take your run of the mill online todo app. If an attacker got
access to the all the todos, vs an attacker got access to the all the todos
_and_ all the user passwords (even if securely stored). What is more valuable
to an attacker?

~~~
ngrilly
I agree that it's better to avoid storing user credentials, but what do you
suggest instead to authenticate the user?

~~~
balls187
If you don't require privileged elevation, then I'm a fan of just using an
email address and send "magic links" \+ persistent (but expiring) sessions.

For mobile apps, I think using SMS and One-Time Passwords is sufficient as
well.

You can also use a delegated auth system put in place by OAuth v2, or
something like Google Accounts, Twitter, etc. Those services do get pushback,
as not every uses Gmail (or likes to give any run of the mill app access to
Google account data).

~~~
ngrilly
> If you don't require privileged elevation

What do you mean by privileged elevation (I'm talking in the context of a web
app)?

> just using an email address and send "magic links" \+ persistent (but
> expiring) sessions

Do you mean something similar to what Medium does?

[https://medium.com/the-story/signing-in-to-medium-by-
email-a...](https://medium.com/the-story/signing-in-to-medium-by-email-
aacc21134fcd)

I like it too. But what about delays in receiving emails (when I suggested
this approach to some customers, they were worried about that)?

> You can also use a delegated auth system

Yes, outsourcing the authentication is another solution, but some (most?)
users are not comfortable with giving so much power to
Google/Twitter/GitHub/etc. (as you wrote in your comment).

~~~
balls187
> What do you mean by privileged elevation (I'm talking in the context of a
> web app)?

For example, prior to changing account settings, reauthenticate the users,
regardless if they have a valid session.

> I like it too. But what about delays in receiving emails (when I suggested
> this approach to some customers, they were worried about that)?

Combo of email & SMS.

As Bruce Schneier has written, security is usually a trade off of user
experience.

~~~
ngrilly
> For example, prior to changing account settings, reauthenticate the users,
> regardless if they have a valid session.

Why not reauthenticate by sending a one time password by email/SMS (instead of
asking for a password)?

> Combo of email & SMS.

Good idea. I was also thinking of sending one time passwords through some chat
applications like WhatsApp, but most of them have no API for such a thing
(except Telegram).

------
intrasight
Storing passwords is like storing credit card numbers - just don't do it

------
giancarlostoro
I'm curious if any D developers care to share their approach to this?

------
pratnala
Does Argon2 have an official website and repo or is it just the PHC repo?

~~~
sarciszewski
[https://github.com/P-H-C/phc-winner-argon2](https://github.com/P-H-C/phc-
winner-argon2) is the official repo.

------
privong
For anyone who reads the comments before clicking the article, the subject is
storing your users' passwords, not managing your passwords for a variety of
services. I had interpreted it as the latter. A better title might be "How to
Safely Store Your Users' Passwords in 2016".

(Title is currently: "How to Safely Store a Password in 2016")

~~~
bigbadgoose
great, thanks. because i was about to reply with "on a piece of paper in the
same place you store your diamonds"

~~~
TeMPOraL
I'm starting to think that if you're a security-conscious person and
understand what's at stake, then the best solution for you would be to simply
memorize it. Your mind is the only place from which an attacker can't steal
your password without drugging you or beating you up until you give it out.

~~~
danso
The main limitation of that is that your passwords are limited to what you can
memorize. Which, for most people, is not very much. Even for just one
password, never mind for multiple services. I think if you're a pragmatic
security conscious person you'd weigh the trade offs...and I thinking of it as
just "simply memorize it" opens you up to other problems.

~~~
TeMPOraL
Yes, I know. But I was thinking about serious people, not general population.
Most people are not willing to expend more than 2 seconds of effort before
deciding "it's not working, I need to make it simpler / write it down". They
don't notice that they probably still remember things like their first
girlfriend's phone number, or any random string they've been typing in more
than 10 times a day. If you put even half the effort into memorizing something
as most do into picking and maintaining e.g. password managers, you'll find
that your memory is a better tool than you expected.

People used to memorize whole books.

------
PixelB
I use an ultra secure method for my passwords, it is 100% unhackable.

Proprietary Analog Password Encryption Routines.

~~~
sarciszewski
That's not very useful for web programmers that are handling their users'
passwords, is it?

------
xs
Lame title. Story talks about storing password hashes and not passwords. I'm
still looking for a solution to storing actual user passwords. Scenario: All
laptops in the company have a unique local administrator password. How do I
manage this effectively as a domain admin?

~~~
jsmeaton
Use a password manager of some kind. Lastpass is nice, and has an enterprise
component that lets you share passwords with co-workers or teams.

