Làm thế nào bcrypt có thể tích hợp muối?


617

Bài viết "Cách lưu trữ mật khẩu an toàn" của Coda Hale tuyên bố rằng:

bcrypt có muối tích hợp để ngăn chặn các cuộc tấn công bảng cầu vồng.

Ông trích dẫn bài báo này , trong đó nói rằng trong triển khai OpenBSD về bcrypt:

OpenBSD tạo ra muối bcrypt 128 bit từ luồng khóa arcfour (arc4random (3)), được gieo bằng dữ liệu ngẫu nhiên mà nhân thu thập từ thời gian của thiết bị.

Tôi không hiểu làm thế nào điều này có thể làm việc. Theo quan niệm của tôi về một loại muối:

  • Nó cần phải khác nhau cho mỗi mật khẩu được lưu trữ, để tạo một bảng cầu vồng riêng biệt cho mỗi mật khẩu
  • Nó cần được lưu trữ ở một nơi nào đó để có thể lặp lại: khi người dùng cố gắng đăng nhập, chúng tôi sẽ thử mật khẩu của họ, lặp lại quy trình muối và băm giống như khi chúng tôi lưu trữ mật khẩu ban đầu và so sánh

Khi tôi đang sử dụng Devise (trình quản lý đăng nhập Rails) với bcrypt, không có cột muối trong cơ sở dữ liệu, vì vậy tôi bối rối. Nếu muối là ngẫu nhiên và không được lưu trữ ở bất cứ đâu, làm thế nào chúng ta có thể lặp lại đáng tin cậy quá trình băm?

Nói tóm lại, làm thế nào bcrypt có thể tích hợp muối ?

Câu trả lời:


789

Đây là bcrypt:

Tạo ra một muối ngẫu nhiên. Một yếu tố "chi phí" đã được cấu hình sẵn. Thu thập mật khẩu.

Lấy khóa mã hóa từ mật khẩu bằng cách sử dụng hệ số muối và chi phí. Sử dụng nó để mã hóa một chuỗi nổi tiếng. Lưu trữ chi phí, muối và văn bản mật mã. Bởi vì ba yếu tố này có độ dài đã biết, thật dễ dàng để ghép chúng và lưu trữ chúng trong một trường duy nhất, nhưng vẫn có thể tách chúng ra sau đó.

Khi ai đó cố gắng xác thực, lấy lại chi phí lưu trữ và muối. Lấy một khóa từ mật khẩu đầu vào, chi phí và muối. Mã hóa cùng một chuỗi nổi tiếng. Nếu văn bản mật mã được tạo khớp với văn bản mật mã được lưu trữ, mật khẩu sẽ khớp.

Bcrypt hoạt động theo cách rất giống với các sơ đồ truyền thống hơn dựa trên các thuật toán như PBKDF2. Sự khác biệt chính là việc sử dụng khóa dẫn xuất để mã hóa văn bản thuần túy đã biết; các lược đồ khác (một cách hợp lý) cho rằng hàm dẫn xuất khóa là không thể đảo ngược và lưu trữ khóa dẫn xuất trực tiếp.


Được lưu trữ trong cơ sở dữ liệu, một bcrypt"hàm băm" có thể trông giống như thế này:

$ 2a $ 10 $ vI8aWBnW3fID.ZQ4 / zo1G.q1lRps.9cGLcZEiGDMVr5yUP1KUOYTa

Đây thực sự là ba trường, được giới hạn bởi "$":

  • 2axác định bcryptphiên bản thuật toán đã được sử dụng.
  • 10là yếu tố chi phí; 2 10 lần lặp của hàm phái sinh chính được sử dụng (bằng cách này là không đủ. Tôi muốn giới thiệu chi phí từ 12 trở lên.)
  • vI8aWBnW3fID.ZQ4/zo1G.q1lRps.9cGLcZEiGDMVr5yUP1KUOYTalà muối và văn bản mật mã, được nối và mã hóa trong Base-64 được sửa đổi. 22 ký tự đầu tiên giải mã thành giá trị 16 byte cho muối. Các ký tự còn lại là văn bản mật mã được so sánh để xác thực.

Ví dụ này được lấy từ tài liệu để thực hiện viên ruby ​​của Coda Hale.


7
Bạn có biết thêm chi tiết về lý do tại sao hệ số chi phí 10 sẽ không đủ? Trong Grails, tôi nhận thấy rằng 10 là giá trị mặc định cho các vòng hệ số / nhật ký chi phí cho bcrypt để có thể cập nhật giá trị theo đề xuất của bạn.
pm_labs

57
Hệ số chi phí cho bcrypt là theo cấp số nhân, hay đúng hơn, hệ số chi phí là 10 có nghĩa là 2 ^ 10 vòng (1024), hệ số chi phí là 16 sẽ có nghĩa là 2 ^ 16 vòng (65536). Đó là điều tự nhiên sau đó sẽ mất 5-10 giây. Nó sẽ mất khoảng 64 lần miễn là một hệ số chi phí là 10. Để xóa thông tin sai lệch khác, chức năng mã hóa của PHP sử dụng thư viện mã hóa unix được triển khai trong c.
thomasrutter

3
@TJChambers Đúng vậy; nếu bạn có thể đặt mật khẩu trên tài khoản, bạn sẽ có thể xác thực. Băm mật khẩu không nhằm mục đích ngăn chặn cuộc tấn công đó. Nó có nghĩa là để ngăn chặn kẻ tấn công có quyền truy cập chỉ đọc vào bảng mật khẩu. Ví dụ, bạn nhận được một băng dự phòng với bảng trên đó.
erickson

8
@LobsterMan Không, không hẳn. Nếu bạn có thể giữ bí mật, bạn sẽ không sử dụng phương pháp này, bạn chỉ cần lưu mật khẩu. Các kế hoạch xác thực mật khẩu dựa trên giả định rằng kẻ tấn công đã phát hiện ra mọi thứ mà bạn biết. Muối ở đó để yêu cầu mỗi mật khẩu bị tấn công riêng lẻ. Nỗ lực tính toán cần thiết để kiểm tra mật khẩu được điều chỉnh bởi các lần lặp. Nếu người dùng chọn mật khẩu tốt, họ sẽ được bảo mật, ngay cả khi muối được tiết lộ. Ẩn muối có thể giúp ai đó có mật khẩu xấu trong một số trường hợp, nhưng trước tiên tôi làm việc với chất lượng mật khẩu.
erickson

1
@NLV Đó là một chuỗi được xác định trong đặc tả bcrypt:"OrpheanBeholderScryDoubt"
erickson

182

Tôi tin rằng cụm từ đó nên được diễn đạt như sau:

bcrypt có muối được tích hợp trong các bảng băm được tạo để ngăn chặn các cuộc tấn công bảng cầu vồng.

Các bcrypttiện ích tự nó không xuất hiện để duy trì một danh sách các muối. Thay vào đó, các muối được tạo ngẫu nhiên và gắn vào đầu ra của hàm để chúng được ghi nhớ sau này (theo cách triển khai Javabcrypt ). Nói cách khác, "băm" được tạo ra bcryptkhông chỉ là hàm băm. Thay vào đó, nó là băm muối kết hợp.


20
OK, vì vậy tôi đăng ký một trang web và chọn mật khẩu "foo". Bcryptthêm một muối ngẫu nhiên "akd2! *", dẫn đến "fooakd2! *", được băm và lưu trữ. Sau đó, tôi cố gắng đăng nhập bằng mật khẩu "thanh". Để xem tôi có đúng không, nó cần băm "barakd2! *". Nếu muối được tạo ngẫu nhiên để bắt đầu, làm thế nào để biết cách thêm nó trở lại "thanh" trước khi băm và so sánh?
Nathan Long

46
@Nathan: bcryptbiết cách trích xuất muối ra khỏi đầu ra được tạo ra (được lưu trữ trong cơ sở dữ liệu). Khi đến lúc xác thực, hãy bcrypttách đầu ra ban đầu thành các thành phần băm và muối. Thành phần muối được áp dụng cho mật khẩu đến được gõ bởi người dùng.
Adam Paynter

22
Để trả lời bình luận của Nathan Long, một cách nghĩ tốt về điều này là muối không có nghĩa là bí mật. Đây là lý do tại sao muối được bao gồm trong đầu ra từ hàm bcrypt như một trong những câu trả lời được chỉ ra ở trên. Muối có ở đó để ngăn các bảng cầu vồng, là danh sách các mật khẩu phổ biến, hoặc chỉ là vũ lực, v.v ... của các mật khẩu khác nhau nhưng được băm. Không có muối, hàm băm cho mật khẩu trong cơ sở dữ liệu A sẽ giống như hàm băm cho mật khẩu trong cơ sở dữ liệu B. Muối chỉ làm thay đổi giá trị băm khiến người nào đó đánh cắp cơ sở dữ liệu để giải mã mật khẩu (không xóa).
Joseph Astrahan

11
@Nathan nhưng kẻ tấn công có thể loại bỏ các muối đã biết trong tất cả mật khẩu và sau đó tạo bảng với chúng không?
Oscar

3
Đây là cách tôi hiểu nó: Ý tưởng là mỗi mật khẩu đều có một loại muối duy nhất. Muối được kết hợp trong hàm băm mật khẩu để tin tặc phải tạo một bảng cầu vồng cho mỗi mật khẩu. Điều này sẽ mất một lượng lớn thời gian cho một cơ sở dữ liệu vừa phải. Đó là tất cả về việc làm chậm một kẻ tấn công xuống và do đó làm cho vũ phu trở nên vô nghĩa.
PVermeer

0

Để làm cho mọi thứ rõ ràng hơn,

Đăng ký / Hướng đăng nhập ->

Mật khẩu + muối được mã hóa bằng một khóa được tạo từ: chi phí, muối và mật khẩu. chúng tôi gọi đó là giá trị mã hóa cipher text. sau đó chúng ta gắn muối vào giá trị này và mã hóa nó bằng base64. đính kèm chi phí cho nó và đây là chuỗi được sản xuất từ bcrypt:

$2a$COST$BASE64

Giá trị này được lưu trữ cuối cùng.

Kẻ tấn công sẽ cần phải làm gì để tìm mật khẩu? (hướng khác <-)

Trong trường hợp kẻ tấn công có quyền kiểm soát DB, kẻ tấn công sẽ giải mã dễ dàng giá trị base64, và sau đó anh ta sẽ có thể nhìn thấy muối. Muối không bí mật. mặc dù nó là ngẫu nhiên Sau đó, anh ta sẽ cần phải giải mã cipher text.

Điều quan trọng hơn: Không có băm trong quá trình này, thay vào đó là mã hóa đắt tiền CPU - giải mã. do đó bảng cầu vồng ít liên quan ở đây.


-2

Đây là từ tài liệu giao diện PasswordEncoder từ Spring Security,

 * @param rawPassword the raw password to encode and match
 * @param encodedPassword the encoded password from storage to compare with
 * @return true if the raw password, after encoding, matches the encoded password from
 * storage
 */
boolean matches(CharSequence rawPassword, String encodedPassword);

Điều đó có nghĩa là, người ta sẽ cần khớp với rawPassword mà người dùng sẽ nhập lại vào lần đăng nhập tiếp theo và khớp với mật khẩu được mã hóa Bcrypt lưu trữ trong cơ sở dữ liệu trong lần đăng nhập / đăng ký trước đó.


Điều này hoàn toàn không trả lời câu hỏi ... Nó không nói gì về cách bcrypt có thể có muối tích hợp
spencer.sm
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.