About Passwords (Outdated do not use)

If you want to host your own web service, at some point you'll most likely need to store passwords.

Here are some [insecure, outdated] ideas of keeping the passwords safe:

  1. Don't store passwords at all. Use Google/Facebook/OpenID to log in.1

  2. If you can't hash and salt them2

  3. Don't use PHP's == for comparing passwords. Use === or don't use PHP at all.3

  4. Whatever you do, never send clear-text passwords over the internet. Send passwords from the browser to the server through a SSL (Preferably a TLS 1.2)4 connection. Always remember to keep your password5 up to date!

  5. Do some sort of two-factor authorization. This won't keep the password safe, however other persons won't get access to an account, unless they have the owner's phone or PC.

Using Google to log in

ProsCons
Most persons have a Google accountSome persons don't use Google for privacy reasons.
One button to log in. One to log offRequires Javascript knowledge to be able to work with things like name and email.6
Can use same 'Project' in Android AppsOne password problem: If someone steals the user's Google account's password, they have the password for your service, too7

I haven't tried it, but it looks pretty straightforward

Hash and Salt password

ProsCons
Very hard to reverse8Bug-Prone: crypt() in PHP's default settings will truncate the password to 8 characters making it almost trivial to brute-force it.9
Lots of code examples. Most forum softwares use this apporach.10

Here is a quick python code example. user is a tuple containing ('username', 'hash', 'salt')

A salt is a random integer and is stored in cleartext in the database.

Suggested hashing algorithms: SHA-111, SHA-211, SHA-311. Please be kind and don't use MD5 or MD4.12

Two factor authorization

This option is not necessarily user-friendly if your server can't send texts, however you can still ask users for an OTP-Password. It's a 6-digit number which changes every 30 seconds and is different from each user. One problem here: You need a private13 key to generate the OTP on the clientside and the same key on serverside to verify.when hacked, the password is pretty much exposed, however you can maybe encrypt it in the database14. (with AES-256-CTR or RSA 4096)15

Never encrypt the user's passwords! If the (private)13 key ever gets leaked, all the passwords can be decrypted!

Password requirements

  • Minimum password length: 8 characters
  • Maximum password length: none/4 Billion characters
  • Password contents: Any combination of printable, non-zero-width, Unicode characters, but at least one number character, one punctuation character. 16
  • Make sure password stays same when trim()ing it! (No leading or trailing space characters)
  • Ask users to change passwords every 3 months- 17

I'll probably write another article about this subject later.

Author's Annotations (2020)

1

This might still be a good idea in 2020, but password security has increased on both the client and the server, plus it reduces the risk of having a "single point of failure"

2

Unlike what the article suggests, you do so using strong key derivation functions like scrypt or argon2id.

3

Not sure what sparked this reccommendation, I think it had something to do with its weak typing

4

Update 2020: Support only TLS 1.2 and 1.3 unless you have to support stupidly old clients

5

I almost certainly meant "certificate" here

6

Given how popular javascript is, I highly doubt this is a problem

7

This password compromise thing can also happen with password managers. It can always happen without zero-knowledge password proofs which are way beyond my ability to explain concisely or this endnote

8

This is false for the method shown in this section. sha2 was never meant to hash passwords. Use argon2id or scrypt instead.

9

The bigger problem is not that its maximum password length is 8 but that it will silently truncate to 8 characters as crypt() uses the password as a DES key to encrypt a block of zeroes. It's just way too quick for password hashing

10

Pretty sure the following code snippet is based on what a lot of forum software did at the time

11

No. Use argon2id or scrypt.

12

Don't use these at all. This also includes sha1.

13

secret* key. private keys are something else and i should have known that

14

Security by obscurity is bullshit. If someone has access to the database server they likely also have access to the secret key.

15

No.

16

No password composition rules please thank you

17

Do not ask users to change their passwords unless there is evidence of compromise