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.
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.