Simple PHP crypt() and MySQL implementation using SHA256

New PHP versions have some nice build-in cypt() features that you can use to securely store your users password to e.g mysql database. I am going to demonstrate and explain why you should encrypt passwords and how that can easily improve your sites basic security. I hope this helps you to better understand passwords, hashes and crypting.

Using PHP crypt() function

<?php
$userspassword = "ThisIsVeryHardPassword!123";
 
// Idea of salt is to make users password longer
// so that it's not vulnerable to attacks like http://en.wikipedia.org/wiki/Rainbow_table
 
$salt = "CrazyassLongSALTThatMakesYourUsersPasswordVeryLong123!!312567__asdSdas";
 
// Now users password will be = 
// CrazyassLongSALTThatMakesYourUsersPasswordVeryLong123!!312567__asdSdas + ThisIsVeryHardPassword!123
 
 
// Users password will now be combined (password+salt) to sha256 hash
$password = hash('sha256', $salt.$userspassword);
 
echo $password;
// output: fb5f7c18a269257d13fe0c409e5dc4f90c1fb9b6fa54996b58356591e0edd8ca
?>

If you want to add extra layer of security you can generate unique salt to each user and store that. Often it’s not really necessary in my opinion because as long as you use good long salt it will be enough to defend against rainbow tables. Just make sure that your users use enough complex password.

Salt is not really a secred and you don’t have to worry about it. Salt by itself wont open any passwords. It just adds more character to password making hash more complex against pre-hashed rainbow tables.

Authenticate crypted password with MySQL

First, the basic idea of crypting and storing password is that after user enters password it will never be plain text again. This means that when you check if password is a match you just compare stored hash with the hash you generate from user inputs. Picture below tries to explain same thing. If you are using unique salt for each user you must first retrive users salt from database and then generate hash and check if it’s a match.

Basic idea of veryfiying user with crypted password
Basic idea of veryfiying user with crypted password using php and mysql

Example code PHP MYSQL Using crypt() SHA256

<?php
  // Basic php MYSQL authentication with crypted password

  $username = $_POST['username'];
  $password = $_POST['password'];
  $salt = "CrazyassLongSALTThatMakesYourUsersPasswordVeryLong123!!312567__asdSdas";
  $password = hash('sha256', $salt.$password);
  //echo $password;
  
  // Mysql connection
  $mysqli = new mysqli("localhost","mysqluser","mysqlpassword","mysqldatabase");
  $stmt = $mysqli->prepare('SELECT userid FROM Users WHERE password = ? AND username = ?');
  // (ss -> string, string) Always bind parameters and use prepared statement to improve security
  $stmt->bind_param("ss", $password, $username);
  $stmt->execute();
  $stmt->bind_result($userid );

  if (!empty($stmt->fetch())) {
    // if fetch is not empty we have results and password hash was correct
    echo "User was found";
  } else
    echo "User was not found";

$mysqli->close();
?>

When you are testing, make sure that you have crypted password stored already in your database with same hash, otherwise it will never match. If you hashed password matches to the hash in MySQL database, user can login.

Conclusions

Sha256 is definetly better than using MD5 or storing passwords plain text. It adds extra layer of protection without hard work and there is not really difference between sha512 and sha256. If you want more secure way to encrypt your data you should use something like bcrypt. For more info about secure crypt methods you can read Bcrypt which is designed for this type of crypting and offers better protection for brute-force attacks. PHP supports Bcrypt

From Wikipedia about Bcrypt:

bcrypt is an adaptive function: over time, the iteration count can be increased to make it slower, so it remains resistant to brute-force search attacks even with increasing computation power.

But for now in my opinion sha256 is enough protection for average site and if you like you can increase rounds of hashing are performed to make it more complex. You can read more about it here.

Why use hash and encrypt password?

You should always store your users passwords in encrypted format because many users unfortunately use same password to their email and others services and if your sites database gets compromised and attacker get a hold of your database then all passwords are still crypted and you have more time to warn your users and ask then to change passwords. Also attacker can’t login to your service if he only have password hashes without cracking them because your database only contains hashes, not actual passwords.

And if the worst case scenario happens and you lose your database, you can still say that passwords are safely encrypted and it’s highly unlikely that attacker can to get them, so good PR for you in bad situation.

Mainokset

PHP Painoindeksilaskuri

Seuraavassa on esiteltynä php:llä koulutyönä tehty painoindeksilaskuri. Voit ladata toimivat kooditiedostot artikkelin lopusta. Tässä raportissa käyn läpi koodin sisältöä ja selitän sen ominaisuuksia ja sitä, mitä jokainen kohta tekee

Esimmäiseksi teemme tiedoston kysymys.html jossa keräämme tiedot käyttäjän painosta ja pituudesta.

<form action="tulos.php" method="post">
<p>Pituus:(<b>HUOM syötä pituus muodossa x.xx käyttäen pistettä</b>)</p><input type="text"value="1.70" name="pituus" />
<p>Paino:(Anna arvo kiloina esimerkiksi 70)</p><input type="text" value="70" name="paino" />     
<p><input value="Lähetä tiedot" type="submit" /></p>
</form>

Tämä kohtaa kerää käyttäjiltä tiedot ”paino” & ”pituus” ja siirtää ne tulos.php tiedostoon

Seuraavaksi tarvitsemme tulos.php tiedoston.

Tässä kohdassa keräättä käyttäjien tiedot paino & pituus ja luomme tämän jälkeen näistä samannimiset muuttujat

<?php
//Otetaan lomakkeesta lähetetyt tiedot paino ja pituus
$paino=$_POST[paino];
$pituus=$_POST[pituus];

Tarkistetaan, että käyttäjän syöttämät tiedot ovat varmasti numeroita ennen jatkoa. Muuten toiminto keskeytetään ja annetaan käyttäjälle virheilmoitus

if (is_numeric($paino) && is_numeric($pituus)) {

Seuraavaksi lasketaan käyttäjien antamat tiedot ja kohdassa round($tulos, 2); pyöristetään tulos 2 desimaalin tarkkuuteen. Painoindeksi lasketaan kaavalla pituus/(paino^2)

$lasku = (pow($pituus,2));
$tulos=$paino/$lasku;
$tulos=round($tulos, 2);

Tässä kohdassa vertaillaan käyttäjän painoindeksiä ja tarkistetaan mihin kohtaan se sopii. Tämän jälkeen tulostetaan käyttäjälle tiedot hänen painoindeksistä ja annetaan vinkki.

if($tulos < 14.99)
echo "Painoindeksi on ".$tulos."<p>Vinkki: Joten Nyt syömään äkkiä sillä olet sairaalloise alipainoinen</p>";
elseif($tulos < 16.99)
echo "<p>Merkittävä alipaino.</p> Painoindeksi: ".$tulos."<p>Vinkki: Olisiko hampurilaisen paikka ?</p> ";
elseif($tulos < 18.4)
echo "<p>Normaalia alhaisempi paino.</p> Painoindeksi: ".$tulos."<p>Vinkki: Muista syödä päivisin enemmän</p>";
elseif($tulos < 24.9)
echo "<p>Normaali paino.</p>Painoindeksi: ".$tulos."<p>Vinkki: Hyvä, sinulla näyttäisi olevan normaali paino!</p>";
elseif($tulos < 29.9)
echo "<p>Lievä ylipaino</p>Painoindeksi: ".$tulos."<p>Vinkki: Kannattaisiko kenties jättää illalla muutama leipä syömättä ?</p>";
elseif($tulos < 34.9)
echo "<p>Merkittävä ylipaino</p> Painoindeksi: ".$tulos."<p>Vinkki: Et taida olla rantakunnossa ? </p>";
elseif ($tulos < 39.9)
echo "<p>Vaikea ylipaino</p>".$tulos."<p>Vinkki: Nyt olisi aika laittaa ruokatottumukset uusiksi. Ylipainoisuus on vakava asia!</p>";
elseif ($tulos > 39.91)
echo "<p>Sairaalloinen ylipaino</p> Painoindeksi: ".$tulos."<p>Vinkki: Suosittelen lääkäriin menoa - Tuloksesi on erittäin vakava</p>";
}

Jos käyttäjä oli alussa syöttänyt vääriä tietoja, kerrotaan ohjeet miten paino ja pituus tulisi syöttää

    } else {
    echo "<p>Error - Yritä uudelleen. Muista syöttää pituus muodossa x.xx jossa x on numero ja käyttää välissä pistettä, <u>eikä pilkkua</u>.</p><p>Paino tulee syöttää numeroina xxx ilman muita merkkejä</p> <a href='kysymys.html'>Palaa takaisin</a>";
}

Lataa Tiedostot:

Lataa lähdekoodi Tästä

Lisenssi

Jos meinaat hyödyntää tätä ohjelmaa sellaisenaan, olisin kiitollinen linkistä takaisin tähän blogiin.

Tätä dokumenttia saa kopioida ja muokata GNU General Public License (versio 2 tai uudempi) mukaisesti. http://www.gnu.org/licenses/gpl.html

Lähteet tämän ohjelman luontiin:

Tero Karvinen / HAAGA-HEALIA oppitunnit / 2.9, 4.9.2012

http://www.php.net/

http://www.ohjelmointiputka.net