From 799fc70a48b68b3403eb150084c28d4e78c035e4 Mon Sep 17 00:00:00 2001 From: Adam Shannon Date: Thu, 25 Oct 2018 12:59:04 -0700 Subject: [PATCH] hash: Raise bcrypt cost factor lower bound (#321) Users of this library can easily create the following: hasher := fosite.BCrypt{} hasher.Hash(..) This is a problem because WorkFactor will default to 0 and x/crypto/bcrypt will default that to 4 (See https://godoc.org/golang.org/x/crypto/bcrypt). Instead this should be some higher cost factor. Callers who need a lower WorkFactor can still lower the cost, if needed. Signed-off-by: Adam Shannon --- compose/config.go | 2 +- hash_bcrypt.go | 5 +++++ hash_bcrypt_test.go | 15 +++++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/compose/config.go b/compose/config.go index f9e7edb7e..b060fe492 100644 --- a/compose/config.go +++ b/compose/config.go @@ -108,7 +108,7 @@ func (c *Config) GetAccessTokenLifespan() time.Duration { // GetHashCost returns the bcrypt cost factor. Defaults to 12. func (c *Config) GetHashCost() int { if c.HashCost == 0 { - return 12 + return fosite.DefaultBCryptWorkFactor } return c.HashCost } diff --git a/hash_bcrypt.go b/hash_bcrypt.go index 77155522b..676ae343a 100644 --- a/hash_bcrypt.go +++ b/hash_bcrypt.go @@ -28,12 +28,17 @@ import ( "golang.org/x/crypto/bcrypt" ) +const DefaultBCryptWorkFactor = 12 + // BCrypt implements the Hasher interface by using BCrypt. type BCrypt struct { WorkFactor int } func (b *BCrypt) Hash(ctx context.Context, data []byte) ([]byte, error) { + if b.WorkFactor == 0 { + b.WorkFactor = DefaultBCryptWorkFactor + } s, err := bcrypt.GenerateFromPassword(data, b.WorkFactor) if err != nil { return nil, errors.WithStack(err) diff --git a/hash_bcrypt_test.go b/hash_bcrypt_test.go index 24448a3fe..0eab769ba 100644 --- a/hash_bcrypt_test.go +++ b/hash_bcrypt_test.go @@ -26,6 +26,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "golang.org/x/crypto/bcrypt" ) func TestCompare(t *testing.T) { @@ -110,3 +111,17 @@ func TestHash(t *testing.T) { }) } } + +func TestDefaultWorkFactor(t *testing.T) { + b := &BCrypt{} + data := []byte("secrets") + hash, err := b.Hash(context.TODO(), data) + if err != nil { + t.Fatal(err) + } + + cost, err := bcrypt.Cost(hash) + if cost != 12 { + t.Errorf("got cost factor %d", cost) + } +}