Phiên bản ngắn
Số lần lặp cung cấp ít nhất 250 mili giây để tính toán
Phiên bản dài
Khi BCrypt được xuất bản lần đầu tiên vào năm 1999, họ đã liệt kê các yếu tố chi phí mặc định của việc triển khai:
- người dùng bình thường: 6
- siêu người dùng: 8
Giá bcrypt là 6 có nghĩa là 64 vòng (2 6 = 64).
Họ cũng lưu ý:
Tất nhiên, bất cứ giá nào mọi người chọn cũng nên được đánh giá lại theo thời gian
- Vào thời điểm triển khai vào năm 1976, crypt có thể băm ít hơn 4 mật khẩu mỗi giây. (250 mili giây cho mỗi mật khẩu)
- Năm 1977, trên VAX-11/780, crypt (MD5) có thể được đánh giá khoảng 3,6 lần mỗi giây. (277 ms cho mỗi mật khẩu)
Điều đó cung cấp cho bạn hương vị của loại sự chậm trễ mà những người triển khai ban đầu đã xem xét khi họ viết nó:
- ~ 250 ms cho người dùng bình thường
- ~ 1 giây cho người dùng siêu.
Nhưng, tất nhiên, bạn có thể đứng càng lâu thì càng tốt. Mọi triển khai BCrypt tôi đã thấy được sử dụng 10
làm chi phí mặc định. Và triển khai của tôi đã sử dụng điều đó. Tôi tin rằng đã đến lúc tôi tăng chi phí mặc định lên 12.
Chúng tôi đã quyết định muốn nhắm mục tiêu không dưới 250 mili giây mỗi băm.
Máy tính để bàn của tôi là CPU Intel Core i7-2700K @ 3,50 GHz. Ban đầu, tôi đã chuẩn hóa việc triển khai BCrypt vào ngày 23 tháng 2 năm 2014:
1/23/2014 Intel Core i7-2700K CPU @ 3.50 GHz
| Cost | Iterations | Duration |
|------|-------------------|-------------|
| 8 | 256 iterations | 38.2 ms | <-- minimum allowed by BCrypt
| 9 | 512 iterations | 74.8 ms |
| 10 | 1,024 iterations | 152.4 ms | <-- current default (BCRYPT_COST=10)
| 11 | 2,048 iterations | 296.6 ms |
| 12 | 4,096 iterations | 594.3 ms |
| 13 | 8,192 iterations | 1,169.5 ms |
| 14 | 16,384 iterations | 2,338.8 ms |
| 15 | 32,768 iterations | 4,656.0 ms |
| 16 | 65,536 iterations | 9,302.2 ms |
Chứng minh trong tương lai
Thay vì có một hằng số cố định, nó phải là một mức tối thiểu cố định .
Thay vì có hàm băm mật khẩu của bạn, hãy:
String HashPassword(String password)
{
return BCrypt.HashPassword(password, BCRYPT_DEFAULT_COST);
}
nó phải là một cái gì đó như:
String HashPassword(String password)
{
/*
Rather than using a fixed default cost, run a micro-benchmark
to figure out how fast the CPU is.
Use that to make sure that it takes **at least** 250ms to calculate
the hash
*/
Int32 costFactor = this.CalculateIdealCost();
//Never use a cost lower than the default hard-coded cost
if (costFactor < BCRYPT_DEFAULT_COST)
costFactor = BCRYPT_DEFAULT_COST;
return BCrypt.HashPassword(password, costFactor);
}
Int32 CalculateIdealCost()
{
//Benchmark using a cost of 5 (the second-lowest allowed)
Int32 cost = 5;
var sw = new Stopwatch();
sw.Start();
this.HashPassword("microbenchmark", cost);
sw.Stop();
Double durationMS = sw.Elapsed.TotalMilliseconds;
//Increasing cost by 1 would double the run time.
//Keep increasing cost until the estimated duration is over 250 ms
while (durationMS < 250)
{
cost += 1;
durationMS *= 2;
}
return cost;
}
Và lý tưởng nhất, đây sẽ là một phần của thư viện BCrypt của mọi người, vì vậy thay vì dựa vào những người sử dụng thư viện để tăng chi phí theo định kỳ, chi phí tự tăng theo định kỳ.