BCrypt có phải là thuật toán băm tốt để sử dụng trong C # không? Tôi có thể tìm thấy nó ở đâu? [đóng cửa]


129

Tôi đã đọc rằng khi băm mật khẩu, nhiều lập trình viên khuyên bạn nên sử dụng thuật toán BCrypt.

Tôi đang lập trình trong C # và tự hỏi liệu có ai biết triển khai tốt cho BCrypt không? Tôi tìm thấy trang này , nhưng tôi không thực sự biết nó có phải là không có thật hay không.

Tôi cần lưu ý điều gì khi chọn sơ đồ băm mật khẩu? BCrypt có phải là một triển khai 'tốt' không?

Câu trả lời:


148

Đầu tiên, một số thuật ngữ quan trọng:

Băm - Hành động lấy một chuỗi và tạo ra một chuỗi các ký tự không thể được hoàn nguyên về chuỗi ban đầu.

Mã hóa đối xứng - (Thường chỉ được gọi là 'mã hóa') - Hành động lấy một chuỗi và tạo ra một chuỗi các ký tự có thể được giải mã thành chuỗi gốc thông qua việc sử dụng cùng một khóa mã hóa đã mã hóa nó.

Bảng cầu vồng - một bảng tra cứu có chứa tất cả các biến thể của các ký tự được băm trong một thuật toán băm cụ thể.

Muối - một chuỗi ngẫu nhiên đã biết được nối vào chuỗi gốc trước khi nó được băm.

Đối với .NET Framework, Bcrypt chưa có triển khai tham chiếu đã được xác minh . Điều này rất quan trọng vì không có cách nào để biết liệu có những sai sót nghiêm trọng trong việc triển khai hiện có hay không. Bạn có thể nhận được một triển khai BCrypt cho .NET tại đây . Tôi không biết đủ về mật mã để nói liệu đó là một triển khai tốt hay xấu. Mật mã học là một lĩnh vực rất sâu sắc. Đừng cố gắng xây dựng thuật toán mã hóa của riêng bạn . Nghiêm túc.

Nếu bạn định thực hiện bảo mật mật khẩu của riêng mình (thở dài), thì bạn cần phải làm một số điều:

  1. Sử dụng thuật toán băm tương đối an toàn .
  2. Muối từng mật khẩu trước khi băm.
  3. Sử dụng một loại muối duy nhất và dài cho mỗi mật khẩu và lưu trữ muối với mật khẩu.
  4. Yêu cầu mật khẩu mạnh .

Thật không may, ngay cả khi bạn làm tất cả những điều này, một hacker quyết tâm vẫn có khả năng tìm ra mật khẩu, nó sẽ khiến anh ta mất một thời gian rất dài. Đó là kẻ thù chính của bạn: Thời gian .

Các thuật toán bcrypt làm việc vì phải mất lăm bậc độ lớn thời gian để băm mật khẩu hơn MD5 ; (và vẫn dài hơn AES hoặc SHA-512). Nó buộc tin tặc phải mất nhiều thời gian hơn để tạo một bảng cầu vồng để tra cứu mật khẩu của bạn, khiến cho khả năng mật khẩu của bạn sẽ có nguy cơ bị hack cao hơn rất nhiều.

Nếu bạn đang muối và băm mật khẩu của mình và mỗi loại muối khác nhau, thì một hacker tiềm năng sẽ phải tạo một bảng cầu vồng cho mỗi biến thể của muối , chỉ cần có một bảng cầu vồng cho một mật khẩu được băm + băm. Điều đó có nghĩa là nếu bạn có 1 triệu người dùng, một hacker phải tạo ra 1 triệu bảng cầu vồng. Nếu bạn đang sử dụng cùng một loại muối cho mọi người dùng, thì hacker chỉ phải tạo 1 bảng cầu vồng để hack thành công hệ thống của bạn.

Nếu bạn không muối mật khẩu của mình, thì tất cả kẻ tấn công phải làm là kéo lên một bảng Rainbow hiện có cho mọi triển khai ngoài đó (AES, SHA-512, MD5) và chỉ xem liệu có khớp với hàm băm không. Điều này đã được thực hiện , kẻ tấn công không cần phải tự tính toán các bảng Rainbow này .

Ngay cả với tất cả điều này, bạn đã được sử dụng các thực hành bảo mật tốt . Nếu họ có thể sử dụng thành công một vectơ tấn công khác (XSS, SQL Injection, CSRF và cộng sự ) trên trang web của bạn, bảo mật mật khẩu tốt không thành vấn đề. Nghe có vẻ như là một tuyên bố gây tranh cãi, nhưng hãy nghĩ về nó: Nếu tôi có thể lấy tất cả thông tin người dùng của bạn thông qua một cuộc tấn công SQL, hoặc tôi có thể khiến người dùng của bạn đưa cho tôi cookie của họ thông qua XSS, thì vấn đề là mật khẩu của bạn tốt đến mức nào an ninh là thế .

Các nguồn lực khác:

  1. Jeff Atwood: .NET Encoding Đơn giản hóa (tuyệt vời cho tổng quan về băm)
  2. Jeff Atwood: Tôi vừa đăng nhập với tư cách là bạn
  3. Jeff Atwood: Có lẽ bạn đang lưu trữ mật khẩu không chính xác
  4. Jeff Atwood: Tốc độ băm

Lưu ý: Vui lòng giới thiệu các tài nguyên tốt khác. Tôi đã phải đọc hàng tá bài viết của hàng tá tác giả, nhưng ít người viết đơn giản về chủ đề như Jeff. Vui lòng chỉnh sửa trong các bài viết khi bạn tìm thấy chúng.


có thể thêm vào đoạn muối của bạn rằng một loại muối phải được chọn ngẫu nhiên
Jacco

2
@Jacco Gọi tốt, thêm. Mặc dù điều đó không quan trọng. Bạn chỉ có thể sử dụng dấu thời gian của thông tin đăng nhập cho muối. Sự khác biệt mà nó tạo ra là kẻ tấn công sau đó cần tính toán lại bảng cầu vồng cho mỗi muối. Đó là điều gây khó khăn, không phải là nó được chọn ngẫu nhiên. Làm cho nó ngẫu nhiên sẽ thêm một lớp ám ảnh khác, nhưng điều đó là vô ích một khi kẻ tấn công có thể nhìn thấy cơ sở dữ liệu của bạn (đó là vấn đề gây ra tất cả sự đau lòng của chúng tôi ngay từ đầu).
George Stocker

3
Không thực sự, muối không phải là bí mật, chỉ là duy nhất cho mỗi trường hợp. Vì duy nhất (như trên toàn thế giới) là không thể, ngẫu nhiên là điều tốt nhất tiếp theo. Ngoài ra, dấu thời gian không phải là một loại muối tốt vì không có đủ entropy.
Jacco

7
Tôi có vấn đề với tuyên bố của bạn "Nếu họ có thể sử dụng thành công phép tiêm XSS hoặc SQL, bảo mật mật khẩu tốt không thành vấn đề." Ngược lại, nếu họ có thể thành công XSS hoặc SQL tiêm trang web của bạn, bảo mật mật khẩu tốt thậm chí còn quan trọng hơn. Chìa khóa ở đây là "phòng thủ theo chiều sâu" - bạn nên thắt chặt bảo mật theo như thực tế ở mọi lớp ứng dụng của bạn.
jammycakes

2
@jammycakes Hoàn toàn; quan điểm của tôi đã bị mất: Bạn không thể chỉ nói, 'Này, chúng tôi băm và muối mật khẩu của chúng tôi, "chúng tôi ổn"!'
George

74

Bạn không được sử dụng BCrypt trong .NET. Bạn phải sử dụng PBKDF2 như với triển khai .NET framework tích hợp. Đây là triển khai được xác minh bằng mật mã có sẵn miễn phí trong .NET cùng với thuật toán được NIST đề xuất .

StackId trước đây đã sử dụng BCrypt và chuyển sang PBKDF2 vì lý do này:

Đối với những người tò mò, chúng tôi đang băm mật khẩu bằng PBKDF2. Mã liên quan có ở đây ( http://code.google.com.vn/p/stackid/source/browse/OpenIdProvider/Cản.cs#1135 ), thông qua một vài lớp cảm ứng. Trong một lần lặp lại trước đó, chúng tôi đã sử dụng BCrypt; nhưng đã chuyển sang PBKDF2 vì nó được tích hợp vào khung .NET, trong khi BCrypt sẽ yêu cầu chúng tôi xác minh việc triển khai (cam kết không nhỏ).

Kevin Montrose, ngày 27 tháng 5 năm 2011

(Liên kết cập nhật trên GitHub)

Biên tập: Ý nghĩa của việc xác minh bằng thuật ngữ mã hóa dường như không dễ hiểu, một triển khai được xác minh có nghĩa là nó đã được chứng minh bằng mật mã để được thực hiện mà không có lỗi. Chi phí này có thể dễ dàng đạt 20.000 USD hoặc cao hơn. Tôi nhớ lại điều này khi tôi đang nghiên cứu về OpenSSL và đọc nơi họ tuyên bố họ chưa hoàn thành toàn bộ quy trình xác minh nhưng nếu bạn cần xác minh đầy đủ rằng họ có thể chỉ cho bạn con đường đúng cho nó và đề cập đến chi phí liên quan. Một số yêu cầu của chính phủ bao gồm các nhiệm vụ cho các thuật toán mã hóa được xác minh.

Việc triển khai bcrypt trong .NET chưa được xác minh. Sử dụng triển khai mã hóa chưa được xác minh, bạn không thể hoàn toàn chắc chắn rằng không có lỗi độc hại cố ý nào trong đó như cho phép cửa hậu vào những lỗi được mã hóa hoặc vô ý thực hiện dẫn đến dữ liệu không an toàn về mật mã.

Chỉnh sửa năm 2014: Đối với bất kỳ ai đặt câu hỏi về tính không hoàn hảo của việc sử dụng thuật toán mã hóa đã được xác minh, hãy nhìn vào sự tàn phá đã bị tấn công bởi vụ hack đau lòng được khai thác trong OpenSSL. Đó là chi phí của việc sử dụng một thực hiện chưa được xác minh. Nó an toàn .... cho đến khi bạn phát hiện ra rằng bất kỳ người nào cũng có thể đọc toàn bộ nội dung bộ nhớ của máy chủ của bạn.

Tác giả của sự thay đổi đã giới thiệu Heartbleed, Robin Seggelmann, tuyên bố rằng ông "đã bỏ lỡ việc xác thực một biến có chứa độ dài" và từ chối mọi ý định gửi một triển khai thiếu sót. Theo tiết lộ của Heartbleed, Seggelmann đề nghị tập trung vào khía cạnh thứ hai, nói rằng OpenSSL không được xem xét bởi đủ người.

Đây là định nghĩa của một thực hiện chưa được xác minh. Ngay cả lỗi nhỏ nhất cũng có thể dẫn đến làm tê liệt toàn bộ bảo mật.

Chỉnh sửa 2015: Đã xóa ngôn ngữ dựa trên đề xuất và thay thế bằng tuyệt đối. Kevin Montrose bình luận gốc cho hậu thế.


25
Để trích dẫn nhận xét được liên kết: "[chúng tôi] đã chuyển sang PBKDF2 vì nó được tích hợp vào khung .NET, trong khi BCrypt sẽ yêu cầu chúng tôi xác minh việc triển khai". Lưu ý rằng nhận xét không nói rằng thuật toán tốt hơn, chỉ là SE Dev Team xem xét việc triển khai PBKDF2 tích hợp đáng tin cậy hơn so với thư viện bên ngoài (cuối cùng là cuộc gọi phán xét).
Piskvor rời khỏi tòa nhà

3
@Piskvor Tôi đã cập nhật câu trả lời của mình. Đây không phải là về những gì nhóm SO coi là an toàn mà là một cuộc gọi phán xét giữa an toàn đã được chứng minh hoặc hy vọng an toàn. Điều thứ hai khi nói đến mật mã là không thể chấp nhận được.
Chris Marisic

6
Tôi tự hỏi làm thế nào SO di chuyển tất cả các mật khẩu băm bcrypt sang băm mới? Họ có cần mật khẩu thô để băm nó bằng thuật toán mới không?
DharmWiki Kumar 'DK'

8
@DK Tôi thậm chí không nghĩ rằng bạn phải yêu cầu họ đặt lại mật khẩu. Ở lần đăng nhập tiếp theo (nơi họ cung cấp mật khẩu văn bản gốc) bạn có thể làm điều đó tôi tin.
Matt Kocaj

12
Đây là lời khuyên tồi và tôi ngạc nhiên khi nó có rất nhiều upvote. Xác minh việc triển khai BCrypt bằng ngôn ngữ được quản lý là rất nhiều, tầm thường hơn nhiều so với việc xác minh một cái gì đó giống như toàn bộ triển khai SSL trong C. Heartbleed là hoàn toàn không liên quan; bạn nên đề cập đến một cái gì đó giống như các vấn đề ép buộc kiểu PHP với kiểm tra đẳng thức băm. Thêm vào đó, phần lớn phù hợp theo nghĩa thực tế, PBKDF2 là một KDF, không phải là thuật toán băm mật khẩu, trong khi BCrypt phù hợp hơn. Bất kể, dù sao đi nữa, việc sử dụng Argon2 sẽ có ý nghĩa hơn nhiều, dù sao đó cũng có thư viện C # được thử nghiệm tốt
Polynomial
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.