Share this page: Follow me to be notified of new articles:

Password guidelines

Go to :
I am a website / software user
I am a website / software developers


Guidelines for users

Not a good example

What should my passwords look like?

A few information:

How can I know if my password is good enough?

I simply recommend to use online password testers. They'll immediately tell you if they consider your passwords strong : If you are not convinced yet, watch this little video :

How can I remember all my passwords?

You can't.
If you can remember them, they are probably not safe enough. If you are sure they are, I recommend you to take a Mensa test.

To find a good way to save your password list, you should first ask yourself this question : Who do I want to protect myself from ?
The precautions to take will be very different if you are trying to keep your girlfriend / boyfriend to access your password list than if you trying to keep the government from accessing it. Meaning that the government of your country probably has more resources than your girlfriend. This does not apply if you live in Greece (just kidding).

Here are a few solutions to protect your password :

Should I give my password to the authorities?

I'm not a lawyer and I recommend you to follow the law.
However, if you did something wrong and get the Feds in front of your house, and you feel a little stressed, I recommend you to relax with this simple mathematical equation :

IF "The jail time I face for refusing to give my password" IS GREATER THAN "The jail time I face for what they will find out when I give my password"
THEN "I give my password."
ELSE "I do not give my password."

As an example, in France you face a maximum of 3 years in jail and a 45 000 euros fine for refusing to give a password to the authorities (see Legifrance).
There is at least one case of a UK teenager jailed for 4 months for refusing to give his 50 caracters computer's password.
In the U.S., it's seems to be more foggy. Read more.

Statistics

According to the website Xato.com created by Mark Burnett :
The following graph illustrates how often users select common passwords :

(credits : Xato.com / Mark Burnett)

You can read more about that and download the Top 10 000 passwords the most comon here.

Pass phrases

This article would not be complete without a few words about "pass phrases", an idea from Robert Hensing from the Microsoft PSS Security Team.

Here is what Robert Hensing says:
"So here's the deal - I don't want you to use passwords, I want you to use pass-PHRASES. What is a pass-phrase you ask?
Let's take a look at some of my recent pass-phrases that I've used inside Microsoft for my 'password'.
"If we weren't all crazy we would go insane" (Jimmy Buffet rules)
"Send the pain below!" (I like Chevell too)
"Mean people suck!" (it's true)

So why are these pass-phrases so great?
1. They meet all password complexity requirements due to the use of upper / lowercase letters and punctuation (you don't HAVE to use numbers to meet password complexity requirements)
2. They are so freaking easy for me to remember it's not even funny. For me, I find it MUCH easier to remember a sentence from a favorite song or a funny quote than to remember 'xYaQxrz!' (which b.t.w. is long enough and complex enough to meet our internal complexity requirements, but is weak enough to not survive any kind of brute-force password grinding attack with say LC5, let alone a lookup table attack). That password would not survive sustained attack with LC5 long enough to matter so in my mind it's pointless to use a password like that. You may as well just leave your password blank.
3. I dare say that even with the most advanced hardware you are not going to guesss, crack, brute-force or pre-compute these passwords in the 70 days or so that they were around (remember you only need the password to survive attack long enough for you to change the password)."

Credits: Robert Hensing / http://blogs.technet.com/b/robert_hensing/archive/2004/07/28/199610.aspx

You can also read more about pass phrases here.

How can I generate a good password?

You can clone my GitHub project gabfl/password-generator-py to generate random secure passwords.


Guidelines for developers

Wrong ideas

A good simple solution: salt your passwords

How it works

The best simple solution, in my opinion, is to salt your passwords. You can ready more about a salt of passwords on Wikipedia.

For example, in PHP, you define a secret key common to all your users :
<?
$SaltKey = "D-Pu8ueALmG*54A;ZehMETb3";
?>
Then, you concatenate your Key and your user passwors :
<?
$SaltKey = "D-Pu8ueALmG*54A;ZehMETb3";
$UserPass = "password";

$Concatenate = $SaltKey.$UserPass;
?>
Then, you just hash the result with sha1 :
<?
$SaltKey = "D-Pu8ueALmG*54A;ZehMETb3";
$UserPass = "password";

$Concatenate = $SaltKey.$UserPass;

$ToSaveInMyDatabase = sha1($Concatenate);
?>

Example of password salting with a PHP script

Here is a working example you can use on your website :
<form method="post">
	<input type="hidden" name="action" value="1" />
	User password : <input type="password" name="password" value="" />
	<input type="submit" value="Go" />
</form>

<?
if($_POST['action']) {
	// Default value
	$SaltKey = "D-Pu8ueALmG*54A;ZehMETb3";
	$TheGoodPassIs = "password";
	$Concatenate = $SaltKey.$TheGoodPassIs;
	$ToSaveInMyDatabase = sha1($Concatenate);
	
	// User input
	$UserInput = trim($_POST['password']);
	$UserInputSalt = sha1($SaltKey.$UserInput);
	
	// Check
	if($UserInputSalt == $ToSaveInMyDatabase) {
		echo "The password is correct.";
	} else {
		echo "The password is incorrect.";
	}
}
?>

Another solution more complicated: unique salts, multiple hash

How it works

In order to provide a stronger security, you can also :
  1. Hash multiple times (hash the password once, then hash the hash itself a thousand times for example) or use a slower hash function like crypt(); in order to make it more difficult for hackers to create rainbow tables
  2. Create a unique password for each customers based on subscription data that you'll store (like his or her subscription IP address and timestamp)

PHP example

<?
// Reception of user's vars
$AccountCreationIP = $_SERVER['REMOTTE_ADDR'];
$AccountCreationTimeStamp = date();
$UserInputPassword = "password"; // $UserInputPassword = $_POST['UserInputPassword'];

// Creation of salted password
$SaltedPassword = sha1($AccountCreationIP.$AccountCreationTimeStamp.$UserInputPassword);

// A thousand hash of the hash
for ($i = 1; $i <= 1000; $i++) {
  $SaltedPassword = sha1($SaltedPassword);
}

// We now have to save in our database the following data : $AccountCreationIP; $AccountCreationTimeStamp; $SaltedPassword
// When the user log on, we need to re-do the same process using again $AccountCreationIP and $AccountCreationTimeStamp
// with his input to check if it matches with the stored hash
?>

That's not it: think about brute force attacks

This method is not completely safe if you do not protect your users from brute force attacks (when a 12 y/o hacker tries a few thousand passwords on your website).
If you do not know anything about this, take a few minutes to read this Wikipedia article.
You should count the number of password mistakes for each user and block the account after 3 or 5 mistakes.

For example, here is a user login MySQL table :
mysql> CREATE TABLE  `account_login` (
    `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
    `user_login` VARCHAR( 255 ) NOT NULL ,
    `user_pass` VARCHAR( 255 ) NOT NULL ,
    `user_pass_errors` INT( 2 ) NOT NULL DEFAULT  '0'
) ENGINE = MYISAM ;
Let's say we have a few users :
mysql> SELECT * FROM account_login;
+----+------------+------------------------------------------+------------------+
| id | user_login | user_pass                                | user_pass_errors |
+----+------------+------------------------------------------+------------------+
|  1 | Gab        | 36aa8098c0384d593a30af171089e54aeee0c746 |                0 |
|  2 | Paul       | 9750006616180deb6af035c2755e303130e1ea9e |                0 |
|  3 | Robert     | 6fa27bc8bd24b8e13b9bb21e5c080e29eaa58753 |                0 |
+----+------------+------------------------------------------+------------------+
3 rows in set (0.00 sec)
When a user tries to log into his account, you can try to match his input (salted) with the good password stored in the database :
mysql> SELECT id FROM account_login WHERE user_login = 'Gab' AND user_pass = 'ac33b5386a536d6b2fc80f70200e273f77b431fb' AND user_pass_errors <= 5;
Empty set (0.00 sec)
In the example above, there is no result. The user input is incorrect or he made more than 5 errors. You need to increment his error counter :
mysql> UPDATE account_login SET user_pass_errors = user_pass_errors + 1 WHERE user_login = 'Gab';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0
You will now see one error for the user "Gab" :
mysql> SELECT * FROM account_login;
+----+------------+------------------------------------------+------------------+
| id | user_login | user_pass                                | user_pass_errors |
+----+------------+------------------------------------------+------------------+
|  1 | Gab        | 36aa8098c0384d593a30af171089e54aeee0c746 |                1 |
|  2 | Paul       | 9750006616180deb6af035c2755e303130e1ea9e |                0 |
|  3 | Robert     | 6fa27bc8bd24b8e13b9bb21e5c080e29eaa58753 |                0 |
+----+------------+------------------------------------------+------------------+
3 rows in set (0.00 sec)
After 5 mistakes, his account will be locked (because we have the instruction "AND user_pass_errors <= 5" in the initial query). He will need to contact you to unlock his account. Make sure to check his identity before to unlock his account (copy of an ID, birth date...).

With theses solutions, you should well protect your customers and save your PR budget in case of a data leak.
Last update of this page: May 31, 2017
Please do not copy any of the content of this website without asking me first.