Actually it seems the benchmark was incorrectly setup I have followed the resource shared by user @Luke Joshua Park and now it works.
package main
import "testing"
func benchmarkBcrypt(i int, b *testing.B){
for n:= 0; n < b.N; n++ {
HashPassword("my pass", i)
}
}
func BenchmarkBcrypt9(b *testing.B){
benchmarkBcrypt(9, b)
}
func BenchmarkBcrypt10(b *testing.B){
benchmarkBcrypt(10, b)
}
func BenchmarkBcrypt11(b *testing.B){
benchmarkBcrypt(11, b)
}
func BenchmarkBcrypt12(b *testing.B){
benchmarkBcrypt(12, b)
}
func BenchmarkBcrypt13(b *testing.B){
benchmarkBcrypt(13, b)
}
func BenchmarkBcrypt14(b *testing.B){
benchmarkBcrypt(14, b)
}
Output:
BenchmarkBcrypt9-4 30 39543095 ns/op
BenchmarkBcrypt10-4 20 79184657 ns/op
BenchmarkBcrypt11-4 10 158688315 ns/op
BenchmarkBcrypt12-4 5 316070133 ns/op
BenchmarkBcrypt13-4 2 631838101 ns/op
BenchmarkBcrypt14-4 1 1275047344 ns/op
PASS
ok go-playground 10.670s
I have a small set on benchmark test in golang and am curios of to what is a recommended bcrypt cost to use as of May 2018.
This is my benchrmark file:
package main
import "testing"
func BenchmarkBcrypt10(b *testing.B){
HashPassword("my pass", 10)
}
func BenchmarkBcrypt12(b *testing.B){
HashPassword("my pass", 12)
}
func BenchmarkBcrypt13(b *testing.B){
HashPassword("my pass", 13)
}
func BenchmarkBcrypt14(b *testing.B){
HashPassword("my pass", 14)
}
func BenchmarkBcrypt15(b *testing.B){
HashPassword("my pass", 15)
}
and this is HashPassword()
func inside main.go
:
import (
"golang.org/x/crypto/bcrypt"
)
func HashPassword(password string, cost int) (string, error) {
bytes, err := bcrypt.GenerateFromPassword([]byte(password), cost)
return string(bytes), err
}
The current output is:
go test -bench=.
BenchmarkBcrypt10-4 2000000000 0.04 ns/op
BenchmarkBcrypt12-4 2000000000 0.16 ns/op
BenchmarkBcrypt13-4 2000000000 0.32 ns/op
BenchmarkBcrypt14-4 1 1281338532 ns/op
BenchmarkBcrypt15-4 1 2558998327 ns/op
PASS
It seems that for a bcrypt with cost of 13 the time it takes is 0.32 nanoseconds, and for cost 14 the time is 1281338532ns or ~1.2 seconds Which I believe is too much. What do is the best bcrypt cost to use for the current year 2018.
The default cost value of Laminas\Crypt\Password\Bcrypt is 10, requiring around 0.07s using a CPU Intel i5 at 3.3Ghz (the cost parameter is a relative value according to the speed of the CPU used).
Bcrypt, however, provides very limited security and its weaknesses to a large extent are protected by another storage algorithm known as Scrypt.
A lot of your research is correct and still applies in 2021, so it is still secure to use BCrypt (which usually generates its own random salt for each password). Good password hashing algorithms are Argon2, SCrypt and BCrypt, they all offer a cost factor which controls the necessary time.
bcrypt has a maximum length input length of 72 bytes for most implementations. To protect against this issue, a maximum password length of 72 bytes (or less if the implementation in use has smaller limits) should be enforced when using bcrypt.
I'm not certain what's going on with Benchmark here. If you just time these, it works fine, and you can work out the right answer for you.
package main
import (
"golang.org/x/crypto/bcrypt"
"time"
)
func main() {
cost := 10
start := time.Now()
bcrypt.GenerateFromPassword([]byte("password"), cost)
end := time.Now()
print(end.Sub(start) / time.Millisecond)
}
For a work factor of 10, on my MacBook Pro I get 78ms. A work factor of 11 is 154ms, and 12 is 334ms. So we're seeing roughly doubling, as expected.
The goal is not a work factor; it's a time. You want as long as you can live with. In my experience (mostly working on client apps), 80-100ms is a nice target because compared to a network request it's undetectable to the user, while being massive in terms of brute-force attacks (so the default of 10 is ideal for my common use).
I generally avoid running password stretching on servers if I can help it, but this scale can be a reasonable trade-off between server impact and security. Remember that attackers may use something dramatically faster than a MacBook Pro, and may use multiple machines in parallel; I pick 80-100ms because of user experience trade-offs. (I perform password stretching on the client when I can get away with it, and then apply a cheap hash like SHA-256 on the server.)
But if you don't do this very often, or can spend more time on it, then longer is of course better, and on my MacBook Pro a work factor of 14 is about 1.2s, which I would certainly accept for some purposes.
But there's a reason that 10 is still the default. It's not an unreasonable value.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With