Có phải băm đôi có một mật khẩu kém an toàn hơn là chỉ băm một lần không?


293

Băm mật khẩu hai lần trước khi lưu trữ có an toàn hơn hoặc ít hơn so với chỉ băm mật khẩu một lần không?

Những gì tôi đang nói là làm điều này:

$hashed_password = hash(hash($plaintext_password));

thay vì chỉ thế này:

$hashed_password = hash($plaintext_password);

Nếu nó kém an toàn, bạn có thể cung cấp một lời giải thích tốt (hoặc một liên kết đến một)?

Ngoài ra, hàm băm được sử dụng có làm nên sự khác biệt không? Liệu nó có khác biệt gì không nếu bạn trộn md5 và sha1 (ví dụ) thay vì lặp lại cùng hàm băm?

Lưu ý 1: Khi tôi nói "băm kép", tôi đang nói về việc băm mật khẩu hai lần trong một nỗ lực để làm cho nó bị che khuất hơn. Tôi không nói về kỹ thuật giải quyết va chạm .

Lưu ý 2: Tôi biết tôi cần thêm một loại muối ngẫu nhiên để thực sự an toàn. Câu hỏi đặt ra là liệu băm hai lần với cùng một thuật toán sẽ giúp hoặc làm tổn thương hàm băm.


2
Hash(password)Hash(Hash(password))không an toàn như nhau. Cả hai đều thiếu khái niệm về an ninh ngữ nghĩa . Đó là, đầu ra phân biệt với ngẫu nhiên. Ví dụ, MD5("password")5f4dcc3b5aa765d61d8327deb882cf99. Tôi biết đó là hàm băm MD5 passwordvà nó có thể phân biệt với ngẫu nhiên. Thay vào đó, bạn nên sử dụng một HMAC. Nó có thể chứng minh an toàn và PRF của nó.
jww

Câu trả lời:


267

Băm mật khẩu một lần là không an toàn

Không, nhiều giá trị băm không kém an toàn; chúng là một phần thiết yếu của việc sử dụng mật khẩu an toàn.

Lặp lại hàm băm làm tăng thời gian kẻ tấn công thử từng mật khẩu trong danh sách ứng cử viên của chúng. Bạn có thể dễ dàng tăng thời gian cần thiết để tấn công mật khẩu từ vài giờ đến nhiều năm.

Lặp lại đơn giản là không đủ

Chỉ có chuỗi đầu ra băm để đầu vào là không đủ để bảo mật. Việc lặp lại sẽ diễn ra trong bối cảnh thuật toán bảo toàn entropy của mật khẩu. May mắn thay, có một số thuật toán được công bố đã có đủ sự xem xét kỹ lưỡng để tự tin trong thiết kế của họ.

Một thuật toán phái sinh khóa tốt như PBKDF2 đưa mật khẩu vào mỗi vòng băm, giảm bớt những lo ngại về va chạm trong đầu ra băm. PBKDF2 có thể được sử dụng để xác thực mật khẩu. Bcrypt tuân theo đạo hàm chính với bước mã hóa; theo cách đó, nếu một cách nhanh chóng để đảo ngược đạo hàm chính được phát hiện, kẻ tấn công vẫn phải hoàn thành một cuộc tấn công bằng văn bản đã biết.

Cách phá mật khẩu

Mật khẩu được lưu trữ cần được bảo vệ khỏi một cuộc tấn công ngoại tuyến. Nếu mật khẩu không được xử lý, chúng có thể bị phá vỡ bằng một cuộc tấn công từ điển được tính toán trước (ví dụ: sử dụng Bảng cầu vồng). Mặt khác, kẻ tấn công phải dành thời gian để tính toán một hàm băm cho mỗi mật khẩu và xem nó có khớp với hàm băm được lưu trữ không.

Tất cả mật khẩu không có khả năng như nhau. Những kẻ tấn công có thể tìm kiếm triệt để tất cả các mật khẩu ngắn, nhưng họ biết rằng cơ hội thành công của vũ phu giảm mạnh với mỗi nhân vật bổ sung. Thay vào đó, họ sử dụng một danh sách theo thứ tự các mật khẩu có khả năng nhất. Họ bắt đầu với "password123" và chuyển sang mật khẩu ít được sử dụng hơn.

Giả sử một danh sách những kẻ tấn công dài, với 10 tỷ ứng cử viên; giả sử rằng một hệ thống máy tính để bàn có thể tính toán 1 triệu băm mỗi giây. Kẻ tấn công có thể kiểm tra toàn bộ danh sách của cô ta dưới ba giờ nếu chỉ sử dụng một lần lặp. Nhưng nếu chỉ 2000 lần lặp được sử dụng, thời gian đó kéo dài đến gần 8 tháng. Để đánh bại kẻ tấn công tinh vi hơn, một người có khả năng tải xuống một chương trình có thể khai thác sức mạnh của GPU của họ, ví dụ, bạn cần nhiều lần lặp hơn.

Bao nhiêu thì đủ?

Số lần lặp để sử dụng là sự đánh đổi giữa bảo mật và trải nghiệm người dùng. Phần cứng chuyên dụng có thể được sử dụng bởi những kẻ tấn công là rẻ, nhưng nó vẫn có thể thực hiện hàng trăm triệu lần lặp mỗi giây. Hiệu năng của hệ thống kẻ tấn công xác định mất bao lâu để phá mật khẩu được cung cấp một số lần lặp. Nhưng ứng dụng của bạn không có khả năng sử dụng phần cứng chuyên dụng này. Bạn có thể thực hiện bao nhiêu lần lặp mà không làm nặng thêm người dùng tùy thuộc vào hệ thống của bạn .

Bạn có thể có thể cho phép người dùng đợi thêm giây hoặc lâu hơn trong khi xác thực. Hồ sơ nền tảng mục tiêu của bạn và sử dụng nhiều lần lặp như bạn có thể đủ khả năng. Các nền tảng tôi đã thử nghiệm (một người dùng trên thiết bị di động hoặc nhiều người dùng trên nền tảng máy chủ) có thể thoải mái hỗ trợ PBKDF2 với khoảng 60.000 đến 120.000 lần lặp hoặc bcrypt với hệ số chi phí là 12 hoặc 13.

Thêm nền

Đọc PKCS # 5 để biết thông tin có thẩm quyền về vai trò của muối và lặp trong băm. Mặc dù PBKDF2 có nghĩa là để tạo khóa mã hóa từ mật khẩu, nó hoạt động tốt như một hàm băm một chiều để xác thực mật khẩu. Mỗi lần lặp của bcrypt đắt hơn hàm băm SHA-2, vì vậy bạn có thể sử dụng ít lần lặp hơn, nhưng ý tưởng là như nhau. Bcrypt cũng vượt xa hầu hết các giải pháp dựa trên PBKDF2 bằng cách sử dụng khóa dẫn xuất để mã hóa một văn bản thuần túy nổi tiếng. Văn bản mật mã kết quả được lưu trữ dưới dạng "hàm băm" cùng với một số dữ liệu meta. Tuy nhiên, không có gì ngăn bạn làm điều tương tự với PBKDF2.

Dưới đây là những câu trả lời khác mà tôi đã viết về chủ đề này:


68
Cố tình tạo một thuật toán chậm là một thực tiễn được chấp nhận khi bạn đang cố gắng ngăn chặn các cuộc tấn công từ điển chống lại các cửa hàng xác thực bị xâm nhập. Kỹ thuật này được gọi là "tăng cường khóa" hoặc "kéo dài khóa". Xem en.wikipedia.org/wiki/Key_stretching

17
@RoBorg: không quan trọng việc triển khai của bạn chậm đến mức nào , nhưng việc thực hiện kẻ tấn công sẽ chậm đến mức nào: nếu bản thân hàm băm chậm hơn hàng nghìn lần, sẽ khiến kẻ tấn công mất hàng nghìn lần để phá vỡ mật khẩu.
orip

5
Có thể cho rằng bạn sẽ muốn va chạm trong không gian 128 bit 0 đến 2 ^ 128-1. Nếu không gian đầu ra 2 ^ 128 của thuật toán băm là hoàn hảo, thì về mặt lý thuyết, bạn chỉ cần có một mật mã thay thế với một bảng chữ cái là 2 ^ 128 glyphs.
jmucchiello

13
@devin - đó không phải là "giải pháp của tôi", đó là một thông lệ được chấp nhận rộng rãi, được xây dựng theo các tiêu chuẩn mã hóa dựa trên mật khẩu như PKCS # 5, và được các chuyên gia như Robert Morris khuyên dùng. Nó cực kỳ có thể mở rộng, vì một phần thời gian dành cho việc xác thực người dùng là rất nhỏ trong một ứng dụng hợp pháp. Nó chỉ trở nên khó mở rộng khi ứng dụng của bạn bẻ khóa mật khẩu do đó khuyến nghị. Chắc chắn, không gian tìm kiếm của hàm băm nhỏ hơn mật khẩu có thể, nhưng ngay cả không gian 128 bit cũng quá lớn để tìm kiếm vũ phu. Mối đe dọa để bảo vệ chống lại là một cuộc tấn công từ điển ngoại tuyến.
erickson

6
Tôi đã đề cập không phải là sự bất tiện cho từng người dùng, mà là sự căng thẳng sẽ xảy ra với máy chủ nếu bạn có một cơ sở người dùng lớn, bởi vì bạn đang dựa vào tải CPU để làm chậm số lượng yêu cầu. Điều đó có nghĩa là nếu bạn thêm nhiều sức mạnh CPU, bạn sẽ giảm được sự hạn chế đối với những kẻ tấn công vũ phu đó. - Tuy nhiên, bạn hoàn toàn chính xác về khả năng mở rộng và thực tiễn được chấp nhận rộng rãi. Tôi đã sai về hầu hết tất cả những điều tôi nói trong các bình luận trước đây của tôi. Xin lỗi :)
DevinB

227

Đối với những người nói rằng nó an toàn, nói chung họ đúng . Băm "nhân đôi" (hoặc mở rộng logic của điều đó, lặp lại hàm băm) là hoàn toàn an toàn nếu được thực hiện đúng , cho một mối quan tâm cụ thể.

Đối với những người nói rằng nó không an toàn, họ đúng trong trường hợp này . Mã được đăng trong câu hỏi không an toàn. Hãy nói về lý do tại sao:

$hashed_password1 = md5( md5( plaintext_password ) );
$hashed_password2 = md5( plaintext_password );

Có hai thuộc tính cơ bản của hàm băm mà chúng tôi quan tâm:

  1. Kháng hình ảnh trước - Đưa ra một hàm băm $h, rất khó để tìm thấy một thông điệp $msao cho$h === hash($m)

  2. Khả năng chống hình ảnh thứ hai - Đưa ra một thông điệp $m1, thật khó để tìm thấy một thông điệp $m2khác như vậyhash($m1) === hash($m2)

  3. Kháng va chạm - Rất khó để tìm thấy một cặp tin nhắn ($m1, $m2)như vậy hash($m1) === hash($m2)(lưu ý rằng điều này tương tự với tính kháng hình ảnh thứ hai, nhưng khác ở đây, kẻ tấn công có quyền kiểm soát cả hai tin nhắn) ...

Đối với việc lưu trữ mật khẩu , tất cả những gì chúng tôi thực sự quan tâm là Kháng hình ảnh trước . Hai cái còn lại sẽ là moot, vì $m1mật khẩu của người dùng chúng tôi đang cố gắng giữ an toàn. Vì vậy, nếu kẻ tấn công đã có nó, hàm băm không có gì để bảo vệ ...

TUYÊN BỐ TỪ CHỐI

Tất cả mọi thứ tiếp theo đều dựa trên tiền đề mà tất cả những gì chúng ta quan tâm là Kháng hình ảnh trước . Hai thuộc tính cơ bản khác của hàm băm có thể không (và thường không) giữ theo cùng một cách. Vì vậy, kết luận trong bài viết này chỉ được áp dụng khi sử dụng hàm băm để lưu trữ mật khẩu. Chúng không được áp dụng chung ...

Bắt đầu nào

Vì lợi ích của cuộc thảo luận này, chúng ta hãy phát minh ra hàm băm của riêng mình:

function ourHash($input) {
    $result = 0;
    for ($i = 0; $i < strlen($input); $i++) {
        $result += ord($input[$i]);
    }
    return (string) ($result % 256);
}

Bây giờ nó sẽ khá rõ ràng những gì hàm băm này làm. Nó tổng hợp các giá trị ASCII của từng ký tự đầu vào và sau đó lấy modulo của kết quả đó với 256.

Vì vậy, hãy thử nghiệm nó:

var_dump(
    ourHash('abc'), // string(2) "38"
    ourHash('def'), // string(2) "47"
    ourHash('hij'), // string(2) "59"
    ourHash('klm')  // string(2) "68"
);

Bây giờ, hãy xem điều gì xảy ra nếu chúng ta chạy nó một vài lần xung quanh một hàm:

$tests = array(
    "abc",
    "def",
    "hij",
    "klm",
);

foreach ($tests as $test) {
    $hash = $test;
    for ($i = 0; $i < 100; $i++) {
        $hash = ourHash($hash);
    }
    echo "Hashing $test => $hash\n";
}

Đó là đầu ra:

Hashing abc => 152
Hashing def => 152
Hashing hij => 155
Hashing klm => 155

Hrm, wow. Chúng tôi đã tạo ra va chạm !!! Hãy thử xem tại sao:

Đây là đầu ra của việc băm một chuỗi của mỗi và mọi đầu ra băm có thể:

Hashing 0 => 48
Hashing 1 => 49
Hashing 2 => 50
Hashing 3 => 51
Hashing 4 => 52
Hashing 5 => 53
Hashing 6 => 54
Hashing 7 => 55
Hashing 8 => 56
Hashing 9 => 57
Hashing 10 => 97
Hashing 11 => 98
Hashing 12 => 99
Hashing 13 => 100
Hashing 14 => 101
Hashing 15 => 102
Hashing 16 => 103
Hashing 17 => 104
Hashing 18 => 105
Hashing 19 => 106
Hashing 20 => 98
Hashing 21 => 99
Hashing 22 => 100
Hashing 23 => 101
Hashing 24 => 102
Hashing 25 => 103
Hashing 26 => 104
Hashing 27 => 105
Hashing 28 => 106
Hashing 29 => 107
Hashing 30 => 99
Hashing 31 => 100
Hashing 32 => 101
Hashing 33 => 102
Hashing 34 => 103
Hashing 35 => 104
Hashing 36 => 105
Hashing 37 => 106
Hashing 38 => 107
Hashing 39 => 108
Hashing 40 => 100
Hashing 41 => 101
Hashing 42 => 102
Hashing 43 => 103
Hashing 44 => 104
Hashing 45 => 105
Hashing 46 => 106
Hashing 47 => 107
Hashing 48 => 108
Hashing 49 => 109
Hashing 50 => 101
Hashing 51 => 102
Hashing 52 => 103
Hashing 53 => 104
Hashing 54 => 105
Hashing 55 => 106
Hashing 56 => 107
Hashing 57 => 108
Hashing 58 => 109
Hashing 59 => 110
Hashing 60 => 102
Hashing 61 => 103
Hashing 62 => 104
Hashing 63 => 105
Hashing 64 => 106
Hashing 65 => 107
Hashing 66 => 108
Hashing 67 => 109
Hashing 68 => 110
Hashing 69 => 111
Hashing 70 => 103
Hashing 71 => 104
Hashing 72 => 105
Hashing 73 => 106
Hashing 74 => 107
Hashing 75 => 108
Hashing 76 => 109
Hashing 77 => 110
Hashing 78 => 111
Hashing 79 => 112
Hashing 80 => 104
Hashing 81 => 105
Hashing 82 => 106
Hashing 83 => 107
Hashing 84 => 108
Hashing 85 => 109
Hashing 86 => 110
Hashing 87 => 111
Hashing 88 => 112
Hashing 89 => 113
Hashing 90 => 105
Hashing 91 => 106
Hashing 92 => 107
Hashing 93 => 108
Hashing 94 => 109
Hashing 95 => 110
Hashing 96 => 111
Hashing 97 => 112
Hashing 98 => 113
Hashing 99 => 114
Hashing 100 => 145
Hashing 101 => 146
Hashing 102 => 147
Hashing 103 => 148
Hashing 104 => 149
Hashing 105 => 150
Hashing 106 => 151
Hashing 107 => 152
Hashing 108 => 153
Hashing 109 => 154
Hashing 110 => 146
Hashing 111 => 147
Hashing 112 => 148
Hashing 113 => 149
Hashing 114 => 150
Hashing 115 => 151
Hashing 116 => 152
Hashing 117 => 153
Hashing 118 => 154
Hashing 119 => 155
Hashing 120 => 147
Hashing 121 => 148
Hashing 122 => 149
Hashing 123 => 150
Hashing 124 => 151
Hashing 125 => 152
Hashing 126 => 153
Hashing 127 => 154
Hashing 128 => 155
Hashing 129 => 156
Hashing 130 => 148
Hashing 131 => 149
Hashing 132 => 150
Hashing 133 => 151
Hashing 134 => 152
Hashing 135 => 153
Hashing 136 => 154
Hashing 137 => 155
Hashing 138 => 156
Hashing 139 => 157
Hashing 140 => 149
Hashing 141 => 150
Hashing 142 => 151
Hashing 143 => 152
Hashing 144 => 153
Hashing 145 => 154
Hashing 146 => 155
Hashing 147 => 156
Hashing 148 => 157
Hashing 149 => 158
Hashing 150 => 150
Hashing 151 => 151
Hashing 152 => 152
Hashing 153 => 153
Hashing 154 => 154
Hashing 155 => 155
Hashing 156 => 156
Hashing 157 => 157
Hashing 158 => 158
Hashing 159 => 159
Hashing 160 => 151
Hashing 161 => 152
Hashing 162 => 153
Hashing 163 => 154
Hashing 164 => 155
Hashing 165 => 156
Hashing 166 => 157
Hashing 167 => 158
Hashing 168 => 159
Hashing 169 => 160
Hashing 170 => 152
Hashing 171 => 153
Hashing 172 => 154
Hashing 173 => 155
Hashing 174 => 156
Hashing 175 => 157
Hashing 176 => 158
Hashing 177 => 159
Hashing 178 => 160
Hashing 179 => 161
Hashing 180 => 153
Hashing 181 => 154
Hashing 182 => 155
Hashing 183 => 156
Hashing 184 => 157
Hashing 185 => 158
Hashing 186 => 159
Hashing 187 => 160
Hashing 188 => 161
Hashing 189 => 162
Hashing 190 => 154
Hashing 191 => 155
Hashing 192 => 156
Hashing 193 => 157
Hashing 194 => 158
Hashing 195 => 159
Hashing 196 => 160
Hashing 197 => 161
Hashing 198 => 162
Hashing 199 => 163
Hashing 200 => 146
Hashing 201 => 147
Hashing 202 => 148
Hashing 203 => 149
Hashing 204 => 150
Hashing 205 => 151
Hashing 206 => 152
Hashing 207 => 153
Hashing 208 => 154
Hashing 209 => 155
Hashing 210 => 147
Hashing 211 => 148
Hashing 212 => 149
Hashing 213 => 150
Hashing 214 => 151
Hashing 215 => 152
Hashing 216 => 153
Hashing 217 => 154
Hashing 218 => 155
Hashing 219 => 156
Hashing 220 => 148
Hashing 221 => 149
Hashing 222 => 150
Hashing 223 => 151
Hashing 224 => 152
Hashing 225 => 153
Hashing 226 => 154
Hashing 227 => 155
Hashing 228 => 156
Hashing 229 => 157
Hashing 230 => 149
Hashing 231 => 150
Hashing 232 => 151
Hashing 233 => 152
Hashing 234 => 153
Hashing 235 => 154
Hashing 236 => 155
Hashing 237 => 156
Hashing 238 => 157
Hashing 239 => 158
Hashing 240 => 150
Hashing 241 => 151
Hashing 242 => 152
Hashing 243 => 153
Hashing 244 => 154
Hashing 245 => 155
Hashing 246 => 156
Hashing 247 => 157
Hashing 248 => 158
Hashing 249 => 159
Hashing 250 => 151
Hashing 251 => 152
Hashing 252 => 153
Hashing 253 => 154
Hashing 254 => 155
Hashing 255 => 156

Lưu ý xu hướng về số lượng cao hơn. Điều đó hóa ra là sự chết chóc của chúng tôi. Chạy hàm băm 4 lần ($ hash = ourHash ($ hash) `, cho mỗi phần tử) kết thúc cho chúng ta:

Hashing 0 => 153
Hashing 1 => 154
Hashing 2 => 155
Hashing 3 => 156
Hashing 4 => 157
Hashing 5 => 158
Hashing 6 => 150
Hashing 7 => 151
Hashing 8 => 152
Hashing 9 => 153
Hashing 10 => 157
Hashing 11 => 158
Hashing 12 => 150
Hashing 13 => 154
Hashing 14 => 155
Hashing 15 => 156
Hashing 16 => 157
Hashing 17 => 158
Hashing 18 => 150
Hashing 19 => 151
Hashing 20 => 158
Hashing 21 => 150
Hashing 22 => 154
Hashing 23 => 155
Hashing 24 => 156
Hashing 25 => 157
Hashing 26 => 158
Hashing 27 => 150
Hashing 28 => 151
Hashing 29 => 152
Hashing 30 => 150
Hashing 31 => 154
Hashing 32 => 155
Hashing 33 => 156
Hashing 34 => 157
Hashing 35 => 158
Hashing 36 => 150
Hashing 37 => 151
Hashing 38 => 152
Hashing 39 => 153
Hashing 40 => 154
Hashing 41 => 155
Hashing 42 => 156
Hashing 43 => 157
Hashing 44 => 158
Hashing 45 => 150
Hashing 46 => 151
Hashing 47 => 152
Hashing 48 => 153
Hashing 49 => 154
Hashing 50 => 155
Hashing 51 => 156
Hashing 52 => 157
Hashing 53 => 158
Hashing 54 => 150
Hashing 55 => 151
Hashing 56 => 152
Hashing 57 => 153
Hashing 58 => 154
Hashing 59 => 155
Hashing 60 => 156
Hashing 61 => 157
Hashing 62 => 158
Hashing 63 => 150
Hashing 64 => 151
Hashing 65 => 152
Hashing 66 => 153
Hashing 67 => 154
Hashing 68 => 155
Hashing 69 => 156
Hashing 70 => 157
Hashing 71 => 158
Hashing 72 => 150
Hashing 73 => 151
Hashing 74 => 152
Hashing 75 => 153
Hashing 76 => 154
Hashing 77 => 155
Hashing 78 => 156
Hashing 79 => 157
Hashing 80 => 158
Hashing 81 => 150
Hashing 82 => 151
Hashing 83 => 152
Hashing 84 => 153
Hashing 85 => 154
Hashing 86 => 155
Hashing 87 => 156
Hashing 88 => 157
Hashing 89 => 158
Hashing 90 => 150
Hashing 91 => 151
Hashing 92 => 152
Hashing 93 => 153
Hashing 94 => 154
Hashing 95 => 155
Hashing 96 => 156
Hashing 97 => 157
Hashing 98 => 158
Hashing 99 => 150
Hashing 100 => 154
Hashing 101 => 155
Hashing 102 => 156
Hashing 103 => 157
Hashing 104 => 158
Hashing 105 => 150
Hashing 106 => 151
Hashing 107 => 152
Hashing 108 => 153
Hashing 109 => 154
Hashing 110 => 155
Hashing 111 => 156
Hashing 112 => 157
Hashing 113 => 158
Hashing 114 => 150
Hashing 115 => 151
Hashing 116 => 152
Hashing 117 => 153
Hashing 118 => 154
Hashing 119 => 155
Hashing 120 => 156
Hashing 121 => 157
Hashing 122 => 158
Hashing 123 => 150
Hashing 124 => 151
Hashing 125 => 152
Hashing 126 => 153
Hashing 127 => 154
Hashing 128 => 155
Hashing 129 => 156
Hashing 130 => 157
Hashing 131 => 158
Hashing 132 => 150
Hashing 133 => 151
Hashing 134 => 152
Hashing 135 => 153
Hashing 136 => 154
Hashing 137 => 155
Hashing 138 => 156
Hashing 139 => 157
Hashing 140 => 158
Hashing 141 => 150
Hashing 142 => 151
Hashing 143 => 152
Hashing 144 => 153
Hashing 145 => 154
Hashing 146 => 155
Hashing 147 => 156
Hashing 148 => 157
Hashing 149 => 158
Hashing 150 => 150
Hashing 151 => 151
Hashing 152 => 152
Hashing 153 => 153
Hashing 154 => 154
Hashing 155 => 155
Hashing 156 => 156
Hashing 157 => 157
Hashing 158 => 158
Hashing 159 => 159
Hashing 160 => 151
Hashing 161 => 152
Hashing 162 => 153
Hashing 163 => 154
Hashing 164 => 155
Hashing 165 => 156
Hashing 166 => 157
Hashing 167 => 158
Hashing 168 => 159
Hashing 169 => 151
Hashing 170 => 152
Hashing 171 => 153
Hashing 172 => 154
Hashing 173 => 155
Hashing 174 => 156
Hashing 175 => 157
Hashing 176 => 158
Hashing 177 => 159
Hashing 178 => 151
Hashing 179 => 152
Hashing 180 => 153
Hashing 181 => 154
Hashing 182 => 155
Hashing 183 => 156
Hashing 184 => 157
Hashing 185 => 158
Hashing 186 => 159
Hashing 187 => 151
Hashing 188 => 152
Hashing 189 => 153
Hashing 190 => 154
Hashing 191 => 155
Hashing 192 => 156
Hashing 193 => 157
Hashing 194 => 158
Hashing 195 => 159
Hashing 196 => 151
Hashing 197 => 152
Hashing 198 => 153
Hashing 199 => 154
Hashing 200 => 155
Hashing 201 => 156
Hashing 202 => 157
Hashing 203 => 158
Hashing 204 => 150
Hashing 205 => 151
Hashing 206 => 152
Hashing 207 => 153
Hashing 208 => 154
Hashing 209 => 155
Hashing 210 => 156
Hashing 211 => 157
Hashing 212 => 158
Hashing 213 => 150
Hashing 214 => 151
Hashing 215 => 152
Hashing 216 => 153
Hashing 217 => 154
Hashing 218 => 155
Hashing 219 => 156
Hashing 220 => 157
Hashing 221 => 158
Hashing 222 => 150
Hashing 223 => 151
Hashing 224 => 152
Hashing 225 => 153
Hashing 226 => 154
Hashing 227 => 155
Hashing 228 => 156
Hashing 229 => 157
Hashing 230 => 158
Hashing 231 => 150
Hashing 232 => 151
Hashing 233 => 152
Hashing 234 => 153
Hashing 235 => 154
Hashing 236 => 155
Hashing 237 => 156
Hashing 238 => 157
Hashing 239 => 158
Hashing 240 => 150
Hashing 241 => 151
Hashing 242 => 152
Hashing 243 => 153
Hashing 244 => 154
Hashing 245 => 155
Hashing 246 => 156
Hashing 247 => 157
Hashing 248 => 158
Hashing 249 => 159
Hashing 250 => 151
Hashing 251 => 152
Hashing 252 => 153
Hashing 253 => 154
Hashing 254 => 155
Hashing 255 => 156

Chúng tôi đã thu hẹp bản thân xuống còn 8 giá trị ... Thật tệ ... Chức năng ban đầu của chúng tôi được ánh xạ S(∞)lên S(256). Đó là chúng tôi đã tạo một Function Surjective bản đồ $inputđể $output.

Vì chúng tôi có chức năng Surjective, chúng tôi không đảm bảo ánh xạ cho bất kỳ tập hợp con nào của đầu vào sẽ không có xung đột (trên thực tế, trong thực tế, chúng sẽ).

Đó là những gì đã xảy ra ở đây! Chức năng của chúng tôi rất tệ, nhưng đó không phải là lý do tại sao điều này hoạt động (đó là lý do tại sao nó hoạt động rất nhanh và hoàn toàn như vậy).

Điều tương tự xảy ra với MD5. Nó bản đồS(∞) lên S(2^128). Vì không có gì đảm bảo rằng việc chạy MD5(S(output))sẽ là Tiêm , nghĩa là nó sẽ không có va chạm.

Phần TL / DR

Do đó, kể từ khi cho đầu ra trở lại md5 trực tiếp có thể tạo ra va chạm, mỗi lần lặp lại sẽ làm tăng cơ hội va chạm. Tuy nhiên, đây là mức tăng tuyến tính, có nghĩa là trong khi tập kết quả 2^128bị giảm, nó không giảm đáng kể đủ nhanh để trở thành một lỗ hổng nghiêm trọng.

Vì thế,

$output = md5($input); // 2^128 possibilities
$output = md5($output); // < 2^128 possibilities
$output = md5($output); // < 2^128 possibilities
$output = md5($output); // < 2^128 possibilities
$output = md5($output); // < 2^128 possibilities

Bạn càng lặp lại nhiều lần, mức giảm càng tăng.

Sửa chữa

May mắn thay cho chúng tôi, có một cách nhỏ để khắc phục điều này: Đưa lại thứ gì đó vào các lần lặp tiếp theo:

$output = md5($input); // 2^128 possibilities
$output = md5($input . $output); // 2^128 possibilities
$output = md5($input . $output); // 2^128 possibilities
$output = md5($input . $output); // 2^128 possibilities
$output = md5($input . $output); // 2^128 possibilities    

Lưu ý rằng các lần lặp tiếp theo không phải là 2 ^ 128 cho mỗi giá trị riêng lẻ cho $input. Có nghĩa là chúng ta có thể tạo ra $inputcác giá trị vẫn va chạm vào dòng (và do đó sẽ giải quyết hoặc cộng hưởng ở mức thấp hơn nhiều so với 2^128đầu ra có thể). Nhưng trường hợp chung cho$input vẫn mạnh như trong một vòng duy nhất.

Đợi đã, phải không? Hãy thử nghiệm điều này với ourHash()chức năng của chúng tôi . Chuyển sang $hash = ourHash($input . $hash);, trong 100 lần lặp:

Hashing 0 => 201
Hashing 1 => 212
Hashing 2 => 199
Hashing 3 => 201
Hashing 4 => 203
Hashing 5 => 205
Hashing 6 => 207
Hashing 7 => 209
Hashing 8 => 211
Hashing 9 => 204
Hashing 10 => 251
Hashing 11 => 147
Hashing 12 => 251
Hashing 13 => 148
Hashing 14 => 253
Hashing 15 => 0
Hashing 16 => 1
Hashing 17 => 2
Hashing 18 => 161
Hashing 19 => 163
Hashing 20 => 147
Hashing 21 => 251
Hashing 22 => 148
Hashing 23 => 253
Hashing 24 => 0
Hashing 25 => 1
Hashing 26 => 2
Hashing 27 => 161
Hashing 28 => 163
Hashing 29 => 8
Hashing 30 => 251
Hashing 31 => 148
Hashing 32 => 253
Hashing 33 => 0
Hashing 34 => 1
Hashing 35 => 2
Hashing 36 => 161
Hashing 37 => 163
Hashing 38 => 8
Hashing 39 => 4
Hashing 40 => 148
Hashing 41 => 253
Hashing 42 => 0
Hashing 43 => 1
Hashing 44 => 2
Hashing 45 => 161
Hashing 46 => 163
Hashing 47 => 8
Hashing 48 => 4
Hashing 49 => 9
Hashing 50 => 253
Hashing 51 => 0
Hashing 52 => 1
Hashing 53 => 2
Hashing 54 => 161
Hashing 55 => 163
Hashing 56 => 8
Hashing 57 => 4
Hashing 58 => 9
Hashing 59 => 11
Hashing 60 => 0
Hashing 61 => 1
Hashing 62 => 2
Hashing 63 => 161
Hashing 64 => 163
Hashing 65 => 8
Hashing 66 => 4
Hashing 67 => 9
Hashing 68 => 11
Hashing 69 => 4
Hashing 70 => 1
Hashing 71 => 2
Hashing 72 => 161
Hashing 73 => 163
Hashing 74 => 8
Hashing 75 => 4
Hashing 76 => 9
Hashing 77 => 11
Hashing 78 => 4
Hashing 79 => 3
Hashing 80 => 2
Hashing 81 => 161
Hashing 82 => 163
Hashing 83 => 8
Hashing 84 => 4
Hashing 85 => 9
Hashing 86 => 11
Hashing 87 => 4
Hashing 88 => 3
Hashing 89 => 17
Hashing 90 => 161
Hashing 91 => 163
Hashing 92 => 8
Hashing 93 => 4
Hashing 94 => 9
Hashing 95 => 11
Hashing 96 => 4
Hashing 97 => 3
Hashing 98 => 17
Hashing 99 => 13
Hashing 100 => 246
Hashing 101 => 248
Hashing 102 => 49
Hashing 103 => 44
Hashing 104 => 255
Hashing 105 => 198
Hashing 106 => 43
Hashing 107 => 51
Hashing 108 => 202
Hashing 109 => 2
Hashing 110 => 248
Hashing 111 => 49
Hashing 112 => 44
Hashing 113 => 255
Hashing 114 => 198
Hashing 115 => 43
Hashing 116 => 51
Hashing 117 => 202
Hashing 118 => 2
Hashing 119 => 51
Hashing 120 => 49
Hashing 121 => 44
Hashing 122 => 255
Hashing 123 => 198
Hashing 124 => 43
Hashing 125 => 51
Hashing 126 => 202
Hashing 127 => 2
Hashing 128 => 51
Hashing 129 => 53
Hashing 130 => 44
Hashing 131 => 255
Hashing 132 => 198
Hashing 133 => 43
Hashing 134 => 51
Hashing 135 => 202
Hashing 136 => 2
Hashing 137 => 51
Hashing 138 => 53
Hashing 139 => 55
Hashing 140 => 255
Hashing 141 => 198
Hashing 142 => 43
Hashing 143 => 51
Hashing 144 => 202
Hashing 145 => 2
Hashing 146 => 51
Hashing 147 => 53
Hashing 148 => 55
Hashing 149 => 58
Hashing 150 => 198
Hashing 151 => 43
Hashing 152 => 51
Hashing 153 => 202
Hashing 154 => 2
Hashing 155 => 51
Hashing 156 => 53
Hashing 157 => 55
Hashing 158 => 58
Hashing 159 => 0
Hashing 160 => 43
Hashing 161 => 51
Hashing 162 => 202
Hashing 163 => 2
Hashing 164 => 51
Hashing 165 => 53
Hashing 166 => 55
Hashing 167 => 58
Hashing 168 => 0
Hashing 169 => 209
Hashing 170 => 51
Hashing 171 => 202
Hashing 172 => 2
Hashing 173 => 51
Hashing 174 => 53
Hashing 175 => 55
Hashing 176 => 58
Hashing 177 => 0
Hashing 178 => 209
Hashing 179 => 216
Hashing 180 => 202
Hashing 181 => 2
Hashing 182 => 51
Hashing 183 => 53
Hashing 184 => 55
Hashing 185 => 58
Hashing 186 => 0
Hashing 187 => 209
Hashing 188 => 216
Hashing 189 => 219
Hashing 190 => 2
Hashing 191 => 51
Hashing 192 => 53
Hashing 193 => 55
Hashing 194 => 58
Hashing 195 => 0
Hashing 196 => 209
Hashing 197 => 216
Hashing 198 => 219
Hashing 199 => 220
Hashing 200 => 248
Hashing 201 => 49
Hashing 202 => 44
Hashing 203 => 255
Hashing 204 => 198
Hashing 205 => 43
Hashing 206 => 51
Hashing 207 => 202
Hashing 208 => 2
Hashing 209 => 51
Hashing 210 => 49
Hashing 211 => 44
Hashing 212 => 255
Hashing 213 => 198
Hashing 214 => 43
Hashing 215 => 51
Hashing 216 => 202
Hashing 217 => 2
Hashing 218 => 51
Hashing 219 => 53
Hashing 220 => 44
Hashing 221 => 255
Hashing 222 => 198
Hashing 223 => 43
Hashing 224 => 51
Hashing 225 => 202
Hashing 226 => 2
Hashing 227 => 51
Hashing 228 => 53
Hashing 229 => 55
Hashing 230 => 255
Hashing 231 => 198
Hashing 232 => 43
Hashing 233 => 51
Hashing 234 => 202
Hashing 235 => 2
Hashing 236 => 51
Hashing 237 => 53
Hashing 238 => 55
Hashing 239 => 58
Hashing 240 => 198
Hashing 241 => 43
Hashing 242 => 51
Hashing 243 => 202
Hashing 244 => 2
Hashing 245 => 51
Hashing 246 => 53
Hashing 247 => 55
Hashing 248 => 58
Hashing 249 => 0
Hashing 250 => 43
Hashing 251 => 51
Hashing 252 => 202
Hashing 253 => 2
Hashing 254 => 51
Hashing 255 => 53

Vẫn còn một mẫu thô ở đó, nhưng lưu ý rằng nó không giống mẫu nào hơn chức năng cơ bản của chúng ta (vốn đã khá yếu).

Tuy nhiên, lưu ý rằng 03 trở thành va chạm, mặc dù họ không phải là trong thời gian duy nhất. Đó là một ứng dụng của những gì tôi đã nói trước đây (rằng khả năng chống va chạm giữ nguyên cho tập hợp tất cả các đầu vào, nhưng các tuyến va chạm cụ thể có thể mở ra do sai sót trong thuật toán cơ bản).

Phần TL / DR

Bằng cách cung cấp lại đầu vào vào mỗi lần lặp, chúng tôi thực sự phá vỡ mọi va chạm có thể xảy ra trong lần lặp trước.

Do đó, md5($input . md5($input));nên ( về lý thuyết ít nhất) mạnh như md5($input).

Điều này có quan trọng không?

Đúng. Đây là một trong những lý do khiến PBKDF2 thay thế PBKDF1 trong RFC 2898 . Hãy xem xét các vòng lặp bên trong của hai ::

PBKDF1:

T_1 = Hash (P || S) ,
T_2 = Hash (T_1) ,
...
T_c = Hash (T_{c-1}) 

Trong trường hợp clà số lần lặp, Pđược Password và Slà muối

PBKDF2:

U_1 = PRF (P, S || INT (i)) ,
U_2 = PRF (P, U_1) ,
...
U_c = PRF (P, U_{c-1})

Trong đó PRF thực sự chỉ là một HMAC. Nhưng với mục đích của chúng tôi ở đây, chúng ta hãy nói rằng PRF(P, S) = Hash(P || S)(nghĩa là PRF của 2 đầu vào là giống nhau, đại khái, là hàm băm với hai đầu nối với nhau). Nó rất nhiều không phải , nhưng cho mục đích của chúng tôi là nó.

Vì vậy, PBKDF2 duy trì khả năng chống va chạm của Hashchức năng cơ bản , trong đó PBKDF1 không có.

Liên kết tất cả lại với nhau:

Chúng tôi biết các cách an toàn để lặp lại một hàm băm. Trong thực tế:

$hash = $input;
$i = 10000;
do {
   $hash = hash($input . $hash);
} while ($i-- > 0);

Thường là an toàn.

Bây giờ, để đi vào lý do tại sao chúng ta muốn băm nó, hãy phân tích chuyển động entropy.

Một hàm băm lấy trong tập vô hạn: S(∞)và tạo ra một tập nhỏ hơn, có kích thước phù hợp S(n). Phiên bản kế tiếp (giả sử đầu vào được chuyển trở lại trong) bản đồ S(∞)lên S(n)một lần nữa:

S(∞) -> S(n)
S(∞) -> S(n)
S(∞) -> S(n)
S(∞) -> S(n)
S(∞) -> S(n)
S(∞) -> S(n)

Lưu ý rằng đầu ra cuối cùng có chính xác cùng một lượng entropy như đầu tiên . Lặp đi lặp lại sẽ không "làm cho nó bị che khuất hơn". Các entropy là giống hệt nhau. Không có nguồn phép thuật không thể đoán trước (đó là Hàm giả ngẫu nhiên, không phải là Hàm ngẫu nhiên).

Tuy nhiên, có một lợi ích để lặp đi lặp lại. Nó làm cho quá trình băm chậm một cách giả tạo. Và đó là lý do tại sao lặp đi lặp lại có thể là một ý tưởng tốt. Trên thực tế, đó là nguyên tắc cơ bản của hầu hết các thuật toán băm mật khẩu hiện đại (thực tế là việc làm quá nhiều thứ khiến nó chậm hơn).

Chậm là tốt, bởi vì nó chống lại mối đe dọa an ninh chính: cưỡng bức vũ phu. Chúng tôi thực hiện thuật toán băm chậm hơn, những kẻ tấn công khó hơn phải làm việc để tấn công băm mật khẩu bị đánh cắp từ chúng tôi. Và đó là một điều tốt !!!


1
$output = md5($output); // < 2^128 possibilities--- nó thực sự nghiêm ngặt <, hay <=?
zerkms

2
@zerkms: Nó hoàn toàn không phải là bất cứ điều gì. Chúng ta cần biết một số chi tiết rất cụ thể của hàm bên dưới ( md5()trong trường hợp này) để thực sự biết chắc chắn. Nhưng nói chung nó sẽ <và không <=... Hãy nhớ rằng, chúng ta đang nói về kích thước của bộ $outputcho tất cả có thể $inputs. Vì vậy, nếu chúng ta có thậm chí một vụ va chạm nó sẽ được <, do đó <là generalizer tốt hơn.
ircmaxell

2
@ TomášFejfar Tôi nghĩ rằng câu hỏi không phải là về sự va chạm nói chung, mà là sự va chạm trong bộ đầu ra nghiêm ngặt (2 ^ 128 đầu ra, mỗi đầu rộng chính xác 128 bit). Đó có thể là Tiêm, nhưng theo như tôi biết thì không thể có bằng chứng chung chung (chỉ có bằng chứng bằng chứng về sự va chạm cho một thuật toán cụ thể). Hãy xem xét hàm băm chỉ đơn giản trả về đầu vào nếu nó là 128 bit (và băm khác). Nói chung, nó sẽ là siêu thực, nhưng khi được cho đầu ra, nó sẽ luôn bị tiêm nhiễm ... Đó là điểm gây tranh cãi ...
ircmaxell


6
Đối với những người muốn tiết kiệm thời gian bằng cách không phải kiểm tra xem cuộc thảo luận giữa Dan & ircmaxell đã kết thúc tốt đẹp như thế nào : Dan đồng ý với ircmaxell.
jeromej

51

Có, băm lại làm giảm không gian tìm kiếm, nhưng không, nó không thành vấn đề - việc giảm hiệu quả là không đáng kể.

Băm lại làm tăng thời gian cần thiết cho vũ phu, nhưng làm như vậy chỉ hai lần cũng là tối ưu.

Những gì bạn thực sự muốn là băm mật khẩu với PBKDF2 - một phương pháp đã được chứng minh là sử dụng hàm băm an toàn với muối và lặp. Kiểm tra phản ứng SO này .

EDIT : Tôi gần như đã quên - KHÔNG SỬ DỤNG MD5 !!!! Sử dụng hàm băm mật mã hiện đại như họ SHA-2 (SHA-256, SHA-384 và SHA-512).


2
@DFTR - đồng ý. bcrypt hoặc scrypt là những lựa chọn tốt hơn.
orip

Đừng sử dụng những thứ đó (họ SHA-2) mà giờ đây chúng cũng có thể bị bẻ khóa dễ dàng, hãy kiểm tra crackstation.net để biết bằng chứng. Nếu bất cứ điều gì sử dụng mã hóa hoặc PBKDF2 là các hàm băm mật mã dựa trên hàm phái sinh chính (KDF).
theodore

3
Trong năm 2016, Argon2 và tiền điện tử là những thứ mà mọi người nên cố gắng sử dụng
Silkfire

10

Có - nó làm giảm số lượng các chuỗi có thể phù hợp với chuỗi.

Như bạn đã đề cập, băm muối là tốt hơn nhiều.

Một bài viết ở đây: http://websecurity.ro/blog/2007/11/02/md5md5-vs-md5/ , thử một bằng chứng tại sao nó tương đương, nhưng tôi không chắc về logic. Một phần họ cho rằng không có phần mềm có sẵn để phân tích md5 (md5 (văn bản)), nhưng rõ ràng việc sản xuất các bảng cầu vồng khá đơn giản.

Tôi vẫn kiên định với câu trả lời của mình rằng có số lượng băm loại md5 (md5 (văn bản)) nhỏ hơn so với băm md5 (văn bản), làm tăng khả năng va chạm (ngay cả khi vẫn có xác suất không thể xảy ra) và giảm không gian tìm kiếm.


5

Hầu hết các câu trả lời là của những người không có nền tảng về mật mã hoặc bảo mật. Và họ đã sai. Sử dụng một muối, nếu có thể duy nhất cho mỗi hồ sơ. MD5 / SHA / etc quá nhanh, ngược lại với những gì bạn muốn. PBKDF2 và bcrypt chậm hơn (wich là tốt) nhưng có thể bị đánh bại với ASIC / FPGA / GPU (ngày nay rất đáng kinh ngạc). Vì vậy, một thuật toán cứng bộ nhớ là cần thiết: nhập mã hóa .

Đây là một lời giải thích của giáo dân về muối và tốc độ (nhưng không phải về các thuật toán cứng bộ nhớ).


4

Tôi chỉ nhìn vào điều này từ một quan điểm thực tế. Tin tặc sau là gì? Tại sao, sự kết hợp của các ký tự mà khi đưa vào hàm băm sẽ tạo ra hàm băm mong muốn.

Bạn chỉ lưu băm cuối cùng, do đó, tin tặc chỉ phải bẻ khóa một băm. Giả sử bạn có cùng tỷ lệ vấp ngã trên hàm băm mong muốn với mỗi bước bruteforce, số lần băm là không liên quan. Bạn có thể thực hiện một triệu lần lặp băm và nó sẽ không tăng hoặc giảm bảo mật một chút nào, vì ở cuối dòng vẫn chỉ có một hàm băm để phá vỡ và tỷ lệ phá vỡ nó cũng giống như bất kỳ hàm băm nào.

Có thể các áp phích trước nghĩ rằng đầu vào có liên quan; nó không thể. Miễn là bất cứ điều gì bạn đưa vào hàm băm sẽ tạo ra hàm băm mong muốn, nó sẽ giúp bạn vượt qua, nhập đúng hoặc nhập sai.

Bây giờ, bàn cầu vồng là một câu chuyện khác. Vì một bảng cầu vồng chỉ mang mật khẩu thô, băm hai lần có thể là một biện pháp bảo mật tốt, vì một bảng cầu vồng chứa mỗi hàm băm của mỗi hàm băm sẽ quá lớn.

Tất nhiên, tôi chỉ xem xét ví dụ mà OP đưa ra, trong đó nó chỉ là mật khẩu văn bản đơn giản được băm. Nếu bạn bao gồm tên người dùng hoặc muối trong hàm băm, thì đó là một câu chuyện khác; băm hai lần là hoàn toàn không cần thiết, vì bảng cầu vồng sẽ quá lớn để có thể thực tế và chứa hàm băm đúng.

Dù sao, không phải là một chuyên gia bảo mật ở đây, nhưng đó chỉ là những gì tôi đã hình dung từ kinh nghiệm của mình.


Câu trả lời này là sai ở mọi khía cạnh. 1. Biết băm tiếp theo cuối cùng không cung cấp giá trị cho kẻ tấn công, bởi vì đầu vào của hàm băm lặp là mật khẩu , sau đó được băm nhiều lần (không phải một lần). 2. Không gian đầu vào là mật khẩu, không gian đầu ra là mật khẩu băm. Không gian của mật khẩu thông thường nhỏ hơn nhiều so với không gian đầu ra. 3. Bảng cầu vồng cho mật khẩu băm kép không được đánh dấu không lớn hơn bảng cầu vồng cho mật khẩu băm đơn không được đánh dấu. 4. Tên người dùng là entropy thấp, một muối tốt là ngẫu nhiên. 5. Salting không thay thế lặp đi lặp lại. Bạn cần cả hai.
Clement Cherlin

3

Từ những gì tôi đã đọc, thực sự có thể được khuyến nghị băm lại mật khẩu hàng trăm hoặc hàng nghìn lần.

Ý tưởng là nếu bạn có thể khiến bạn mất nhiều thời gian hơn để mã hóa mật khẩu, thì kẻ tấn công sẽ phải chạy qua nhiều lần đoán để phá mật khẩu. Đó dường như là lợi thế để băm lại - không phải là nó an toàn hơn về mặt mật mã, mà đơn giản là mất nhiều thời gian hơn để tạo ra một cuộc tấn công từ điển.

Tất nhiên máy tính trở nên nhanh hơn mọi lúc, vì vậy lợi thế này giảm dần theo thời gian (hoặc yêu cầu bạn tăng số lần lặp).


Tôi cũng đã đề cập đến điều này trong một bình luận khác, nhưng en.wikipedia.org/wiki/Key_stretching

2

Cá nhân tôi sẽ không bận tâm với nhiều hàm băm, nhưng tôi chắc chắn cũng sẽ băm tên người dùng (hoặc một trường ID người dùng khác) cũng như mật khẩu để hai người dùng có cùng mật khẩu sẽ không có cùng một hàm băm. Ngoài ra, tôi có thể ném một số chuỗi không đổi khác vào chuỗi đầu vào quá tốt.

$hashed_password = md5( "xxx" + "|" + user_name + "|" + plaintext_password);

13
Trên thực tế, nó phải là một chuỗi được tạo ngẫu nhiên cho mỗi người dùng, không phải là hằng số.
Bill Lizard

7
Một bí mật liên tục hoạt động (và dễ làm việc hơn), nếu bạn nhập tên người dùng như đề xuất. Điều đó về cơ bản tạo ra một khóa cụ thể người dùng ngẫu nhiên.
SquareCog

4
Một muối bí mật liên tục là an ninh thông qua tối nghĩa. Nếu "bí mật" nhận ra rằng bạn đang sử dụng "xxx" + tên người dùng + mật khẩu, thì kẻ tấn công thậm chí không cần dữ liệu từ các bảng của bạn để khởi động một cuộc tấn công chống lại nó.
Bill Lizard

8
Tôi không nghĩ rằng đó là bảo mật thông qua tối nghĩa. Lý do sử dụng muối là bạn không thể tính toán một bảng cầu vồng chống lại nhiều băm md5 cùng một lúc. Xây dựng một mật khẩu cho "xxx" + (cùng muối) xảy ra một lần. Xây dựng bảng cho "xxx" + tên người dùng + mật khẩu tồi tệ hơn so với cưỡng bức.
FryGuy

5
@Bill the Lizard: "cuộc tấn công được giảm xuống để xây dựng một từ điển để tấn công một tên người dùng cụ thể" chỉ là một cuộc tấn công vũ phu (thực sự thậm chí còn tồi tệ hơn, vì ngoài việc tính toán tất cả các băm bạn phải lưu trữ chúng), vì vậy muối hoạt động hoàn hảo trong trường hợp này.
Kornel

2

Giả sử bạn sử dụng thuật toán băm: tính toán rot13, lấy 10 ký tự đầu tiên. Nếu bạn làm điều đó hai lần (hoặc thậm chí 2000 lần), có thể thực hiện một chức năng nhanh hơn, nhưng sẽ cho kết quả tương tự (cụ thể là chỉ mất 10 ký tự đầu tiên).

Tương tự như vậy, có thể tạo ra một hàm nhanh hơn cung cấp cùng một đầu ra như một hàm băm lặp đi lặp lại. Vì vậy, sự lựa chọn của bạn về chức năng băm là rất quan trọng: như với ví dụ rot13, không có nghĩa là băm lặp đi lặp lại sẽ cải thiện bảo mật. Nếu không có nghiên cứu nào nói rằng thuật toán được thiết kế để sử dụng đệ quy, thì sẽ an toàn hơn khi cho rằng nó sẽ không cung cấp cho bạn sự bảo vệ bổ sung.

Điều đó nói rằng: Đối với tất cả các hàm băm đơn giản nhất, rất có thể các chuyên gia mật mã sẽ tính toán các hàm nhanh hơn, vì vậy nếu bạn bảo vệ chống lại những kẻ tấn công không có quyền truy cập vào các chuyên gia mã hóa thì có thể an toàn hơn khi sử dụng hàm băm lặp đi lặp lại .


1

Nói chung, nó không cung cấp bảo mật bổ sung để nhân đôi mã hóa hoặc nhân đôi thứ gì đó. Nếu bạn có thể phá vỡ hàm băm một lần, bạn có thể phá vỡ nó một lần nữa. Nó thường không làm tổn hại đến an ninh để làm điều này, mặc dù.

Trong ví dụ của bạn về việc sử dụng MD5, như bạn có thể biết có một số vấn đề va chạm. "Double Hashing" không thực sự giúp bảo vệ chống lại điều này, vì các va chạm tương tự vẫn sẽ dẫn đến cùng một hàm băm đầu tiên, sau đó bạn có thể MD5 một lần nữa để có được hàm băm thứ hai.

Điều này không bảo vệ chống lại các cuộc tấn công từ điển, như các "cơ sở dữ liệu MD5 ngược", nhưng muối cũng vậy.

Trên một tiếp tuyến, Mã hóa kép một cái gì đó không cung cấp bất kỳ bảo mật bổ sung nào vì tất cả những gì nó làm là một khóa khác nhau, đó là sự kết hợp của hai khóa thực sự được sử dụng. Vì vậy, nỗ lực tìm "chìa khóa" không được nhân đôi vì hai khóa không thực sự cần tìm. Điều này không đúng với băm, vì kết quả của hàm băm thường không cùng độ dài với đầu vào ban đầu.


1
Tất cả đều đúng, nhưng tôi chỉ muốn lưu ý rằng tác động của thỏa hiệp kháng va chạm mạnh đối với MD5 bị thổi phồng lên một chút - hầu hết các kịch bản sử dụng hàm băm mật mã không dựa vào khả năng chống va chạm mạnh, chỉ là khả năng chống va chạm yếu. Họ không bị ảnh hưởng bởi lỗ hổng này.
SquareCog

1

Băm kép chỉ có ý nghĩa với tôi nếu tôi băm mật khẩu trên máy khách, rồi lưu hàm băm (với muối khác nhau) của hàm băm đó trên máy chủ.

Theo cách đó, ngay cả khi ai đó xâm nhập vào máy chủ (do đó bỏ qua SSL an toàn cung cấp), anh ta vẫn không thể lấy được mật khẩu rõ ràng.

Có, anh ta sẽ có dữ liệu cần thiết để vi phạm vào hệ thống, nhưng anh ta sẽ không thể sử dụng dữ liệu đó để thỏa hiệp các tài khoản bên ngoài mà người dùng có. Và mọi người được biết là sử dụng cùng một mật khẩu cho hầu hết mọi thứ.

Cách duy nhất anh ta có thể nhận được mật khẩu rõ ràng là cài đặt keygen trên máy khách - và đó không còn là vấn đề của bạn nữa.

Vì vậy, trong ngắn hạn:

  1. Băm đầu tiên trên máy khách sẽ bảo vệ người dùng của bạn trong trường hợp 'vi phạm máy chủ'.
  2. Băm thứ hai trên máy chủ phục vụ để bảo vệ hệ thống của bạn nếu ai đó nắm giữ bản sao lưu cơ sở dữ liệu của bạn, vì vậy anh ta không thể sử dụng các mật khẩu đó để kết nối với các dịch vụ của bạn.

1
+1 Tôi đã chờ đợi để xem một câu trả lời như thế này, vì tôi đã nghĩ về cùng một kịch bản khi bạn không muốn lưu trữ mật khẩu văn bản đơn giản trên máy khách, nhưng cũng không gửi mật khẩu được mã hóa cuối cùng qua dây để thực hiện so sánh đơn giản với DB.
Đánh dấu

1
Không giúp cho các ứng dụng web. nếu máy chủ của bạn bị xâm phạm, mã máy chủ của bạn đang gửi cho máy khách cũng bị xâm phạm. Kẻ tấn công sẽ vô hiệu hóa hàm băm phía máy khách của bạn và nắm bắt mật khẩu thô.
Clement Cherlin

0

Mối quan tâm về việc giảm không gian tìm kiếm là chính xác về mặt toán học, mặc dù không gian tìm kiếm vẫn đủ lớn cho tất cả các mục đích thực tế (giả sử bạn sử dụng muối), ở mức 2 ^ 128. Tuy nhiên, vì chúng ta đang nói về mật khẩu, số chuỗi 16 ký tự có thể có (chữ số, chữ hoa, một vài ký hiệu được ném vào) là khoảng 2 ^ 98, theo tính toán ngược của tôi. Vì vậy, việc giảm nhận thức trong không gian tìm kiếm là không thực sự phù hợp.

Bên cạnh đó, thực sự không có sự khác biệt, nói theo mật mã.

Mặc dù có một loại tiền điện tử nguyên thủy được gọi là "chuỗi băm" - một kỹ thuật cho phép bạn thực hiện một số thủ thuật thú vị, như tiết lộ khóa chữ ký sau khi được sử dụng, mà không làm mất tính toàn vẹn của hệ thống - đồng bộ hóa thời gian tối thiểu, điều này cho phép bạn dọn dẹp sạch sẽ vấn đề phân phối khóa ban đầu. Về cơ bản, bạn tính toán trước một tập băm lớn băm - h (h (h (h .... (h (k)) ...))), sử dụng giá trị thứ n để ký, sau một khoảng thời gian đã đặt, bạn gửi ra khóa và ký tên bằng phím (n-1). Người nhận hiện có thể xác minh rằng bạn đã gửi tất cả các tin nhắn trước đó và không ai có thể giả mạo chữ ký của bạn vì khoảng thời gian mà nó hợp lệ đã qua.

Băm lại hàng trăm ngàn lần như Bill gợi ý chỉ là sự lãng phí cpu của bạn .. hãy sử dụng khóa dài hơn nếu bạn lo ngại về việc mọi người phá vỡ 128 bit.


1
Băm lại chính xác là làm chậm băm. Đây là một tính năng bảo mật quan trọng trong mật mã dựa trên mật khẩu. Xem các liên kết cho PCKS5 và PBKDF2.
orip

0

Như một số câu trả lời trong bài viết này cho thấy, có một số trường hợp nó có thể cải thiện an ninh và những trường hợp khác chắc chắn làm tổn thương nó. Có một giải pháp tốt hơn chắc chắn sẽ cải thiện an ninh. Thay vì nhân đôi số lần bạn tính băm, hãy nhân đôi kích thước muối của bạn hoặc nhân đôi số bit được sử dụng trong hàm băm hoặc làm cả hai! Thay vì SHA-245, hãy nhảy lên SHA-512.


Điều này không trả lời câu hỏi.
Lập hóa đơn cho thằn lằn

1
Băm kép không đáng để bỏ công sức, nhưng nhân đôi kích thước băm của bạn là. Tôi nghĩ rằng đây là một điểm có giá trị hơn.
Stefan Rusek

-1

Băm kép là xấu xí vì nhiều khả năng kẻ tấn công đã xây dựng một bảng để đưa ra hầu hết các băm. Tốt hơn là muối muối băm của bạn, và trộn băm với nhau. Ngoài ra còn có các lược đồ mới để "ký" băm (về cơ bản là muối), nhưng theo cách an toàn hơn.


-1

Đúng.

Tuyệt đối không sử dụng nhiều lần lặp của hàm băm thông thường, như thế nào md5(md5(md5(password))). Tại tốt nhất bạn sẽ nhận được một sự gia tăng cận biên trong bảo mật (một chương trình như cung cấp này hầu như không có bảo vệ chống lại một cuộc tấn công GPU, chỉ cần đường ống nó.) Tại tồi tệ nhất, bạn đang làm giảm không gian băm của bạn (và do đó an ninh) với mỗi lần lặp bạn thêm . Trong bảo mật, thật khôn ngoan khi cho rằng điều tồi tệ nhất.

Đừng sử dụng một mật khẩu đã đó là được thiết kế bởi một mật mã có thẩm quyền là một hash mật khẩu có hiệu quả, và đề kháng với cả brute-force và các cuộc tấn công thời gian. Chúng bao gồm bcrypt, tiền điện tử và trong một số tình huống PBKDF2. Hàm băm dựa trên glibc SHA-256 cũng được chấp nhận.


-1

Tôi sẽ đi ra ngoài trên chi và nói rằng nó an toàn hơn trong một số trường hợp nhất định ... mặc dù vậy, đừng hạ thấp tôi!

Từ quan điểm toán học / mật mã, nó kém an toàn hơn, vì những lý do mà tôi chắc chắn người khác sẽ cho bạn một lời giải thích rõ ràng hơn những gì tôi có thể.

Tuy nhiên , tồn tại cơ sở dữ liệu lớn băm MD5, có nhiều khả năng chứa văn bản "mật khẩu" hơn MD5 của nó. Vì vậy, bằng cách băm kép, bạn sẽ làm giảm hiệu quả của các cơ sở dữ liệu đó.

Tất nhiên, nếu bạn sử dụng một loại muối thì lợi thế này (bất lợi?) Sẽ biến mất.

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.