The Speed of Various Existential PHP Functions

You want to right a pretty existential function in PHP so you can do things like the following without throwing warnings (warnings that write to disc, or the screen, slow things down and burn platters).

If $ar[1][2][3] is not set then a warning is thrown.

Examples of Places You Should Use Existential Calls

if(42 == $ar[1][2][3]){
  echo "We have the Answer!";
}
 
some_func($ar[1][2][3]);

Here are some timed tests of existential functions. The most common is
the ternary isset.

Ternary Existential Calls (ugly)

if(42 == (isset($ar[1][2][3])) ? $ar[1][2][3] : False){
   echo "We have the Answer!";
}

But i find that syntax ugly, i would like to do something more cogent, with out all the extra ? and : in the if‘s predicate. I have created a function isgd stands for “Is Set Get” This would be nicer, but it comes at a speed cost.

An Existential Function Call

if(42 == isg($ar,1,2,3)){
  echo "We Have The Answer!";
}
 
// Or you might want to call a function with a default value
// if $ar[1][2][3] is not set:
 
 
some_func(isgd($ar,"Don't Panic!",1,2,3));

Here are a list of 5 solutions for the existential crisis, I have a speed summary as well as an explanation/guideline below.

An Existential Speed Tests

 
$iters = 1e5;
 
$ar[5][5][5][5][5] = 5;
 
$tic = microtime(true);
for($ii=0; $ii<$iters; $ii++){
  $val = @$ar[5][5][5][5][5];
}
$toc = microtime(true);
$elapsed_time = round($toc - $tic,2);
echo "Elapsed Time Using @ $elapsed_time seconds\n";
 
$tic = microtime(true);
for($ii=0; $ii<$iters; $ii++){
  $val = isg($ar,5,5,5,5,5);
}
$toc = microtime(true);
$elapsed_time = round($toc - $tic,2);
echo "Elapsed Time Using isg $elapsed_time seconds\n";
 
$tic = microtime(true);
for($ii=0; $ii<$iters; $ii++){
  $val = isgd($ar,NULL,5,5,5,5,5);
}
$toc = microtime(true);
$elapsed_time = round($toc - $tic,2);
echo "Elapsed Time Using isgd $elapsed_time seconds\n";
 
 
$tic = microtime(true);
for($ii=0; $ii<$iters; $ii++){
  $val = (isset($ar[5][5][5][5][5])) ? $ar[5][5][5][5][5] : False;
}
$toc = microtime(true);
$elapsed_time = round($toc - $tic,2);
echo "Elapsed Time Using Terinary $elapsed_time seconds\n";
 
$tic = microtime(true);
for($ii=0; $ii<$iters; $ii++){
  $val = array_multi_key_exists(Array(5,5,5,5,5),$ar);
}
$toc = microtime(true);
$elapsed_time = round($toc - $tic,2);
echo "Elapsed Time Using array_multi_key_exists $elapsed_time seconds\n";
 
$tic = microtime(true);
for($ii=0; $ii<$iters; $ii++){
  $val = eval_iff($ar,5,5,5,5,5);
}
$toc = microtime(true);
$elapsed_time = round($toc - $tic,2);
echo "Elapsed Time Using eval_iff $elapsed_time seconds\n";
 
 
 
// From php.net/array_key_exists
function array_multi_key_exists(array $arrNeedles, array $arrHaystack, $blnMatchAll=true){
    $blnFound = array_key_exists(array_shift($arrNeedles), $arrHaystack);
 
    if($blnFound && (count($arrNeedles) == 0 || !$blnMatchAll))
        return true;
 
    if(!$blnFound && count($arrNeedles) == 0 || $blnMatchAll)
        return false;
 
    return array_multi_key_exists($arrNeedles, $arrHaystack, $blnMatchAll);
}
 
// is set get
function isg($ar){
  $val = $ar;
  for($ii = 1; $ii < func_num_args(); $ii++){
    $arg = func_get_arg($ii);
    if(!isset($val[$arg])){
      return NULL;
    }
    $val = $val[$arg];
  }
  return $val;
}
 
// is set get with a defualt
function isgd($ar,$default){
  $val = $ar;
  for($ii = 2; $ii < func_num_args(); $ii++){
    $arg = func_get_arg($ii);
    if(!isset($val[$arg])){
      return NULL;
    }
    $val = $val[$arg];
  }
  return $default;
}
 
 
// Not safe and very slow
function eval_iff($ar){
  $val = $ar;
  $to_eval = '$ar';
 
  for($ii = 1; $ii < func_num_args(); $ii++){
    $arg = func_get_arg($ii);
    $to_eval .= "[$arg]";
  }
  eval('$val = (isset(' . $to_eval . ')) ? ' . $to_eval . ' : NULL;');
  return $val;
}
 
 
/*
Running PHP 5.3
 
Results for 10000 iterations.
Elapsed Time Using @ 0.13 seconds
Elapsed Time Using isg 0.5 seconds
Elapsed Time Using isgd 0.51 seconds
Elapsed Time Using Terinary 0.07 seconds
Elapsed Time Using array_multi_key_exists 0.44 seconds
Elapsed Time Using eval_iff 2.71 seconds
 
*/

Summary : ? is the fastest, but is bulky. isg is slower than @ with little benefit. Ternary is the fastest and allows default, but also pretty ugly inside of code. Ugly code takes a long time to debug so only use Ternary when all that maters is super-fast code. array_multi_key_exists and isg are both slower than @ but because there is not default there is little benefit. eval_iff is just bad all around.

So if you don’t need a default and NULL is OK, then use @. If you do need a default and you don’t need the particular check to be very fast (like its only called a handful of times) then use isgd. If must be really fast so being ugly doesn’t matter use the Ternary.

Share
Posted in beginner-programming | Leave a comment

Hashing Passwords in PHP Using md5 vs sha256 vs bcrypt vs …

Many people have had questions about how to properly store passwords in the database. Most of us have learned that it is a really bad idea to store them in plaintext.

Instead of storing them in plaintext we do store them with a one-way hash, such as md5, sha256 or bcrypt. This way even if someone gets a copy of your password database it will become harder to figure out a users password. A one way hash in this examples is a (seemingly) one to one mapping from a string to another string. In theory you can’t run a function on the hashed password to get back the plaintext password. So if someone gets your database than, no problem?

Well yes and no; a baddie can still try running a huge list of possible passwords and see if they match any of hashes in the database. So the faster a hash function is to calculate the worse it is for security, because the baddie can try more passwords faster and cheaply.

MD5 and SHA256 (or any of the sha* functions) where designed to be really, really fast. So a baddie can run many possible passwords through them in order to check. BCRYPT, which is a variant of the blowfish encryption algorithm, can be made arbitrarily difficult. Put it another way, the number of CPU cycles for MD5 and SHA256 are very few because they are meant to be fast, bcrypt can be made to require a huge amount of CPU cycles to calculate the result.

Bcrypt is better because it can be made to take up more CPU cycles. END OF STORY!

Or is it… Well in reality all we are REALLY trying to do is make a trade-off between the number of CPU cycles we are willing to give up in-order to make the users passwords more secure vs how many CPU cycles the baddies are willing to give up in order to crack the password.

Sidenote: adding a random salt doesn’t in practice significantly increase the number of CPU cycles, it only makes it so the baddies must recalculate hashes for common passwords. Its never a bad idea to hash, its just not terribly effective either.

Bcrypt would be an obvious choice if it was more portable, however as of the writing of this post bcrypt is not built into most database servers or PHP itself. MD5 and SHA256 are available in most servers and languages. Loading an external bcrypt library takes a bit of CPU cycles that could be better used in running the hash function and you have to port all that library. Loading the library doesn’t make the password more secure, only running the algorithm does. So if we want to make things simple just use md5 iteratively.

Here is an example of a hardening function that iterates the md5 algorithm many times in order to use up more cpu cycles, change $md5_iters so that it takes about .1 seconds to run on your production server. Higher number means more security but also takes away cpu cycles from other things the server needs to do.

Hardening Password Function (with iterative MD5)

function harden_password($clear_text_password,$random_salt){
  // a non-round number, works similar to a salt as well as increasing
  // number of cpu cycles, set it and forget it, number of iters
  // should be increased until this function takes about .1 seconds on
  // your production server.
  $md5_iters = 81378;
 
  $hashed_password = md5($clear_text_password); // first hash
  // iterate the hash
  for($ii=0; $ii<$md5_iters; $ii++){
    $hashed_password = md5($hashed_password . $random_salt);
  }
  return $hashed_password;
}

Here is an example of how to use the hardening function to create hashes and validate passwords

Example of Using Hardening Function

$clear_text_password = '123456789'; // an "average" length password string
// a 'random' salt this should be unique for EACH user, but it is also
// a set it and forget it variable for that user
$random_salt = md5(mt_rand(0,1<<30)); 
 
function harden_password($clear_text_password,$random_salt){
  // a non-round number, works similar to a salt as well as increasing
  // number of cpu cycles, set it and forget it, number of iters
  // should be increased until this function takes about .1 seconds on
  // your production server.
  $md5_iters = 81378;
 
  $hashed_password = md5($clear_text_password); // first hash
  // iterate the hash
  for($ii=0; $ii<$md5_iters; $ii++){
    $hashed_password = md5($hashed_password . $random_salt);
  }
  return $hashed_password;
}
 
// a function to store the password in
function timed_hash($clear_text_password,$random_salt){
  $tic = microtime(true);
  $hashed_password = harden_password($clear_text_password,$random_salt);
  $time_elapsed = microtime(true) - $tic;
 
  return Array(
    "time_elapsed"=>$time_elapsed, // increase md5_iters inside
                                   // harden_password() until about .1
                                   // seconds
    "hashed_password"=>$hashed_password // store this and the
                                        // $random_salt in the
                                        // database
 
               );
}
 
function validate_password(
  $clear_text_password, // gotten from user i.e. from $_POST['password']
  $random_salt, // stored on a per user basis
  $hashed_password // password hash from the database
                           ){
 
  $hardened_password = harden_password($clear_text_password,$random_salt);
  return ($hardened_password == $hashed_password);
}
 
 
$result = timed_hash($clear_text_password,$random_salt);
$time_elapsed = $result['time_elapsed'];
$hardened_password = $result['hashed_password'];
echo "Time Elapsed: $time_elapsed\n";
 
if(validate_password($clear_text_password,$random_salt,$hardened_password)){
  echo "Passwords Match!\n";
}else{
  echo "Passwords Do Not Match\n";
}

Hopefully now you can see how to use the more portable MD5 Correctly and understand that hashing for security is less about the hashing alogrithm but more about the number of CPU cycles to use.

Please rate and comment or hire me for freelance work, thanks!

Share
Posted in beginner-programming | Leave a comment

How to Make One Thousand Two Hundred Ninety Seven Dollars and Thirty Six Cents with DFHU

To follow up to the “How to Hire a Coder” Post, I would like to offer you the chance to work with me personally, FOR FREE.

Do you have an idea for a cool and marketable IM/SEO related web application?

Think, Internet Marketing or Search Engine Optimization tools that could be sold on DFHU.oRG.

Here is the deal: Lots of people who are newer to IM have some really cool ideas for Widgets, Web-Apps, Plugins, etc… but for whatever reason they do not get them made (maybe they wish to invest their dollars elsewhere or may not yet have built the confidence).

Many times people have me create a widget for them, they use it, make some good money with it’s utility, but fail to go the next step and make money off the widget itself.

If you have an idea for a widget that you think can be sold on places like dfhu.org then you could make some monies.

Read More »

Share
Posted in marketing | Tagged , , | Leave a comment

How to Find High Quality and Affordable Programmers.

Fact: Hiring a programmer sucks; everyone has horror stories. Good, affordable programmers are rare and very often constantly booked solid.

Fact: I am a programmer and some of the tips I will give will probably cramp programmers style (ironically, including my own).

If you have ever talked to me in person about business, chances are I have at some point told you that if I was ever to create an info product it would be on just this subject. As of now I don’t have any serious plans to do so and I would rather help you folks out instead of hording the information.

Fair warning this post will not go into wear to find programmers, but instead focus on how to screen a list of canidates once you have them.

Hint: Standards.

Read More »

Share
Posted in outsourcing | Tagged , , , | Leave a comment

When Should You Use a Web Framework Such as CakePHP, Pylons, etc…?

I would like to discuss a few good reasons you or your web developer should use or not use a web framework.

Web Development frameworks have taken off since the release of Ruby on Rails (RoR).

Some other frameworks that have come along are CakePHP, CodeIgniter (PHP) and Pylons (Python).

The basic goal of web frameworks is to increase the quality and speed of development by giving a collection of tools and methodologies that build on an existing language.

Or in short write better code, faster.

But what is the reality and when should a framework be used?

I will focus on PHP and Python frameworks because those are the ones I know best.

Read More »

Share
Posted in intermediate.programming | Tagged , , , , , , | Leave a comment