Time taken for Password encryption

[adrotate group=”3,7,8,9″]

One of the recent posts showed how to connect to a remote IBM i system and store the password in a secure method in the session variables. As part of another development project we decided to add the process to the connection code to see what effect it would have. The time taken to make the connection and display the data seemed to take a much longer time. Not sure if the time was due to the data being collected or due to the connection process we decided to write a test page to see the actual time it took. The results were quite shocking, in effect the encryption process increased the connection time by a factor of 3. This meant every time we loaded a page of data it was 3 times slower than if we just did a normal unencrypted connection.

The connection is the same for every request so the additional time can only be associated with the time it took the system to encrypt and decrypt the password. The encryption is only done once on login but decryption is done every time a new set of data was requested. To prove the point we created a sample page that would show a login screen if no connection had been made and show the connection time if the connection was made. its a very simple page and the functions that back it up are just as simple. The encryption process is the same as published in the post mentioned above so it you want to see those functions go to the post.

Here is the page we used for the initial sign on.

<?php
/*
Copyright © 2010, Shield Advanced Solutions Ltd
All rights reserved.
http://www.shieldadvanced.ca/

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.

- Neither the name of the Shield Advanced Solutions, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior written
permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/
// start the session to allow  session variables to be stored and addressed
session_start();
require_once("scripts/functions.php");
if(!isset($_SESSION['server'])) {
	load_config();
	}
?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Test PHP</title>
<!-- add the main CSS -->
<link rel="stylesheet" href="css/tst.css" type="text/css">
</head>

<body>
<?php
// if valid user is set connect using Private connection
if(isset($_SESSION['valid_usr'])) {
	$start_time = microtime();
	$conn = 0;
	if(!connect($conn)) {
		if(isset($_SESSION['Err_Msg'])) {
			echo($_SESSION['Err_Msg']); $_SESSION['Err_Msg'] = "";
			}
		}
	else {
		echo("Connected to " .$_SESSION['server'] ."using " .$_SESSION['conn_type']);
		$end_time = microtime();
		$wire_time= control_microtime_used($start_time,$end_time)*1000000;
		printf("<br>total=%1.2f sec ",round($wire_time/1000000,2));
		echo("<br><a href='scripts/logout.php'>logout</a>");
		}
	}
else { ?>
        <form name=login method="post" action="scripts/login.php">
            <table width="20%" align="center" border="1" cellpadding="1">
                <tr><td><label>User ID :</label></td><td><input type="text" name="usr" /></td></tr>
                <tr><td>Password:</td><td><input type="password" name="pwd" /></td></tr>
                <tr><td colspan="2"><?php if(isset($_SESSION['Err_Msg'])) { echo($_SESSION['Err_Msg']); $_SESSION['Err_Msg'] = ''; } ?></td></tr>
                <tr><td><label>Connection type</label></td><td><select id="conn_type" name="conn_type"><option value="encrypt">Encrypted</option><option value="decrypt">Decrypted</option></select></td></tr>
                <tr><td colspan="2" align=center><input type="submit" value="Log in" /></td></tr><?php
                if(isset($_SESSION['Pwd_Err'])) {
                    if($_SESSION['Pwd_Err'] == 1) { ?>
                        <tr><td colspan="2" align=center>Sorry the credentials were rejected by the <?php echo($_SESSION['sys']); ?> System</td></tr><?php
                        $_SESSION['Pwd_Err'] = 0;
                        }
                    } ?>
            </table>
        </form><?php
	} ?>
</body>
</html>

If the user information is correct and the connection is made the sign on screen is no longer displayed and the connection information is displayed.

This is the login script.

<?php
/*
Copyright © 2010, Shield Advanced Solutions Ltd
All rights reserved.
http://www.shieldadvanced.ca/

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.

- Neither the name of the Shield Advanced Solutions, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior written
permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

// allow session variables
session_start();
$conn = 0;
require_once"functions.php";
// make sure they are not trying to sign on with a system profile
$prf = strtoupper($_POST['usr']);
if(($prf == "QDBSHR") ||
	($prf == "QDOC") ||
	($prf == "QLPAUTO") ||
	($prf == "QLPINSTALL") ||
	($prf == "QRJE") ||
	($prf == "QSECOFR") ||
	($prf == "QSPL") ||
	($prf == "QDFTOWN") ||
	($prf == "QTSTRQS") ||
	($prf == "QSYS")) {
	$_SESSION['Err_Msg'] = "Cannot use user profile " .$_POST['usr'] ." for connection";
	header('Location: /index.php');
	exit(0);
	}
$_SESSION['usr'] = $_POST['usr'];
if($_POST['conn_type'] == 'encrypt')
	e_pwd($_POST['pwd']);
else
   $_SESSION['pwd'] = $_POST['pwd'];
$_SESSION['conn_type']  = $_POST['conn_type'];
// if failed to connect set the $_SESSION variables to empty
if(connect($conn) == -1) {
	$_SESSION['Pwd_Err'] = 1;
	$_SESSION['usr'] = "";
	$_SESSION['pwd'] = "";
	$_SESSION['valid_usr'] = NULL;
	header('Location: /index.php');
	exit(0);
	}
// connect set the required session variables so just set the valid user variable
$_SESSION['valid_usr'] = $_POST['usr'];
header('Location: /index.php');
exit(0);
?>

As you can see it is pretty simple in that it just determines the selected connection type and then calls the connect, if it succeeds it sets the relevant session variables.
For the connect function we have the following code

function connect(&$conn) {
// reset the the ErrMsg variable
unset($_SESSION['ErrMsg']);
// connect to the i5
$conId = 0;
if (isset($_SESSION['ConnectionID'])) {
		$conId = $_SESSION['ConnectionID'];
		}
$server = $_SESSION['server'];
$addlibl = array($_SESSION['install_lib']);
// options array for the private connection
$options = array(
      			I5_OPTIONS_PRIVATE_CONNECTION => $conId,
      			I5_OPTIONS_IDLE_TIMEOUT => $_SESSION['timeout'],
      			I5_OPTIONS_JOBNAME => 'PHPTSTSVR');
// connect to the system
if($_SESSION['conn_type'] == 'encrypt')
	$conn = i5_pconnect($server,$_SESSION['usr'],d_pwd($_SESSION['pwd']),$options);
else
	$conn = i5_pconnect($server,$_SESSION['usr'],$_SESSION['pwd'],$options);
// if connect failed
if(is_bool($conn) && $conn == FALSE) {
	$errorTab = i5_error();
	if ($errorTab['cat'] == 9 && $errorTab['num'] == 285){
		$_SESSION['ConnectionID'] = 0;
  		$_SESSION['Err_Msg'] = "Failed to connect";
  		return -1;
 		}
 	else {
 		//set the error message
 		$_SESSION['Err_Msg'] = "Connection Failed " .i5_errormsg();
		// send back to the sign on screen
		$_SESSION['ConnectionID'] = 0;
 		return -1;
 		}
	}
return 1;
}

The only other function we use are the microtime() function and a function which calculates the time taken between the start and end time.
Here is the page information which was collected for a unencrypted connection.

Connected to shield3using decrypt
total=0.13 sec

and here are the results when we connect using encryption for the password.

Connected to shield3using encrypt
total=0.38 sec

As you can see it is nearly 3 times as long to make the connection when encrypting the password. So our challenge now is to see if we can find a better or should I say faster encryption method to use. If the connection is not important because the data is refreshed too often it should not be an issue especially when you consider just how much better the security is for the stored passwords, but you will have to weight up that with the user experience for slow connections.

If you can see anything we did wrong let us know and we will happily re-code and try it again. Sorry about the code layout but it is pretty hard to show correctly formatted code on the blog setup we have.

Chris…

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.