2010-11-16 45 views
6

Tôi đang viết một thủ tục muối mật khẩu/băm cho các ứng dụng .NET của tôi, chủ yếu sau đây hướng dẫn của bài viết này: http://www.aspheute.com/english/20040105.aspHash trên Unicode Mật khẩu

Về cơ bản mã để tính băm ướp muối là thế này:

public string ComputeSaltedHash(string password, byte[] salt) { 

    // Get password ASCII text as bytes: 
    byte[] passwordBytes = System.Text.Encoding.ASCII.GetBytes(password); 

    // Append the two arrays 
    byte[] toHash = new byte[passwordBytes.Length + salt.Length]; 
    Array.Copy(passwordBytes, 0, toHash, 0, passwordBytes.Length); 
    Array.Copy(salt, 0, toHash, passwordBytes.Length, salt.Length); 

    byte[] computedHash = SHA1.Create().ComputeHash(toHash); 

    // Return as an ASCII string 
    return System.Text.Encoding.ASCII.GetString(computedHash); 
} 

Tuy nhiên, tôi muốn cho phép người dùng sử dụng ký tự Unicode trong mật khẩu của họ, nếu thích. (Điều này có vẻ như là một ý tưởng hay; ai có thể nghĩ ra một lý do nào đó không?)

Tuy nhiên, tôi không biết cách Unicode hoạt động, và tôi lo lắng nếu tôi thay đổi cả hai tham chiếu System.Text.Encoding.ASCII thành System.Text.Encoding.Unicode, thuật toán băm có thể tạo ra một số kết hợp byte không tạo thành các ký tự Unicode hợp lệ và lệnh gọi GetString sẽ không hoạt động.

Đây có phải là mối quan tâm hợp lệ hay không?

Trả lời

12

Bạn không nên sử dụng bất kỳ mã hóa thông thường nào để chuyển đổi từ dữ liệu nhị phân tùy ý trở lại thành chuỗi. Nó không phải là văn bản được mã hóa - nó chỉ là một chuỗi các byte. Đừng cố diễn giải nó như thể đó là văn bản "bình thường". Liệu mật khẩu ban đầu có chứa bất kỳ ký tự không phải ASCII nào không liên quan đến điều này - mã hiện tại của bạn bị hỏng. (Tôi sẽ đối xử với các bài viết liên kết với một liều lượng lớn có sự nghi ngờ đơn giản trên cơ sở đó.)

tôi sẽ đề nghị:

  • Sử dụng Encoding.UTF8 để có được các byte từ mật khẩu. Điều đó sẽ cho phép mật khẩu chứa bất kỳ ký tự unicode nào. Encoding.Unicode cũng sẽ ổn ở đây.
  • Sử dụng Convert.ToBase64String để chuyển đổi từ hàm băm được tính thành văn bản. Base64 được thiết kế đặc biệt để biểu diễn dữ liệu nhị phân mờ trong văn bản trong bộ ký tự ASCII.
+0

Điểm tốt. Vấn đề không liên quan đến việc thực thi Unicode. Việc triển khai ASCII hiện tại cũng không đúng. –

+0

Cảm ơn bạn đã nhận xét sâu sắc này về mã hóa ASCII. Điều này nhắc tôi nhớ đến bài đăng của Eric Lippert, đạo đức trong đó là "không sử dụng một hệ thống mật mã mà bạn không hiểu rõ" (http://blogs.msdn.com/b/ericlippert/archive/2009/12/ 14/use-the-right-tool-for-the-job.aspx). P.S. - Chỉ cần nhận được C# của tôi trong ebook 2 chiều, mong được dành chút thời gian với nó! –

2

Đủ để thay đổi tham chiếu đầu tiên thành Unicode hoặc UTF-8. Tuy nhiên, bạn có thể muốn chuẩn hóa đầu vào để tính các cách nhập dấu trọng âm và tương tự.

0

Tôi thích giải pháp Jon tốt hơn nhưng một tùy chọn khác là chỉ lưu trữ phần thập lục phân thô dưới dạng chuỗi. Thay thế dòng cuối cùng của bạn bằng:

return BitConverter.ToString(computedHash) 

Một điều bạn có thể muốn xem xét là tăng cường mật khẩu.
SHA1 rất nhanh, đôi khi quá nhanh. Một hệ thống sẽ có thể tính toán vài triệu băm mỗi giây. Tốc độ cho phép kẻ tấn công thử một cuộc tấn công từ điển phổ biến (bao gồm cả các biến thể viết hoa) và số mở rộng. Tốc độ của SHA1 cho phép một không gian từ điển rộng được hoàn thành trong một khoảng thời gian hợp lý phá vỡ mật khẩu của người dùng nhất.

Một phương pháp để tăng cường mật khẩu là băm nhiều lần, điều này làm tăng yêu cầu CPU của hàm băm. Lấy đầu ra của hàm băm SHA1 và chuyển nó thành đầu vào cho vòng thứ hai. Làm điều đó ít nhất 1000 lần. Điều này làm chậm tính toán băm cho cả bạn và kẻ tấn công. Đối với người dùng của bạn, nó sẽ trì hoãn quyền truy cập bởi một lượng thời gian nhỏ; thói quen sẽ trở lại sau 0,01 giây thay vì 0,0001 giây. Tuy nhiên, để tấn công vũ phu, bạn đã tăng thời gian thực hiện lên 1000 lần.

Bạn có thể tự cuộn của mình nhưng.khung lưới cho thấy một lớp để làm điều đó: System.Security.Cryptography.Rfc2898DeriveBytes

RFC2898 sử dụng thuật toán SHA1 và chấp nhận văn bản thuần túy, muối và số lần lặp lại. Nó có thể xuất ra một khóa độ dài biến đổi.

http://msdn.microsoft.com/en-us/library/system.security.cryptography.rfc2898derivebytes.aspx

Các vấn đề liên quan