it-swarm-vi.com

HMAC - Tại sao không phải là HMAC để lưu trữ mật khẩu?

Nota bene: Tôi biết rằng câu trả lời tốt để bảo mật lưu trữ mật khẩu là scrypt hoặc bcrypt . Câu hỏi này không phải để thực hiện trong phần mềm thực tế, nó là sự hiểu biết của riêng tôi.

Giả sử Joe Lập trình được giao nhiệm vụ lưu trữ an toàn mật khẩu người dùng cuối trong cơ sở dữ liệu cho ứng dụng web; hoặc lưu trữ mật khẩu trên đĩa để đăng nhập vào một phần mềm. Anh ta rất có thể:

  1. Có được $password từ người dùng cuối.
  2. Tạo $nonce dưới dạng giá trị ngẫu nhiên lớn khoảng 64 hoặc 128 bit.
  3. Tạo $hash = SHA256($nonce$password) và lưu trữ $nonce cùng với $hash trong cơ sở dữ liệu.

Câu hỏi thứ nhất:

Tại sao điều sau đây không tốt hơn những điều trên?

  1. Tạo $long_string một lần và chỉ một lần. Lưu trữ này như là một hằng số trong mã ứng dụng. $long_string có thể f.x. được 2 kilobyte các ký tự ngẫu nhiên.
  2. Có được $password từ người dùng cuối.
  3. Tạo $mac = HMAC-SHA256($long_string)[$password] (tức là tạo MAC bằng mật khẩu người dùng cuối làm khóa) và lưu trữ $mac này trong cơ sở dữ liệu.

Tôi sẽ tưởng tượng HMAC có những lợi ích nào sau đây?

  • Va chạm ít gặp hơn?
  • Nó là tính toán có phần đắt hơn so với băm đơn giản? (Nhưng không phải bất cứ nơi nào gần tiền điện tử, tất nhiên.)
  • Để thành công với một cuộc tấn công vũ phu trong một thời gian hợp lý và kẻ tấn công sẽ cần có quyền truy cập vào hai điều: 1) cơ sở dữ liệu, nơi lưu trữ $mac 2) mã ứng dụng, nơi lưu trữ $long_string gốc. Đó là một chức năng tốt hơn hàm băm, nơi kẻ tấn công chỉ cần truy cập vào cơ sở dữ liệu?

Tuy nhiên, dường như không ai đề xuất sử dụng HMAC, vì vậy tôi có phải đang hiểu nhầm điều gì không?

Câu hỏi hai:

Ý nghĩa của việc thêm giá trị muối $nonce sẽ là gì?

  1. Tạo $long_string một lần và chỉ một lần. Lưu trữ này như là một hằng số trong mã ứng dụng.
  2. Có được $password từ người dùng cuối.
  3. Tạo $nonce dưới dạng giá trị ngẫu nhiên lớn khoảng 128 bit.
  4. Tạo $mac = HMAC-SHA256($long_string)[$nonce$password] và lưu trữ $nonce$mac trong cơ sở dữ liệu.
46
Jesper M

Quan điểm của muối là ngăn chặn chia sẻ chi phí tấn công: nếu kẻ tấn công muốn tấn công hai mật khẩu, thì nó sẽ đắt gấp đôi so với tấn công một mật khẩu.

Với đề xuất của bạn ("câu hỏi 1" của bạn), hai người dùng có cùng mật khẩu sẽ kết thúc bằng cùng một MAC. Nếu kẻ tấn công đã đọc quyền truy cập vào cơ sở dữ liệu của bạn, anh ta có thể "thử" mật khẩu (bằng cách tính lại MAC) và tra cứu cơ sở dữ liệu cho khớp. Anh ta sau đó có thể tấn công tất cả mật khẩu song song, với chi phí tấn công một mật khẩu. Nếu là của bạn long_string là một hằng số được mã hóa cứng trong mã nguồn ứng dụng, sau đó tất cả các phiên bản được cài đặt của ứng dụng đều chia sẻ hằng số này và nó trở nên đáng giá (đối với kẻ tấn công) để tính trước một từ điển lớn các cặp mật khẩu-MAC, còn được gọi là "a Bàn cầu vồng ".

Với một nonce ("câu hỏi 2" của bạn), bạn tránh được việc chia sẻ chi phí. Nonce thường được gọi là "muối". Của bạn long_string và việc sử dụng HMAC không mua cho bạn nhiều ở đây (và bạn không sử dụng HMAC cho những gì nó được thiết kế cho, vì vậy, bạn đang ở trên nền tảng run rẩy, nói theo mật mã học). Sử dụng muối là một ý tưởng rất tốt (tốt, không sử dụng muối là một ý tưởng rất tồi, ít nhất) nhưng nó chỉ thực hiện được một nửa công việc. Bạn cũng phải có một chậm thủ tục băm. Vấn đề ở đây là muối ngăn chia sẻ chi phí, nhưng không ngăn chặn việc tấn công một mật khẩu duy nhất. Tấn công mật khẩu có nghĩa là thử mật khẩu có thể cho đến khi một mật khẩu trùng khớp (đó là "tấn công từ điển") và, theo trí tưởng tượng của người dùng trung bình, các cuộc tấn công từ điển có xu hướng hoạt động: mọi người chỉ sử dụng mật khẩu có thể được đoán Cách giải quyết là sử dụng quy trình băm vốn đã chậm, thường bằng cách lặp lại hàm băm vài nghìn lần. Ý tưởng là làm cho việc xác minh mật khẩu trở nên đắt hơn: khiến người dùng chờ 1ms thay vì 1, không khó khăn gì (người dùng sẽ không chú ý đến nó), nhưng nó cũng sẽ khiến từ điển tấn công đắt hơn 1000 lần. Của bạn long_stringcó thể được sử dụng cho điều đó, với điều kiện là nó thực sự dài (không phải 2 kilobyte, thay vì 20 megabyte).

HMAC có thể được sử dụng thay cho hàm băm thô để tăng cường hệ thống xác minh mật khẩu, nhưng trong một thiết lập khác. Đưa ra một hệ thống kiểm tra mật khẩu bằng muối và hàm băm lặp, bạn có thể thay thế hàm băm bằng HMAC, sử dụng khóa bí mật K . Điều này ngăn chặn các cuộc tấn công từ điển ngoại tuyến miễn là bạn có thể giữ K bí mật. Giữ bí mật giá trị không dễ, nhưng vẫn giữ bí mật 128 bit K so với cơ sở dữ liệu hoàn chỉnh.

35
Thomas Pornin

HMAC không mua cho bạn nhiều ở đây mặc dù tôi đoán nó hoạt động như một hàm băm có thể thay thế (có thể thay thế bằng cách thay đổi khóa). Dù sao nó chỉ có vẻ như quá mức cần thiết ở đây.

Tuy nhiên, lược đồ đầu tiên mà bạn đề xuất ở trên thất bại thảm hại nếu $ long_opes trở thành kẻ tấn công được biết đến, điều này có thể sẽ xảy ra do mã có thể không được coi là bí mật (và nói chung là thực tế kém để dựa vào bí mật của mã dù sao).

Bạn nên sử dụng lược đồ thứ hai vì $ nonce là cần thiết để bảo vệ chống lại các cuộc tấn công được tính toán trước.

3
frankodwyer