Posts tagged php
Hash Authentication
0After coming across this article on Reddit today, and chatting with a good friend and colleague about the benefits and issues of using the authentication method outlined by the author, we both came to the conclusion that we were not fans of the way the author handled the hash table comparisons for users, so I decided to work on it a little bit at home and try to make it better.
Before I go into details, here are the database tables I created to get this authentication to work:
mysql> DESCRIBE hashes; +_______+_____________+______+_____+_________+_______+ | FIELD | TYPE | NULL | KEY | DEFAULT | Extra | +_______+_____________+______+_____+_________+_______+ | hash | VARCHAR(64) | NO | PRI | NULL | | | salt | VARCHAR(64) | NO | | NULL | | +_______+_____________+______+_____+_________+_______+ 2 ROWS IN SET (0.01 sec) mysql> DESCRIBE users; +__________+_____________+______+_____+_________+________________+ | FIELD | TYPE | NULL | KEY | DEFAULT | Extra | +__________+_____________+______+_____+_________+________________+ | uid | INT(11) | NO | PRI | NULL | AUTO_INCREMENT | | username | VARCHAR(30) | NO | | NULL | | | hash | VARCHAR(64) | NO | | NULL | | | salt | VARCHAR(64) | NO | | NULL | | +__________+_____________+______+_____+_________+________________+ 4 ROWS IN SET (0.00 sec) |
I set the hash field in the hashes table to an indexed column to allow quick(er) searching through the table, trying to alleviate the issues we might run into if this table becomes too large. Without the user’s password, there is no connection between these two tables, as it is required to generate the data within the hash column in the hashes table. Creating a user would happen like so:
// note, this uses my database class, which can be found at http://code.imyourdeveloper.com/database.txt function create($applicationSalt, $user) { //generate salts $userSalt = hash("sha256", $applicationSalt.rand().time()); $hashesSalt = hash("sha256", $applicationSalt.rand().time().$applicationSalt); //generate hashes $userHash = hash("sha256", $applicationSalt.$user->password.$hashSalt); $hashesHash = hash("sha256", $applicationSalt.$user->password.$userSalt); //create queries $user = 'insert into users (uid, username, hash, salt) values (null, "'.$user->username.'", "'.$userHash.'", "'.$userSalt.'")'; $hash = 'insert into hashes (hash, salt) values ("'.$hashesHash.'", "'.$hashesSalt.'")'; //run queries $db->query($user); $db->query($hash); } |
This was a little bit of a pain, and took some staring at my monitor to wrap my head around, trying to remember what went where, but I eventually got it working. The application salt is your secret salt set in the application that you will use to salt data going to the database, and user passes through any data you want to write about the user to the database. A combination of the user salt, the application hash, and the user’s password is used to generate the user hash and the authentication lookup hash in the hashes table. When the user types in a password, it runs through the algorithm creating a hash, looks up that hash in the hashes table, recalculates another hash using a randomly generated salt in the hashes table, the user’s password, and the application salt, then compares with the hash in the Users table. If this matches, then the user is who he says he is, and is logged in. This happens like so:
function lookup($applicationSalt, $user) { GLOBAL $db; $userLookup = $db->getObj('select * from Users where username = "'.$user->username.'"'); $check = $applicationHash.$user->password.$userLookup->salt; $hash = hash("sha256", $check); $hashSalt = $db->getObj("select * from Hashes where hash = '$hash'")->salt; if ($userLookup->hash == hash("sha256", $applicationSalt.$user->password.$hashSalt)) { return true; // logged in } else { return false; // login failed } } |
This may not be a perfect implementation of this code, but I wasn’t a fan of the way it was being handled in the other article; and this was a neat little problem to work on, so expect updates in the future.. The mathematical probability of you being able to brute force the user’s password was astronomically low before, but it was nothing more than a one-way relation. This way, you not only need to brute force the users password to go one way (towards the hashes table), but the password you get is likely not going to work, as another hash is checked going in reverse, ensuring the only string that is accepted is the user’s.
If you have any better ideas of how to implement this, please feel free to post it below. Click here for a full version of the code above.
The Birthday Club and Facebook’s API
0I recently finished working on KMart’s Birthday Club website, a wordpress-based children’s site that is geared towards parents looking to make their child’s special day memorable. My role was handling all the social media aspects required in the project plan.
One of the bigger problems I ran into with this – I really didn’t like any of the existing facebook plugins for WordPress, so I ended up building my own. It was really an interesting learning experience. This gave me the opportunity to dig deeper into the new facebook Graph API than I have in the past, and it wasn’t as terrible as the facebook API once was.
My largest, and most interesting task, was to pull down photo-galleries and create a taxonomy for each one. The interaction with facebook for pretty much everything I had to do was fairly simple:
/** * Fetches data from facebook API * * @author Jason Corradino * * @param $path (required) facebook query path * @param $format (optional) format data is returned as either an object or json [obj|json] * @param $attr (optional) Adds additional attributes to the URL * * @return returns object of facebook data by default, json if 'format' parameter is set to json * */ static function getData($path, $format="obj", $attr="") { $pluginOptions = get_option('facebook_gallery_options'); $token = $pluginOptions["token"] ? $pluginOptions["token"] : FACEBOOK_APP_TOKEN; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "https://graph.facebook.com/".$path."?access_token=".$token."&api_key=".FACEBOOK_API_KEY."&".$attr); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $return = curl_exec($ch); curl_close($ch); return ($format == "json") ? $return : json_decode($return); } |
The above code will use your facebook application token to open up a curl with the facebook graph API, pulling down the requested data set within the URL, returning in the format set within the function call — defaulting to an object, but allowing a JSON response.
There will be a more detailed post about this down the line, and I am considering releasing the plugin I built to wordpress.org extend. So look forward to that.
Happy coding
Yeah…. well I lied…
0Sorry, I have not been able to update with the new projects – they are finished, just not launched. As soon as the powers that be throws them out there, I will be able to put them up here. They should be coming out very soon, so keep an eye out. Below is a sample of one of the cooler ones.
Groupon Central
Groupon Central is an internal tool for all the US employees to easily send out messages to the right person. This app is PHP and a lot of AJAX, that will guide them to the right place. Set up with Google Authentication, I get their personal information when they go to the site, allowing me to personalize the site for them in their job role.
More to come on this soon.
Groupon: In the News – Press Blog
0Groupon’s press blog was probably the least troublesome site I launched yet. My portion of the project started as the production manager. I only had to make sure the space was there and get the site online. But, when the person working on the site got pulled to a different project, the whole thing fell into my lap. This sounds as if it would be a pain, but it was actually a pretty easy-going site. A good chunk of the design work was already completed, and all that was required of me was to fine-tune the design based on what was wanted, and develop custom modules for the site.
This project also forced me to learn how to work and integrate a site with an Amazon S3 server, which was an interesting experience. I also have to deal with hundreds and hundreds of videos and determine the best hosting solution for them, which as of now is looking to be a mixture of Amazon S3 and LimeLight.
I would share a link, but the video use-licenses on the page prohibit publicly sharing. As soon as that changes, however, I will share.
The Tech Mumbo-Jumbo
Since I am anticipating this site to get a rather decent amount of traffic, I decided to run this off of a MediaTemple VE server, which I happen to like since it gives you full control of the box and you don’t have to worry about some proprietary piece of software fubaring the whole machine. The site is running off of a rather out-of-the-box installation of wordpress with just a few tweaks to allow for heavy traffic and integration between S3 and LimeLight. I also incorporated a partially-custom chromeless video player into the sidebar that can be edited to show any youtube video the editors may want to play.