PHP Notes - Encryption
Hash
password_hash() creates a new password hash using a strong one-way hashing algorithm.
password_verify() checks to see if a given password matches a hashed password.
password_hash( string $password, string|int|null $algo, array $options = [] ): string
The following algorithms are currently supported:
PASSWORD_DEFAULT | Use the bcrypt algorithm (default as of PHP 5.5.0). Note that this constant is designed to change over time as new and stronger algorithms are added to PHP. For that reason, the length of the result from using this identifier can change over time. Therefore, it is recommended to store the result in a database column that can expand beyond 60 characters (255 characters would be a good choice). |
---|---|
PASSWORD_BCRYPT | Use the CRYPT_BLOWFISH algorithm to create the hash. This will produce a standard crypt() compatible hash using the "$2y$" identifier. The result will always be a 60 character string, or false on failure. |
PASSWORD_ARGON2I | Use the Argon2i hashing algorithm to create the hash. This algorithm is only available if PHP has been compiled with Argon2 support. |
PASSWORD_ARGON2ID | Use the Argon2id hashing algorithm to create the hash. This algorithm is only available if PHP has been compiled with Argon2 support. |
password |
The user's password Note: Using the PASSWORD_BCRYPT as the algorithm, will result in the password parameter being truncated to a maximum length of 72 bytes. |
---|---|
algo | A password algorithm constant denoting the algorithm to use when hashing the password. |
options |
An associative array containing options. See the password algorithm constants for
documentation on the supported options for each algorithm. If omitted, a random salt will be created and the default cost will be used. |
Return Values | Returns the hashed password. |
<?php echo password_hash("rasmuslerdorf", PASSWORD_DEFAULT); ?>
$2y$10$IRwiqYXmy188dv/R5vedAOB2owIrfuATGsBXrTsLBpolMAmCGg81q
password_verify( string $password, string $hash ): bool
password | The user's password. |
---|---|
hash | A hash created by password_hash(). |
Return Value | Returns true if the password and hash match, or false otherwise. |
<?php $hash = password_hash("rasmuslerdorf", PASSWORD_DEFAULT); if (password_verify('rasmuslerdorf', $hash)) { echo 'Password is valid!'; } else { echo 'Invalid password.'; } ?>
Password is valid!
User Login
The login process usually involves two pieces of information, a user name and a pass word. For security purposes this is most often this is done while in SSL mode for a site with a valid SSL certificate. It makes sense that the data being sent should be encrypted.
Client Side
- User enters their username and password then clicks a button to submit it for verification.
- Javascript validates that the data is in the correct format and that it is not empty.
- Javascript makes an AJAX call to the server to process the request.
Server Side
- Posted information is gathered
- Database is opened and SQL is applied
- Submitted data is compared to record data
- Data is returned to the client
Client Side
- Response is processed
Sending Data
- Delimited Text - Sending data as a delimited string.
- JSON - Sending data as JSON from a converted JS Object.
- FormData - Sending data as FormData.
let data = "username="+ username.value +"&userpass="+ userpass.value; ... xmlhttp.send(data);
let data = {}; // JS OBJECT data.hidVal1 = hidVal1.value; data.hidVal2 = hidVal2.value; data.hidVal3 = hidVal3.value; data.username = username.value; data.userpass = userpass.value; // CONVERT JS OBJECT TO JSON let json_str = JSON.stringify(data); ... xmlhttp.setRequestHeader("Content-Type","application/json;charset=UTF-8"); xmlhttp.send(json_str);
<form id="form3" name="form3"> ... </form> // JavaScript let form3 = document.forms.form3; let formData = new FormData(form3); // ADD A COUPLE OF FIELDS TO THE FORM DATA formData.append("altName", "Drogo"); formData.append("accountNum", 123456); ... xmlhttp.send(formData);
Received Data - Server Side
$username = $_POST['username']; $userpass = $_POST['userpass'];
$json = file_get_contents('php://input'); $data = json_decode($json); $hidVal1=$data->hidVal1; $hidVal2=$data->hidVal2; $hidVal3=$data->hidVal3; $username=$data->username; $userpass=$data->userpass;
- Retrieving the JSON sent cannot be done with $_POST[].
- It must be obtained by using php://input as the parameter to the PHP file_get_contents() function.
- php://input is a read-only stream that allows you to read raw data from the request body.
- php://input is not available with enctype="multipart/form-data".
- Once the raw data is retrieved it must be decoded using the PHP function json_decode before it can be used.
// GET POST VALUES $hidVal1 = $_POST['hidVal3_1']; $hidVal2 = $_POST['hidVal3_2']; $hidVal3 = $_POST['hidVal3_3']; $username = $_POST['username']; $userpass = $_POST['userpass']; $altName = $_POST['altName']; $accountNum = $_POST['accountNum'];
Returned Data
The returned data may be simple text or JSON. If the response from the PHP file is JSON, it must be parsed by javascript using JSON.parse() before it can be used.
... xmlhttp.onreadystatechange=function() { if (xmlhttp.readyState==4 && xmlhttp.status==200) { ProcessResponseJson(xmlhttp.responseText); } } xmlhttp.open("POST","SomeFile.php",true); xmlhttp.setRequestHeader("Content-Type","application/json;charset=UTF-8"); xmlhttp.send(json_str); ... let ProcessResponseJson = function(respText) { let rtObj = JSON.parse(respText); let resp_str = ""; resp_str = "hidVal1: "+ rtObj.hidVal1 +"<br/>" resp_str += "hidVal2: "+ rtObj.hidVal2 +"<br/>" resp_str += "hidVal3: "+ rtObj.hidVal3 +"<br/>" resp_str += "Username: "+ rtObj.username +"<br/>" resp_str += "Alt Name: "+ rtObj.altName +"<br/>" resp_str += "accountNumber: "+ rtObj.accountNumber +"<br/>" ... }
Login Sample
Username: <input type="text" id="username" name="username" required /> Password: <input type="password" id="userpass" name="userpass" required /> <input type="button" id="btn_login1" name="btn_login1" value="Register" />
window.addEventListener("DOMContentLoaded", (event) => { const btn_login1 = document.getElementById("btn_login1"); if (btn_login1) { btn_login1.addEventListener("click", function() { post_proc1(); },false); } else { console.log("Button does not exist yet"); } let post_proc1 = function() { let xmlhttp; let username = document.getElementById("username"); let userpass = document.getElementById("userpass"); let response = document.getElementById("login_results1"); let errorstr = ""; let data = ""; // VALIDATE CONTENT HERE // AJAX CALL TO SERVER if (errorstr == "") { // PACKAGE THE DATA data = "username="+ username.value +"&userpass="+ userpass.value; if (window.XMLHttpRequest) { xmlhttp = new XMLHttpRequest(); } else { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.onreadystatechange=function() { if (xmlhttp.readyState==4 && xmlhttp.status==200) { //ProcessResponseFunc(xmlhttp.responseText); response.innerHTML = "Login Called:"+ xmlhttp.responseText; } } xmlhttp.open("POST","SomeFile.php",true); xmlhttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); xmlhttp.send(data); } }; let ProcessResponseFunc = function(respText) { let rtObj = JSON.parse(respText); // rtObj.Val1 // rtObj.Val2 // rtObj.Val3 // ... }; });
$_POST - HTTP POST Variables
An associative array of variables passed to the current script via the HTTP POST method when using application/x-www-form-urlencoded or multipart/form-data as the HTTP Content-Type in the request.
This is a 'superglobal', or automatic global, variable. This simply means that it is available in all scopes throughout a script. There is no need to do global $variable; to access it within functions or methods.