Loại dữ liệu nào sẽ được sử dụng cho trường mật khẩu băm và độ dài?


269

Tôi không chắc cách băm mật khẩu hoạt động (sẽ triển khai sau), nhưng cần tạo lược đồ cơ sở dữ liệu ngay bây giờ.

Tôi đang nghĩ đến việc giới hạn mật khẩu ở 4-20 ký tự, nhưng theo tôi hiểu sau khi mã hóa chuỗi băm sẽ có độ dài khác nhau.

Vậy, làm thế nào để lưu trữ các mật khẩu này trong cơ sở dữ liệu?


Cũng xem khung băm mật khẩu PHP của Openwall (PHPass). Nó di động và cứng đối với một số cuộc tấn công phổ biến vào mật khẩu người dùng. Anh chàng đã viết khung (SolarDesigner) là cùng một người đã viết John The Ripper và ngồi trong vai trò giám khảo trong Cuộc thi băm mật khẩu . Vì vậy, anh ta biết một hoặc hai điều về các cuộc tấn công vào mật khẩu.
jww

2
Vui lòng không đặt giới hạn trên cho mật khẩu của bạn. Bạn đang băm chúng, không có lý do lưu trữ cho một giới hạn trên. Nếu bạn lo lắng về các cuộc tấn công DoS bằng cách sử dụng hàm băm mật khẩu, 1000 hoặc 1024 là giới hạn trên hợp lý.
Iiridayn

Tại sao lại giới hạn độ dài mật khẩu? Ít nhất hãy để người dùng tạo mật khẩu 100 ký tự :)
Andrew

4 ký tự là một mật khẩu giới hạn dưới khá nguy hiểm vì chúng không đáng để bẻ khóa. Ít nhất sử dụng 8 nhưng 14 hoặc 16 thì tốt hơn nhiều.
quikchange

Đây là một câu hỏi rất cũ với một câu trả lời lỗi thời. Xem câu trả lời Gilles để cập nhật.
kelalaka

Câu trả lời:


448

Cập nhật: Đơn giản chỉ cần sử dụng hàm băm là không đủ mạnh để lưu trữ mật khẩu. Bạn nên đọc câu trả lời từ Gilles trên chủ đề này để được giải thích chi tiết hơn.

Đối với mật khẩu, sử dụng thuật toán băm tăng cường khóa như Bcrypt hoặc Argon2i. Ví dụ: trong PHP, sử dụng hàm password_hash () , sử dụng Bcrypt theo mặc định.

$hash = password_hash("rasmuslerdorf", PASSWORD_DEFAULT);

Kết quả là một chuỗi 60 ký tự tương tự như sau (nhưng các chữ số sẽ thay đổi, vì nó tạo ra một loại muối duy nhất).

$2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a

Sử dụng kiểu dữ liệu SQL CHAR(60)để lưu trữ mã hóa này của hàm bcrypt. Lưu ý rằng hàm này không mã hóa dưới dạng một chuỗi các chữ số thập lục phân, vì vậy chúng ta không thể dễ dàng mở khóa nó để lưu trữ dưới dạng nhị phân.

Các hàm băm khác vẫn có cách sử dụng, nhưng không phải để lưu trữ mật khẩu, vì vậy tôi sẽ giữ câu trả lời ban đầu bên dưới, được viết vào năm 2008.


Nó phụ thuộc vào thuật toán băm bạn sử dụng. Băm luôn tạo ra kết quả có cùng độ dài, bất kể đầu vào. Nó là điển hình để biểu thị kết quả băm nhị phân trong văn bản, dưới dạng một loạt các chữ số thập lục phân. Hoặc bạn có thể sử dụng UNHEX()hàm để giảm một nửa số chữ số hex.

  • MD5 tạo ra giá trị băm 128 bit. Bạn có thể sử dụng CHAR (32) hoặc BINary (16)
  • SHA-1 tạo ra giá trị băm 160 bit. Bạn có thể sử dụng CHAR (40) hoặc BINary (20)
  • SHA-224 tạo ra giá trị băm 224 bit. Bạn có thể sử dụng CHAR (56) hoặc BINary (28)
  • SHA-256 tạo ra giá trị băm 256 bit. Bạn có thể sử dụng CHAR (64) hoặc BINary (32)
  • SHA-384 tạo ra giá trị băm 384 bit. Bạn có thể sử dụng CHAR (96) hoặc BINary (48)
  • SHA-512 tạo ra giá trị băm 512 bit. Bạn có thể sử dụng CHAR (128) hoặc BINary (64)
  • BCrypt tạo ra giá trị băm 450 bit phụ thuộc vào việc thực hiện. Bạn có thể cần CHAR (56), CHAR (60), CHAR (76), BINary (56) hoặc BINary (60)

Kể từ năm 2015, NIST khuyến nghị sử dụng SHA-256 hoặc cao hơn cho bất kỳ ứng dụng nào của hàm băm yêu cầu khả năng tương tác. Nhưng NIST không khuyến nghị sử dụng các hàm băm đơn giản này để lưu trữ mật khẩu một cách an toàn.

Các thuật toán băm ít hơn có công dụng của chúng (như nội bộ cho một ứng dụng, không phải để trao đổi), nhưng chúng được biết là có thể bẻ khóa .


47
@Hippo: Xin vui lòng, không sử dụng tên người dùng làm muối. Tạo một muối ngẫu nhiên cho mỗi người dùng.
Bill Karwin

11
Có, không có lý do gì để không lưu trữ nó trong cùng một hàng. Ngay cả khi kẻ tấn công giành được quyền truy cập vào cơ sở dữ liệu của bạn, họ sẽ phải xây dựng bảng cầu vồng dựa trên muối đó. Và đó chỉ là công việc đơn giản như đoán mật khẩu.
Bill Karwin

5
@SgtPooki: Bạn cần một cột khác để lưu trữ muối trong văn bản gốc. Sau đó, bạn có thể băm mật khẩu của người dùng với cùng một loại muối khi họ nhập mật khẩu và so sánh kết quả với thông báo băm được lưu trữ trong bảng.
Bill Karwin

12
Nếu bạn đang lưu trữ muối trong cùng một bảng (hoặc bất kỳ vị trí nào khác có cùng quyền truy cập), không có lý do gì để không sử dụng tên người dùng làm muối, vì nó sẽ là duy nhất cho mỗi người dùng. Tuy nhiên, bất kỳ loại muối nào được biết đều làm cho hàm băm có mật mã yếu hơn nếu không có muối được biết đến. Một muối chỉ thêm giá trị nếu nó cũng không rõ.
fijiaaron

9
Tôi không hiểu thỏa thuận với muối đã biết so với muối chưa biết. Nếu bạn đang triển khai một trang web - muối cần được biết đến trang đăng nhập / tập lệnh / dịch vụ đang kiểm tra mật khẩu. Vì vậy - bạn "không biết" ủng hộ muối - bạn có cho rằng mã cho quá trình đăng nhập là không xác định đối với kẻ tấn công? Mặt khác - kẻ tấn công sẽ luôn biết muối, cho dù đó là ngẫu nhiên, duy nhất, được lưu trữ cùng với mật khẩu băm hay tách rời?
mattstuehler

13

Bạn thực sự có thể sử dụng CHAR(độ dài của hàm băm) để xác định kiểu dữ liệu của mình cho MySQL vì mỗi thuật toán băm sẽ luôn đánh giá cùng một số ký tự. Ví dụ: SHA1luôn trả về số thập lục phân 40 ký tự.


1
SHA-1 không phù hợp để băm mật khẩu.
Gilles 'SO- ngừng trở nên xấu xa'

10

Luôn sử dụng thuật toán băm mật khẩu: Argon2 , scrypt , bcrypt hoặc PBKDF2 .

Argon2 giành chiến thắng trong cuộc thi băm mật khẩu 2015.Scrypt , bcryptPBKDF2 là các thuật toán cũ được coi là ít được ưa thích hơn bây giờ, nhưng về cơ bản vẫn có âm thanh, vì vậy nếu nền tảng của bạn chưa hỗ trợ Argon2, bạn có thể sử dụng thuật toán khác ngay bây giờ.

Không bao giờ lưu trữ mật khẩu trực tiếp trong cơ sở dữ liệu. Đừng mã hóa nó, nếu không, nếu trang web của bạn bị xâm phạm, kẻ tấn công sẽ lấy khóa giải mã và do đó có thể lấy được tất cả mật khẩu. Mật khẩu PHẢI được băm .

Một băm mật khẩu có tính chất khác nhau từ một hash bảng băm hoặc băm mật mã. Không bao giờ sử dụng hàm băm mật mã thông thường như MD5, SHA-256 hoặc SHA-512 trên mật khẩu. Thuật toán băm mật khẩu sử dụng một loại muối duy nhất (không được sử dụng cho bất kỳ người dùng nào khác hoặc trong cơ sở dữ liệu của bất kỳ ai khác). Muối là cần thiết để kẻ tấn công không thể tính toán trước các băm của mật khẩu phổ biến: với một loại muối, chúng phải khởi động lại phép tính cho mọi tài khoản. Một thuật toán băm mật khẩu là về bản chất chậm - chậm như bạn có thể đủ khả năng. Slowness làm tổn thương kẻ tấn công nhiều hơn bạn vì kẻ tấn công phải thử nhiều mật khẩu khác nhau. Để biết thêm thông tin, hãy xem Cách băm mật khẩu an toàn .

Băm mật khẩu mã hóa bốn mẩu thông tin:

  • Một chỉ báo về thuật toán được sử dụng. Điều này là cần thiết cho sự nhanh nhẹn : các khuyến nghị về mật mã thay đổi theo thời gian. Bạn cần có khả năng chuyển sang một thuật toán mới.
  • Một chỉ số khó khăn hoặc độ cứng. Giá trị này càng cao, càng cần nhiều tính toán để tính toán hàm băm. Đây phải là giá trị cấu hình không đổi hoặc toàn cầu trong chức năng thay đổi mật khẩu, nhưng nó sẽ tăng theo thời gian vì máy tính trở nên nhanh hơn, vì vậy bạn cần nhớ giá trị cho từng tài khoản. Một số thuật toán có một giá trị số duy nhất, một số thuật toán khác có nhiều tham số hơn (ví dụ để điều chỉnh việc sử dụng CPU và sử dụng RAM riêng biệt).
  • Muối. Vì muối phải là duy nhất trên toàn cầu, nên nó phải được lưu trữ cho mỗi tài khoản. Muối nên được tạo ngẫu nhiên trên mỗi thay đổi mật khẩu.
  • Băm thích hợp, tức là đầu ra của phép tính toán học trong thuật toán băm.

Nhiều thư viện bao gồm một hàm cặp đóng gói thông tin này một cách thuận tiện dưới dạng một chuỗi: một chuỗi lấy chỉ báo thuật toán, chỉ báo độ cứng và mật khẩu, tạo ra một muối ngẫu nhiên và trả về chuỗi băm đầy đủ; và một mật khẩu lấy mật khẩu và chuỗi băm đầy đủ làm đầu vào và trả về một boolean cho biết liệu mật khẩu có đúng hay không. Không có tiêu chuẩn chung, nhưng mã hóa phổ biến là

$ thuật toán $ tham số $ salt $ đầu ra

trong đó algorithmmột số hoặc một chuỗi ký tự chữ và số ngắn mã hóa sự lựa chọn của thuật toán, parameterslà một chuỗi có thể in saltoutputđược mã hóa trong Base64 mà không kết thúc= .

16 byte là đủ cho muối và đầu ra. (Xem ví dụ: các đề xuất cho Argon2 .) Được mã hóa trong Base64, mỗi ký tự gồm 21 ký tự. Hai phần còn lại phụ thuộc vào thuật toán và tham số, nhưng 20 ký tự là4040 là điển hình. Đó là tổng cộng khoảng 82 ký tự ASCII ( CHAR(82)và không cần Unicode), mà bạn nên thêm một giới hạn an toàn nếu bạn nghĩ rằng sẽ khó mở rộng trường sau này.

Nếu bạn mã hóa hàm băm ở định dạng nhị phân, bạn có thể giảm xuống còn 1 byte cho thuật toán, 1 byte4 byte cho độ cứng (nếu bạn mã hóa một số tham số) và 16 byte cho mỗi muối và đầu ra , với tổng số 37 byte. Nói 40 byte ( BINARY(40)) để có ít nhất một vài byte dự phòng. Lưu ý rằng đây là các byte 8 bit, không thể in các ký tự, đặc biệt là trường có thể bao gồm các byte rỗng.

Lưu ý rằng độ dài của hàm băm hoàn toàn không liên quan đến độ dài của mật khẩu.


9

Bạn có thể tìm thấy bài viết Wikipedia này về muối đáng giá . Ý tưởng là thêm một chút dữ liệu được thiết lập để ngẫu nhiên hóa giá trị băm của bạn; điều này sẽ bảo vệ mật khẩu của bạn khỏi các cuộc tấn công từ điển nếu ai đó truy cập trái phép vào băm mật khẩu.


2
Điều đó thực sự rất đáng giá (+1), nhưng nó không trả lời câu hỏi! (-1)
Bill Karwin

3
Có, nhưng chắc chắn có liên quan trong bối cảnh này (+1)
Treb

7

Là một chuỗi có độ dài cố định (VARCHAR (n) hoặc tuy nhiên MySQL gọi nó). Một hàm băm luôn có độ dài cố định ví dụ 12 ký tự (tùy thuộc vào thuật toán băm bạn sử dụng). Vì vậy, mật khẩu 20 char sẽ được giảm xuống còn băm 12 char và mật khẩu 4 char cũng mang lại hàm băm 12 char.


3
'hoặc tuy nhiên MySQL gọi nó' - MYSQL gọi nó là CHAR. Loại này là cho giá trị chiều dài cố định. Vì vậy, tôi nghĩ CHAR là loại tốt hơn VARCHAR.
t298712383

4

Bạn nên sử dụng TEXT(lưu trữ số lượng ký tự không giới hạn) để tương thích về phía trước. Các thuật toán băm (cần) trở nên mạnh hơn theo thời gian và do đó trường cơ sở dữ liệu này sẽ cần hỗ trợ nhiều ký tự hơn theo thời gian. Ngoài ra, tùy thuộc vào chiến lược di chuyển của bạn, bạn có thể cần lưu trữ các giá trị băm mới và cũ trong cùng một trường, do đó không nên sửa độ dài cho một loại băm.


3

Nó thực sự phụ thuộc vào thuật toán băm bạn đang sử dụng. Độ dài của mật khẩu ít liên quan đến độ dài của hàm băm, nếu tôi nhớ chính xác. Tra cứu thông số kỹ thuật về thuật toán băm bạn đang sử dụng, chạy một vài bài kiểm tra và cắt ngắn ngay trên đó.


3

Băm là một chuỗi các bit (128 bit, 160 bit, 256 bit, v.v., tùy thuộc vào thuật toán). Cột của bạn phải được gõ nhị phân, không phải gõ văn bản / ký tự, nếu MySQL cho phép nó (kiểu dữ liệu SQL Server là binary(n)hoặc varbinary(n)). Bạn cũng nên muối băm. Muối có thể là văn bản hoặc nhị phân, và bạn sẽ cần một cột tương ứng.


Công lý hoàn toàn chính xác ở đây - MySQL sẽ lưu trữ chúng dưới dạng giá trị số và sẽ giúp tìm kiếm trên cột này hiệu quả hơn nhiều so với thực hiện khớp chuỗi, tuy nhiên không nên lưu trữ muối trong cơ sở dữ liệu bên cạnh dữ liệu muối - loại bỏ sự an toàn mà muối cung cấp .
Tony Maro

6
Muối không bí mật. Các chỉ bí mật là mật khẩu. Chỉ cần đảm bảo rằng mọi mật khẩu mới sẽ có một loại muối mới. Mỗi lần người dùng thay đổi mật khẩu, hệ thống sẽ tạo ra một loại muối mới cho mật khẩu đó. Các muối nên dài và ngẫu nhiên, chẳng hạn như 16 byte được tạo từ PRNG bảo mật bằng mật mã.
yfeldblum

1
@TonyMaro Không chắc chắn liệu chuỗi mật khẩu có khớp với cấp độ SQL hay không là một chiến lược tốt. Nói cách khác, bạn không nên tìm kiếm cơ sở dữ liệu của mình để tìm mật khẩu, thay vào đó hãy truy xuất người dùng dựa trên tên người dùng của anh ta và so sánh mật khẩu trong mã, thay vì SQL.
bart

1

Tôi đã luôn kiểm tra để tìm độ dài chuỗi MAX của chuỗi được mã hóa và đặt đó là độ dài ký tự của loại VARCHAR. Tùy thuộc vào số lượng bản ghi bạn sẽ có, nó thực sự có thể giúp kích thước cơ sở dữ liệu.


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.