Bạn không nên thiết kế mã băm mật khẩu của riêng mình.
Việc tạo ra các chức năng mật mã vẫn là một quá trình thử và sai. Chắc chắn, theo thời gian, chúng tôi đã tình cờ phát hiện ra một số điều là một ý tưởng hay hoặc thậm chí là bắt buộc. Và chúng tôi chắc chắn đã học được rất nhiều điều mà đừng công việc. Nhưng chúng tôi không biết làm thế nào để tạo ra những thứ đã được chứng minh là an toàn. Một lỗi nhỏ rất tinh vi có thể khiến cấu trúc mật mã bị lỗi nghiêm trọng. Và có rất nhiều cơ hội cho những sai lầm như vậy. Tôi sẽ kể tên một số sau.
Điều tốt nhất chúng tôi có thể làm ngay bây giờ là những người có kinh nghiệm trong lĩnh vực này tạo ra một thứ tiền điện tử, và sau đó mọi người sẽ cố gắng phá vỡ thứ tiền điện tử đó. Nếu mọi người cố gắng hết sức và không thành công trong một thời gian dài thì chúng ta có thứ gì đó có lẽ đủ tốt. Chúng tôi vẫn không thể chứng minh sự vắng mặt của các vấn đề, nhưng nếu hàng ngàn nhà phân tích mật mã không thể, thì hy vọng hàng nghìn người tiếp theo cũng không thể.
Nhưng ngay cả điều này thất bại theo thời gian. Đôi khi sau nhiều năm, thậm chí nhiều thập kỷ, một vấn đề nghiêm trọng được tìm thấy trong một thứ đã được những người thông minh nhất xem xét kỹ lưỡng trong nhiều năm. Đó là lý do tại sao MD5 không còn được coi là ổn nữa và tại sao RC4 được coi là có vấn đề. Hoặc cảnh quan thay đổi, ví dụ hàng đầu. đến nhu cầu về muối trong hàm băm mật khẩu và các hàm băm làm chậm có chủ ý.
Bằng cách sử dụng các thuật toán mật mã được biết đến nhiều nhất hiện nay, chúng ta có thể tận dụng trải nghiệm tập thể này và có thể tránh lặp lại những sai lầm trong quá khứ. Sai lầm mới có thể bị phát hiện, nhưng điều đó không thể tránh được. Tuy nhiên, một số người xây dựng các chức năng tiền điện tử của riêng họ có khả năng lặp lại một số sai lầm đó hoặc tạo ra những sai lầm hoàn toàn mới.
Tôi biết, tôi biết, thật thú vị khi tự mình thiết kế những thứ đó. Và thật tuyệt khi xây dựng thứ gì đó mang lại cảm giác an toàn. Stack Exchange có rất nhiều câu hỏi về mã hóa tùy chỉnh và (đặc biệt) băm mật khẩu. Vấn đề là, thật dễ dàng để xây dựng một cái gì đó mà bản thân bạn không thể phá vỡ. Nhưng điều đó không có nghĩa là những người khác không thể.Câu ngạn ngữ này đã có từ xa xưa và được nhắc đến thường xuyên đến mức ngày nay nó được gọi là Định luật Schneier.
Cái mà có thể sai lầm?
Vì vậy, có thể có vấn đề với cốt lõi của thuật toán tiền điện tử. Đây là thứ đã phá vỡ MD5 và RC4.
Hoặc thuật toán có thể hoàn toàn ổn, nhưng việc triển khai có thể bị hỏng. Đây có thể là một lỗi đơn giản hoặc có thể là một lỗi tinh vi hơn như lỗi tấn công kênh phụ (đôi khi khó tránh một cách đáng ngạc nhiên).
Nhưng cũng có thể (dễ dàng, thậm chí) đối với các nguyên hàm mật mã an toàn với các triển khai không có lỗi được sử dụng không chính xác, khiến hệ thống không an toàn. Ví dụ: sử dụng chính xác mã hóa và chữ ký số, nhưng đưa ra các giả định ngây thơ trong quá trình bắt tay giao tiếp (SSL có một số vấn đề với điều này). Một ví dụ nổi tiếng khác là AES-ECB, sử dụng AES hoàn hảo theo cách có thể làm rò rỉ thông tin quan trọng.
Trong hàm băm của bạn?
Chức năng băm mật khẩu của riêng bạn cũng trở thành con mồi của một thứ như thế này ở đây:
lặp lại 100_000:
hàm băm = sha512(băm)
SHA-512 hoàn toàn ổn (theo như chúng tôi biết). Sử dụng nó như thế này là cau mày.
SHA-512 tạo đầu ra 512 bit "không thể phân biệt với ngẫu nhiên" cho mọi đầu vào. Nó có thể tạo ra cùng một đầu ra cho hai đầu vào riêng biệt, điều này được gọi là xung đột. Vấn đề là các hàm băm N-bit trên đầu vào N-bit thường không phỏng đoán. Điều đó có nghĩa là khi cung cấp đầu ra SHA-512 cho chính nó, một số giá trị 512 bit có thể sẽ xung đột với các giá trị khác, tạo ra cùng một đầu ra. Qua sự cần thiết, điều này cũng có nghĩa là một số giá trị băm khác hoàn toàn không thể được tạo.
Hãy xem cách điều này hoạt động đối với SHA-512, bị cắt bớt thành 4 bit. Cụ thể, chúng tôi lấy byte đầu tiên từ đầu ra và loại bỏ 4 bit cao trong byte này. Byte đơn kết quả được sử dụng làm đầu vào cho vòng tiếp theo. Các cách chọn bit khác nhau cho kết quả khác nhau, nhưng nguyên tắc là giống nhau.
Thử tất cả 16 đầu vào có thể trong vài vòng sẽ cho chúng ta các chuỗi sau:
trong 1. 2. 3. 4. 5. 6. 7.
00 -> 08 -> 06 -> 08 -> 06 -> 08 -> 06 -> 08
06 -> 08 /
07 -> 06 -> 08 -> 06 -> 08 -> 06 -> 08 -> 06
08 -> 06 /
03 -> 04 -> 05 \
13 -> 15 -> 05 -> 09 -> 02 -> 10 -> 14 -> 14
04 -> 05 -> 09 -> 02 -> 10 -> 14 -> 14 /
15 -> 05 -> 09 -> 02 -> 10 -> 14 /
05 -> 09 -> 02 -> 10 -> 14 -> 14
01 -> 11 -> 02 -> 10 -> 14 /
09 -> 02 -> 10 -> 14 -> 14
11 -> 02 -> 10 -> 14 /
02 -> 10 -> 14 -> 14
12 -> 10 //
10 -> 14 -> 14
14 -> 14 /
Chỉ sau 6 vòng, 16 đầu ra có thể đã giảm xuống chỉ còn 3. Hiệu ứng tương tự có thể được nhìn thấy đối với các đoạn cắt ngắn lớn hơn. Tôi đã chạy một số mô phỏng cho SHA-512 bị cắt bớt thành 1 byte đầu tiên (2â¸), 2 byte (2¹â¶) và 3 byte (2²â´):
byte: 1 2 3
không gian đầu vào: 256 65536 16777216
hội tụ về giá trị M: 13 330 2765
sau N vòng: 31 518 7114
Bạn có thể thấy rằng hiệu ứng hội tụ xuất hiện trong cả ba kịch bản. Đối với SHA-512 chưa cắt, máy tính của tôi không đủ nhanh để tính toán điều này, tôi không thể tìm thấy bất kỳ thông tin nào về độ mạnh và mức độ chắc chắn của hiệu ứng và tôi không đủ thông minh để tạo ra bằng chứng (nếu bằng chứng là thậm chí có thể). Nhưng tỷ lệ cược là bạn cũng sẽ thấy hiệu ứng trong SHA-512 đầy đủ. Bản năng của tôi nghi ngờ rằng nó làm giảm không gian băm bằng căn bậc hai của nó (giảm một nửa độ dài bit), nhưng tôi có thể đã rất sai [cập nhật: xem các liên kết được cung cấp trong các nhận xét: một, hai, số ba]. 100k viên đạn có lẽ cũng hạn chế sát thương.
Bây giờ, điều này có thực sự gây hại cho hàm băm của bạn không? Chắc là không. Nhưng nó Là một điểm yếu, một điểm yếu mà các hàm băm mật khẩu trong thế giới thực cần cẩn thận tránh (ví dụ: bằng cách đảm bảo mật khẩu và muối được trộn lại thường xuyên).
Tôi nghĩ đây là một ví dụ tuyệt vời về những cái bẫy tinh vi trong thiết kế tiền điện tử. Thật dễ dàng để bỏ lỡ một cái gì đó như thế này. Đó là lý do tại sao tôi khuyên bạn nên sử dụng thuật toán đã được thử nghiệm trong trận chiến. Chúng tốt hơn bất cứ thứ gì bạn hoặc tôi có thể nghĩ ra.
Các câu trả lời khác đã đưa ra một số khuyến nghị về việc sử dụng hàm băm nào; Được rồi: pbkdf2, bcrypt. Tốt hơn: argon2, scrypt. Tôi nghe thấy Balloon là một thứ, nhưng tôi không biết gì về nó nên tôi không có ý kiến gì về nó.