Sunday, 24 June 2018

The Rope Anatomy Analogy

My time in the Republic of Singapore Navy brought me into contact with rope. Lots of rope. Miles and miles of rope. So today, I wanna talk about... yep, you guessed it. Rope.

A rope looks like just some long thick string you use to tie stuff. But it's actually a work of physics. Let's take a look at how a typical three-strand rope is constructed.

Firstly, we have fibers. They could be hemp, manila or even hair. Each bunch of fibers is twisted in a clockwise direction to form a rope yarn.

Now, a group of rope yarns are twisted together in an anti-clockwise direction to form a strand. Got that so far?

When you have three strands, put them together and twist them in a clockwise direction. This forms your basic rope.

Taken from
http://www.boatsafe.com/marlinespike/rope.htm


What's with all that clockwise and anti-clockwise stuff, you may ask. Well, when you twist something in any direction, its natural instinct is to twist back into its original shape. This means that if a bunch of fibers was twisted in a clockwise direction to form a rope yarn and made to stay that way, there would be potential energy locked within that rope yarn just waiting to un-twist back the way it was. If a bunch of these yarns were then twisted in an anti-clockwise direction into a strand, the different directional forces would counteract each other. Now you add one more layer of opposing force on top of this - twisting the strands clockwise into a rope - and this is where the strength of a rope comes from.

The Web Development Analogy

A web application goes through layering as well. Different components such as session management, security protocols, database connections and so on, make up the core of the application. On top of those, another layer is built. This is the DOM, and the user interface. These layers interact with each other, turning the web application into a strong sturdy piece of engineering - just like the humble rope.

Nope, a web application isn't simply just a web application. Even if you didn't have to deal with all the infrastructure and scaffolding; even if you simply coded features, that doesn't mean those layers aren't there. That is precisely why it's often not enough for a developer to know how to code either in the back-end or in the front-end. Developers have to understand how the different layers interact with and complement each other; how every layer affects the layer preceding it and following it. Because, similar to how a rope gets its strength from the opposing tensions generated by its different layers, that is how a web application gets its strength.

Where there's life, there's rope!
T___T

Tuesday, 19 June 2018

Web Tutorial: AngularJS Password Strength Validator (Part 2/2)

In the previous part, we implemented quite a few checks for password strength. Now, we're going to implement a Dictionary Check. This basically checks for any words in the password that can be found in the dictionary. This is important because most password-guessing attacks use a dictionary. So in order to be safe, you probably want to check the given password for such vulnerabilities.

There's a catch, though. Unless you're willing to host an entire dictionary database on your server, you'll have to use an API. The good news is, the Internet is full of these APIs. The one we're going to use today is at Oxford Dictionaries. We are going to use an AJAX call to this URL, passing in a series of strings that might be words, and the returned result will determine if any of the strings you sent, are actually dictionary words.

So, first, register an account and obtain a key.


Next, create a file, validate.php. In there, obtain the POST variables, url and words, and assign them to local variables. words will be a JSON array, so we need to run it through the json_decode() function.

Then declare two variables, wordsFound (which defaults to false) and wordToValidate. This file will print out an array, result, which contains wordsFound in JSON format.

validate.php
<?php
$url = $_POST["url"];
$words = json_decode($_POST["words"]);
$wordsFound = false;
$wordToValidate = "";

$result = array("wordsFound" =>$wordsFound);
echo json_encode($result);
?>


Next, implement a For loop to iterate through the words array. For each iteration, set wordToValidate to the current element of the words array.

validate.php
<?php
$url = $_POST["url"];
$words = json_decode($_POST["words"]);
$wordsFound = false;
$wordToValidate = "";

for ($i = 0; $i < sizeof($words); $i++)
{
    $wordToValidate = $words[$i];
}

$result = array("wordsFound" =>$wordsFound);
echo json_encode($result);
?>


We'll use cURL to access the URL. First, we have to initialize an object using the curl_init() function. Then we need to disable verification. Note that this is not recommended in a live environment - you need to verify stuff to ensure it's safe. But for the purposes of this exercise, sure, disable it.

validate.php
<?php
$url = $_POST["url"];
$words = json_decode($_POST["words"]);
$wordsFound = false;
$wordToValidate = "";

for ($i = 0; $i < sizeof($words); $i++)
{
    $wordToValidate = $words[$i];
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
}

$result = array("wordsFound" =>$wordsFound, "word" => $wordToValidate);
echo json_encode($result);
?>


Now we use the curl_setopt_array() function, passing in the curl object and an array as arguments. And after that, we execute the curl_close() function on the curl object.

validate.php
<?php
$url = $_POST["url"];
$words = json_decode($_POST["words"]);
$wordsFound = false;
$wordToValidate = "";

for ($i = 0; $i < sizeof($words); $i++)
{
    $wordToValidate = $words[$i];
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);

    curl_setopt_array($curl, array()));

    curl_close($curl);
}

$result = array("wordsFound" =>$wordsFound);
echo json_encode($result);
?>


In the array, we include key-value pairs that will work as configuration. CURLOPT_URL will be set to the URL and the current word in the words array. The rest is pretty straightforward until you get to the last part, which is yet another array, CURLOPT_HTTPHEADER. This is where your id and key for the API are to be passed in. This is important. The API host is not going to let you use its services without some form of verification. No, my id and key aren't "xxxxx". Just get your own, already.

validate.php
<?php
$url = $_POST["url"];
$words = json_decode($_POST["words"]);
$wordsFound = false;
$wordToValidate = "";

for ($i = 0; $i < sizeof($words); $i++)
{
    $wordToValidate = $words[$i];
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);

    curl_setopt_array($curl, array(
    CURLOPT_URL => $url . $wordToValidate,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "GET",
    CURLOPT_HTTPHEADER => array(
    "app_id: xxxxx",
    "app_key: xxxxx"
    ),
    ));

    curl_close($curl);
}

$result = array("wordsFound" =>$wordsFound);
echo json_encode($result);
?>


Now, run the function curl_exec() on the curl object, and return the result to the variable response.

validate.php
<?php
$url = $_POST["url"];
$words = json_decode($_POST["words"]);
$wordsFound = false;
$wordToValidate = "";

for ($i = 0; $i < sizeof($words); $i++)
{
    $wordToValidate = $words[$i];
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);

    curl_setopt_array($curl, array(
    CURLOPT_URL => $url . $wordToValidate,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "GET",
    CURLOPT_HTTPHEADER => array(
    "app_id: xxxxx",
    "app_key: xxxxx"
    ),
    ));

    $response = curl_exec($curl);

    curl_close($curl);
}

$result = array("wordsFound" =>$wordsFound);
echo json_encode($result);
?>


The response will contain a "404" if no matches are found, and an array of matches otherwise. Now, we don't actually care how many matches there are - we just need to know that there is at least one match. So, if there's no "404" in the result, wordsFound is true. Not exactly ironclad logic, but it'll do for now.

validate.php
<?php
$url = $_POST["url"];
$words = json_decode($_POST["words"]);
$wordsFound = false;
$wordToValidate = "";

for ($i = 0; $i < sizeof($words); $i++)
{
    $wordToValidate = $words[$i];
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);

    curl_setopt_array($curl, array(
    CURLOPT_URL => $url . $wordToValidate,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "GET",
    CURLOPT_HTTPHEADER => array(
    "app_id: xxxxx",
    "app_key: xxxxx"
    ),
    ));

    $response = curl_exec($curl);

    if (strpos($response, "404") === false) $wordsFound = true;

    curl_close($curl);
}

$result = array("wordsFound" =>$wordsFound, "word" => $wordToValidate);
echo json_encode($result);
?>


Now, we'll want to work on the JavaScript some more. Let's start by dissecting the entered password and retrieving all the possible words of five letters and above from it. For this, we'll use the getWords() function which we'll create later. We'll pass in the scope variable enteredPassword, and the result will be the value of a new variable, possibleWords.

js/main.js
        if (/[0-9]/g.test($scope.enteredPassword))
        {
            pts ++;
        }
        else
        {
            $scope.strengthMessage += "Try including numbers in your password.\n";
        }

        var possibleWords = getWords($scope.enteredPassword)


Let's create the getWords() function. In this function, we declare the variable newArr as an empty array. At the end of the function, we will return newArr. We'll also create another array, arr, splitting the password by any non-alphanumeric characters. Thus, if you enter in a password like "teochew-thunder3pass@word", you'll get an array containing "teochew", "thunder", "pass" and "word".

js/main.js
    function getWords(password)
    {
        var arr = password.split(/[^A-Za-z]/);
        var newArr = [];

        return newArr;
    }

    function getCode(pts)
    {
        if (pts <= 0) return "weak";   
        if (pts == 1) return "moderate";   
        if (pts == 2) return "strong";   
        if (pts >= 3) return "excellent";
    }


However, we only want words that are 5 characters and above. Because searching for words 4 letters and below would return too many positives. Thus, we iterate through the arr array, and push any result greater than 4 characters, into the newArr array. We also convert the pushed string to lowercase. Thus, if the array contained "teochew", "thunder", "pass" and "word", only "teochew" and "thunder" would get through.

js/main.js
    function getWords(password)
    {
        var arr = password.split(/[^A-Za-z]/);
        var newArr = [];

        for (var i = 0; i <arr.length; i++)
        {
            if (arr[i].length > 4)
            {
                newArr.push(arr[i].toLowerCase());
            }
        }

        return newArr;
    }


Next, we're going to get all possible words within the strings in newArr. Declare another variable, tempArr, as an empty array. Iterate through newArr with a For loop. The operation will only affect those strings that are longer than 5 characters, so put in a conditional for that.

js/main.js
    function getWords(password)
    {
        var arr = password.split(/[^A-Za-z]/);
        var newArr = [];

        for (var i = 0; i <arr.length; i++)
        {
            if (arr[i].length > 4)
            {
                newArr.push(arr[i].toLowerCase());
            }
        }

        var tempArr = [];

        for (var i = 0; i < newArr.length; i++)
        {
            if (newArr[i].length > 5)
            {

            }
        }

        return newArr;
    }


Now, this is how we process the strings that are greater than 5 characters. Say, for the string "teochew", we will derive the strings "teoch", "teoche", "teochew", "eoche", "eochew" and "ochew".

Next up is another nested For loop. The outer loop will start the search from strings beginning with the first three letters of the string "teochew", because starting the string with anything after those first three letters will net you a string of less than 5 characters.

The inner loop will process strings of 5 characters and above, to the maximum allowed by the length of the string "teochew".

js/main.js
    function getWords(password)
    {
        var arr = password.split(/[^A-Za-z]/);
        var newArr = [];

        for (var i = 0; i <arr.length; i++)
        {
            if (arr[i].length > 4)
            {
                newArr.push(arr[i].toLowerCase());
            }
        }

        var tempArr = [];

        for (var i = 0; i < newArr.length; i++)
        {
            if (newArr[i].length > 5)
            {
                for (var j = 0; j < newArr[i].length - 4; j++)
                {
                    for (var k = 5; k < newArr[i].length; k++)
                    {
               
                    }
                }
            }
        }

        return newArr;
    }


Thus, the sub-string is represented by newArr[i].substr(j, k). We then check if it's already in tempArr before pushing it in.

js/main.js
    function getWords(password)
    {
        var arr = password.split(/[^A-Za-z]/);
        var newArr = [];

        for (var i = 0; i <arr.length; i++)
        {
            if (arr[i].length > 4)
            {
                newArr.push(arr[i].toLowerCase());
            }
        }

        var tempArr = [];

        for (var i = 0; i < newArr.length; i++)
        {
            if (newArr[i].length > 5)
            {
                for (var j = 0; j < newArr[i].length - 4; j++)
                {
                    for (var k = 5; k < newArr[i].length; k++)
                    {
                        if (j + k <= newArr[i].length)
                        {
                            if (tempArr.indexOf(newArr[i].substr(j, k).toLowerCase()) == -1)
                            tempArr.push(newArr[i].substr(j, k).toLowerCase());   
                        }               
                    }
                }
            }
        }

        return newArr;
    }


After that, we use another For loop to iterate through tempArr. If newArr does not already contain the element in tempArr (this is possible because you may be processing multiple identical strings, for example, if the password was "teochew-teochew3pass@word"), then push that element into newArr.

js/main.js
    function getWords(password)
    {
        var arr = password.split(/[^A-Za-z]/);
        var newArr = [];

        for (var i = 0; i <arr.length; i++)
        {
            if (arr[i].length > 4)
            {
                newArr.push(arr[i].toLowerCase());
            }
        }

        var tempArr = [];

        for (var i = 0; i < newArr.length; i++)
        {
            if (newArr[i].length > 5)
            {
                for (var j = 0; j < newArr[i].length - 4; j++)
                {
                    for (var k = 5; k < newArr[i].length; k++)
                    {
                        if (j + k <= newArr[i].length)
                        {
                            if (tempArr.indexOf(newArr[i].substr(j, k).toLowerCase()) == -1)
                            tempArr.push(newArr[i].substr(j, k).toLowerCase());   
                        }               
                    }
                }
            }
        }

        for (var i = 0; i < tempArr.length; i++)
        {
            if (newArr.indexOf(tempArr[i].toLowerCase()) == -1)
            newArr.push(tempArr[i].toLowerCase());
        }

        return newArr;
    }


Now back to the processPassword() scope function!  Wrap the call to the getCode() function in an If statement. If the getWords() function had returned a non-empty array, we'll do more processing. If not, we end the function there with a return statement.

js/main.js
        var possibleWords = getWords($scope.enteredPassword)

        if (possibleWords.length > 0)
        {

        }
        else
        {
            $scope.strengthCode = getCode(pts);
            return;
        }


To process a non-empty array containing all the words you want to validate against the dictionary,  call some AJAX. Everything's pretty standard here. The file you are sending the POST to, is the validate.php file we wrote earlier. You pass in arguments such as a JSON string of the words, and the URL where your API resides.

js/main.js
        var possibleWords = getWords($scope.enteredPassword)

        if (possibleWords.length > 0)
        {
            var xmlhttp = new XMLHttpRequest();
            xmlhttp.onreadystatechange = function()
            {
                if (this.readyState == 4 && this.status == 200)
                {

                }
            };

            xmlhttp.open("POST", "validate.php", true);
            xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            xmlhttp.send("words=" +  JSON.stringify(possibleWords) + "&url=https://od-api.oxforddictionaries.com/api/v1/entries/en/");
        }
        else
        {
            $scope.strengthCode = getCode(pts);
            return;
        }



Next, you use the parse() method of the JSON object on the returned response. If wordsFound is true, then decrement pts, set the strengthMessage and strengthCode variables, and return.

js/main.js
        var possibleWords = getWords($scope.enteredPassword)

        if (possibleWords.length > 0)
        {
            var xmlhttp = new XMLHttpRequest();
            xmlhttp.onreadystatechange = function()
            {
                 if (this.readyState == 4 && this.status == 200)
                 {
                      var result = JSON.parse(this.responseText);

                      if (result.wordsFound)
                      {
                          pts --;
                          $scope.strengthMessage += "Avoid using dictionary words. (" + result.word + ")\n";   
                          $scope.strengthCode = getCode(pts);
                          return;
                       }
                  }
            };

            xmlhttp.open("POST", "validate.php", true);
            xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            xmlhttp.send("words=" +  JSON.stringify(possibleWords) + "&url=https://od-api.oxforddictionaries.com/api/v1/entries/en/");
        }
        else
        {
            $scope.strengthCode = getCode(pts);
            return;
        }


Try it!


Something seems to have gone wrong... and I'm getting a warning from oxforddictionaries.com!




Yeah, that's to be expected. If you're a cheap bastard like me, you got the free version of the API, which means you can only make that many calls to the API within one minute. If you tested with an extra long password, that would have sent a gazillion requests to the API.

But the logic for this validation is sound... I think.

Till we meet again, stay STRONG.
T___T

Sunday, 17 June 2018

Web Tutorial: AngularJS Password Strength Validator (Part 1/2)

The strength of a password often depends on many factors. Most commonly, the length and composition of a password is what makes it strong or weak. Basically, the harder it is to guess your password, the stronger it is.

Whenever you're asked to change your password by a system, quite often the password has to conform to certain rules. It can't be too short, too predictable, or entirely alphabetical. Some may even insist that it must be a mix of uppercase and lowercase characters.

We're going to be creating this functionality, using AngularJS along with some CSS.

Is it really necessary to use AngularJS?

Well, no. Just that the templating system is pretty useful and saves me some labor. Use what you like!

Also...

This is a two-part tutorial and the second part of this tutorial will involve some AJAX. Thus, a server is required. But the second part is entirely optional, and if you just want to stop at the first (server-less) part, that's entirely OK.

We first create the body in a file, index.html. Remember that for AngularJS, we need to define an Application Scope, and a Controller Scope. They are passvalApp and passvalCtrl respectively. Also, the link to the AngularJS JavaScript file has been included.

index.html
<!DOCTYPE html>
<html>
    <head>
        <title>Password Validator</title>

        <style>

        </style>

        <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
    </head>

        <body ng-app="passvalApp">
        <div ng-controller="passvalCtrl">

        </div>
    </body>
</html>


Here, we'll insert one div, and within that div, nest two divs and put a template field in each. One template field will be strengthCode and the other strengthMessage. We will also have a label and text box, and the text box's id will be txtPassword.

index.html
<!DOCTYPE html>
<html>
    <head>
        <title>Password Validator</title>

        <style>

        </style>

        <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
    </head>

        <body ng-app="passvalApp">
        <div ng-controller="passvalCtrl">
            <label for="txtPassword">Enter your password here: </label>
            <input type="text" id="txtPassword">
            <br />
            <div>
                <div>
                    {{ strengthCode }}
                </div>
                <div>
                    {{ strengthMessage }}
                </div>
            </div>
        </div>
    </body>
</html>


Style the divs.

index.html
            <div class="container">
                <div class="txtStrength">
                    {{ strengthCode }}
                </div>
                <div class="txtMessage">
                    {{ strengthMessage }}
                </div>
            </div>


This is pretty much cosmetic. Just prettying it up a bit.

index.html
        <style>
            .container
            {
                width: 200em;
            }

            .txtStrength
            {
                font-weight: bold;
                font-size: 3em;
                width: 50%;
                float: left;
            }

            .txtMessage
            {
                font-size: 1em;
                width: 50%;
                float: left;
                margin-left: 2em;
                white-space: pre-wrap;
            }
        </style>


So far, this is what we've got.


Now add this. We'll be working on the JavaScript next, which is the main.js file in the js directory. You can choose to embed the JavaScript in the index.html file, but it's a lot neater this way.

index.html
        <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
        <script src="js/main.js"></script>


This is where we start defining events and rules. First, of course, is the Application Scope.

js/main.js
var app = angular.module("passvalApp", []);

app.controller("passvalCtrl",
function($scope)
{

}
);


Here, we define the scope function processPassword() and the scope variables strengthCode, strengthMessage and enteredPassword.
js/main.js
var app = angular.module("passvalApp", []);

app.controller("passvalCtrl",
function($scope)
{
    $scope.processPassword=
    function()
    {

    };

    $scope.strengthCode = "";
    $scope.strengthMessage = "";
    $scope.enteredPassword = "";
}
);


Back to the index.html file, bind in the scope variables to the appropriate DOM elements. We run processPassword() whenever we change the value in the txtPassword text box, and the value of the text box is enteredPassword.

index.html
        <body ng-app="passvalApp">
        <div ng-controller="passvalCtrl">
            <label for="txtPassword">Enter your password here: </label>
            <input type="text" id="txtPassword" ng-change="processPassword()" ng-model="enteredPassword">
            <br />
            <div class="container">
                <div class="txtStrength">
                    {{ strengthCode }}
                </div>
                <div class="txtMessage">
                    {{ strengthMessage }}
                </div>
            </div>
        </div>
    </body>


Now, let's process the password! In the main.js file, add this to the processPassword() function. This basically says that if enteredPassword is empty, don't bother.

js/main.js
    $scope.processPassword=
    function()
    {
        if ($scope.enteredPassword.length == 0) return;
    };


If enteredPassword is less than 8 characters, set strengthCode to "weak", set strengthMessage, then stop processing.
js/main.js
    $scope.processPassword=
    function()
    {
        if ($scope.enteredPassword.length == 0) return;

        if ($scope.enteredPassword.length < 8)
        {
            $scope.strengthCode = "weak";
            $scope.strengthMessage = "Password is too short. 8 characters or above recommended.";
            return;
        }
    };


Try it. Type in something less than 8 characters. Does the message appear?


OK, let's get really serious. Declare a variable, pts and set it to a default of 1. Set strengthMessage to an empty string. From here on, we are handling cases in which enteredPassword is longer than 8 characters, and evaluating how strong the password is based on the composition of the password.

js/main.js
    $scope.processPassword=
    function()
    {
        if ($scope.enteredPassword.length == 0) return;

        if ($scope.enteredPassword.length < 8)
        {
            $scope.strengthCode = "weak";
            $scope.strengthMessage = "Password is too short. 8 characters or above recommended.";
            return;
        }

        var pts = 1;
        $scope.strengthMessage = "";
    };


Now, let's use a regular expression to determine if the password has any special characters. If there are, increment pts. If not, set strengthMessage.

js/main.js
    $scope.processPassword=
    function()
    {
        if ($scope.enteredPassword.length == 0) return;

        if ($scope.enteredPassword.length < 8)
        {
            $scope.strengthCode = "weak";
            $scope.strengthMessage = "Password is too short. 8 characters or above recommended.";
            return;
        }

        var pts = 1;
        $scope.strengthMessage = "";

        if (/[~`!#$%\^&@*+=\-\[\]\\';,/{}|\\":<>\?]/g.test($scope.enteredPassword))
        {
            pts ++;
        }
        else
        {
            $scope.strengthMessage += "Try using special characters in your password.\n";
        }
    };


Repeat the process, but this time use a regular expression for checking if there are any uppercase letters in enteredPassword.

js/main.js
    $scope.processPassword=
    function()
    {
        if ($scope.enteredPassword.length == 0) return;

        if ($scope.enteredPassword.length < 8)
        {
            $scope.strengthCode = "weak";
            $scope.strengthMessage = "Password is too short. 8 characters or above recommended.";
            return;
        }

        var pts = 1;
        $scope.strengthMessage = "";

        if (/[~`!#$%\^&@*+=\-\[\]\\';,/{}|\\":<>\?]/g.test($scope.enteredPassword))
        {
            pts ++;
        }
        else
        {
            $scope.strengthMessage += "Try using special characters in your password.\n";
        }

        if (/[A-Z]/g.test($scope.enteredPassword))
        {
            pts ++;
        }
        else
        {
            $scope.strengthMessage += "Try using a mix of uppercase letter and lowercase letters.\n";
        }
    };


You know the drill by now. This time, we check for numbers.

js/main.js
    $scope.processPassword=
    function()
    {
        if ($scope.enteredPassword.length == 0) return;

        if ($scope.enteredPassword.length < 8)
        {
            $scope.strengthCode = "weak";
            $scope.strengthMessage = "Password is too short. 8 characters or above recommended.";
            return;
        }

        var pts = 1;
        $scope.strengthMessage = "";

        if (/[~`!#$%\^&@*+=\-\[\]\\';,/{}|\\":<>\?]/g.test($scope.enteredPassword))
        {
            pts ++;
        }
        else
        {
            $scope.strengthMessage += "Try using special characters in your password.\n";
        }

        if (/[A-Z]/g.test($scope.enteredPassword))
        {
            pts ++;
        }
        else
        {
            $scope.strengthMessage += "Try using a mix of uppercase letter and lowercase letters.\n";
        }

        if (/[0-9]/g.test($scope.enteredPassword))
        {
            pts ++;
        }
        else
        {
            $scope.strengthMessage += "Try including numbers in your password.\n";
        }
    };


Now, obtain strengthCode by running the getCode() function, and pass pts in as an argument.

js/main.js
    $scope.processPassword=
    function()
    {
        if ($scope.enteredPassword.length == 0) return;

        if ($scope.enteredPassword.length < 8)
        {
            $scope.strengthCode = "weak";
            $scope.strengthMessage = "Password is too short. 8 characters or above recommended.";
            return;
        }

        var pts = 1;
        $scope.strengthMessage = "";

        if (/[~`!#$%\^&@*+=\-\[\]\\';,/{}|\\":<>\?]/g.test($scope.enteredPassword))
        {
            pts ++;
        }
        else
        {
            $scope.strengthMessage += "Try using special characters in your password.\n";
        }

        if (/[A-Z]/g.test($scope.enteredPassword))
        {
            pts ++;
        }
        else
        {
            $scope.strengthMessage += "Try using a mix of uppercase letter and lowercase letters.\n";
        }

        if (/[0-9]/g.test($scope.enteredPassword))
        {
            pts ++;
        }
        else
        {
            $scope.strengthMessage += "Try including numbers in your password.\n";
        }

        $scope.strengthCode = getCode(pts);
        return;
    };


getCode() is not a scope function because we're not attempting to access it from the front-end. So here we have a series of If statements, returning codes that correspond to the value of pts.

js/main.js
    function getCode(pts)
    {
        if (pts <= 0) return "weak";   
        if (pts == 1) return "moderate";   
        if (pts == 2) return "strong";   
        if (pts >= 3) return "excellent";
    }

    $scope.processPassword=
    function()
    {
        if ($scope.enteredPassword.length == 0) return;

        if ($scope.enteredPassword.length < 8)
        {
            $scope.strengthCode = "weak";
            $scope.strengthMessage = "Password is too short. 8 characters or above recommended.";
            return;
        }

        var pts = 1;
        $scope.strengthMessage = "";

        if (/[~`!#$%\^&@*+=\-\[\]\\';,/{}|\\":<>\?]/g.test($scope.enteredPassword))
        {
            pts ++;
        }
        else
        {
            $scope.strengthMessage += "Try using special characters in your password.\n";
        }

        if (/[A-Z]/g.test($scope.enteredPassword))
        {
            pts ++;
        }
        else
        {
            $scope.strengthMessage += "Try using a mix of uppercase letter and lowercase letters.\n";
        }

        if (/[0-9]/g.test($scope.enteredPassword))
        {
            pts ++;
        }
        else
        {
            $scope.strengthMessage += "Try including numbers in your password.\n";
        }

        $scope.strengthCode = getCode(pts);
        return;
    };


Have fun with this! Type in an eight-letter word. What's the strength code?


Type in something alphanumeric.


What if you enter in a random uppercase letter?


And if you throw in a special character?


One more thing...

Let's spruce it up a bit by changing the colors to fit the strength code. Add this to the CSS.

index.html
            .color_weak { color: #440000; }
            .color_moderate { color: #444400; }
            .color_strong { color: #FFFF00; }
            .color_excellent { color: #44FF00; }

            .container
            {
                width: 200em;
            }


Then add this to the HTML.

index.html
                <div class="txtStrength color_{{ strengthCode }}">
                    {{ strengthCode }}
                </div>


Try this again!








Next

These are merely some of the different ways one can gauge the strength of a password. For the most part, this is enough. But if you want something more advanced, the next part of this tutorial will require a server and internet connection.

Friday, 8 June 2018

Microsoft's Acquisition of GitHub

Holy crap!

It's come to my attention that Microsoft is in the process of buying GitHub for USD 7.5 million. Like, why? Wasn't LinkedIn, Skype and Nokia enough?

Apparently not.


GitHub, within the software development industry, needs no introduction. It is a code repository company and service which developers use to store their code online. The service is free, as long as users adhere to open-source conditions.

What could Microsoft want with GitHub?

Microsoft buying over GitHub would seem an odd move considering that Microsoft hasn't exactly endeared itself to the open-source community since 2003. On the other hand, it's been over ten years, and things change just like that. Perhaps Microsoft has gone with the inevitable and embraced open-source. Hey, stranger things have happened.

Developers could be forgiven for thinking this is bad news. After all, Microsoft is pretty much synonymous with the word "proprietary", which in layman's terms, means, "you use my stuff, you pay for it". Which actually sounds pretty reasonable in any context outside of software development.

Perhaps Microsoft has finally cottoned on to the fact that a sizeable chunk of the world's developers, perhaps even a staggering majority,  all benefit regularly from open-source code. And that hoarding shit might have been the way to go in the past, but is looking ridiculously outdated now. A move like this, properly done, could go a long way in restoring some measure of trust and respect.

Or, Microsoft might have simply decided now that so many developers are depending on GitHub, a really profitable dick move would be to take over GitHub and start charging fees. Which is pretty much what many developers are thinking. This is silly because while GitHub could possibly be the world's most popular code repository, it's still one code repository out of many. Finding an alternative, for cheap bastards like myself, isn't that big a deal.

Does this mean GitHub is no longer free?

Well, this was one of the reasons we all loved it, right? It enabled us to share our code with the world, collaborate with each other, and lowered the barrier to entry. You didn't need to buy a lot of expensive software or attend expensive courses just to learn how to code.

In order to provide the service to us free, the assumption was that GitHub probably could afford it. But in the evidence of its impending sale to Microsoft, maybe not. You see, this could be the case of GitHub going the way of Uber. Uber was giving ultra-cheap cab rides to users without turning a profit (To this day, I'm pretty sure Uber still hasn't turned a profit yet) in return for a huge consumer base, popularity and a supreme level of visibility. But these things aren't sustainable, and at some point the buck has to stop somewhere.

Perhaps GitHub has reached that point, though no one can argue it hasn't achieved the same things Uber has, albeit within the software development community. GitHub has played quite a central role in software development over the years. 

Microsoft says that GitHub will remain free for use, and it has no plans to change that. I'm gonna have to reserve judgement on that one.

Will you be deleting your GitHub account, or migrating your code?

What, to prevent the eventuality of Microsoft abusing their power to snoop through my code and steal it?

Dude, my code is really basic. It's there for anyone who wants to use it, but honestly, it's so rudimentary that I'd be flattered if someone wanted to grab it. So, unless your code is so revolutionary and life-changing that tech giants like Microsoft must never get their hands on it, I'd suggest staying put.

That's it for now. Git outta here!
T___T

Saturday, 2 June 2018

Restricting Input Lengths

In any web application that requires user input, one of the decisions web developers often have to make is regarding the maximum length of a text field. No, not how many characters (though that is certainly pertinent), but where to implement it.

Why restrict the length?

Well, the main reason is security. If no length restrictions are in place, this leaves the door open for malicious input that could wreak havoc on an unprepared database. Restricting the length of a text field, however, cannot be the main line of defense. It should be one of the many safety checks in place.

Restricting from the back end

This basically involves specifying, at database schema level, how many characters your field will allow.

Here's an example.
CREATE TABLE Test (
    id int,
    name varchar(10)
);


If you attempt an SQL statement like this...
INSERT INTO test (id, name)
VALUES (1, "Ramabalakrishnan")


"Ramabalakrishnan" has more than 10 characters. Depending on your configuration, an error may be raised, or, more commonly, the input truncated.

Restricting from the front end

This is when you specify the restriction in your HTML like so...
<input type="text" maxlength="10" id="name" placeholder="Your name here" />


So when you attempt to enter in a very long line of text, it gets cut off at 10 characters. Try it!


Which is better? What's recommended?

To answer that question, let's examine the pros and cons of each approach.

While the back-end approach is undeniably more secure and no-nonsense, using it exclusively could be a user interface problem. Imagine typing a very long string into a textbox and having it truncated upon being saved. It's a visibility issue. Users generally have more confidence in a system when it performs as expected.

The front-end approach is very visible, and users know right off the bat that they can't enter more than a certain number of characters, because the textbox simply won't allow them to. But there's a catch... it's implemented at client-side, and any attacker worth his salt would know a ton of ways to defeat it.

So what now? Simple. There's no need to pick one over the other. Use both.

Having the restriction implemented at the front-end will make it far less annoying for users. Having it implemented additionally at the back-end is a security boost.

So long!
T___T