ให้กับผู้ที่บอกว่ามันเป็นที่เชื่อถือได้ของพวกเขาจะถูกต้องโดยทั่วไป การแฮ็ช "คู่" (หรือการขยายตรรกะของการทำซ้ำฟังก์ชันแฮช) จะปลอดภัยอย่างแน่นอนหากทำถูกต้องสำหรับข้อกังวลเฉพาะ
สำหรับผู้ที่พูดว่าไม่ปลอดภัยพวกเขาจะถูกต้องในกรณีนี้ รหัสที่ถูกโพสต์ในคำถามคือไม่ปลอดภัย มาพูดคุยเกี่ยวกับสาเหตุ:
$hashed_password1 = md5( md5( plaintext_password ) );
$hashed_password2 = md5( plaintext_password );
มีคุณสมบัติพื้นฐานสองอย่างของฟังก์ชันแฮชที่เรากังวล:
การต่อต้านภาพก่อน - ได้รับกัญชา$h
มันควรจะยากที่จะหาข้อความ$m
เช่นนั้น$h === hash($m)
การต้านทานภาพที่สองล่วงหน้า - รับข้อความ$m1
ควรหาข้อความ$m2
อื่นที่ยากเช่นนั้นhash($m1) === hash($m2)
ความต้านทานการชน - มันควรจะยากที่จะหาคู่ของข้อความ($m1, $m2)
เช่นนั้นhash($m1) === hash($m2)
(โปรดทราบว่าสิ่งนี้คล้ายกับการต่อต้าน Second-Pre-Image แต่ที่แตกต่างกันตรงนี้ผู้โจมตีมีอำนาจควบคุมข้อความทั้งสอง) ...
สำหรับการจัดเก็บรหัสผ่านสิ่งที่เราสนใจคือการต้านทานภาพล่วงหน้า อีกสองคนจะเป็นที่สงสัยเนื่องจาก$m1
เป็นรหัสผ่านของผู้ใช้ที่เราพยายามรักษาความปลอดภัย ดังนั้นหากผู้โจมตีมีอยู่แล้วแฮชจะไม่ป้องกัน ...
การปฏิเสธความรับผิด
ทุกอย่างที่เป็นไปตามจะขึ้นอยู่กับสมมติฐานที่ว่าทุกสิ่งที่เราดูแลเกี่ยวกับPre-ภาพต้านทาน คุณสมบัติพื้นฐานอีกสองอย่างของฟังก์ชั่นแฮชอาจไม่ (และโดยทั่วไปไม่ได้) ค้างไว้ในลักษณะเดียวกัน ดังนั้นข้อสรุปในโพสต์นี้จะใช้ได้เฉพาะเมื่อใช้ฟังก์ชันแฮชสำหรับการจัดเก็บรหัสผ่าน พวกเขาไม่สามารถใช้งานได้โดยทั่วไป ...
มาเริ่มกันเลย
เพื่อประโยชน์ของการสนทนานี้ลองประดิษฐ์ฟังก์ชันแฮชของเราเอง:
function ourHash($input) {
$result = 0;
for ($i = 0; $i < strlen($input); $i++) {
$result += ord($input[$i]);
}
return (string) ($result % 256);
}
ตอนนี้มันควรจะชัดเจนว่าฟังก์ชันแฮชนี้ทำอะไร ซึ่งจะรวมค่า ASCII ของอักขระแต่ละตัวของอินพุตเข้าด้วยกันแล้วนำโมดูโลของผลลัพธ์นั้นมาพร้อมกับ 256
ดังนั้นลองทดสอบดู:
var_dump(
ourHash('abc'), // string(2) "38"
ourHash('def'), // string(2) "47"
ourHash('hij'), // string(2) "59"
ourHash('klm') // string(2) "68"
);
ตอนนี้เรามาดูกันว่าจะเกิดอะไรขึ้นถ้าเราเรียกใช้ฟังก์ชันรอบสองสามครั้ง:
$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";
}
ผลลัพธ์นั้น:
Hashing abc => 152
Hashing def => 152
Hashing hij => 155
Hashing klm => 155
อืมว้าว เราได้สร้างการชนกัน !!! ลองดูสาเหตุ:
นี่คือผลลัพธ์ของการแฮชสตริงของเอาต์พุตแฮชที่เป็นไปได้แต่ละรายการ:
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
สังเกตุแนวโน้มไปสู่ตัวเลขที่สูงขึ้น นั่นกลายเป็นความตายของเรา ใช้แฮช 4 ครั้ง ($ hash = ourHash ($ hash) `, สำหรับแต่ละองค์ประกอบ) จบลงด้วยการให้เรา:
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
เราได้คอตัวเองลงไป 8 ค่า ... ที่ไม่ดี ... ฟังก์ชั่นเดิมของเราแมปบนS(∞)
S(256)
นั่นคือเราได้สร้างฟังก์ชั่น surjectiveทำแผนที่ไป$input
$output
เนื่องจากเรามีฟังก์ชั่น Surjective เราจึงไม่รับประกันว่าการแมปสำหรับชุดย่อยของอินพุตจะไม่มีการชน (ในความเป็นจริงในทางปฏิบัติพวกเขาจะ)
นั่นคือสิ่งที่เกิดขึ้นที่นี่! ฟังก์ชั่นของเราไม่ดี แต่นั่นไม่ใช่เหตุผลว่าทำไมสิ่งนี้ถึงได้ผล
MD5
สิ่งเดียวกันที่เกิดขึ้นกับ มันแผนที่บนS(∞)
S(2^128)
เนื่องจากไม่มีการรับประกันว่าการรันMD5(S(output))
จะเป็นแบบInjectiveซึ่งหมายความว่าจะไม่เกิดการชน
มาตรา TL / DR
ดังนั้นเนื่องจากการป้อนเอาต์พุตกลับไปที่md5
โดยตรงสามารถสร้างการชนได้ทุกการวนซ้ำจะเพิ่มโอกาสในการชน นี่เป็นการเพิ่มเชิงเส้นซึ่งหมายความว่าในขณะที่ชุดผลลัพธ์ของ2^128
ลดลง แต่ก็ไม่ได้ลดลงเร็วพอที่จะเป็นข้อบกพร่องที่สำคัญ
ดังนั้น,
$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
ยิ่งคุณทำซ้ำมากเท่าไหร่
การแก้ไข
โชคดีสำหรับเรามีวิธีแก้ไขปัญหานี้เล็กน้อย : ป้อนข้อมูลบางอย่างลงในการทำซ้ำเพิ่มเติม:
$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
โปรดทราบว่าการทำซ้ำอีกไม่ได้ 2 ^ 128 $input
สำหรับแต่ละบุคคลสำหรับค่า หมายความว่าเราอาจจะสามารถที่จะสร้าง$input
ค่านิยมที่ยังคงชนกันลงเส้น (และด้วยเหตุนี้จะตัดสินหรือสะท้อนที่น้อยกว่า2^128
ผลเป็นไปได้) แต่กรณีทั่วไปสำหรับ$input
ยังคงแข็งแกร่งเหมือนเดิมในรอบเดียว
เดี๋ยวก่อนใช่มั้ย ลองทดสอบด้วยourHash()
ฟังก์ชันของเรากัน สลับเป็น$hash = ourHash($input . $hash);
100 ซ้ำ:
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
ยังคงมีรูปแบบหยาบมี แต่ทราบว่ามันไม่มากขึ้นของรูปแบบมากกว่าฟังก์ชั่นพื้นฐานของเรา (ซึ่งมีอยู่แล้วค่อนข้างอ่อนแอ)
โปรดสังเกตว่า0
และ3
กลายเป็นความขัดแย้งแม้ว่าพวกเขาจะไม่ได้อยู่ในการวิ่งครั้งเดียว นั่นเป็นแอปพลิเคชันที่ฉันพูดไว้ก่อนหน้านี้ (ความต้านทานการชนยังคงเหมือนเดิมสำหรับชุดของอินพุตทั้งหมด แต่เส้นทางการชนที่เฉพาะเจาะจงอาจเปิดขึ้นเนื่องจากข้อบกพร่องในอัลกอริทึมพื้นฐาน)
มาตรา TL / DR
ด้วยการป้อนข้อมูลกลับเข้าไปในการวนซ้ำแต่ละครั้งเราจะทำลายการชนที่อาจเกิดขึ้นในการทำซ้ำก่อนหน้าอย่างมีประสิทธิภาพ
ดังนั้นmd5($input . md5($input));
ควรจะเป็น ( ในทางทฤษฎีอย่างน้อย) md5($input)
เป็นที่แข็งแกร่งเป็น
สิ่งนี้สำคัญหรือไม่
ใช่. นี้เป็นหนึ่งในเหตุผลที่ PBKDF2 แทนที่ PBKDF1 ในRFC 2898 ลองพิจารณาลูปด้านในของทั้งสอง ::
PBKDF1:
T_1 = Hash (P || S) ,
T_2 = Hash (T_1) ,
...
T_c = Hash (T_{c-1})
c
การนับซ้ำอยู่ที่ไหนโดยP
ใช้รหัสผ่านและS
เป็นเกลือ
PBKDF2:
U_1 = PRF (P, S || INT (i)) ,
U_2 = PRF (P, U_1) ,
...
U_c = PRF (P, U_{c-1})
ที่ PRF เป็นเพียง HMAC แต่สำหรับจุดประสงค์ของเราที่นี่สมมุติว่าPRF(P, S) = Hash(P || S)
(นั่นคือ PRF ของ 2 อินพุตเหมือนกันพูดคร่าวๆเหมือนแฮชกับทั้งสองตัวต่อกัน) มันไม่มากแต่สำหรับวัตถุประสงค์ของเรามันเป็น
ดังนั้น PBKDF2 จึงรักษาความต้านทานการชนของHash
ฟังก์ชันพื้นฐานโดยที่ PBKDF1 ไม่ได้
การผูกทั้งหมดเข้าด้วยกัน:
เรารู้ถึงวิธีการแฮชอย่างปลอดภัย ในความเป็นจริง:
$hash = $input;
$i = 10000;
do {
$hash = hash($input . $hash);
} while ($i-- > 0);
โดยทั่วไปแล้วจะปลอดภัย
ทีนี้มาดูว่าทำไมเราถึงต้องการแฮชลองวิเคราะห์การเคลื่อนที่ของเอนโทรปี
กัญชาจะใช้เวลาอยู่ในชุดที่ไม่มีที่สิ้นสุด: และผลิตขนาดเล็กชุดกลางอย่างต่อเนื่องS(∞)
S(n)
การทำซ้ำครั้งถัดไป (สมมติว่าอินพุตถูกส่งกลับเข้าไป) แผนที่S(∞)
เข้าสู่S(n)
อีกครั้ง:
S(∞) -> S(n)
S(∞) -> S(n)
S(∞) -> S(n)
S(∞) -> S(n)
S(∞) -> S(n)
S(∞) -> S(n)
ขอให้สังเกตว่าผลลัพธ์สุดท้ายนั้นมีปริมาณเอนโทรปีเท่ากันทุกประการ การทำซ้ำจะไม่ทำให้ "ทำให้ชัดเจนยิ่งขึ้น" เอนโทรปีนั้นเหมือนกัน ไม่มีแหล่งเวทมนตร์ที่คาดเดาไม่ได้ (เป็น Pseudo-Random-Function ไม่ใช่ฟังก์ชั่น Random)
อย่างไรก็ตามมีประโยชน์ในการวนซ้ำ มันทำให้กระบวนการ hashing ช้าลงอย่างผิด ๆ และนั่นเป็นเหตุผลที่การทำซ้ำอาจเป็นความคิดที่ดี ในความเป็นจริงมันเป็นหลักการพื้นฐานของอัลกอริทึมการแฮ็กรหัสผ่านที่ทันสมัยที่สุด
ช้าเป็นสิ่งที่ดีเพราะมันเป็นการต่อสู้กับภัยคุกคามความปลอดภัยหลัก: บังคับให้เดรัจฉาน ยิ่งเราสร้างอัลกอริทึมการแฮชที่ช้ากว่าผู้โจมตีที่ยากกว่าต้องทำงานเพื่อโจมตีแฮ็กรหัสผ่านที่ถูกขโมยไป และนั่นเป็นสิ่งที่ดี !!!
Hash(password)
และHash(Hash(password))
ไม่มั่นคงเท่ากัน ทั้งขาดความคิดของความหมายของการรักษาความปลอดภัย นั่นคือผลลัพธ์จะแตกต่างจากการสุ่ม ยกตัวอย่างเช่นเป็นMD5("password")
5f4dcc3b5aa765d61d8327deb882cf99
ฉันรู้ว่ากัญชา MD5 ของpassword
และมันเป็นความแตกต่างจากการสุ่ม คุณควรใช้ HMAC แทน พิสูจน์แล้วว่าปลอดภัยและเป็น PRF