Which bcrypt cost to use for 2018?












2















Update



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




Old incorrect benchmark



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.










share|improve this question




















  • 1





    10 is the default cost and your benchmarks is nonsensical (0.3ns/op means code compiled away by the compiler).

    – Volker
    May 22 '18 at 13:17











  • @Volker how can I benchmark time taken to execute the function?

    – CommonSenseCode
    May 22 '18 at 13:29













  • This is largely a matter of opinion and highly dependent upon what level of security is necessary for your particular application. Even NIST and OWASP, two of the top sources of security recommendations, remain intentionally vague on the subject of work factors.

    – Adrian
    May 22 '18 at 13:35











  • @commonSenseCode by not throwing away the result of the hash but e.g. keep it in a global.

    – Volker
    May 22 '18 at 13:54











  • @Volker I've been digging into this, and it doesn't feel like that's the problem. Even printing the hash doesn't change the result. I've also checked the error result, and it's fine, too. Even changing this to result, _ = HashPassword(string(b.N), 10) generates the same timing. I'm wondering if it has to do with the calculation of N^work itself? (Though these times are really really short, so I'm not convinced that's it either.)

    – Rob Napier
    May 22 '18 at 14:01


















2















Update



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




Old incorrect benchmark



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.










share|improve this question




















  • 1





    10 is the default cost and your benchmarks is nonsensical (0.3ns/op means code compiled away by the compiler).

    – Volker
    May 22 '18 at 13:17











  • @Volker how can I benchmark time taken to execute the function?

    – CommonSenseCode
    May 22 '18 at 13:29













  • This is largely a matter of opinion and highly dependent upon what level of security is necessary for your particular application. Even NIST and OWASP, two of the top sources of security recommendations, remain intentionally vague on the subject of work factors.

    – Adrian
    May 22 '18 at 13:35











  • @commonSenseCode by not throwing away the result of the hash but e.g. keep it in a global.

    – Volker
    May 22 '18 at 13:54











  • @Volker I've been digging into this, and it doesn't feel like that's the problem. Even printing the hash doesn't change the result. I've also checked the error result, and it's fine, too. Even changing this to result, _ = HashPassword(string(b.N), 10) generates the same timing. I'm wondering if it has to do with the calculation of N^work itself? (Though these times are really really short, so I'm not convinced that's it either.)

    – Rob Napier
    May 22 '18 at 14:01
















2












2








2


2






Update



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




Old incorrect benchmark



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.










share|improve this question
















Update



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




Old incorrect benchmark



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.







go encryption hash bcrypt






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited May 25 '18 at 7:23







CommonSenseCode

















asked May 22 '18 at 12:57









CommonSenseCodeCommonSenseCode

10k1678124




10k1678124








  • 1





    10 is the default cost and your benchmarks is nonsensical (0.3ns/op means code compiled away by the compiler).

    – Volker
    May 22 '18 at 13:17











  • @Volker how can I benchmark time taken to execute the function?

    – CommonSenseCode
    May 22 '18 at 13:29













  • This is largely a matter of opinion and highly dependent upon what level of security is necessary for your particular application. Even NIST and OWASP, two of the top sources of security recommendations, remain intentionally vague on the subject of work factors.

    – Adrian
    May 22 '18 at 13:35











  • @commonSenseCode by not throwing away the result of the hash but e.g. keep it in a global.

    – Volker
    May 22 '18 at 13:54











  • @Volker I've been digging into this, and it doesn't feel like that's the problem. Even printing the hash doesn't change the result. I've also checked the error result, and it's fine, too. Even changing this to result, _ = HashPassword(string(b.N), 10) generates the same timing. I'm wondering if it has to do with the calculation of N^work itself? (Though these times are really really short, so I'm not convinced that's it either.)

    – Rob Napier
    May 22 '18 at 14:01
















  • 1





    10 is the default cost and your benchmarks is nonsensical (0.3ns/op means code compiled away by the compiler).

    – Volker
    May 22 '18 at 13:17











  • @Volker how can I benchmark time taken to execute the function?

    – CommonSenseCode
    May 22 '18 at 13:29













  • This is largely a matter of opinion and highly dependent upon what level of security is necessary for your particular application. Even NIST and OWASP, two of the top sources of security recommendations, remain intentionally vague on the subject of work factors.

    – Adrian
    May 22 '18 at 13:35











  • @commonSenseCode by not throwing away the result of the hash but e.g. keep it in a global.

    – Volker
    May 22 '18 at 13:54











  • @Volker I've been digging into this, and it doesn't feel like that's the problem. Even printing the hash doesn't change the result. I've also checked the error result, and it's fine, too. Even changing this to result, _ = HashPassword(string(b.N), 10) generates the same timing. I'm wondering if it has to do with the calculation of N^work itself? (Though these times are really really short, so I'm not convinced that's it either.)

    – Rob Napier
    May 22 '18 at 14:01










1




1





10 is the default cost and your benchmarks is nonsensical (0.3ns/op means code compiled away by the compiler).

– Volker
May 22 '18 at 13:17





10 is the default cost and your benchmarks is nonsensical (0.3ns/op means code compiled away by the compiler).

– Volker
May 22 '18 at 13:17













@Volker how can I benchmark time taken to execute the function?

– CommonSenseCode
May 22 '18 at 13:29







@Volker how can I benchmark time taken to execute the function?

– CommonSenseCode
May 22 '18 at 13:29















This is largely a matter of opinion and highly dependent upon what level of security is necessary for your particular application. Even NIST and OWASP, two of the top sources of security recommendations, remain intentionally vague on the subject of work factors.

– Adrian
May 22 '18 at 13:35





This is largely a matter of opinion and highly dependent upon what level of security is necessary for your particular application. Even NIST and OWASP, two of the top sources of security recommendations, remain intentionally vague on the subject of work factors.

– Adrian
May 22 '18 at 13:35













@commonSenseCode by not throwing away the result of the hash but e.g. keep it in a global.

– Volker
May 22 '18 at 13:54





@commonSenseCode by not throwing away the result of the hash but e.g. keep it in a global.

– Volker
May 22 '18 at 13:54













@Volker I've been digging into this, and it doesn't feel like that's the problem. Even printing the hash doesn't change the result. I've also checked the error result, and it's fine, too. Even changing this to result, _ = HashPassword(string(b.N), 10) generates the same timing. I'm wondering if it has to do with the calculation of N^work itself? (Though these times are really really short, so I'm not convinced that's it either.)

– Rob Napier
May 22 '18 at 14:01







@Volker I've been digging into this, and it doesn't feel like that's the problem. Even printing the hash doesn't change the result. I've also checked the error result, and it's fine, too. Even changing this to result, _ = HashPassword(string(b.N), 10) generates the same timing. I'm wondering if it has to do with the calculation of N^work itself? (Though these times are really really short, so I'm not convinced that's it either.)

– Rob Napier
May 22 '18 at 14:01














1 Answer
1






active

oldest

votes


















5














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.






share|improve this answer


























  • thanks rob I'll check this out later

    – CommonSenseCode
    May 22 '18 at 14:25






  • 1





    so better to just use DefaultCost var from bcrypt package. Do you have an idea why the benchmarks don't work? when should one use benchmarks? I though it was a perfect use case for comparing bcrypt cost performances

    – CommonSenseCode
    May 24 '18 at 7:52






  • 1





    Just a tip, you can use time.Since(start) instead of time.Now().Sub(start)

    – Moshe Revah
    May 24 '18 at 18:19








  • 2





    The benchmark issue is due to the fact that you aren't running the code b.N times. This is required and not optional when writing Go benchmarks.

    – Luke Joshua Park
    May 24 '18 at 22:01






  • 1





    check my update the benchmark was incorrectly set, I used @Luke Josua Park resource and got it working. Do you think the output now makes sense it is roughly doubling with every increase of bcryp

    – CommonSenseCode
    May 25 '18 at 7:25











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f50468319%2fwhich-bcrypt-cost-to-use-for-2018%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









5














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.






share|improve this answer


























  • thanks rob I'll check this out later

    – CommonSenseCode
    May 22 '18 at 14:25






  • 1





    so better to just use DefaultCost var from bcrypt package. Do you have an idea why the benchmarks don't work? when should one use benchmarks? I though it was a perfect use case for comparing bcrypt cost performances

    – CommonSenseCode
    May 24 '18 at 7:52






  • 1





    Just a tip, you can use time.Since(start) instead of time.Now().Sub(start)

    – Moshe Revah
    May 24 '18 at 18:19








  • 2





    The benchmark issue is due to the fact that you aren't running the code b.N times. This is required and not optional when writing Go benchmarks.

    – Luke Joshua Park
    May 24 '18 at 22:01






  • 1





    check my update the benchmark was incorrectly set, I used @Luke Josua Park resource and got it working. Do you think the output now makes sense it is roughly doubling with every increase of bcryp

    – CommonSenseCode
    May 25 '18 at 7:25
















5














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.






share|improve this answer


























  • thanks rob I'll check this out later

    – CommonSenseCode
    May 22 '18 at 14:25






  • 1





    so better to just use DefaultCost var from bcrypt package. Do you have an idea why the benchmarks don't work? when should one use benchmarks? I though it was a perfect use case for comparing bcrypt cost performances

    – CommonSenseCode
    May 24 '18 at 7:52






  • 1





    Just a tip, you can use time.Since(start) instead of time.Now().Sub(start)

    – Moshe Revah
    May 24 '18 at 18:19








  • 2





    The benchmark issue is due to the fact that you aren't running the code b.N times. This is required and not optional when writing Go benchmarks.

    – Luke Joshua Park
    May 24 '18 at 22:01






  • 1





    check my update the benchmark was incorrectly set, I used @Luke Josua Park resource and got it working. Do you think the output now makes sense it is roughly doubling with every increase of bcryp

    – CommonSenseCode
    May 25 '18 at 7:25














5












5








5







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.






share|improve this answer















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.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 25 '18 at 23:31









Alexis Wilke

10.2k34280




10.2k34280










answered May 22 '18 at 14:18









Rob NapierRob Napier

205k28303431




205k28303431













  • thanks rob I'll check this out later

    – CommonSenseCode
    May 22 '18 at 14:25






  • 1





    so better to just use DefaultCost var from bcrypt package. Do you have an idea why the benchmarks don't work? when should one use benchmarks? I though it was a perfect use case for comparing bcrypt cost performances

    – CommonSenseCode
    May 24 '18 at 7:52






  • 1





    Just a tip, you can use time.Since(start) instead of time.Now().Sub(start)

    – Moshe Revah
    May 24 '18 at 18:19








  • 2





    The benchmark issue is due to the fact that you aren't running the code b.N times. This is required and not optional when writing Go benchmarks.

    – Luke Joshua Park
    May 24 '18 at 22:01






  • 1





    check my update the benchmark was incorrectly set, I used @Luke Josua Park resource and got it working. Do you think the output now makes sense it is roughly doubling with every increase of bcryp

    – CommonSenseCode
    May 25 '18 at 7:25



















  • thanks rob I'll check this out later

    – CommonSenseCode
    May 22 '18 at 14:25






  • 1





    so better to just use DefaultCost var from bcrypt package. Do you have an idea why the benchmarks don't work? when should one use benchmarks? I though it was a perfect use case for comparing bcrypt cost performances

    – CommonSenseCode
    May 24 '18 at 7:52






  • 1





    Just a tip, you can use time.Since(start) instead of time.Now().Sub(start)

    – Moshe Revah
    May 24 '18 at 18:19








  • 2





    The benchmark issue is due to the fact that you aren't running the code b.N times. This is required and not optional when writing Go benchmarks.

    – Luke Joshua Park
    May 24 '18 at 22:01






  • 1





    check my update the benchmark was incorrectly set, I used @Luke Josua Park resource and got it working. Do you think the output now makes sense it is roughly doubling with every increase of bcryp

    – CommonSenseCode
    May 25 '18 at 7:25

















thanks rob I'll check this out later

– CommonSenseCode
May 22 '18 at 14:25





thanks rob I'll check this out later

– CommonSenseCode
May 22 '18 at 14:25




1




1





so better to just use DefaultCost var from bcrypt package. Do you have an idea why the benchmarks don't work? when should one use benchmarks? I though it was a perfect use case for comparing bcrypt cost performances

– CommonSenseCode
May 24 '18 at 7:52





so better to just use DefaultCost var from bcrypt package. Do you have an idea why the benchmarks don't work? when should one use benchmarks? I though it was a perfect use case for comparing bcrypt cost performances

– CommonSenseCode
May 24 '18 at 7:52




1




1





Just a tip, you can use time.Since(start) instead of time.Now().Sub(start)

– Moshe Revah
May 24 '18 at 18:19







Just a tip, you can use time.Since(start) instead of time.Now().Sub(start)

– Moshe Revah
May 24 '18 at 18:19






2




2





The benchmark issue is due to the fact that you aren't running the code b.N times. This is required and not optional when writing Go benchmarks.

– Luke Joshua Park
May 24 '18 at 22:01





The benchmark issue is due to the fact that you aren't running the code b.N times. This is required and not optional when writing Go benchmarks.

– Luke Joshua Park
May 24 '18 at 22:01




1




1





check my update the benchmark was incorrectly set, I used @Luke Josua Park resource and got it working. Do you think the output now makes sense it is roughly doubling with every increase of bcryp

– CommonSenseCode
May 25 '18 at 7:25





check my update the benchmark was incorrectly set, I used @Luke Josua Park resource and got it working. Do you think the output now makes sense it is roughly doubling with every increase of bcryp

– CommonSenseCode
May 25 '18 at 7:25




















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f50468319%2fwhich-bcrypt-cost-to-use-for-2018%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Ottavio Pratesi

Tricia Helfer

15 giugno