Câu hỏi Phương thức lưu trữ mật khẩu ưu tiên trong cơ sở dữ liệu


Phương thức / kiểu dữ liệu ưa thích của bạn để lưu trữ mật khẩu trong cơ sở dữ liệu (tốt nhất là SQL Server 2005). Cách tôi đã làm nó trong một số ứng dụng của chúng tôi là lần đầu tiên sử dụng các thư viện mã hóa .NET và sau đó lưu trữ chúng trong cơ sở dữ liệu dưới dạng nhị phân (16). Đây có phải là phương pháp ưa thích hay tôi nên sử dụng một kiểu dữ liệu khác hoặc phân bổ nhiều không gian hơn 16?


76
2018-03-05 17:10


gốc


Tôi có một cảm giác này có thể là một sự lừa gạt nhưng những gì tôi nghĩ có thể là một sự lừa đảo của nó hóa ra là liên quan đến đăng nhập DB thực tế và không chỉ lưu trữ thông tin đăng nhập ứng dụng / trang web. - TheTXI
Bạn có thể vui lòng làm rõ câu hỏi của bạn để giải thích cho dù bạn đang sử dụng "mã hóa" hoặc "băm" chức năng? Tôi nghĩ rằng bạn có nghĩa là sau này, nhưng sự khác biệt là rất đáng kể. - ine


Các câu trả lời:


Tôi lưu trữ hàm băm muối tương đương với mật khẩu trong cơ sở dữ liệu và không bao giờ là mật khẩu, sau đó luôn so sánh giá trị băm với mật khẩu được tạo ra từ những gì người dùng đã chuyển vào.

Quá nguy hiểm khi lưu trữ dữ liệu mật khẩu ở mọi nơi. Điều này làm cho việc khôi phục không thể, nhưng khi ai đó quên hoặc mất mật khẩu, bạn có thể chạy qua một số kiểm tra và tạo mật khẩu mới.


80
2018-03-05 17:12



@Quinton: Đó là khá nhiều những gì tôi làm. Với các thư viện mã hóa .net nó sẽ băm mật khẩu và sau đó tôi chuyển nó vào DB và lưu trữ dưới dạng nhị phân. Tôi chỉ có thể so sánh mật khẩu bằng cách băm đầu vào của người dùng và so sánh nó với những gì được lưu trữ. - TheTXI
Có vẻ như bạn đang đi đúng hướng rồi. - Quintin Robinson
Tôi khuyên bạn nên jbcrypt nếu bạn đang làm việc với java. Cực kỳ đơn giản để sử dụng - Jens Schauder
Chúng tôi lưu trữ mật khẩu muối quá. Trong trường hợp của chúng tôi, chúng tôi chuyển đổi 160-bit đã thành base64, và lưu trữ nó trong một varchar - nó chỉ làm cho mọi việc dễ dàng hơn (các chuỗi dễ đọc / ghi / xem). Ngoài một muối toàn cầu, chúng tôi tiền muối với id của người dùng (sid hoặc guid), để hai người dùng có cùng mật khẩu không cung cấp cùng một băm. Điều này làm cho các cuộc tấn công từ điển trở nên khó khăn hơn (chi phí CPU nhiều hơn) và ngăn bạn phát hiện mật khẩu cho nhiều người cùng một lúc, khi mọi người chọn cùng một mật khẩu. - Ian Boyd
@IanBoyd, trong trường hợp bạn không thay đổi phương pháp muối, bạn đang làm điều đó sai. Nó phải là ngẫu nhiên, với đủ entropy và người dùng cụ thể, trong trường hợp bạn chỉ tuân thủ sau này. - Francisco Presencia


Phương thức ưa thích: không bao giờ lưu trữ mật khẩu trong DB của bạn. Chỉ có băm của chúng. Thêm muối để nếm.


47
2018-03-05 17:16



mod lên, đã phải làm điều đó, chỉ cho các trò đùa muối;) - Jakub
tôi cũng cười toe toét với nó. - Ian Boyd


Tôi làm điều tương tự như bạn đã mô tả, ngoại trừ nó được lưu trữ như một String. I Base64 mã hóa giá trị nhị phân được mã hóa. Số lượng không gian để phân bổ phụ thuộc vào thuật toán mã hóa / độ mạnh mã hóa.

Tôi nghĩ bạn đang làm đúng (cho rằng bạn sử dụng Muối).


15
2018-03-05 17:15



1 để giải quyết câu hỏi thực sự ở đây. - erickson


Vì kết quả của hàm băm là một chuỗi byte trong phạm vi từ 0 đến 255 (hoặc -128 đến 127, tùy thuộc vào ký hiệu của loại dữ liệu 8 bit của bạn), lưu trữ nó dưới dạng trường nhị phân thô có ý nghĩa nhất , vì nó là đại diện nhỏ gọn nhất và không yêu cầu thêm các bước mã hóa và giải mã.

Một số cơ sở dữ liệu hoặc trình điều khiển không có hỗ trợ tuyệt vời cho các kiểu dữ liệu nhị phân hoặc đôi khi các nhà phát triển không đủ quen thuộc với họ để cảm thấy thoải mái. Trong trường hợp đó, sử dụng mã hóa nhị phân thành văn bản như Base-64 hoặc Base-85 và việc lưu trữ văn bản kết quả trong trường ký tự là chấp nhận được.

Kích thước của trường cần thiết được xác định bởi hàm băm mà bạn sử dụng. MD5 luôn luôn xuất ra 16 byte, SHA-1 luôn xuất ra 20 byte. Khi bạn chọn hàm băm, bạn thường bị kẹt với nó, vì thay đổi yêu cầu đặt lại tất cả mật khẩu hiện có. Vì vậy, sử dụng trường có kích thước biến không mua cho bạn bất kỳ thứ gì.


Về cách "tốt nhất" để thực hiện băm, tôi đã cố gắng cung cấp nhiều câu trả lời cho các câu hỏi SO khác về chủ đề đó:


8
2018-03-05 17:22



Nếu bạn đọc câu hỏi của tôi một chút chặt chẽ hơn, bạn sẽ thấy tôi tập trung nhiều hơn cùng với lưu trữ thực tế về kiểu dữ liệu và không gian được phân bổ cho trường. - TheTXI
Nhưng +1 để cung cấp thêm thông tin cho những người khác có thể đến sau. - TheTXI
Ngay trên. Có vẻ như tôi không phải là người duy nhất bỏ lỡ điều đó;) - erickson


  1. lưu trữ băm của mật khẩu muối, chẳng hạn như bcrypt (nounce + pwd). Bạn có thể thích bcrypt hơn SHA1 hoặc MD5 bởi vì nó có thể được điều chỉnh để được CPU-chuyên sâu, do đó làm cho một cuộc tấn công bạo lực cách lâu hơn.
  2. thêm hình ảnh xác thực vào biểu mẫu đăng nhập sau một vài lỗi đăng nhập (để tránh các cuộc tấn công bạo lực)
  3. nếu ứng dụng của bạn có liên kết "quên mật khẩu của tôi", hãy đảm bảo rằng nó không gửi mật khẩu mới qua email, nhưng thay vào đó nó sẽ gửi một liên kết đến trang (bảo mật) cho phép người dùng xác định mật khẩu mới (có thể chỉ sau khi xác nhận một số thông tin cá nhân, ví dụ như ngày sinh của người dùng). Ngoài ra, nếu ứng dụng của bạn cho phép người dùng xác định mật khẩu mới, hãy đảm bảo bạn yêu cầu người dùng xác nhận mật khẩu hiện tại.
  4. và rõ ràng, bảo mật biểu mẫu đăng nhập (thường là với HTTPS) và các máy chủ

Với các biện pháp này, mật khẩu của người dùng của bạn sẽ được bảo vệ khá tốt khỏi:

  1. => tấn công từ điển ngoại tuyến
  2. => tấn công từ điển trực tiếp
  3. => tấn công từ chối dịch vụ
  4. => tất cả các loại tấn công!

8
2018-03-05 17:51



Tất cả các biện pháp này có thể được thực hiện nhanh chóng và đóng gói khá một cú đấm cho nỗ lực tối thiểu! +1 =) - Luke Antins
Các cuộc tấn công DOS có liên quan đến bảo mật mật khẩu không? - Arj
@ a12jun: nếu bạn có liên kết "quên mật khẩu của tôi" trên trang web của mình với thông tin đăng nhập "đăng nhập" đơn giản và nút "vui lòng tạo mật khẩu mới và gửi mật khẩu cho tôi qua email", thì bất kỳ ai biết thông tin đăng nhập của bạn đều có thể buộc bạn phải thay đổi mật khẩu của mình. Nếu anh ta tự động hóa việc này để chạy 10 giây một lần, thì anh ta có thể từ chối bạn truy cập vào tài khoản của bạn. Nếu anh ta điều này chống lại hàng ngàn người dùng, anh ta có thể nhận được rất nhiều người trong số họ không thích dịch vụ của bạn. Hướng dẫn # 3 có thể bảo vệ bạn chống lại điều này, đó là những gì tôi có nghĩa là (nó không phải là rất rõ ràng, tôi phải thừa nhận). Bảo mật = Bảo ​​mật, Liêm chính, khả dụng. - MiniQuark
@MiniQuark: giải thích tốt, tôi đã không nghĩ về điều đó! - Arj


Tôi sử dụng băm sha của tên người dùng, một guid trong cấu hình web và mật khẩu, được lưu trữ dưới dạng varchar (40). Nếu họ muốn bạo lực / từ điển họ sẽ cần phải hack máy chủ web cho các guid là tốt. Tên người dùng phá vỡ việc tạo một bảng cầu vồng trên toàn bộ cơ sở dữ liệu nếu họ tìm thấy mật khẩu. Nếu người dùng muốn thay đổi tên người dùng của họ, tôi chỉ cần đặt lại mật khẩu cùng một lúc.

System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(
    username.ToLower().Trim(),
    ConfigurationManager.AppSettings("salt"),
    password
);

4
2018-03-05 23:05



tôi đã từng sử dụng tên người dùng như muối được thêm vào. Nhưng sau đó chúng tôi không thể đổi tên người dùng. Chúng tôi chuyển sang sử dụng muối với id, guid, sid, hoặc khóa thay thế khác của người dùng. - Ian Boyd
tru, gọi tốt. bằng cách này bạn không phải đặt lại mật khẩu khi đổi tên người dùng - Shawn


Một băm đơn giản của mật khẩu, hoặc thậm chí (muối + mật khẩu) nói chung là không đầy đủ.

xem:

http://www.matasano.com/log/958/enough-with-the-rainbow-tables-what-you-need-to-know-about-secure-password-schemes/

http://gom-jabbar.org/articles/2008/12/03/why-you-should-use-bcrypt-to-store-your-passwords

Cả hai đều đề xuất các thuật toán bcrypt. Việc triển khai miễn phí có thể được tìm thấy trực tuyến cho hầu hết các ngôn ngữ phổ biến.


3
2018-03-05 18:05



Các liên kết tuyệt vời vượt ra ngoài các mối quan tâm về bảo mật bề ngoài. Đối với các thuật toán chậm cố ý, điều quan trọng là phải có các hash được tính toán ở phía máy khách để không làm quá tải máy chủ (có thể đã khá bận) chưa? - cheduardo
Không hẳn. Mục tiêu chỉ đơn giản là làm cho nó "hơi" chậm hơn. Chỉ để cung cấp cho bạn một ý tưởng. Tôi có thể SHA1 băm khoảng 200K mật khẩu mỗi giây trên hệ thống lõi tứ. Tôi nghi ngờ bất cứ ai cần phải xử lý 200K đăng nhập đồng thời bao giờ thứ hai .... Vì vậy, bạn sử dụng một chức năng như PBKDF2 hoặc bcrypt để làm chậm nó xuống để nói chỉ 100 băm mỗi giây (tăng thời gian brute lực lượng của một yếu tố 200). - Gerald Davis


Bạn có thể sử dụng nhiều băm trong cơ sở dữ liệu của bạn, nó chỉ đòi hỏi một chút nỗ lực. Nó cũng có giá trị nó mặc dù nếu bạn nghĩ rằng có cơ hội remotest bạn sẽ cần phải hỗ trợ định dạng bổ sung trong tương lai. Tôi thường sử dụng các mục nhập mật khẩu như

{hashId} $ {salt} $ {băm mật khẩu}

trong đó "hashId" chỉ là một số mà tôi sử dụng trong nội bộ để nhận ra điều đó, ví dụ: tôi đang sử dụng SHA1 với mẫu băm cụ thể; "muối" là muối ngẫu nhiên được mã hóa base64; và "băm mật khẩu" là băm mã hóa base64. Nếu bạn cần di chuyển băm, bạn có thể chặn mọi người bằng định dạng mật khẩu cũ và làm cho họ thay đổi mật khẩu của họ vào lần đăng nhập tiếp theo.

Như những người khác đã đề cập đến bạn muốn cẩn thận với băm của bạn vì thật dễ dàng để làm điều gì đó không thực sự an toàn, ví dụ, H (muối, mật khẩu) yếu hơn H (mật khẩu, muối), nhưng đồng thời bạn muốn cân bằng nỗ lực đưa vào điều này với giá trị của nội dung trang web. Tôi thường sử dụng H (H (mật khẩu, muối), mật khẩu).

Cuối cùng, chi phí sử dụng mật khẩu được mã hóa base64 là khiêm tốn khi so sánh với lợi ích của việc có thể sử dụng các công cụ khác nhau mong đợi dữ liệu văn bản. Vâng, họ nên linh hoạt hơn, nhưng bạn đã sẵn sàng để nói với sếp của bạn rằng anh ta không thể sử dụng công cụ của bên thứ ba yêu thích của bạn bởi vì bạn muốn lưu một vài byte cho mỗi bản ghi? :-)

Chỉnh sửa để thêm một bình luận khác: nếu tôi đề nghị cố tình sử dụng một thuật toán đã đốt cháy ngay cả 1 / 10th của một giây băm mỗi mật khẩu tôi sẽ may mắn khi được cười ra khỏi văn phòng của ông chủ của tôi. (Không may mắn như vậy? Anh ấy sẽ viết một cái gì đó xuống để thảo luận tại đánh giá hàng năm tiếp theo của tôi.) Đốt thời gian đó không phải là một vấn đề khi bạn có hàng tá, hoặc thậm chí hàng trăm người dùng. Nếu bạn đang đẩy 100 nghìn người dùng, bạn thường sẽ có nhiều người đăng nhập cùng một lúc. Bạn cần thứ gì đó nhanh và mạnh, không chậm và mạnh. "Nhưng những gì về thông tin thẻ tín dụng?" là không trung thực nhất kể từ khi thông tin thẻ tín dụng được lưu trữ không nên ở bất cứ đâu gần cơ sở dữ liệu thông thường của bạn và sẽ được mã hóa bởi ứng dụng, chứ không phải người dùng cá nhân.


3
2018-03-23 16:17



Không có thứ gì như nhanh và mạnh khi nói đến băm. Lấy làm tiếc. Nếu nó là nhanh chóng cho bạn nó là nhanh chóng cho một kẻ tấn công bạo lực. Sử dụng một hàm dẫn xuất quan trọng là một phương thức hợp lệ để tăng cường mật khẩu. - Gerald Davis


Nếu bạn đang làm việc với ASP.Net, bạn có thể sử dụng API thành viên được tích hợp sẵn.

Nó hỗ trợ nhiều loại tùy chọn lưu trữ, inlcuding; băm một chiều, mã hóa hai chiều, md5 + muối. http://www.asp.net/learn/security để biết thêm thông tin.

Nếu bạn không cần bất cứ điều gì quá ưa thích, điều này là rất tốt cho các trang web.

Nếu bạn không sử dụng ASP.Net ở đây là một liên kết tốt đến một vài bài viết từ 4guys và codeproject

http://aspnet.4guysfromrolla.com/articles/081705-1.aspx http://aspnet.4guysfromrolla.com/articles/103002-1.aspx http://www.codeproject.com/KB/security/SimpleEncryption.aspx


2
2018-03-05 18:24





Vì câu hỏi của bạn là về phương pháp và kích thước lưu trữ, tôi sẽ giải quyết vấn đề đó.

Loại lưu trữ có thể là biểu diễn nhị phân hoặc văn bản (base64 là phổ biến nhất). Nhị phân nhỏ hơn nhưng tôi thấy làm việc với văn bản dễ dàng hơn. Nếu bạn đang làm cho mỗi người dùng salting (muối khác nhau cho mỗi mật khẩu) sau đó nó dễ dàng hơn để lưu trữ muối + băm như là một chuỗi kết hợp duy nhất.

Kích thước là thuật toán băm phụ thuộc. Đầu ra của MD5 luôn là 16 byte, SHA1 luôn là 20 byte. SHA-256 & SHA-512 tương ứng là 32 & 64 byte. Nếu bạn đang sử dụng mã hóa văn bản, bạn sẽ cần lưu trữ nhiều hơn một chút tùy thuộc vào phương pháp mã hóa. Tôi có xu hướng sử dụng Base64 vì lưu trữ tương đối rẻ. Base64 sẽ đòi hỏi khoảng 33% trường lớn hơn.

Nếu bạn có mỗi người dùng salting bạn sẽ cần không gian cho băm cũng. Đặt nó tất cả cùng nhau 64bit muối + SHA1 băm (160 bit) base64 mã hóa mất 40 ký tự vì vậy tôi lưu trữ nó như char (40).

Cuối cùng, nếu bạn muốn làm điều đó đúng, bạn không nên sử dụng một hàm băm đơn lẻ mà là một hàm dẫn xuất quan trọng như RBKDF2. Băm SHA1 và MD5 cực kỳ nhanh. Ngay cả một ứng dụng đơn luồng có thể băm khoảng 30K đến 50K mật khẩu mỗi giây với mật khẩu lên đến 200K mỗi giây trên máy lõi tứ. GPU có thể băm 100x đến 1000x như nhiều mật khẩu mỗi giây.Với tốc độ như thế lực tấn công bạo lực đó trở thành một phương pháp xâm nhập có thể chấp nhận được. RBKDF2 cho phép bạn chỉ định số lần lặp lại để tinh chỉnh cách băm của bạn "chậm". Điểm không phải là để đưa hệ thống đến đầu gối của nó mà là chọn một số lần lặp để bạn giới hạn trên mức thông lượng băm (nói 500 băm mỗi giây). Một phương pháp chứng minh trong tương lai sẽ bao gồm số lần lặp lại trong trường mật khẩu (lặp + muối + băm). Điều này sẽ cho phép tăng lặp lại trong tương lai để bắt kịp với các bộ vi xử lý mạnh mẽ hơn. Để sử dụng linh hoạt hơn, hãy sử dụng varchar để cho phép các băm có thể lớn hơn / thay thế trong tương lai.

Việc triển khai .Net là RFC2892DeriveBytes http://msdn.microsoft.com/en-us/library/system.security.cryptography.rfc2898derivebytes.aspx


2
2017-11-16 23:22