Wachtwoord encrypten
Hey iedereen,
ik ben me wat aan het verdiepen in wachtwoordbeveiliging. Ik gebruik altijd gewoon een MD5 maar nu vraag ik me af of dit wel zo veilig is?
Ik heb al redelijk wat gelezen en heb al wel ontdekt dat je best niet meerde hashes over elkaar gebruikt omdat het dan makelijker 'te kraken' is. Hoe komt dit ik snap de analogie hier niet van. Welke methode gebruiken jullie?
Alvast bedankt
ik ben me wat aan het verdiepen in wachtwoordbeveiliging. Ik gebruik altijd gewoon een MD5 maar nu vraag ik me af of dit wel zo veilig is?
Ik heb al redelijk wat gelezen en heb al wel ontdekt dat je best niet meerde hashes over elkaar gebruikt omdat het dan makelijker 'te kraken' is. Hoe komt dit ik snap de analogie hier niet van. Welke methode gebruiken jullie?
Alvast bedankt
Gewijzigd op 23/01/2013 15:56:54 door Sam H
De beste manier is SHA1() met een unieke salt...
Dus $pass = "PHpHu1pi$7H383$7".$_POST['password'];
Zodra je de leden zich aanmelden sla je hun password op met die unieke salt ervoor. Zo is kraken zeer lastig, gezien het wachtwoord uiteindelijk minimaal 26 tekens kent (ervanuitgaande dat je alleen wachtwoorden toestaat van 6 tekens lang.
Dus $pass = "PHpHu1pi$7H383$7".$_POST['password'];
Zodra je de leden zich aanmelden sla je hun password op met die unieke salt ervoor. Zo is kraken zeer lastig, gezien het wachtwoord uiteindelijk minimaal 26 tekens kent (ervanuitgaande dat je alleen wachtwoorden toestaat van 6 tekens lang.
Gewijzigd op 23/01/2013 16:07:19 door - Ariën -
Ah ik dacht altijd dat bij een salt erdoorheen werd gegooid als volgt:
Salt: APPELS
Pass: phphulp123
=> pAhpPhPuElpL1S23
Simpel voorbeeld maar je snapt wel wat ik bedoel.
EDIT:
Ik vond over sha1 dit nog op php.net:
Salt: APPELS
Pass: phphulp123
=> pAhpPhPuElpL1S23
Simpel voorbeeld maar je snapt wel wat ik bedoel.
EDIT:
Ik vond over sha1 dit nog op php.net:
Quote:
Note: Secure password hashing
It is not recommended to use this function to secure passwords, due to the fast nature of this hashing algorithm. See here for details.
It is not recommended to use this function to secure passwords, due to the fast nature of this hashing algorithm. See here for details.
Gewijzigd op 23/01/2013 16:20:04 door Sam H
Als ik het artikel goed versta, wilt het zeggen dat bcrypt een zeer traag encryptie algoritme is. Dus dit is veiliger omdat het voor bruteforce attacks pakken langer gaat duren? Dus het enige wat bcrypt doet, is de tijd nodig om in te loggen tragen maken, of zit ik mis?
Alvast bedankt beiden voor de hulp
Alvast bedankt beiden voor de hulp
Sam H op 23/01/2013 16:17:41:
Ik vond over sha1 dit nog op php.net:
Ik vond over sha1 dit nog op php.net:
Quote:
Note: Secure password hashing
It is not recommended to use this function to secure passwords, due to the fast nature of this hashing algorithm. See here for details.
It is not recommended to use this function to secure passwords, due to the fast nature of this hashing algorithm. See here for details.
Tenzij je een salt gebruikt.
Ik heb hier een class gevonden die bcrypt genereert en verifieerd.
Als ik het localhost run, duurt het 9 seconden (!) voor het simpele wachtwoord 'password' te encrypten.
Dit is toch wel héél erg lang ?
Als ik het localhost run, duurt het 9 seconden (!) voor het simpele wachtwoord 'password' te encrypten.
Dit is toch wel héél erg lang ?
Code (php)
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
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
<?php
class Bcrypt {
private $rounds;
public function __construct($rounds = 12) {
if(CRYPT_BLOWFISH != 1) {
throw new Exception("bcrypt not supported in this installation. See http://php.net/crypt");
}
$this->rounds = $rounds;
}
public function hash($input) {
$hash = crypt($input, $this->getSalt());
if(strlen($hash) > 13)
return $hash;
return false;
}
public function verify($input, $existingHash) {
$hash = crypt($input, $existingHash);
return $hash === $existingHash;
}
private function getSalt() {
$salt = sprintf('$2a$%02d$', $this->rounds);
$bytes = $this->getRandomBytes(16);
$salt .= $this->encodeBytes($bytes);
return $salt;
}
private $randomState;
private function getRandomBytes($count) {
$bytes = '';
if(function_exists('openssl_random_pseudo_bytes') &&
(strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN')) { // OpenSSL slow on Win
$bytes = openssl_random_pseudo_bytes($count);
}
if($bytes === '' && is_readable('/dev/urandom') &&
($hRand = @fopen('/dev/urandom', 'rb')) !== FALSE) {
$bytes = fread($hRand, $count);
fclose($hRand);
}
if(strlen($bytes) < $count) {
$bytes = '';
if($this->randomState === null) {
$this->randomState = microtime();
if(function_exists('getmypid')) {
$this->randomState .= getmypid();
}
}
for($i = 0; $i < $count; $i += 16) {
$this->randomState = md5(microtime() . $this->randomState);
if (PHP_VERSION >= '5') {
$bytes .= md5($this->randomState, true);
} else {
$bytes .= pack('H*', md5($this->randomState));
}
}
$bytes = substr($bytes, 0, $count);
}
return $bytes;
}
private function encodeBytes($input) {
// The following is code from the PHP Password Hashing Framework
$itoa64 = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
$output = '';
$i = 0;
do {
$c1 = ord($input[$i++]);
$output .= $itoa64[$c1 >> 2];
$c1 = ($c1 & 0x03) << 4;
if ($i >= 16) {
$output .= $itoa64[$c1];
break;
}
$c2 = ord($input[$i++]);
$c1 |= $c2 >> 4;
$output .= $itoa64[$c1];
$c1 = ($c2 & 0x0f) << 2;
$c2 = ord($input[$i++]);
$c1 |= $c2 >> 6;
$output .= $itoa64[$c1];
$output .= $itoa64[$c2 & 0x3f];
} while (1);
return $output;
}
}
?>
class Bcrypt {
private $rounds;
public function __construct($rounds = 12) {
if(CRYPT_BLOWFISH != 1) {
throw new Exception("bcrypt not supported in this installation. See http://php.net/crypt");
}
$this->rounds = $rounds;
}
public function hash($input) {
$hash = crypt($input, $this->getSalt());
if(strlen($hash) > 13)
return $hash;
return false;
}
public function verify($input, $existingHash) {
$hash = crypt($input, $existingHash);
return $hash === $existingHash;
}
private function getSalt() {
$salt = sprintf('$2a$%02d$', $this->rounds);
$bytes = $this->getRandomBytes(16);
$salt .= $this->encodeBytes($bytes);
return $salt;
}
private $randomState;
private function getRandomBytes($count) {
$bytes = '';
if(function_exists('openssl_random_pseudo_bytes') &&
(strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN')) { // OpenSSL slow on Win
$bytes = openssl_random_pseudo_bytes($count);
}
if($bytes === '' && is_readable('/dev/urandom') &&
($hRand = @fopen('/dev/urandom', 'rb')) !== FALSE) {
$bytes = fread($hRand, $count);
fclose($hRand);
}
if(strlen($bytes) < $count) {
$bytes = '';
if($this->randomState === null) {
$this->randomState = microtime();
if(function_exists('getmypid')) {
$this->randomState .= getmypid();
}
}
for($i = 0; $i < $count; $i += 16) {
$this->randomState = md5(microtime() . $this->randomState);
if (PHP_VERSION >= '5') {
$bytes .= md5($this->randomState, true);
} else {
$bytes .= pack('H*', md5($this->randomState));
}
}
$bytes = substr($bytes, 0, $count);
}
return $bytes;
}
private function encodeBytes($input) {
// The following is code from the PHP Password Hashing Framework
$itoa64 = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
$output = '';
$i = 0;
do {
$c1 = ord($input[$i++]);
$output .= $itoa64[$c1 >> 2];
$c1 = ($c1 & 0x03) << 4;
if ($i >= 16) {
$output .= $itoa64[$c1];
break;
}
$c2 = ord($input[$i++]);
$c1 |= $c2 >> 4;
$output .= $itoa64[$c1];
$c1 = ($c2 & 0x0f) << 2;
$c2 = ord($input[$i++]);
$c1 |= $c2 >> 6;
$output .= $itoa64[$c1];
$output .= $itoa64[$c2 & 0x3f];
} while (1);
return $output;
}
}
?>
Brute force gewoon uitsluiten, drie keer fout = gelocked en nieuw password aanvragen door gebruiker.
Ja dit gebruik ik ook (enkel ipv gelocked gebruik ik een timeout van 5 minuten).
Aad B op 23/01/2013 16:48:53:
Brute force gewoon uitsluiten, drie keer fout = gelocked en nieuw password aanvragen door gebruiker.
Is dat niet heel erg extreem? De gebruiker logt per ongeluk 3x verkeerd in en moet dan meteen een nieuw wachtwoord aanvragen? Lijkt me niet echt gebruiksvriendelijk.
Aad B op 23/01/2013 16:48:53:
Brute force gewoon uitsluiten, drie keer fout = gelocked en nieuw password aanvragen door gebruiker.
En wat als ze in een brute force attack een hele lijst met usernamen aflopen, maar dan met elke keer hetzelfde (een gebruikelijk) password? Ben je alsnog de Sjaak.
Brute Force attacks kan je helaas niet met een simpele beveiliging voorkomen. Als dat namelijk zou kunnen zou het niet meer voorkomen. Meerdere beveiligingen is altijd beter.
- loggen waar de aanvragen vandaan komen
- loggen op welke username er wordt geprobeerd
- inlog vertragen
En als iemand nog andere mogelijkheden heeft om attacks tegen te gaan ben ik ook nog wel benieuwd.
Ik sla momenteel het IP adres en username op bij een mislukte inlogpoging, is dit groter dan 3 dan geef ik die username en/of IP een timeout van 5 minuten. Nu ga ik ook bcrypt gebruiken, ik heb een class gevonden waarbij het ongeveer 3 seconden duurt om een wachtwoord te verifiëren.
Dus dit lijkt me wel veilig genoeg?
Voor de geïnteresseerden, dit is de uiteindelijke klasse die ik ga gebruiken (de vorige deed er 9 seconden over, dit lijkt me wat extreem):
Dus dit lijkt me wel veilig genoeg?
Voor de geïnteresseerden, dit is de uiteindelijke klasse die ik ga gebruiken (de vorige deed er 9 seconden over, dit lijkt me wat extreem):
Code (php)
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
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
<?php
class Bcrypt {
private $rounds;
private $prefix;
public function __construct($prefix = '', $rounds = 12) {
if(CRYPT_BLOWFISH != 1) {
throw new Exception("bcrypt not supported in this installation. See http://php.net/crypt");
}
$this->rounds = $rounds;
$this->prefix = $prefix;
}
public function hash($input) {
$hash = crypt($input, $this->getSalt());
if(strlen($hash) > 13)
return $hash;
return false;
}
public function verify($input, $existingHash) {
$hash = crypt($input, $existingHash);
return $hash === $existingHash;
}
private function getSalt() {
// the base64 function uses +'s and ending ='s; translate the first, and cut out the latter
return sprintf('$2a$%02d$%s', $this->rounds, substr(strtr(base64_encode($this->getBytes()), '+', '.'), 0, 22));
}
private function getBytes() {
$bytes = '';
if(function_exists('openssl_random_pseudo_bytes') &&
(strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN')) { // OpenSSL slow on Win
$bytes = openssl_random_pseudo_bytes(18);
}
if($bytes === '' && is_readable('/dev/urandom') &&
($hRand = @fopen('/dev/urandom', 'rb')) !== FALSE) {
$bytes = fread($hRand, 18);
fclose($hRand);
}
if($bytes === '') {
$key = uniqid($this->prefix, true);
// 12 rounds of HMAC must be reproduced / created verbatim, no known shortcuts.
// Changed the hash algorithm from salsa20, which has been removed from PHP 5.4.
for($i = 0; $i < 12; $i++) {
$bytes = hash_hmac('snefru256', microtime() . $bytes, $key, true);
usleep(10);
}
}
return $bytes;
}
}
?>
class Bcrypt {
private $rounds;
private $prefix;
public function __construct($prefix = '', $rounds = 12) {
if(CRYPT_BLOWFISH != 1) {
throw new Exception("bcrypt not supported in this installation. See http://php.net/crypt");
}
$this->rounds = $rounds;
$this->prefix = $prefix;
}
public function hash($input) {
$hash = crypt($input, $this->getSalt());
if(strlen($hash) > 13)
return $hash;
return false;
}
public function verify($input, $existingHash) {
$hash = crypt($input, $existingHash);
return $hash === $existingHash;
}
private function getSalt() {
// the base64 function uses +'s and ending ='s; translate the first, and cut out the latter
return sprintf('$2a$%02d$%s', $this->rounds, substr(strtr(base64_encode($this->getBytes()), '+', '.'), 0, 22));
}
private function getBytes() {
$bytes = '';
if(function_exists('openssl_random_pseudo_bytes') &&
(strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN')) { // OpenSSL slow on Win
$bytes = openssl_random_pseudo_bytes(18);
}
if($bytes === '' && is_readable('/dev/urandom') &&
($hRand = @fopen('/dev/urandom', 'rb')) !== FALSE) {
$bytes = fread($hRand, 18);
fclose($hRand);
}
if($bytes === '') {
$key = uniqid($this->prefix, true);
// 12 rounds of HMAC must be reproduced / created verbatim, no known shortcuts.
// Changed the hash algorithm from salsa20, which has been removed from PHP 5.4.
for($i = 0; $i < 12; $i++) {
$bytes = hash_hmac('snefru256', microtime() . $bytes, $key, true);
usleep(10);
}
}
return $bytes;
}
}
?>
Gewoon een vertraging per IP.
3x een foute pass, 10 seconden wachttijd, daarna meer drie, en dan steeds 25 sec wachttijd en dat steeds ophogen of het IP blokkeren na verloop van tijd.
Zorg ervoor dat de gebruiker buiten schot blijft.
3x een foute pass, 10 seconden wachttijd, daarna meer drie, en dan steeds 25 sec wachttijd en dat steeds ophogen of het IP blokkeren na verloop van tijd.
Zorg ervoor dat de gebruiker buiten schot blijft.
Ik heb gehoord dat hackers constant van IP adres veranderen (hoe, geen idee) en daarom doe ik ook de username.
Precies, gewoon IP en/of gebruikersnaam.
Als er op 1 gebruikersnaam 3 (of meer) inlogpogingen zijn gewoon met sleep() de boel een paar seconden vertragen.
En na 10x IP adres blokkeren (al is het maar voor 10 minuten).
Als er op 1 gebruikersnaam 3 (of meer) inlogpogingen zijn gewoon met sleep() de boel een paar seconden vertragen.
En na 10x IP adres blokkeren (al is het maar voor 10 minuten).
En dan voor de hash is eigenlijk MD5 prima?
Nee, MD5 is A-Z, a-z en 0-9
Dan mis je alle $*(@&$_#Y)#€½¾@!&*()[]|\ dingen bijvoorbeeld terwijl die juist het moeilijk maken.
Dan mis je alle $*(@&$_#Y)#€½¾@!&*()[]|\ dingen bijvoorbeeld terwijl die juist het moeilijk maken.
Inderdaad, MD5 en SHA1 zijn hashes en GEEN encryptie.
Die hashes zijn algoritmes die je zelf kunt programmeren, en daardoor kan je gewoon ook simpel gestelt ze terugvoeren naar het oorspronkelijke als je de tijd en de moeite neemt.
Die hashes zijn algoritmes die je zelf kunt programmeren, en daardoor kan je gewoon ook simpel gestelt ze terugvoeren naar het oorspronkelijke als je de tijd en de moeite neemt.
Dus wat moet ik dan gebruiken? Toch Bcrypt?
Eddy E op 23/01/2013 18:43:44:
... gewoon met sleep() de boel een paar seconden vertragen.
Hoe moet ik dat zien... kun je dan sleep instellen op 5 minuten en doet de website dan 5 minuten niks meer?
SSL is de meest optimale beveiliging, de rest is allemaal maar een beetje extra hangsloten op de deur.




