Autor |
Beitrag |
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Do 01.01.09 16:12
Ich beschäftige mich derzeit damit, verschiedene Hash-Funktionen für PHP zu portieren, da bei PHP nicht alle Algorithmen für Crypt implementiert sind (Speziell die Algorithmen, die mit SHA256 und SHA512 arbeiten).
Ich hab auch eine entsprechende Anleitung mit zugehörigem C-Source gefunden, jedoch erhalte ich, wenn ich nach dieser Anleitung vorgehe, falsche Ausgaben für die angegebenen Testvektoren.
Meine derzeitige Implementation sieht so aus:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237: 238: 239: 240: 241: 242: 243: 244: 245: 246: 247: 248: 249: 250: 251: 252: 253: 254: 255: 256: 257: 258: 259: 260: 261: 262: 263: 264: 265: 266: 267: 268: 269: 270: 271: 272: 273: 274: 275: 276: 277: 278: 279: 280: 281: 282: 283: 284: 285: 286: 287: 288: 289: 290: 291: 292: 293: 294: 295: 296: 297: 298: 299: 300: 301: 302: 303: 304: 305: 306: 307: 308: 309: 310: 311: 312: 313: 314: 315: 316: 317: 318: 319: 320: 321: 322: 323: 324: 325: 326: 327: 328: 329: 330: 331: 332: 333: 334: 335: 336: 337: 338: 339: 340: 341: 342: 343: 344: 345: 346: 347: 348: 349: 350: 351: 352: 353: 354: 355: 356: 357: 358: 359: 360: 361: 362: 363: 364: 365: 366: 367: 368: 369: 370: 371: 372: 373: 374: 375: 376: 377: 378: 379: 380: 381: 382: 383: 384: 385: 386: 387: 388: 389: 390: 391: 392: 393: 394: 395: 396: 397: 398: 399: 400: 401: 402: 403: 404: 405: 406: 407: 408: 409: 410: 411: 412: 413: 414: 415: 416: 417: 418: 419: 420: 421: 422: 423: 424: 425: 426: 427: 428: 429:
| <?
include "salt_api.php"; include "random_gendata.php";
if(!function_exists('sha512')) { function sha512($data,$raw=false){
return hash('sha512', $data, $raw); } }
function crypt_sha512($password, $salt = "") { $i_rounds = 5000; $i_salt = ''; $i_has_rounds = false;
if(!empty($salt)) { if(substr($salt, 0, 3) != '$6$') { return false; }
$salt = substr($salt, 3);
if(strtolower(substr($salt, 0, 7)) == 'rounds=') { $i = strpos($salt, '$'); if(false !== $i) { $s = substr($salt, 7, $i-7); $i_rounds = @(int)$s; $i_has_rounds = true; $salt = substr($salt, $i+1); } }
$i = strpos($salt, '$'); if(false !== $i) { $salt = substr($salt, 0, $i); }
$i_salt = $salt; } else { $i_salt = gen_salt(16); }
if($i_rounds < 1000) { $i_rounds = 1000; } else if($i_rounds > 999999999) { $i_rounds = 999999999; }
$i_salt = substr($i_salt, 0, 16);
unset($i); unset($rounds); unset($salt);
$d_A = hash_init('sha512'); hash_update($d_A, $password); hash_update($d_A, $i_salt);
$d_B = hash_init('sha512'); hash_update($d_B, $password); hash_update($d_B, $i_salt); hash_update($d_B, $password); $B = hash_final($d_B, true);
for($i = strlen($password); $i >= strlen($B); $i -= strlen($B)) { hash_update($d_A, $B); } hash_update($d_A, substr($B, 0, $i));
$i = strlen($password); while($i) { if($i&1) { hash_update($d_A, $B); } else { hash_update($d_A, $password); } $i >>= 1; }
$A = hash_final($d_A, true);
$d_DP = hash_init('sha512'); for($i = strlen($password); $i; $i--) { hash_update($d_DP, $password); } $DP = hash_final($d_DP, true);
$P = ''; for($i = strlen($password); $i >= strlen($DP); $i -= strlen($DP)) { $P .= $DP; } $P .= substr($DP, 0, $i);
$d_DS = hash_init('sha512'); for($i = 16+ord($A[0]); $i; $i--) { hash_update($d_DS, $i_salt); } $DS = hash_final($d_DS, true);
$S = ''; for($i = strlen($i_salt); $i >= strlen($DS); $i -= strlen($DS)) { $S .= $DS; } $S .= substr($DS, 0, $i);
for($round = 0; $round < $i_rounds; $round++) { $d_C = hash_init('sha512');
if($round&1) { hash_update($d_C, $P); } else { hash_update($d_C, $A); }
if($round%3) { hash_update($d_C, $S); } if($round%7) { hash_update($d_C, $P); } if($round&1) { hash_update($d_C, $A); } else { hash_update($d_C, $P); } $A = hash_final($d_C, true); }
$result = '$6$';
if($i_has_rounds || ($i_rounds != 5000)) { $result .= "rounds={$i_rounds}\$"; }
$result .= $i_salt . '$';
$pos = array( 42, 21, 0, 1, 43, 22, 23, 2, 44, 45, 24, 3, 4, 46, 25, 26, 5, 47, 48, 27, 6, 7, 49, 28, 29, 8, 50, 51, 30, 9, 10, 52, 31, 32, 11, 53, 54, 33, 12, 13, 55, 34, 35, 14, 56, 57, 36, 15, 16, 58, 37, 38, 17, 59, 60, 39, 18, 19, 61, 40, 41, 20, 62, 63);
$tmp = ''; for($i = 0; $i < 64; $i++) { $tmp .= $A[$pos[$i]]; }
$tmp = strtr(base64_encode($tmp), "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"); $tmp = str_replace('=', '', $tmp);
$result .= $tmp; return $result; }
$tv = array( array( '$6$saltstring', 'Hello world!', '$6$saltstring$svn8UoSVapNtMuq1ukKS4tPQd8iKwSMHWjl/O817G3uBnIFNjnQJuesI68u4OTLiBFdcbYEdFCoEOfaS35inz1' ), array( '$6$rounds=10000$saltstringsaltstring', 'Hello world!', '$6$rounds=10000$saltstringsaltst$OW1/O6BYHV6BcXZu8QVeXbDWra3Oeqh0sbHbbMCVNSnCM/UrjmM0Dp8vOuZeHBy/YTBmSK6H9qs/y3RnOaw5v.' ), array( '$6$rounds=5000$toolongsaltstring', 'This is just a test', '$6$rounds=5000$toolongsaltstrin$lQ8jolhgVRVhY4b5pZKaysCLi0QBxGoNeKQzQ3glMhwllF7oGDZxUhx1yxdYcz/e1JSbq3y6JMxxl8audkUEm0' ), array( '$6$rounds=1400$anotherlongsaltstring', 'a very much longer text to encrypt. This one even stretches over morethan one line.', '$6$rounds=1400$anotherlongsalts$POfYwTEok97VWcjxIiSOjiykti.o/pQs.wPvMxQ6Fm7I6IoYN3CmLs66x9t0oSwbtEW7o7UmJEiDwGqd8p4ur1' ), array( '$6$rounds=77777$short', 'we have a short salt string but not a short password', '$6$rounds=77777$short$WuQyW2YR.hBNpjjRhpYD/ifIw05xdfeEyQoMxIXbkvr0gge1a1x3yRULJ5CCaUeOxFmtlcGZelFl5CxtgfiAc0' ), array( '$6$rounds=123456$asaltof16chars..', 'a short string', '$6$rounds=123456$asaltof16chars..$BtCwjqMJGx5hrJhZywWvt0RLE8uZ4oPwcelCjmw2kSYu.Ec6ycULevoBK25fs2xXgMNrCzIMVcgEJAstJeonj1' ), array( '$6$rounds=10$roundstoolow', 'the minimum number is still observed', '$6$rounds=1000$roundstoolow$kUMsbe306n21p9R.FRkW3IGn.S9NPN0x50YhH1xhLsPuWGsUSklZt58jaTfF4ZEQpyUNGc0dqbpBYYBaHHrsX.' ) );
foreach($tv as $tvd) { echo crypt_sha512($tvd[1], $tvd[0]) . "\n" . $tvd[2] . "\n<br/>\n"; }
?> |
Die in der Datei eingebundenen Includes werden für den Selftest nicht benötigt; diese sind nur für die Generierung zufälliger Hashes zuständig, sofern kein solcher angegeben wurde.
Würde mich über zielführende Hinweise sehr freuen.
TIA,
BenBE.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
BenBE 
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Do 01.01.09 18:16
Ok, hab den Fehler in meiner Implementation gefunden: Ich hatte beim Encodieren der Result-Hashes einen Fehler drin. Base64_encode mit Übersetzugnstabelle funktionierte nicht wie erwartet; macht man's per Hand, geht's ...
Naja, hier die korrigierten Sources, falls jemand wirklich sichere Passwort-Hashes nutzen will:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236:
| <?
include "salt_api.php";
if(!function_exists('sha256')) { function sha256($data,$raw=false){ if(false === array_search('sha256', hash_algos(), true)) { return false; }
return hash('sha256', $data, $raw); } }
function crypt_sha256($password, $salt = "") { $i_rounds = 5000; $i_salt = ''; $i_has_rounds = false;
if(!empty($salt)) { if(substr($salt, 0,3) != '$5$') { return false; }
$salt = substr($salt, 3);
if(strtolower(substr($salt, 0, 7)) == 'rounds=') { $i = strpos($salt, '$'); if(false !== $i) { $s = substr($salt, 7, $i-7); $i_rounds = @(int)$s; $i_has_rounds = true; $salt = substr($salt, $i+1); } }
$i = strpos($salt, '$'); if(false !== $i) { $salt = substr($salt, 0, $i); }
$i_salt = $salt; } else { $i_salt = gen_salt(16); }
if($i_rounds < 1000) { $i_rounds = 1000; } else if($i_rounds > 999999999) { $i_rounds = 999999999; }
$i_salt = substr($i_salt, 0, 16);
unset($i); unset($rounds); unset($salt);
$d_A = hash_init('sha256'); hash_update($d_A, $password); hash_update($d_A, $i_salt);
$d_B = hash_init('sha256'); hash_update($d_B, $password); hash_update($d_B, $i_salt); hash_update($d_B, $password); $B = hash_final($d_B, true);
for($i = strlen($password); $i >= strlen($B); $i -= strlen($B)) { hash_update($d_A, $B); } hash_update($d_A, substr($B, 0, $i));
$i = strlen($password); while($i) { if($i&1) { hash_update($d_A, $B); } else { hash_update($d_A, $password); } $i >>= 1; }
$A = hash_final($d_A, true);
$d_DP = hash_init('sha256'); for($i = strlen($password); $i; $i--) { hash_update($d_DP, $password); } $DP = hash_final($d_DP, true);
$P = ''; for($i = strlen($password); $i >= strlen($DP); $i -= strlen($DP)) { $P .= $DP; } $P .= substr($DP, 0, $i);
$d_DS = hash_init('sha256'); for($i = 16+ord($A[0]); $i; $i--) { hash_update($d_DS, $i_salt); } $DS = hash_final($d_DS, true);
$S = ''; for($i = strlen($i_salt); $i >= strlen($DS); $i -= strlen($DS)) { $S .= $DS; } $S .= substr($DS, 0, $i);
for($round = 0; $round < $i_rounds; $round++) { $d_C = hash_init('sha256');
if($round&1) { hash_update($d_C, $P); } else { hash_update($d_C, $A); }
if($round%3) { hash_update($d_C, $S); } if($round%7) { hash_update($d_C, $P); } if($round&1) { hash_update($d_C, $A); } else { hash_update($d_C, $P); } $A = hash_final($d_C, true); }
$result = '$5$';
if($i_has_rounds || ($i_rounds != 5000)) { $result .= "rounds={$i_rounds}\$"; }
$result .= $i_salt . '$';
$tmp = crypt_sha256_encode($A);
$result .= $tmp; return $result; }
function crypt_sha256_encode($data){ $chars = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; $pos = array( 0 , 10 , 20, 21 , 1 , 11, 12 , 22 , 2, 3 , 13 , 23, 24 , 4 , 14, 15 , 25 , 5, 6 , 16 , 26, 27 , 7 , 17, 18 , 28 , 8, 9 , 19 , 29, -1 , 31 , 30 );
$result = '';
for($i = 0; $i < count($pos);) { $B2 = $pos[$i++]; $B1 = $pos[$i++]; $B0 = $pos[$i++]; $B2 = $B2 < 0 ? 0 : ord($data[$B2]); $B1 = $B1 < 0 ? 0 : ord($data[$B1]); $B0 = $B0 < 0 ? 0 : ord($data[$B0]);
$n = 4; if($pos[$i-3] < 0) { $n--; } if($pos[$i-2] < 0) { $n--; }
$w = ($B2 << 16) + ($B1 << 8) + $B0; while($n--) { $result .= $chars[$w & 0x3F]; $w >>= 6; } }
return $result; }
$tv = array( array( '$5$saltstring', 'Hello world!', '$5$saltstring$5B8vYYiY.CVt1RlTTf8KbXBH3hsxY/GNooZaBBGWEc5' ), array( '$5$rounds=10000$saltstringsaltstring', 'Hello world!', '$5$rounds=10000$saltstringsaltst$3xv.VbSHBb41AL9AvLeujZkZRBAwqFMz2.opqey6IcA' ), array( '$5$rounds=5000$toolongsaltstring', 'This is just a test', '$5$rounds=5000$toolongsaltstrin$Un/5jzAHMgOGZ5.mWJpuVolil07guHPvOW8mGRcvxa5' ), array( '$5$rounds=1400$anotherlongsaltstring', 'a very much longer text to encrypt. This one even stretches over morethan one line.', '$5$rounds=1400$anotherlongsalts$Rx.j8H.h8HjEDGomFU8bDkXm3XIUnzyxf12oP84Bnq1' ), array( '$5$rounds=77777$short', 'we have a short salt string but not a short password', '$5$rounds=77777$short$JiO1O3ZpDAxGJeaDIuqCoEFysAe1mZNJRs3pw0KQRd/' ), array( '$5$rounds=123456$asaltof16chars..', 'a short string', '$5$rounds=123456$asaltof16chars..$gP3VQ/6X7UUEW3HkBn2w1/Ptq2jxPyzV/cZKmF/wJvD' ), array( '$5$rounds=10$roundstoolow', 'the minimum number is still observed', '$5$rounds=1000$roundstoolow$yfvwcWrQ8l/K0DAWyuPMDNHpIVlTQebY9l/gL972bIC' ), );
foreach($tv as $tvd) { echo crypt_sha256($tvd[1], $tvd[0]) . "\n" . $tvd[2] . "\n<br/>\n"; }
?> |
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237: 238: 239:
| <?
include "salt_api.php";
if(!function_exists('sha512')) { function sha512($data,$raw=false){ if(false === array_search('sha512', hash_algos(), true)) { return false; }
return hash('sha512', $data, $raw); } }
function crypt_sha512($password, $salt = "") { $i_rounds = 5000; $i_salt = ''; $i_has_rounds = false;
if(!empty($salt)) { if(substr($salt, 0, 3) != '$6$') { return false; }
$salt = substr($salt, 3);
if(strtolower(substr($salt, 0, 7)) == 'rounds=') { $i = strpos($salt, '$'); if(false !== $i) { $s = substr($salt, 7, $i-7); $i_rounds = @(int)$s; $i_has_rounds = true; $salt = substr($salt, $i+1); } }
$i = strpos($salt, '$'); if(false !== $i) { $salt = substr($salt, 0, $i); }
$i_salt = $salt; } else { $i_salt = gen_salt(16); }
if($i_rounds < 1000) { $i_rounds = 1000; } else if($i_rounds > 999999999) { $i_rounds = 999999999; }
$i_salt = substr($i_salt, 0, 16);
unset($i); unset($rounds); unset($salt);
$d_A = hash_init('sha512'); hash_update($d_A, $password); hash_update($d_A, $i_salt);
$d_B = hash_init('sha512'); hash_update($d_B, $password); hash_update($d_B, $i_salt); hash_update($d_B, $password); $B = hash_final($d_B, true);
for($i = strlen($password); $i >= strlen($B); $i -= strlen($B)) { hash_update($d_A, $B); } hash_update($d_A, substr($B, 0, $i));
$i = strlen($password); while($i) { if($i&1) { hash_update($d_A, $B); } else { hash_update($d_A, $password); } $i >>= 1; }
$A = hash_final($d_A, true);
$d_DP = hash_init('sha512'); for($i = strlen($password); $i; $i--) { hash_update($d_DP, $password); } $DP = hash_final($d_DP, true);
$P = ''; for($i = strlen($password); $i >= strlen($DP); $i -= strlen($DP)) { $P .= $DP; } $P .= substr($DP, 0, $i);
$d_DS = hash_init('sha512'); for($i = 16+ord($A[0]); $i; $i--) { hash_update($d_DS, $i_salt); } $DS = hash_final($d_DS, true);
$S = ''; for($i = strlen($i_salt); $i >= strlen($DS); $i -= strlen($DS)) { $S .= $DS; } $S .= substr($DS, 0, $i);
for($round = 0; $round < $i_rounds; $round++) { $d_C = hash_init('sha512');
if($round&1) { hash_update($d_C, $P); } else { hash_update($d_C, $A); }
if($round%3) { hash_update($d_C, $S); } if($round%7) { hash_update($d_C, $P); } if($round&1) { hash_update($d_C, $A); } else { hash_update($d_C, $P); } $A = hash_final($d_C, true); }
$result = '$6$';
if($i_has_rounds || ($i_rounds != 5000)) { $result .= "rounds={$i_rounds}\$"; }
$result .= $i_salt . '$';
$tmp = crypt_sha512_encode($A);
$result .= $tmp; return $result; }
function crypt_sha512_encode($data){ $chars = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; $pos = array( 0 , 21 , 42, 22 , 43 , 1, 44 , 2 , 23, 3 , 24 , 45, 25 , 46 , 4, 47 , 5 , 26, 6 , 27 , 48, 28 , 49 , 7, 50 , 8 , 29, 9 , 30 , 51, 31 , 52 , 10, 53 , 11 , 32, 12 , 33 , 54, 34 , 55 , 13, 56 , 14 , 35, 15 , 36 , 57, 37 , 58 , 16, 59 , 17 , 38, 18 , 39 , 60, 40 , 61 , 19, 62 , 20 , 41, -1 , -1 , 63 );
$result = '';
for($i = 0; $i < count($pos);) { $B2 = $pos[$i++]; $B1 = $pos[$i++]; $B0 = $pos[$i++]; $B2 = $B2 < 0 ? 0 : ord($data[$B2]); $B1 = $B1 < 0 ? 0 : ord($data[$B1]); $B0 = $B0 < 0 ? 0 : ord($data[$B0]);
$n = 4; if($pos[$i-3] < 0) { $n--; } if($pos[$i-2] < 0) { $n--; }
$w = ($B2 << 16) + ($B1 << 8) + $B0; while($n--) { $result .= $chars[$w & 0x3F]; $w >>= 6; } }
return $result; }
$tv = array( array( '$6$saltstring', 'Hello world!', '$6$saltstring$svn8UoSVapNtMuq1ukKS4tPQd8iKwSMHWjl/O817G3uBnIFNjnQJuesI68u4OTLiBFdcbYEdFCoEOfaS35inz1' ), array( '$6$rounds=10000$saltstringsaltstring', 'Hello world!', '$6$rounds=10000$saltstringsaltst$OW1/O6BYHV6BcXZu8QVeXbDWra3Oeqh0sbHbbMCVNSnCM/UrjmM0Dp8vOuZeHBy/YTBmSK6H9qs/y3RnOaw5v.' ), array( '$6$rounds=5000$toolongsaltstring', 'This is just a test', '$6$rounds=5000$toolongsaltstrin$lQ8jolhgVRVhY4b5pZKaysCLi0QBxGoNeKQzQ3glMhwllF7oGDZxUhx1yxdYcz/e1JSbq3y6JMxxl8audkUEm0' ), array( '$6$rounds=1400$anotherlongsaltstring', 'a very much longer text to encrypt. This one even stretches over morethan one line.', '$6$rounds=1400$anotherlongsalts$POfYwTEok97VWcjxIiSOjiykti.o/pQs.wPvMxQ6Fm7I6IoYN3CmLs66x9t0oSwbtEW7o7UmJEiDwGqd8p4ur1' ), array( '$6$rounds=77777$short', 'we have a short salt string but not a short password', '$6$rounds=77777$short$WuQyW2YR.hBNpjjRhpYD/ifIw05xdfeEyQoMxIXbkvr0gge1a1x3yRULJ5CCaUeOxFmtlcGZelFl5CxtgfiAc0' ), array( '$6$rounds=123456$asaltof16chars..', 'a short string', '$6$rounds=123456$asaltof16chars..$BtCwjqMJGx5hrJhZywWvt0RLE8uZ4oPwcelCjmw2kSYu.Ec6ycULevoBK25fs2xXgMNrCzIMVcgEJAstJeonj1' ), array( '$6$rounds=10$roundstoolow', 'the minimum number is still observed', '$6$rounds=1000$roundstoolow$kUMsbe306n21p9R.FRkW3IGn.S9NPN0x50YhH1xhLsPuWGsUSklZt58jaTfF4ZEQpyUNGc0dqbpBYYBaHHrsX.' ) );
foreach($tv as $tvd) { echo crypt_sha512($tvd[1], $tvd[0]) . "\n" . $tvd[2] . "\n<br/>\n"; }
?> |
Und hier noch die fehlenden Funktionen zur Salt-Generierung:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69:
| <?
function gen_salt($length, $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./") { if($length < 1) { $length = 1; }
$raw = random_getbytes($length);
$lc = strlen($chars); $salt = ''; $i = $length; while($i) { $salt .= $chars[ord($raw[--$i]) % $lc]; }
return $salt; }
function gen_salt_des() { return gen_salt(2); }
function gen_salt_des2() { return gen_salt(9); }
function gen_salt_apr1() { return gen_salt(8); }
function gen_salt_sha() { return gen_salt(16); }
function random_getbytes($count) { if($count < 1) { $count = 1; }
if(is_readable('/dev/urandom')) { $fp = @fopen('/dev/urandom','rb'); if ($fp !== FALSE) { $pr_bits .= @fread($fp,$count); @fclose($fp); return $pr_bits; } }
if(function_exists('mt_rand')) { $pr_bits = ''; for ($i = 0; $i < $count; $i++) { $pr_bits .= chr(mt_rand(0,255)); } return $pr_bits; }
$pr_bits = ''; for($i = 0; $i < $count; $i++) { $pr_bits .= chr(rand(0,255)); } return $pr_bits; }
?> |
Dank trotzdem. Wer die Routinen nutzen möchte: Die Lizenz ist die gleiche wie für TMutexIPC von mir.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
matze
      
Beiträge: 4613
Erhaltene Danke: 24
XP home, prof
Delphi 2009 Prof,
|
Verfasst: Do 01.01.09 21:20
äh ja cool. Aber wieso nochmal genau hast du dir die Mühe gemacht? Ich steh auf dem Schlauch... 
_________________ In the beginning was the word.
And the word was content-type: text/plain.
|
|
BenBE 
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Do 01.01.09 22:07
matze hat folgendes geschrieben : | äh ja cool. Aber wieso nochmal genau hast du dir die Mühe gemacht? Ich steh auf dem Schlauch...  |
Ich hab mir daher die Mühe gemacht, da SHA256-Crypt- und SHA512-Crypt-Hashes zur Speicherung von Passwörtern in PHP nicht in allen Versionen unterstützt werden, Verfahren wie DES\3DES-Crypt und MD5-Crypt allerdings auf Grund der geringen Hashlänge nicht mehr als sicher betrachtet werden können. Es gibt ferner zwar noch eine ganze Reihe anderer Verfahren (APR1 beim Apache z.B., MD5-Hashes [$1$] bei einigen Linux-Distries und Blowfish, diese sind aber im Wesentlichen von den Original-Crypts nur unterschiedlich abgedeckt.
Ziel war es hier, eine Crypt-Implementation in PHP für eigene Scripte zu schreiben, die weitestgehend unabhängig von der verwendeten PHP-Implementation ist, um auch beim Erzeugen der Hashes etwas mehr Flexibilität zu haben. Die Skripte werden später zum Schreiben von Config-Files benötigt, wo teilweise bestimmte Hashes gefordert sind.
Warum ich kein einfaches Salted MD5 implementiere: Da das jedes Programm anders macht; crypt_sha256/512 ist eine "standardisierte" Form, die aktuelle Versionen von crypt(3) unter Linux können; auf diese Art kann ich mit PHP-Skripten reibungslos diverse Password-Files wie z.B. htpasswd für'n Apache oder auch LDIF-Files schreiben.
Anmerkung: Die jetzige Implementation mit hash* benötigt zwar PHP 5.1.2+, das lässt sich aber durch Austausch einzelner Funktionsaufrufe auch auf ältere PHP-Versionen portieren (auch wenn ich das für meinen Einsatz-Zweck weniger brauch).
Ach ja: Eine Frage hätt ich dann noch:
Kennt jemand noch andre Hash-Formate (wenn möglich mit nem Link zur Beschreibung):
$1$ (MD5 Hashes
$2$ (Blowfish)
$2a$ (Blowfish, BSD-style)
$5$ (SHA256)
$6$ (SHA512)
$apr1$ (Apache 2 htpasswd file)
$H$ (phpBB3 Implementation of PHPass portable Hashes)
$P$ (PHPass portable Hashes)
13-char 3DES hashes (old Linux style)
20-char 3DES hashes (Extended 3DES hashes)
(ADie Liste sind die, von denen ich weiß, dass sie definiert sind; gibt's da noch weitere?
TIA.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
KenanSulayman
Hält's aus hier
Beiträge: 3
|
Verfasst: Sa 03.01.09 01:43
Titel: Reimplementation
Hallo BenBE!
Ich mag deine Art zu programmieren zwar nicht aber ich habe das Ganze akzeptabel als mögliche Implementation ausgearbeitet.
Folgendes würde ich auf jeden Fall wegschneiden:
C#-Quelltext 1: 2: 3: 4: 5:
| <? unset( $i ); unset( $rounds ); unset( $salt ); ?> |
Änderungen:
- { ~ } Teile bei If - Parts mit einer Zeile
+ Class -> Public Deklaration von [$rounds, $salt, $has_rounds]
- Namentliche Funktionsdeklaration verkürtzt -> [ crypt_sha512_encode ~ enc ]
Code:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189:
| <?php class Sha512 { public $iterations = 5000; public $salt = ''; public $rounds = false; public function crypt_sha512( $password, $salt = "" ) { $i_rounds = $this -> iterations; $i_salt = $this -> salt; $i_has_rounds = $this -> rounds; if ( !empty( $salt ) ) { if ( substr( $salt, 0, 3 ) != '$6$' ) return false; $salt = substr( $salt, 3 ); if ( strtolower( substr( $salt, 0, 7 ) ) == 'rounds=' ) { $i = strpos( $salt, '$' ); if ( false !== $i ) { $s = substr( $salt, 7, $i - 7 ); $i_rounds = @( int )$s; $i_has_rounds = true; $salt = substr( $salt, $i + 1 ); } } $i = strpos( $salt, '$' ); if ( false !== $i ) $salt = substr( $salt, 0, $i ); $i_salt = $salt; } else { $i_salt = $this -> gen_salt( 16 ); } if ( $i_rounds < 1000 ) { $i_rounds = 1000; } elseif ( $i_rounds > 999999999 ) { $i_rounds = 999999999; } $i_salt = substr( $i_salt, 0, 16 ); $d_A = hash_init( 'sha512' ); hash_update( $d_A, $password ); hash_update( $d_A, $i_salt ); $d_B = hash_init( 'sha512' ); hash_update( $d_B, $password ); hash_update( $d_B, $i_salt ); hash_update( $d_B, $password ); $B = hash_final( $d_B, true ); for ( $i = strlen( $password ); $i >= strlen( $B ); $i -= strlen( $B ) ) { hash_update( $d_A, $B ); } hash_update( $d_A, substr( $B, 0, $i ) ); $i = strlen( $password ); while ( $i ) { if ( $i & 1 ) { hash_update( $d_A, $B ); } else { hash_update( $d_A, $password ); } $i >>= 1; } $A = hash_final( $d_A, true ); $d_DP = hash_init( 'sha512' ); for ( $i = strlen( $password ); $i; $i-- ) { hash_update( $d_DP, $password ); } $DP = hash_final( $d_DP, true ); $P = ''; for ( $i = strlen( $password ); $i >= strlen( $DP ); $i -= strlen( $DP ) ) { $P .= $DP; } $P .= substr( $DP, 0, $i ); $d_DS = hash_init( 'sha512' ); for ( $i = 16 + ord( $A[ 0 ] ); $i; $i-- ) { hash_update( $d_DS, $i_salt ); } $DS = hash_final( $d_DS, true ); $S = ''; for ( $i = strlen( $i_salt ); $i >= strlen( $DS ); $i -= strlen( $DS ) ) { $S .= $DS; } $S .= substr( $DS, 0, $i ); for ( $round = 0; $round < $i_rounds; $round++ ) { $d_C = hash_init( 'sha512' ); if ( $round & 1 ) { hash_update( $d_C, $P ); } else { hash_update( $d_C, $A ); } if ( $round % 3 ) { hash_update( $d_C, $S ); } if ( $round % 7 ) { hash_update( $d_C, $P ); } if ( $round & 1 ) { hash_update( $d_C, $A ); } else { hash_update( $d_C, $P ); } $A = hash_final( $d_C, true ); } $result = '$6$'; if ( $i_has_rounds || ( $i_rounds != 5000 ) ) { $result .= "rounds={$i_rounds}\$"; } $result .= $i_salt . '$'; $tmp = $this -> enc( $A ); $result .= $tmp; return $result; } public function enc( $data ) { $chars = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; $pos = array( 0, 21, 42, 22, 43, 1, 44, 2, 23, 3, 24, 45, 25, 46, 4, 47, 5, 26, 6, 27, 48, 28, 49, 7, 50, 8, 29, 9, 30, 51, 31, 52, 10, 53, 11, 32, 12, 33, 54, 34, 55, 13, 56, 14, 35, 15, 36, 57, 37, 58, 16, 59, 17, 38, 18, 39, 60, 40, 61, 19, 62, 20, 41, -1, -1, 63 ); $result = ''; for ( $i = 0; $i < count( $pos ); ) { $B2 = $pos[ $i++ ]; $B1 = $pos[ $i++ ]; $B0 = $pos[ $i++ ]; $B2 = $B2 < 0 ? 0 : ord( $data[ $B2 ] ); $B1 = $B1 < 0 ? 0 : ord( $data[ $B1 ] ); $B0 = $B0 < 0 ? 0 : ord( $data[ $B0 ] ); $n = 4; if ( $pos[ $i - 3 ] < 0 ) $n--; if ( $pos[ $i - 2 ] < 0 ) $n--; $w = ( $B2 << 16 ) + ( $B1 << 8 ) + $B0; while ( $n-- ) { $result .= $chars[ $w & 0x3F ]; $w >>= 6; } } return $result; } public function gen_salt( $length, $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./" ) { if ( $length < 1 or !is_numeric($length) ) $length = 1; $raw = $this -> random_getbytes( $length ); $lc = strlen( $chars ); $salt = ''; $i = $length; while ( $i ) { $salt .= $chars[ ord( $raw[ --$i ] ) % $lc ]; } return $salt; } public function random_getbytes( $count ) { if ( $count < 1 or !is_numeric($count) ) $count = 1; for ( $i = 0, $pr_bits = ''; $i < $count; $i++ ) $pr_bits .= chr( rand( 0, 255 ) ); return $pr_bits; } } ($d = new Sha512) and print $d -> crypt_sha512('d'); ?> |
Wobei ich mich immer noch wundere: dass das um den Tod keine richtige Sha512 Ausgabe ist?
Arbeite lieber mal an einem richtigem Sha512 Algorithmus.
--
Kenan Sulayman
KurealCorporation inc.
Global Application Designer
|
|
BenBE 
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Sa 03.01.09 01:58
Titel: Re: Reimplementation
KenanSulayman hat folgendes geschrieben : | Hallo BenBE!
Ich mag deine Art zu programmieren zwar nicht aber ich habe das Ganze akzeptabel als mögliche Implementation ausgearbeitet. |
Über Code-Formatierung kann man streiten.
KenanSulayman hat folgendes geschrieben : | Folgendes würde ich auf jeden Fall wegschneiden:
C#-Quelltext 1: 2: 3: 4: 5:
| <? unset( $i ); unset( $rounds ); unset( $salt ); ?> | |
Verwendet werden diese Variablen eben ja noch  Zumindest $i. Die besagten Zeilen waren aber eh hauptsächlich zum Finden von Bugs (Gibt ne Warnung, wenn ich mich im unteren Teil vertan hätte).
Zudem hatte die Formatierung einen Sinn: Achte in meinem Source einmal auf die Kommentare. Da müsste Dir auffallen, dass das die Referenzen auf die Original-Implementierung laut Algo sind, d.h. die Kommentare geben an, was aus der Algorithmen-Beschreibung an der jeweiligen Stelle getan wird.
KenanSulayman hat folgendes geschrieben : | Änderungen:
- { ~ } Teile bei If - Parts mit einer Zeile
+ Class -> Public Deklaration von [$rounds, $salt, $has_rounds]
- Namentliche Funktionsdeklaration verkürtzt -> [ crypt_sha512_encode ~ enc ] |
Ist eh vorerst eine Grob-Implementation gewesen; wird im Ziel-Projekt, wo es mal eingebunden wird, auf jeden Fall als Klasse implementiert (mit noch ein paar andren Änderungen). Mir ging es hier erstmal hauptsächlich darum, die Implementierung an sich korrekt zu haben: Optimieren und Formatieren des Codes kann man dan immer noch.
Deine Variante des Codes find ich übrigens auf Grund der fehlenden Referenzierung der Spezifikation unübersichtlicher, auch wenn man i.d.R. lange Routinen eher splitten sollte.
KenanSulayman hat folgendes geschrieben : | Wobei ich mich immer noch wundere: dass das um den Tod keine richtige Sha512 Ausgabe ist? |
Ist auch nicht dazu gedacht, SHA512 an sich zu berechnen, sondern den (oben mehrfach verlinkten) Algorithmus zu Validierung von Passwörtern mit Hilfe von Unix-Style crypt_sha256\512-Hashes abzugleichen.
KenanSulayman hat folgendes geschrieben : | Arbeite lieber mal an einem richtigem Sha512 Algorithmus. |
Siehe die Funktionen sha256 und sha512 in meiner Implementation. Die machen genau das. die beiden crypt-Varianten berechnen Hashes unter Nutzung von SHA256\SHA512 analog dem, was crypt macht, wenn man $1$ (MD5) oder $2a$ (Blowfish) generiert. Siehe die PHP-Doku zu [url= php.net/crypt]crypt[/url] für mehr Details. Die genannten Routinen ergänzen dort nur (so Portabel wie möglich) die Nutzung weiterer Hash-Formate.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
KenanSulayman
Hält's aus hier
Beiträge: 3
|
Verfasst: Sa 03.01.09 02:13
Titel: Re: Reimplementation
Verstanden.
Wo hasst du deine Vorlage her ? / Sprich Ursprung der Definition des Algorithmus ?
--
Kenan Sulayman
KurealCorporation inc.
Global Application Designer
|
|
BenBE 
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Sa 03.01.09 02:15
Titel: Re: Reimplementation
KenanSulayman hat folgendes geschrieben : | Wo hasst du deine Vorlage her ? / Sprich Ursprung der Definition des Algorithmus ? |
people.redhat.com/drepper/SHA-crypt.txt
(Lesen des ersten Posts, sowie meines Sources müsste Dir diesenLink eigentlich offenbart haben, denn da taucht dieser Link mehrfach auf).
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
KenanSulayman
Hält's aus hier
Beiträge: 3
|
Verfasst: Sa 03.01.09 02:18
Titel: Re: Reimplementation
Entschulding. Ich bin gerade etwas beschäftig, da* habe ich das doch tatsächlich übersehen ...
--
Kenan Sulayman
KurealCorporation inc.
Global Application Designer
P.s.: Schönes neues Jahr!
|
|
|