built-in alternative to bcrypt?

922 views
Skip to first unread message

whiteh...@googlemail.com

unread,
Apr 22, 2019, 6:14:48 AM4/22/19
to golang-nuts
I'm porting some code over to Go, and currently looking at some password hashing.  I'm wondering if there is a 'standard library' alternative to using bcrypt?

I am concerned about the Go binary size, since I'm already at 15MB!  So I'm trying to limit external dependencies as much as possible. 

The data being stored is not critical or sensitive, just some email address mainly. 

From my research it sounds like 'golang.org/pkg/crypto/sha512/' might be what I need, but I dont see any clear alternative for the following functions below: 

I'm still new to Go, so I'm wondering what would be the recommended solution using the standard library please?

Peter


bcrypt.GenerateFromPassword

bcrypt.CompareHashAndPassword

Aldrin Leal

unread,
Apr 22, 2019, 6:38:12 AM4/22/19
to whiteh...@googlemail.com, golang-nuts
Hashing passwords without salt are prone to rainbow table attacks. I particularly like this comment in a Java Source Code:


When storing password, always go for salted approaches (thus bcrypt)

Also, bear in mind upx works like a charm on Go Binaries:


--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

buc...@gmail.com

unread,
Apr 22, 2019, 10:13:52 AM4/22/19
to golang-nuts

I'm a hobbiest new to Go as well.

In the x library (still part of the standard library) written by the Go Authors is argon2. It allows for salting, stretching and hashing passwords.  The recent guru commentary I've read is that "new implementations of applications which will use password hashing should probably use argon2". In my particular case I salt, pepper, stretch and hash all passwords. And use sha3 (also in the x library) for preliminary twiddling.

Cheers!

lgo...@gmail.com

unread,
Apr 22, 2019, 11:47:55 AM4/22/19
to golang-nuts
Try scrypt     at   github.com/elithrar/simple-scrypt  . It's not a 'standard lib' item, but I've found the authors code easy to implemented as 'package main' code vs 'package' code

Sam Whited

unread,
Apr 22, 2019, 11:55:16 AM4/22/19
to jsonp via golang-nuts
On Mon, Apr 22, 2019, at 10:14, whitehexagon via golang-nuts wrote:
> I am concerned about the Go binary size, since I'm already at 15MB! So
> I'm trying to limit external dependencies as much as possible.

Staying in the standard library won't help you here. You'll still
have to link in the code you use regardless of where it comes from
(the entire standard library isn't linked into your binary, just
whatever you use).

As someone else mentioned, argon2 is probably what you want [1]. It's
the current OWASP recommendation [2].

—Sam

[1]: https://godoc.org/golang.org/x/crypto/argon2
[2]: https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Password_Storage_Cheat_Sheet.md#leverage-an-adaptive-one-way-function

whiteh...@googlemail.com

unread,
Apr 22, 2019, 4:18:51 PM4/22/19
to golang-nuts
Thanks everyone, plenty more reading for me! 

I'm also pleased to discover the increasing binary size isn't being ignored by the team :) especially since I'm also planning some more Go WASM stuff (although currently I switched to Java WASM for exactly this reason for that part of the project). 

Also good to know only what I'm using gets linked in, but then the size of 'hello world' is even more surprising.

The argon2 looks interesting, but it sounds like it could be very memory heavy.  The code I'm porting is running on a PAAS/SAAS setup, and that might have cost implications exceeding the worth of my low value data.  But I will also have a look then at the sha3 that was mentioned, now that I know the 'x' stuff is internally produced by the same team!

I get the impression from some of the info I'm going through, that since I'm running on hosted systems, which optionally also have encrypted file systems, that some of the brute force defense stuff might be less applicable?  ie unless the database is physically stolen from some nuclear bunker somewhere in the world, and decrypted, and my noddy system is deemed worth hacking, it's probably pretty safe already.  So the main attack vector would be multiple login attempts, which I can detect fairly easily.  for example, 5 failed logins and the account is locked...

I was also thinking in this case I could use a client side hash so that the backend system never see's a plain text password.  I realise of course that the hash becomes the password, but at least the hosted environments would never see clear text before reaching my hosted hash stuff. ie clients that reuse 123456 for everything :)

Anyway plenty for me to think about, thank you everybody.

Peter



Sam Whited

unread,
Apr 22, 2019, 6:52:40 PM4/22/19
to jsonp via golang-nuts
On Mon, Apr 22, 2019, at 20:18, whitehexagon via golang-nuts wrote:
> Also good to know only what I'm using gets linked in, but then the
> size of 'hello world' is even more surprising.

That's because the runtime is being linked in. Go requires, among other
things, a garbage collector and goroutine scheduler. These things are
always linked in because you're always using them.

> The argon2 looks interesting, but it sounds like it could be very
> memory heavy. The code I'm porting is running on a PAAS/SAAS setup,
> and that might have cost implications exceeding the worth of my low
> value data. But I will also have a look then at the sha3 that was
> mentioned, now that I know the 'x' stuff is internally produced by the
> same team!

Being memory heavy is the point; you don't want a fast hash to protect
your users data or if the hashes ever get stolen it's much easier for an
attacker to brute force them. SHA3 is a great hash, but it is not
appropriate for password storage. Please don't put your users passwords
at risk just to lower your operating overhead.

> I get the impression from some of the info I'm going through, that
> since I'm running on hosted systems, which optionally also have
> encrypted file systems, that some of the brute force defense stuff
> might be less applicable?

This is not true. An encrypted filesystem only prevents your database
from being stolen by eg. someone coming into your datacenter and running
off with your hard disk. It is no substitute for storing passwords
correctly.

> ie unless the database is physically stolen from some nuclear bunker
> somewhere in the world, and decrypted, and my noddy system is deemed
> worth hacking, it's probably pretty safe already.

Please don't put your users passwords at risk because you think
something you've done is "good enough". Always follow password storage
best practices.

> So the main attack vector would be multiple login attempts, which I
> can detect fairly easily. for example, 5 failed logins and the account
> is locked...

That's one way, and you should be doing that. However, you are human and
will make mistakes so another attack vector is someone managing to dump
your database, or getting in some otherway and downloading it.

> I was also thinking in this case I could use a client side hash so
> that the backend system never see's a plain text password. I realise
> of course that the hash becomes the password, but at least the hosted
> environments would never see clear text before reaching my hosted hash
> stuff. ie clients that reuse 123456 for everything :)

This generally isn't necessary and probably doesn't add much since
you're not likely to have your passwords stolen out of memory. Just
follow industry standard best practices.

—Sam

Tom Mitchell

unread,
Apr 22, 2019, 9:09:15 PM4/22/19
to whiteh...@googlemail.com, golang-nuts
On Mon, Apr 22, 2019 at 1:18 PM whitehexagon via golang-nuts <golan...@googlegroups.com> wrote:
Thanks everyone, plenty more reading for me! 
.... 
The argon2 looks interesting, but it sounds like it could be very memory heavy.  The code I'm porting is running on a PAAS/SAAS setup, and that might have cost implications exceeding the worth of my low value data. 

Try to not judge the value of your data as being low.
Store only hashed and salted passwords and data. 
Passwords in the clear or stored in a lame or fragile manner is something that gets negative and snarky press world wide.
Data at rest should be safe.
Revisions to update to a better solution might be hampered if you start out thinking your data is low value and 
success happens.    

The size of a go program is likely darn close to the netsum memory footprint of a C program and the resident set size 
might be smaller with go.   

Plan ahead.


--
   T o m    M i t c h e l l

whiteh...@googlemail.com

unread,
Apr 23, 2019, 11:03:09 AM4/23/19
to golang-nuts
Don't get me wrong, I strongly believe in storing user data safely, and especially passwords, hence my original question.  But as I mentioned, I'm basically trying to protect a customers email address at this point.  So if the attack vector I'm defending against is someone having direct access to the DB, whether physical or dumped.  Then they already have the email addresses I'm trying to protect.  So I'm paying to protect a password that will be superfluous.

I do hear the message to plan ahead, but looking at bcrypt, it seems like I could scale the cost factor as and when data becomes more valuable, or when it becomes a killer app ;) It even has a method there to determine the cost from the previous hash which seems designed for that task?  Since I'm guessing it's not been added to help determine brute force efforts :) and now that I know the 'x' stuff is internally developed I feel more comfortable using it.

In the case of client side hashing, I'm worried about clear text passwords ending up in log files or some such, as just happened with fb last week.  Since I have no control over the data between the clients, and the hosted execution environment.  This may possibly be the weakest link, or a debug statement left in code that accidentally does the same...

Thanks all for your feedback,
Peter

Henry

unread,
Apr 25, 2019, 1:07:24 AM4/25/19
to golang-nuts
Hello,

If you want to store passwords, then bcrypt, scrypt, and argon2 are commonly used. They are available in Go's extended library.

SHA is a hashing algorithm but by itself is not meant for password storage. Unlike bcrypt, scrypt and argon2, SHA is designed to be fast. It is meant to be used in conjunction with other cryptographic primitives.

All those mentioned above are one way hashing algorithms. If you use any of them to 'protect' email addresses, you will not be able to recover those addresses. You need encryption and not hashing to protect those email addresses.

If you are not familiar with cryptographic primitives, you are better off using higher level cryptographic libraries such as NaCL. There are many things that may go wrong when building your own cryptographic solution.
Reply all
Reply to author
Forward
0 new messages