Yesterday I purchased hosting for the Nothing Definitive Series and will be separating that content from this blog. You can find the new site here, which is, and will continue, to be full of philosophical insights, enlightenment material, inspirational videos, self improvement techniques, and more. I think separating that content from business and programming insights is probably a good idea. :P
So from now on, this blog will be dedicated to business insights, code and programming lessons, entrepreneurial advice, social networking tips and tricks, how to's and tutorials, improving SEO, etc. Be sure to check out both websites and subscribe/follow each of them!
Wednesday, April 3, 2013
Monday, February 25, 2013
Wausau Area Bulletin Boards
I did a Google search for "wausau bulletin boards" hoping to find a listing of different places you could post flyers but nothing came up. So a friend and I decided to begin trekking around looking for potential advertising spots that are open to posting. Here is a map of the ones we've found so far:
Updated as of 25 February 2013
View Bulletin Boards in a larger map
Remember to ask permission before posting and bring your own tacks / push pins.
Updated as of 25 February 2013
View Bulletin Boards in a larger map
Remember to ask permission before posting and bring your own tacks / push pins.
Thursday, February 7, 2013
Wausau Area Web Design, SJC Media LLC
Last year I registered a company called SJC Media LLC in Wisconsin. I didn't use it. Instead I worked on personal programming projects and video content. But now in 2013, I've decided to begin pursuing freelance website design and development for the central Wisconsin area (Wausau, Merrill, Rib Mountain, Stevens Point, etc.). That way I will be able to continue blogging, producing YouTube content, researching, and studying, while making some money on the side. I also hope that I can make enough to cover some purchases I've been wanting to make, like tuning up my truck (which hasn't been sounding so hot), buying a dog (I want to test my dog training skills), and getting some office supplies (I definitely need a new chair). And so, a couple weeks ago I reworked the website, prepared some things, and have begun looking for clients.
This is where the quick advertisement comes in: ladies and gentlemen, business folk, and hobbyists. Are you in need of a new website? Updating or maintenance to an existing or old one? Need general computer advice or consultation? I offer a wide variety of services to the Central Wisconsin area with expertise lying in web design, content management systems, PHP, and MVC framework development! Whatever your needs, we can work out a reasonable contract that will leave you with a project you'll be proud to share with friends, family, and clients. Just head over to sjcmediallc.com and see what we can offer you.
Ok, that's long enough. If you're interested in quick, efficient, and beautiful web design, check me out. And if you know anyone else interested, send them my way. Thanks!
Lastly, I wanted to mention some tools I've been using to setup shop. I've spent the last couple days working on SEO and social networking and love this website: Woorank. Such a great tool for quickly analyzing your websites. I also, as I've mentioned before, use Astrid and Google Documents to help organize and track tasks, client information, and reminders. Always remember to take thorough notes. Finally, services like box.com, dropbox, and Google Drive are also really handy for backing up files. I have all 3 running and upload to them regularly. That way you can adequately protect your work.
I'll keep this document updated with random tips and tools I find for helping with web development. Until then, cheers!
This is where the quick advertisement comes in: ladies and gentlemen, business folk, and hobbyists. Are you in need of a new website? Updating or maintenance to an existing or old one? Need general computer advice or consultation? I offer a wide variety of services to the Central Wisconsin area with expertise lying in web design, content management systems, PHP, and MVC framework development! Whatever your needs, we can work out a reasonable contract that will leave you with a project you'll be proud to share with friends, family, and clients. Just head over to sjcmediallc.com and see what we can offer you.
Ok, that's long enough. If you're interested in quick, efficient, and beautiful web design, check me out. And if you know anyone else interested, send them my way. Thanks!
Lastly, I wanted to mention some tools I've been using to setup shop. I've spent the last couple days working on SEO and social networking and love this website: Woorank. Such a great tool for quickly analyzing your websites. I also, as I've mentioned before, use Astrid and Google Documents to help organize and track tasks, client information, and reminders. Always remember to take thorough notes. Finally, services like box.com, dropbox, and Google Drive are also really handy for backing up files. I have all 3 running and upload to them regularly. That way you can adequately protect your work.
I'll keep this document updated with random tips and tools I find for helping with web development. Until then, cheers!
Thursday, January 24, 2013
Hydroponics Report #1
Note: this post will be updated periodically as new information is gathered.
Recently I became interested in hydroponics as a potential source for growing fresh vegetables for myself. The designs for an at-home system look interesting, and according to multiple sources you gain higher yields, more nutritious vegetables, and leave less of a footprint than soil-based agriculture. I also love being around nature and find it very calming. So I've begun research into the field and wanted to present what I've found thus far.
There are two Instructables I liked. The first is fairly simple and would probably work best for small plants. The second is more complex, but could also support larger plants and would probably have higher yields and potential for a more "commercialized" operation. The estimated cost can be found in this spreadsheet I created for the supplies (price estimates as of January 2013). Of course one could easily reduce the cost by purchasing less of the supplies, building a more basic structure, and eliminating some of the complicated wiring steps. But I would estimate these setups to cost between $200 and $250.
Note: in the first Instructable, he claims to have built his setup for around $30, but I don't see how that's possible unless you already had some of the supplies. At the absolute bare minimum, after setup, seeds/plants, etc. it's probably going to be over $100, but even then, you're probably going to have to make changes/additions which will eventually raise the cost.
Alright, so after you've taken a look at those setups and understand what it is I'm doing here, what about plants? I looked at various articles about which crops to grow, but most would only say a 3-4 plants at a time without revealing a nice comprehensive list. Why? Who knows. So I'll do it, here are all the plants I could find listed that people have grown Hydroponically.
Vegetables
Fruits
Flowers
Trees
Recently I became interested in hydroponics as a potential source for growing fresh vegetables for myself. The designs for an at-home system look interesting, and according to multiple sources you gain higher yields, more nutritious vegetables, and leave less of a footprint than soil-based agriculture. I also love being around nature and find it very calming. So I've begun research into the field and wanted to present what I've found thus far.
Hydroponic Systems
Note: in the first Instructable, he claims to have built his setup for around $30, but I don't see how that's possible unless you already had some of the supplies. At the absolute bare minimum, after setup, seeds/plants, etc. it's probably going to be over $100, but even then, you're probably going to have to make changes/additions which will eventually raise the cost.
What To Grow
Vegetables
- Lettuce / salad greens
- Chervil
- Endive
- Collard
- Mustard greens
- Kale
- Arugula
- Celery
- Cabbage
- Broccoli
- Beans
- Peas
- Cucumbers
- Peppers (colored, bell, hot, chili, etc.)
- Corn
- Warning: these take up a lot of space and need special care/consideration.
Root Vegetables
- Turnips
- Radishes
- Onions (bulb)
- Spring Onions (scallions, green onions)
- Potatos
- Carrots
- Yams
- Beets
- Parsnips
Herbs
- Pepper plants
- Thyme
- Basil
- Oregano
- Parsley
- Sweet marjoram
- Dill
- Sage
- Rosemary
- Cilantro
- Tarragon
- Mint
- Tomatoes
- Apparently these respond especially well to Hydroponics.
- Eggplants
- Strawberries
- Melons, zucchini and squash
- Warning: these take up a lot of space and need special care/consideration.
- Yarrow
- Lilies
- Tulips
- Carnations
- Orchids
- Roses
- Banana trees
Some Basics
Lastly, let's talk about some basic tips and other information you should know before jumping into Hydroponics.
- Mixing plants in the same nutrient water can yield varying results since certain plants need different nutrients.
- It's probably best at some point to dedicate a tub per plant type.
- Refresh your water/nutrient mixture at least every 2 weeks since it can become toxic.
- Storage bins / containers should be opaque since light can damage roots and cause harmful algae to grow.
- Be sure to maintain the water level which can deplete quickly. One solution I found said that if you're going to be gone for a few days, try dangling a string or wick that can soak up water deep in solution. That way liquids will still try to reach the plant if the water level drops.
- Be cautious about introducing foreign substances into your growing area since waterborne diseases can easily kill your plants.
- Sterilize tools, tubs, and other items that come into contact with the system.
- Regularly check on your system to make sure the plants look healthy and there are no visible bacteria growths.
- Hydroponics works well because the plants can focus all its energy on growing fruits/flowers/leaves, rather than roots to find water. This results in higher yields and better tasting plants.
- Additionally, soil doesn't allow for proper aeration and may lack important nutrients that Hydroponic systems deliver continuously.
- The growing medium used in these systems are simply there to support the plant and allow liquids to flow through them. Make sure the medium you buy is pH neutral and clean.
- This site had some good information regarding different mediums.
- Some plants may be better suited to Aeroponics like root vegetables which grow down.
Thursday, July 26, 2012
DayZ Journal Entry #1 - Part 1
I awoke on the coastline near Kamyshovo. It was raining and there was a heavy mist in the air. Down the road I could barely make out a town and people shuffling around. As I neared I knew something wasn't right. These weren't people, something was wrong. Wanting a closer look, I crouched and skirted the town, trying to stay hidden. At one point I was forced to crawl on my stomach to avoid being seen. I got really close to one of them and saw his blood covered face, smelt the rotting flesh, and heard his pained moans as he stumbled around. Zombies. A sudden fear hit me as I realized what had happened. I wanted to scream and run for the hills, but I forced myself to stay calm. Controlled breaths, slow your heart, I thought to myself as I crawled away from the city. I had to get into the hills, away from this city.
A long time ago, my friends and I had jokingly talked about zombies and what we would do if it happened. Somewhere within the conversation the city of Mogilevka was brought up because of the large industrial buildings they had. It seemed like a safe haven, somewhere you could fight and holdout for a long time. That was my destination and with any luck, someone would have survived to make it that far.
I ran through the woods north of Kamyshovo, crossed a dirt path and began to beeline for Pusta, a small village I knew of. It was quiet and eerie under the canopy and every twig snap made me jump. Along the way I discovered a tree stand with a 12-gauge shotgun. As I descended the ladder smiling, I turned to face my first zombie. Apparently I wasn't as sneaky as I thought. I lined up the barrel and watched his head pop, the round ripping through his flesh. I almost threw up as I scrambled away. Somehow I had never imagined killing zombies to be so brutal.
For hours I walked under the shady trees, the rain finally dying, until I found a road. It ran north and south and I guessed it to be the one that ran between Elektro and Msta. I also recalled there being some tourist stop along the way with an old ruin or something. I decided to press my luck and see whether I found it. It was risky but I was growing thirsty and needed to find something soon. The road stretched on for miles uphill and I had to stop numerous times to catch my breath. After what seemed like the millionth bend, I saw an odd rock structure. Quietly I approached and saw a sign reading Rog Por. This was it. Within the grounds and inside the crumbling buildings I found supplies. I wondered if someone was coming back for them, but shrugged away the thought as I abated my thirst and hunger. Every man for himself seemed fitting.
I returned the way I came and continued my trek through the woods. It was uneventful and I was grateful for that, until I reached Pusta, a small country village. Again I was forced to skirt the edges and stay hidden. It was tense half-hour as I passed dangerously close to zombies, but soon I found the old dirt road that led to Mogilevka. I jogged for miles until I saw a fork in the road and, my heart stopped, a person. I fumbled with my gun and brought it up. Would they fire on me? He saw me as well and we both cautiously approached one another. My finger was tight on the trigger, but I kept the barrel slightly off him, ready to snap to his chest at any moment. But as his face became visible I realized it was my old friend Devin. The fear lifted. After a brief celebratory greeting and an exchange of stories, we looked towards Mogilevka in the distance and the fields of zombies in the way.
Gripping our weapons and feeling a new surge of confidence, we rushed forward. As we slid up against a wooden fence I heard a growl and turned to face a zombie stepping out of bush. I panicked and fell backwards, managing to bring my shotgun up. The round exploded from the barrel and splattered into his chest and face. I looked at Devin and we knew what was about to happen. Zombie after zombie began showing up, wondering what the loud bang was. We began firing and running, trying to dodge their lunges and savage arms. I had never seen such anger, almost as if their thirst for blood was a horrible addiction, something they would do anything to satisfy. After body after body fell to the ground, we realized we had to make a move. We ran along the old wooden house and into the field. We were able to confuse them by hitting the dirt and remaining quiet. After a few minutes we began crawling towards the city.
We were about half way there when stopped at another old house. As we caught our breath I peeked around the corner and saw multiple zombies moving towards us. I went around the other way and saw more coming up the road and from the field. We were surrounded. There was an exchange of nods as we both realized it was time to run. Standing up and yelling we both fired our guns and shot the closest zombies. More rushed in and met their demise. Devin headed around one side the house as I went another. We both sprinted towards the large industrial building. Almost there I yelled to myself, just keep running. As I tore through the doorway I frantically scrambled to close the door. I didn't see Devin. I ran the length of the building checking other exits. Unfortunately one side had no doors and couldn't be blocked. I prayed none would come that way. Turning back I heard a door slam shut as zombies crashed up against it. Devin was panting and barely able to run as he crossed the building towards me. That was too close, Mogilevka was a bad idea. As we caught our breath and looked around the area we saw nothing but broken down buildings leading into the heart of the city. We needed supplies and more importantly, ammunition. We walked slowly towards some of the smaller buildings to check them out. A few minutes passed in silence as we explored the rubble. Nothing. All of a sudden I saw a couple zombies wandering in from the large building. They must have realized where we were. We fell back to a small building and waited. As we sat inside, a loud pounding echoed through the building as zombies began beating on a door behind us. Where were they coming from? I ran over and looked through the window and saw a face looking back at me. I almost screamed as I lined up my gun. No save the round, I thought, he can't get through. We had to run again. On the count of three we both stood and sprinted from the building. We ran back the way we came, through the large industrial building and out a side door. I led the charge as we crossed a field. Looking back I saw Devin being pursued by multiple targets. It was a horrible moment as I realized I might watch him die. Crouching down I brought up my gun and waited for him to pass. As he ran by, I lit up the first one. The round caught him and he dropped. Devin began to fire as well. Mogilevka was a bad idea.
We headed east for a short while. Both of us were wore out and needed rest. We passed into a small area with buildings. It was quiet and only had a couple zombies we easily finished off. We split up to find supplies. I opened an outhouse and discovered ammo and bandages on the floor. It was disgusting but I couldn't complain. As I gathered up what I could I heard an awful crashing noise. I ran over and found Devin on the ground, writhing in pain. The wooden platform above him was cracked and broken. He indicated towards his legs as he gritted his teeth. "Can you move them?" I asked as he tried to apply pressure. He muffled a scream. They were broken, maybe fractured. Fuck, this was bad. After an hour of lying around, Devin realized what needed to be done. "Shoot me," he said simply, trying to keep the emotion out of his voice.
"What?!" I exclaimed, "I can't do that." He sighed and explained the situation very clearly. Even if we decided he could be saved, it would require me to head alone to Elektro or Chernogorsk, find a hospital, get lucky and discover the right supplies, escape the city and return. It would take days probably, be extremely risky for both of us, probably risk Devin dying anyway since zombies would find him, and he might die of dehydration anyway. He said it again, "shoot me." My hands shook furiously as I raised the barrel. The iron sights came into focus with a blurry head behind it. After I fire don't look, I told myself. I swallowed the lump in my throat and felt my eyes water. Fuck this shit. A long silent moment passed and then I squeezed the trigger. I felt the boom ripple through my body, echoing loudly off the buildings and scaring birds from trees. I fell to my knees and saw his mangled face sputter its last dying breath. I ran into the woods, not looking back.
A long time ago, my friends and I had jokingly talked about zombies and what we would do if it happened. Somewhere within the conversation the city of Mogilevka was brought up because of the large industrial buildings they had. It seemed like a safe haven, somewhere you could fight and holdout for a long time. That was my destination and with any luck, someone would have survived to make it that far.
I ran through the woods north of Kamyshovo, crossed a dirt path and began to beeline for Pusta, a small village I knew of. It was quiet and eerie under the canopy and every twig snap made me jump. Along the way I discovered a tree stand with a 12-gauge shotgun. As I descended the ladder smiling, I turned to face my first zombie. Apparently I wasn't as sneaky as I thought. I lined up the barrel and watched his head pop, the round ripping through his flesh. I almost threw up as I scrambled away. Somehow I had never imagined killing zombies to be so brutal.
For hours I walked under the shady trees, the rain finally dying, until I found a road. It ran north and south and I guessed it to be the one that ran between Elektro and Msta. I also recalled there being some tourist stop along the way with an old ruin or something. I decided to press my luck and see whether I found it. It was risky but I was growing thirsty and needed to find something soon. The road stretched on for miles uphill and I had to stop numerous times to catch my breath. After what seemed like the millionth bend, I saw an odd rock structure. Quietly I approached and saw a sign reading Rog Por. This was it. Within the grounds and inside the crumbling buildings I found supplies. I wondered if someone was coming back for them, but shrugged away the thought as I abated my thirst and hunger. Every man for himself seemed fitting.
I returned the way I came and continued my trek through the woods. It was uneventful and I was grateful for that, until I reached Pusta, a small country village. Again I was forced to skirt the edges and stay hidden. It was tense half-hour as I passed dangerously close to zombies, but soon I found the old dirt road that led to Mogilevka. I jogged for miles until I saw a fork in the road and, my heart stopped, a person. I fumbled with my gun and brought it up. Would they fire on me? He saw me as well and we both cautiously approached one another. My finger was tight on the trigger, but I kept the barrel slightly off him, ready to snap to his chest at any moment. But as his face became visible I realized it was my old friend Devin. The fear lifted. After a brief celebratory greeting and an exchange of stories, we looked towards Mogilevka in the distance and the fields of zombies in the way.
Gripping our weapons and feeling a new surge of confidence, we rushed forward. As we slid up against a wooden fence I heard a growl and turned to face a zombie stepping out of bush. I panicked and fell backwards, managing to bring my shotgun up. The round exploded from the barrel and splattered into his chest and face. I looked at Devin and we knew what was about to happen. Zombie after zombie began showing up, wondering what the loud bang was. We began firing and running, trying to dodge their lunges and savage arms. I had never seen such anger, almost as if their thirst for blood was a horrible addiction, something they would do anything to satisfy. After body after body fell to the ground, we realized we had to make a move. We ran along the old wooden house and into the field. We were able to confuse them by hitting the dirt and remaining quiet. After a few minutes we began crawling towards the city.
We were about half way there when stopped at another old house. As we caught our breath I peeked around the corner and saw multiple zombies moving towards us. I went around the other way and saw more coming up the road and from the field. We were surrounded. There was an exchange of nods as we both realized it was time to run. Standing up and yelling we both fired our guns and shot the closest zombies. More rushed in and met their demise. Devin headed around one side the house as I went another. We both sprinted towards the large industrial building. Almost there I yelled to myself, just keep running. As I tore through the doorway I frantically scrambled to close the door. I didn't see Devin. I ran the length of the building checking other exits. Unfortunately one side had no doors and couldn't be blocked. I prayed none would come that way. Turning back I heard a door slam shut as zombies crashed up against it. Devin was panting and barely able to run as he crossed the building towards me. That was too close, Mogilevka was a bad idea. As we caught our breath and looked around the area we saw nothing but broken down buildings leading into the heart of the city. We needed supplies and more importantly, ammunition. We walked slowly towards some of the smaller buildings to check them out. A few minutes passed in silence as we explored the rubble. Nothing. All of a sudden I saw a couple zombies wandering in from the large building. They must have realized where we were. We fell back to a small building and waited. As we sat inside, a loud pounding echoed through the building as zombies began beating on a door behind us. Where were they coming from? I ran over and looked through the window and saw a face looking back at me. I almost screamed as I lined up my gun. No save the round, I thought, he can't get through. We had to run again. On the count of three we both stood and sprinted from the building. We ran back the way we came, through the large industrial building and out a side door. I led the charge as we crossed a field. Looking back I saw Devin being pursued by multiple targets. It was a horrible moment as I realized I might watch him die. Crouching down I brought up my gun and waited for him to pass. As he ran by, I lit up the first one. The round caught him and he dropped. Devin began to fire as well. Mogilevka was a bad idea.
We headed east for a short while. Both of us were wore out and needed rest. We passed into a small area with buildings. It was quiet and only had a couple zombies we easily finished off. We split up to find supplies. I opened an outhouse and discovered ammo and bandages on the floor. It was disgusting but I couldn't complain. As I gathered up what I could I heard an awful crashing noise. I ran over and found Devin on the ground, writhing in pain. The wooden platform above him was cracked and broken. He indicated towards his legs as he gritted his teeth. "Can you move them?" I asked as he tried to apply pressure. He muffled a scream. They were broken, maybe fractured. Fuck, this was bad. After an hour of lying around, Devin realized what needed to be done. "Shoot me," he said simply, trying to keep the emotion out of his voice.
"What?!" I exclaimed, "I can't do that." He sighed and explained the situation very clearly. Even if we decided he could be saved, it would require me to head alone to Elektro or Chernogorsk, find a hospital, get lucky and discover the right supplies, escape the city and return. It would take days probably, be extremely risky for both of us, probably risk Devin dying anyway since zombies would find him, and he might die of dehydration anyway. He said it again, "shoot me." My hands shook furiously as I raised the barrel. The iron sights came into focus with a blurry head behind it. After I fire don't look, I told myself. I swallowed the lump in my throat and felt my eyes water. Fuck this shit. A long silent moment passed and then I squeezed the trigger. I felt the boom ripple through my body, echoing loudly off the buildings and scaring birds from trees. I fell to my knees and saw his mangled face sputter its last dying breath. I ran into the woods, not looking back.
Tuesday, July 24, 2012
DayZ Tutorial, quick tips
The other day I finally got Arma 2 from the Steam Summer Sale and eagerly loaded up DayZ. Unfortunately it wasn't the easiest of tasks and put me in right state of fury! But the game turned out to be fun and I wanted to share some of the basics so people don't get discouraged and stop playing right out the gates.
Steam installation
The DayZ Steam installation was surprisingly easy, but it seems like there's a few spots people might make mistakes. So please follow these instructions carefully:
- Download Arma 2 and Arma 2: Operation Arrowhead.
- NOTE: Arma 2: Combined Operations is simply the name of the expansion pack containing the two games. It just gives you the option to buy them separately or together.
- Run Arma 2 and Arma 2: Combined Operations.
- When launching OA, it gives you multiple options, launch Combined Operations.
- Also, don't bother configuring controls and settings, it does NOT appear to save them between games.
- Close each game and navigate to here. Click "Download v2.9.7pre" or whatever version it's on.
- You can also use a mirror if necessary.
- Install the SIX Updater and launch it.
- Once it loads, click the big button on the left which says, "Install" or "Update". Let it run.
- If everything went smoothly, it should say "Verify" or appear complete in some way.
- In the background it is updating/installing beta files and updating/installing DayZ mod files.
- You are now set to play.
- NOTE: the server list takes awhile to load. Be patient if you are looking for a specific server.
Playing DayZ
There are a few key things to know about DayZ:
- LOADING: It may take a LONG time to load so be patient. If you think you've froze on a black screen that says "Loading", it is simply just taking a really long time. I almost think they did it on purpose to discourage people from dying...
- LOCATION: as the game finally loads up, quickly look at the bottom right corner for some text. This is your starting location. Remember what it is and look here. If that doesn't help, look for signs or determine the shape of the coast to find your location. Knowing where you are is essential if you're playing with friends.
- FIRST 10 MINUTES: When you get in for the first time, don't get discouraged about dying. I ran around like an idiot the first couple times not realizing how powerful zombies were. I also couldn't figure out how to use items or where I should go. All I will say is avoid coastal cities and head for the hills.
- USING ITEMS: when you press G to open your inventory, you'll be presented with a list of items and bag slots. To use say, a bandage, you would right click on it in the bag slot (NOT the list). Then left click on the dialog that slides open ("use bandage"). For weapons, you use the mouse scroll wheel to bring up item selections in the center of the screen, then press ENTER to select that weapon.
- DYING: When you die, you can't simply click respawn. You must abort, disconnect and reconnect. Why? I have no idea, it's dumb.
- LOOTING: the interface is terrible. When you see something to loot (a body or pile of shit), you press ENTER to open the menu. The numbers on the left are items you do NOT have. The numbers on the right are items you do have. Click the arrows to exchange items from left-to-right or right-to-left.
- FALL DAMAGE: if you fall and break your legs, call over your best mate and have him put a slug in your face. You can only fix broken legs if you visit a hospital (there are only 4 locations in the world). The alternative is you crawl on your stomach which would take ages.
That should get you going. It's a really fun game despite the flaws in interface and controls. My biggest tip through all this is BE PATIENT. Good luck and happy surviving!
Wednesday, July 18, 2012
Encrypted User Signup/Login using hash_hmac
So I've been working with CodeIgniter for awhile now and needed a secure user login system. I chose to develop my own since I wanted to learn as much about building a framework as possible. At one point during development I realized I needed a good user password system that didn't store passwords as a hashed string. So I went online and implemented this solution:
Ok, before we do anything, we need to add a "site_key" to our application/config/config.php file:
/*
|------------------------------------------------------------------------
| Site Key
|------------------------------------------------------------------------
|
| This is the global site key used for secure password generation.
|
*/
$config['site_key'] = 'long_random_alphanumeric_string';
The site_key will be used below. I generated mine through KeePass. Now the signup controller:
// SIGNUP for user account controller:
public function validate_signup()
{
// Use the form validation library to validate user input
$this->load->library('form_validation');
$this->form_validation->set_rules('...');
// Run the form validation
if ($this->form_validation->run() == FALSE)
{
$this->index("Optional custom error message!");
}
else // if form validation passed
{
// Run the INSERT statement and return TRUE/FALSE
if ($this->user_model->InsertSanitize($_POST['password']))
{
redirect('login');
}
else
{
$this->index("ERROR: signup failed!");
}
}
}
The signup controller handles taking new user information, validating it, and then sending the information to the user model to be INSERTED. Next let's look at the user model:
public function InsertSanitize($password)
{
// Retrieve user input data through POST:
$user_name = $this->input->post('user_name');
// Or passed through the method (choose one or the other, not both):
$password = $password;
// Do additional validation here if needed:
if (!isset($user_name) || $user_name == "")
{
// You can also use regex or functions like is_numeric()
return FALSE;
}
return $this->Insert($list_of_safe_values, $password);
}
private function Insert($list_of_safe_values, $password)
{
// Now it's time for the fun stuff!
// First we need to use crypt() to hash the input password
$hashed_pass = crypt($password);
// Next we need to call a custom function below (scroll down):
$enc_pass = $this->encrypt($password, $hashed_pass);
// Create an array of user info to INSERT
// Be sure to store the encrypted and hashed password
$data = array(
'list_of_safe_values' => $list_of_safe_values,
'enc_pass' => $enc_pass,
'hashed_pass' => $hashed_pass
);
// Run the INSERT
if ($this->db->insert('user_table', $data))
{
// Optional: Return the last records ID
return mysql_insert_id();
// Or simply:
return TRUE;
}
else // if INSERT failed
{
return FALSE;
}
}
private function encrypt($password, $nonce)
{
// Retrieve the site_key
$site_key = $this->config->item('site_key');
// Return the encrypted password using hash_hmac
return hash_hmac('sha512', $password . $nonce, $site_key);
}
Be sure when updating your website or overwriting files that you keep the site key! If you forget to re-add it, existing users won't be able to login and new users won't have the site_key attached to their accounts.
Finally, I'll show you how to use this system when logging in:
public function validate_login()
{
// Just like before, run form validation
$this->load->library('form_validation');
$this->form_validation->set_rules('...');
if ($this->form_validation->run() == FALSE)
{
$this->index("Optional custom error message!");
}
else // if form validation passed
{
// Next, run validation in the user model:
$data = $this->user_model->Validate($_POST['password']);
}
}
public function Validate($password)
{
// Retrieve user input data through POST:
$user_name = $this->input->post('user_name');
// Or passed through the method:
$password = $password;
// Do additional validation here if needed:
if (!isset($user_name) || $user_name == "")
{
// You can also use regex or functions like is_numeric()
return FALSE;
}
// Next we need to call a custom function below (scroll down):
$enc_pass = $this->retrieve($user_name, $password);
// With the encrypt password we can now validate our user login
$sql = sprintf(self::constant . " WHERE user_name = '%s'
AND password = '%s' LIMIT 1",
mysql_real_escape_string($user_name),
mysql_real_escape_string($enc_pass));
// Run your queries however you normally do
return $this->LoadFromDb($sql);
}
private function retrieve($user_name, $password)
{
// Find user by user_name
$data = $this->FindUser($user_name);
// Get the hashed user password
if (isset($data))
{
foreach ($data as $obj)
{
$hashed_pass = $obj->hashed_pass;
}
return $this->encrypt($password, $hashed_pass);
}
else
{
return FALSE;
}
}
And that's it! But before I leave, let me explain quickly in case it's a little unclear.
First we created a site key, which is used to further enhance the encryption process.
Then we allowed a user to signup, validating form data and then data that's passed to the model. Within the Insert() function we took the submitted user password and hashed it, creating a randomly generated, alphanumeric string. This is what is used as a key for decrypting the encrypted password. Then we called the encrypt() function which takes the user password and the hashed key, along with the site key and encrypts them altogether. We returned this encrypted password and INSERTED it into the database along with the hashed key and any other user data (like username, email, etc.).
Now that we have a new user account with an encrypted password, we need to login. We validate the login form and data that's passed to the model. If everything looks good, we call the retrieve() function which loads the requested user information. We grab the supposed user's hashed key, along with the password they provided at login, and run it through the encryption process again.
From here we created a query using the provided user_name and processed encrypted password to see if any entries in the database are returned. If there is a record, that means that the username and password the login provided, matched and was successful. If it fails, that means either the username or password was wrong, or the user doesn't even exist.
Hopefully that all makes sense. Good luck!
Note: sorry if the code looks messed up, Blogger apparently sucks at pasting...also we're technically never decrypting anything. Just encrypting again and comparing.
Ok, before we do anything, we need to add a "site_key" to our application/config/config.php file:
/*
|------------------------------------------------------------------------
| Site Key
|------------------------------------------------------------------------
|
| This is the global site key used for secure password generation.
|
*/
$config['site_key'] = 'long_random_alphanumeric_string';
The site_key will be used below. I generated mine through KeePass. Now the signup controller:
// SIGNUP for user account controller:
public function validate_signup()
{
// Use the form validation library to validate user input
$this->load->library('form_validation');
$this->form_validation->set_rules('...');
// Run the form validation
if ($this->form_validation->run() == FALSE)
{
$this->index("Optional custom error message!");
}
else // if form validation passed
{
// Run the INSERT statement and return TRUE/FALSE
if ($this->user_model->InsertSanitize($_POST['password']))
{
redirect('login');
}
else
{
$this->index("ERROR: signup failed!");
}
}
}
The signup controller handles taking new user information, validating it, and then sending the information to the user model to be INSERTED. Next let's look at the user model:
public function InsertSanitize($password)
{
// Retrieve user input data through POST:
$user_name = $this->input->post('user_name');
// Or passed through the method (choose one or the other, not both):
$password = $password;
// Do additional validation here if needed:
if (!isset($user_name) || $user_name == "")
{
// You can also use regex or functions like is_numeric()
return FALSE;
}
return $this->Insert($list_of_safe_values, $password);
}
private function Insert($list_of_safe_values, $password)
{
// Now it's time for the fun stuff!
// First we need to use crypt() to hash the input password
$hashed_pass = crypt($password);
// Next we need to call a custom function below (scroll down):
$enc_pass = $this->encrypt($password, $hashed_pass);
// Create an array of user info to INSERT
// Be sure to store the encrypted and hashed password
$data = array(
'list_of_safe_values' => $list_of_safe_values,
'enc_pass' => $enc_pass,
'hashed_pass' => $hashed_pass
);
// Run the INSERT
if ($this->db->insert('user_table', $data))
{
// Optional: Return the last records ID
return mysql_insert_id();
// Or simply:
return TRUE;
}
else // if INSERT failed
{
return FALSE;
}
}
private function encrypt($password, $nonce)
{
// Retrieve the site_key
$site_key = $this->config->item('site_key');
// Return the encrypted password using hash_hmac
return hash_hmac('sha512', $password . $nonce, $site_key);
}
Be sure when updating your website or overwriting files that you keep the site key! If you forget to re-add it, existing users won't be able to login and new users won't have the site_key attached to their accounts.
Finally, I'll show you how to use this system when logging in:
public function validate_login()
{
// Just like before, run form validation
$this->load->library('form_validation');
$this->form_validation->set_rules('...');
if ($this->form_validation->run() == FALSE)
{
$this->index("Optional custom error message!");
}
else // if form validation passed
{
// Next, run validation in the user model:
$data = $this->user_model->Validate($_POST['password']);
}
}
public function Validate($password)
{
// Retrieve user input data through POST:
$user_name = $this->input->post('user_name');
// Or passed through the method:
$password = $password;
// Do additional validation here if needed:
if (!isset($user_name) || $user_name == "")
{
// You can also use regex or functions like is_numeric()
return FALSE;
}
// Next we need to call a custom function below (scroll down):
$enc_pass = $this->retrieve($user_name, $password);
// With the encrypt password we can now validate our user login
$sql = sprintf(self::constant . " WHERE user_name = '%s'
AND password = '%s' LIMIT 1",
mysql_real_escape_string($user_name),
mysql_real_escape_string($enc_pass));
// Run your queries however you normally do
return $this->LoadFromDb($sql);
}
private function retrieve($user_name, $password)
{
// Find user by user_name
$data = $this->FindUser($user_name);
// Get the hashed user password
if (isset($data))
{
foreach ($data as $obj)
{
$hashed_pass = $obj->hashed_pass;
}
return $this->encrypt($password, $hashed_pass);
}
else
{
return FALSE;
}
}
And that's it! But before I leave, let me explain quickly in case it's a little unclear.
First we created a site key, which is used to further enhance the encryption process.
Then we allowed a user to signup, validating form data and then data that's passed to the model. Within the Insert() function we took the submitted user password and hashed it, creating a randomly generated, alphanumeric string. This is what is used as a key for decrypting the encrypted password. Then we called the encrypt() function which takes the user password and the hashed key, along with the site key and encrypts them altogether. We returned this encrypted password and INSERTED it into the database along with the hashed key and any other user data (like username, email, etc.).
Now that we have a new user account with an encrypted password, we need to login. We validate the login form and data that's passed to the model. If everything looks good, we call the retrieve() function which loads the requested user information. We grab the supposed user's hashed key, along with the password they provided at login, and run it through the encryption process again.
From here we created a query using the provided user_name and processed encrypted password to see if any entries in the database are returned. If there is a record, that means that the username and password the login provided, matched and was successful. If it fails, that means either the username or password was wrong, or the user doesn't even exist.
Hopefully that all makes sense. Good luck!
Note: sorry if the code looks messed up, Blogger apparently sucks at pasting...also we're technically never decrypting anything. Just encrypting again and comparing.
Labels:
CodeIgniter,
controller,
database,
encryption,
hash_hmac,
model,
MVC,
MySQL,
PHP,
security
Subscribe to:
Posts (Atom)