<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>Warren Krewenki</title>
 <link href="http://krewenki.github.com/atom.xml" rel="self"/>
 <link href="http://krewenki.github.com/"/>
 <updated>2011-05-25T12:28:30-07:00</updated>
 <id>http://krewenki.github.com</id>
 <author>
   <name>Warren Krewenki</name>
 </author>
 
 
 <entry>
   <title>Password Hashing Done Right</title>
   <link href="http://krewenki.github.com/2011/05/password-hashing-done-right"/>
   <updated>2011-05-24T00:00:00-07:00</updated>
   <id>http://krewenki.github.com/2011/05/password-hashing-done-right</id>
   <content type="html">&lt;p&gt;After reading a very informative piece by &lt;a href=&quot;http://codahale.com/how-to-safely-store-a-password/&quot;&gt;Coda Hale&lt;/a&gt; about the proper way to store a password, I thought i&amp;rsquo;d provide a bit of information on the topic to help drive his point home.&lt;/p&gt;

&lt;p&gt;There are at least two important things to think about when generating and storing passwords for any application. The first is general password strength, and the other is how you store that password.&lt;/p&gt;

&lt;h2&gt;Strong Passwords&lt;/h2&gt;

&lt;p&gt;The first thing to consider when dealing with passwords is enforcing some general measure of password strength.  All of the salting and encryption in the world won&amp;rsquo;t do you any good if you have users with passwords that are too short, easily guessable, etc.  By enforcing a reasonable minimum length, and some rules for the composition of the password, you can introduce your first line of defence against brute force and/or dictionary attacks.&lt;/p&gt;

&lt;p&gt;My personal stance is that the most important rule to enforce is password length. The simple act of adding a character to a password makes a brute force attack take an order of magnitude longer.  8 characters takes longer to brute force than 7, and 9 takes longer than 8, etc.  I often default to 8 characters, so that&amp;rsquo;s the example I will use here.&lt;/p&gt;

&lt;p&gt;For the purpose of this example, I&amp;rsquo;m going to build on the assumption that all of my passwords are made up of the following characters:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
0123456789
!@#$%^&amp;amp;*()_+-=?
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It is important to note that you may have more available characters, and you may have less.  I&amp;rsquo;m going to base my example around these 77 characters.  Again, the more characters available, the stronger a potential password is.&lt;/p&gt;

&lt;p&gt;Your passwords are now made up of a minimum of 8 characters with 77 possible characters in each position.  To calculate the number of total possibilities for this schema, the math is simple. Number of characters raised to the power of length of password, or more simply:&lt;/p&gt;

&lt;p&gt;77 * 77 * 77 * 77 * 77 * 77 * 77 * 77 = 1,235,736,291,547,681&lt;/p&gt;

&lt;p&gt;In plain english, that&amp;rsquo;s 1.2 quadrillion.  Seems like a lot, doesn&amp;rsquo;t it?  If you were a human trying to guess the password through brute force &lt;em&gt;00000000, 00000001, 00000002 etc&lt;/em&gt; and you could type passwords at a rate of 1 per second, it would take you just under 40,000,000 years (without stopping for coffee or bathroom breaks!)&lt;/p&gt;

&lt;p&gt;If your computer, on the other hand, was trying to guess your password by means of brute force, it would take substantially less time.  My laptop, as of May 2011, can generate roughly 1,300,000 guesses per second, and that&amp;rsquo;s based on unoptimized node.js code running on an already busy macbook pro.  As Coda &lt;a href=&quot;http://www.golubev.com/hashgpu.htm&quot;&gt;pointed out&lt;/a&gt; , there are methods available currently (for around $2,000 USD) that will allow for the generation of 5,600,000,000 hashes (not just attempts, full hashes) per second.  Your 40 million human years is now broken down to 3 days before your 8 character password can be guessed.&lt;/p&gt;

&lt;p&gt;The problem with relying on strength alone is that these numbers are going to change quickly, and leaving the onus on your users to come up with more and more unique/strong passwords is a horrible solution.  Strong passwords increase the number of required guesses, but now you need to slow down the guessing.&lt;/p&gt;

&lt;h2&gt;Generating and Storing Password Hashes&lt;/h2&gt;

&lt;p&gt;Modern computers can generate hashes incredibly fast.  While the example of 5,600,000,000 per second was a very specialized (albeit cheap) solution,  your own computer can generate a standard MD5 hash very quickly.  When you loaded this article, some simple code was run in the background, and determined that your web browser was able to generate &lt;span id=&quot;perSecond&quot;&gt;0&lt;/span&gt; hashes per second.  You would have made &lt;span id=&quot;calcCount&quot;&gt;0&lt;/span&gt; attempts at an md5 hashed password in the time you spent reading this.  As technology improves, so will the number of attempts per second. The same specialized application that attained 5,600,000,000 attempts per second a year ago may be able to do 10,000,000,000 next year.&lt;/p&gt;

&lt;h3&gt;What about SHA1, SHA256, or even SHA512&lt;/h3&gt;

&lt;p&gt;While methods like SHA512 are slower than MD5, they are not the answer.  SHA512 will increase in speed on the same path that MD5 does, eventually allowing for billions or even trillions of attempts per second.&lt;/p&gt;

&lt;h2&gt;Enter bcrypt&lt;/h2&gt;

&lt;p&gt;Coda explains why to use bcrypt best with the following:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;How? Basically, it&amp;rsquo;s slow as hell. It uses a variant of the Blowfish encryption algorithm&amp;rsquo;s keying schedule, and introduces a work factor, which allows you to determine how expensive the hash function will be. Because of this, bcrypt can keep up with Moore&amp;rsquo;s law. As computers get faster you can increase the work factor and the hash will get slower.&lt;/p&gt;

&lt;p&gt;How much slower is bcrypt than, say, MD5? Depends on the work factor. Using a work factor of 12, bcrypt hashes the password yaaa in about 0.3 seconds on my laptop. MD5, on the other hand, takes less than a microsecond.&lt;/p&gt;

&lt;p&gt;So we&amp;rsquo;re talking about 5 or so orders of magnitude. Instead of cracking a password every 40 seconds, I&amp;rsquo;d be cracking them every 12 years or so. Your passwords might not need that kind of security and you might need a faster comparison algorithm, but bcrypt&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Basically, you can specify the amount of &lt;em&gt;work&lt;/em&gt; bcrypt performs to generate your hash.  As technology improves, you can increase the amount of work you do to derive your hashes, keeping up with the modern technology curve.&lt;/p&gt;

&lt;p&gt;Until there is a massively parallel version of bcrypt that can benefit from CUDA/OpenCL, this method moves brute forcing your hashes back into the thousands/millions of years range.  I&amp;rsquo;d say that is about as &amp;ldquo;difficult to brute force&amp;rdquo; as anyone can currently ask for.&lt;/p&gt;

&lt;h2&gt;Closing Thoughts&lt;/h2&gt;

&lt;p&gt;While this focuses primarily on the generation and hashing of passwords, and is meant to deal with ensuring the security of your passwords should your password database be compromised, it is not all you need to focus on when securing your password data.  There are a host of other methods that can and should be used to ensure proper password handling such as lockouts, resets, etc.  Other security measures can be covered in a separate post. This one covers the important thing:&lt;/p&gt;

&lt;p&gt;Use bcrypt&lt;/p&gt;

&lt;script&gt;
/*
 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
 * Digest Algorithm, as defined in RFC 1321.
 * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
 * Distributed under the BSD License
 * See http://pajhome.org.uk/crypt/md5 for more info.
 */
var hexcase=0;function hex_md5(a){return rstr2hex(rstr_md5(str2rstr_utf8(a)))}function hex_hmac_md5(a,b){return rstr2hex(rstr_hmac_md5(str2rstr_utf8(a),str2rstr_utf8(b)))}function md5_vm_test(){return hex_md5(&quot;abc&quot;).toLowerCase()==&quot;900150983cd24fb0d6963f7d28e17f72&quot;}function rstr_md5(a){return binl2rstr(binl_md5(rstr2binl(a),a.length*8))}function rstr_hmac_md5(c,f){var e=rstr2binl(c);if(e.length&gt;16){e=binl_md5(e,c.length*8)}var a=Array(16),d=Array(16);for(var b=0;b&lt;16;b++){a[b]=e[b]^909522486;d[b]=e[b]^1549556828}var g=binl_md5(a.concat(rstr2binl(f)),512+f.length*8);return binl2rstr(binl_md5(d.concat(g),512+128))}function rstr2hex(c){try{hexcase}catch(g){hexcase=0}var f=hexcase?&quot;0123456789ABCDEF&quot;:&quot;0123456789abcdef&quot;;var b=&quot;&quot;;var a;for(var d=0;d&lt;c.length;d++){a=c.charCodeAt(d);b+=f.charAt((a&gt;&gt;&gt;4)&amp;15)+f.charAt(a&amp;15)}return b}function str2rstr_utf8(c){var b=&quot;&quot;;var d=-1;var a,e;while(++d&lt;c.length){a=c.charCodeAt(d);e=d+1&lt;c.length?c.charCodeAt(d+1):0;if(55296&lt;=a&amp;&amp;a&lt;=56319&amp;&amp;56320&lt;=e&amp;&amp;e&lt;=57343){a=65536+((a&amp;1023)&lt;&lt;10)+(e&amp;1023);d++}if(a&lt;=127){b+=String.fromCharCode(a)}else{if(a&lt;=2047){b+=String.fromCharCode(192|((a&gt;&gt;&gt;6)&amp;31),128|(a&amp;63))}else{if(a&lt;=65535){b+=String.fromCharCode(224|((a&gt;&gt;&gt;12)&amp;15),128|((a&gt;&gt;&gt;6)&amp;63),128|(a&amp;63))}else{if(a&lt;=2097151){b+=String.fromCharCode(240|((a&gt;&gt;&gt;18)&amp;7),128|((a&gt;&gt;&gt;12)&amp;63),128|((a&gt;&gt;&gt;6)&amp;63),128|(a&amp;63))}}}}}return b}function rstr2binl(b){var a=Array(b.length&gt;&gt;2);for(var c=0;c&lt;a.length;c++){a[c]=0}for(var c=0;c&lt;b.length*8;c+=8){a[c&gt;&gt;5]|=(b.charCodeAt(c/8)&amp;255)&lt;&lt;(c%32)}return a}function binl2rstr(b){var a=&quot;&quot;;for(var c=0;c&lt;b.length*32;c+=8){a+=String.fromCharCode((b[c&gt;&gt;5]&gt;&gt;&gt;(c%32))&amp;255)}return a}function binl_md5(p,k){p[k&gt;&gt;5]|=128&lt;&lt;((k)%32);p[(((k+64)&gt;&gt;&gt;9)&lt;&lt;4)+14]=k;var o=1732584193;var n=-271733879;var m=-1732584194;var l=271733878;for(var g=0;g&lt;p.length;g+=16){var j=o;var h=n;var f=m;var e=l;o=md5_ff(o,n,m,l,p[g+0],7,-680876936);l=md5_ff(l,o,n,m,p[g+1],12,-389564586);m=md5_ff(m,l,o,n,p[g+2],17,606105819);n=md5_ff(n,m,l,o,p[g+3],22,-1044525330);o=md5_ff(o,n,m,l,p[g+4],7,-176418897);l=md5_ff(l,o,n,m,p[g+5],12,1200080426);m=md5_ff(m,l,o,n,p[g+6],17,-1473231341);n=md5_ff(n,m,l,o,p[g+7],22,-45705983);o=md5_ff(o,n,m,l,p[g+8],7,1770035416);l=md5_ff(l,o,n,m,p[g+9],12,-1958414417);m=md5_ff(m,l,o,n,p[g+10],17,-42063);n=md5_ff(n,m,l,o,p[g+11],22,-1990404162);o=md5_ff(o,n,m,l,p[g+12],7,1804603682);l=md5_ff(l,o,n,m,p[g+13],12,-40341101);m=md5_ff(m,l,o,n,p[g+14],17,-1502002290);n=md5_ff(n,m,l,o,p[g+15],22,1236535329);o=md5_gg(o,n,m,l,p[g+1],5,-165796510);l=md5_gg(l,o,n,m,p[g+6],9,-1069501632);m=md5_gg(m,l,o,n,p[g+11],14,643717713);n=md5_gg(n,m,l,o,p[g+0],20,-373897302);o=md5_gg(o,n,m,l,p[g+5],5,-701558691);l=md5_gg(l,o,n,m,p[g+10],9,38016083);m=md5_gg(m,l,o,n,p[g+15],14,-660478335);n=md5_gg(n,m,l,o,p[g+4],20,-405537848);o=md5_gg(o,n,m,l,p[g+9],5,568446438);l=md5_gg(l,o,n,m,p[g+14],9,-1019803690);m=md5_gg(m,l,o,n,p[g+3],14,-187363961);n=md5_gg(n,m,l,o,p[g+8],20,1163531501);o=md5_gg(o,n,m,l,p[g+13],5,-1444681467);l=md5_gg(l,o,n,m,p[g+2],9,-51403784);m=md5_gg(m,l,o,n,p[g+7],14,1735328473);n=md5_gg(n,m,l,o,p[g+12],20,-1926607734);o=md5_hh(o,n,m,l,p[g+5],4,-378558);l=md5_hh(l,o,n,m,p[g+8],11,-2022574463);m=md5_hh(m,l,o,n,p[g+11],16,1839030562);n=md5_hh(n,m,l,o,p[g+14],23,-35309556);o=md5_hh(o,n,m,l,p[g+1],4,-1530992060);l=md5_hh(l,o,n,m,p[g+4],11,1272893353);m=md5_hh(m,l,o,n,p[g+7],16,-155497632);n=md5_hh(n,m,l,o,p[g+10],23,-1094730640);o=md5_hh(o,n,m,l,p[g+13],4,681279174);l=md5_hh(l,o,n,m,p[g+0],11,-358537222);m=md5_hh(m,l,o,n,p[g+3],16,-722521979);n=md5_hh(n,m,l,o,p[g+6],23,76029189);o=md5_hh(o,n,m,l,p[g+9],4,-640364487);l=md5_hh(l,o,n,m,p[g+12],11,-421815835);m=md5_hh(m,l,o,n,p[g+15],16,530742520);n=md5_hh(n,m,l,o,p[g+2],23,-995338651);o=md5_ii(o,n,m,l,p[g+0],6,-198630844);l=md5_ii(l,o,n,m,p[g+7],10,1126891415);m=md5_ii(m,l,o,n,p[g+14],15,-1416354905);n=md5_ii(n,m,l,o,p[g+5],21,-57434055);o=md5_ii(o,n,m,l,p[g+12],6,1700485571);l=md5_ii(l,o,n,m,p[g+3],10,-1894986606);m=md5_ii(m,l,o,n,p[g+10],15,-1051523);n=md5_ii(n,m,l,o,p[g+1],21,-2054922799);o=md5_ii(o,n,m,l,p[g+8],6,1873313359);l=md5_ii(l,o,n,m,p[g+15],10,-30611744);m=md5_ii(m,l,o,n,p[g+6],15,-1560198380);n=md5_ii(n,m,l,o,p[g+13],21,1309151649);o=md5_ii(o,n,m,l,p[g+4],6,-145523070);l=md5_ii(l,o,n,m,p[g+11],10,-1120210379);m=md5_ii(m,l,o,n,p[g+2],15,718787259);n=md5_ii(n,m,l,o,p[g+9],21,-343485551);o=safe_add(o,j);n=safe_add(n,h);m=safe_add(m,f);l=safe_add(l,e)}return Array(o,n,m,l)}function md5_cmn(h,e,d,c,g,f){return safe_add(bit_rol(safe_add(safe_add(e,h),safe_add(c,f)),g),d)}function md5_ff(g,f,k,j,e,i,h){return md5_cmn((f&amp;k)|((~f)&amp;j),g,f,e,i,h)}function md5_gg(g,f,k,j,e,i,h){return md5_cmn((f&amp;j)|(k&amp;(~j)),g,f,e,i,h)}function md5_hh(g,f,k,j,e,i,h){return md5_cmn(f^k^j,g,f,e,i,h)}function md5_ii(g,f,k,j,e,i,h){return md5_cmn(k^(f|(~j)),g,f,e,i,h)}function safe_add(a,d){var c=(a&amp;65535)+(d&amp;65535);var b=(a&gt;&gt;16)+(d&gt;&gt;16)+(c&gt;&gt;16);return(b&lt;&lt;16)|(c&amp;65535)}function bit_rol(a,b){return(a&lt;&lt;b)|(a&gt;&gt;&gt;(32-b))};

var totalCalculated = 0;
var perSecond = 0;
var possibleCharacters = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','0','1','2','3','4','5','6','7','8','9','!','@','$','%','^','&amp;','*','(',')','-','=','_','+'];
var calculateBlock = function(){
    var start = new Date().getTime() / 1000;
    for(i=0;i&lt;10000;i++){
        password = '';
        for(n=0;n&lt;8;n++){
            password += possibleCharacters[Math.floor(Math.random()*possibleCharacters.length)]
        }
        hash = hex_md5(password)
        totalCalculated++;
    }
    var finish = new Date().getTime() / 1000;
    var totalTime = finish - start;
    perSecond = Math.floor(10000 * (1/totalTime));
    document.getElementById('perSecond').innerHTML = Math.floor(perSecond);
    setInterval(function(){ totalCalculated += perSecond; document.getElementById('calcCount').innerHTML = totalCalculated; },1000);
}

calculateBlock();


&lt;/script&gt;

</content>
 </entry>
 
 <entry>
   <title>Deploying Redmine on Amazon EC2</title>
   <link href="http://krewenki.github.com/2011/05/deploying-redmine-on-amazon-ec2"/>
   <updated>2011-05-03T00:00:00-07:00</updated>
   <id>http://krewenki.github.com/2011/05/deploying-redmine-on-amazon-ec2</id>
   <content type="html">&lt;p&gt;It&amp;rsquo;s insanely easy to get &lt;a href=&quot;http://www.redmine.org&quot;&gt;Redmine&lt;/a&gt; up and running on &lt;a href=&quot;http://aws.amazon.com/ec2/&quot;&gt;Amazon EC2&lt;/a&gt;.  I went through the process
today and thought it would make sense to document it on here for others to read.&lt;/p&gt;

&lt;h2&gt;Why EC2&lt;/h2&gt;

&lt;p&gt;You may ask yourself, &amp;ldquo;Why EC2? &lt;a href=&quot;http://www.heroku.com&quot;&gt;Heroku&lt;/a&gt; has a free tier of rails hosting&amp;rdquo;. You&amp;rsquo;re right, they do.  The difference is, EC2 gives you a full linux install with 10gb of persistent storage, whereas heroku gives you a 5mb database.  Couple storage differences with the ability hook redmine up to your local git repo on your EC2 instance, upload files and documents, and do full backup snapshots to S3 out of the box, and EC2 seemed like an easy choice to me.&lt;/p&gt;

&lt;h2&gt;Start to Finish in 5 Minutes&lt;/h2&gt;

&lt;p&gt;If you don&amp;rsquo;t already have an EC2 account, go sign up for one now.  You won&amp;rsquo;t be able to do any of this without an account.  Once you are signed up, and in the EC2 management console, click on &amp;ldquo;Launch Instance&amp;rdquo;.  A window will pop up showing 6 sections. Here is a quick overview of what to select in each section:&lt;/p&gt;

&lt;h3&gt;Choose an AMI&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Click the Community AMIs tab&lt;/li&gt;
&lt;li&gt;Set viewing to All Images&lt;/li&gt;
&lt;li&gt;Type &amp;ldquo;bitnami redmine&amp;rdquo; in the box next to &amp;ldquo;Viewing&amp;rdquo;&lt;/li&gt;
&lt;li&gt;As of writing this, the most recent version is 1.1.2 on Ubuntu with ebs as the root device.  Find the most recent version in the list and click the appropriate &amp;ldquo;Select&amp;rdquo; button&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;Instance Details&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Set instance type to Micro&lt;/li&gt;
&lt;li&gt;Click Continue&lt;/li&gt;
&lt;li&gt;Set any User Data you&amp;rsquo;d like, and click Continue again&lt;/li&gt;
&lt;li&gt;Set any tags you&amp;rsquo;d like, and click Continue again&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;Create Key Pair&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Create a new key pair (or use an existing set)&lt;/li&gt;
&lt;li&gt;Download a copy of your keypair&lt;/li&gt;
&lt;li&gt;Click Continue&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;Configure Firewall&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Click Continue&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;Review&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Click Launch&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;Adjust Security Group&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Click on Security Groups in the left hand bar&lt;/li&gt;
&lt;li&gt;Select your default group&lt;/li&gt;
&lt;li&gt;Click the Inbound tab in the details pane&lt;/li&gt;
&lt;li&gt;Add preset rules for SSH, HTTP and HTTPS&lt;/li&gt;
&lt;li&gt;Click Apply Rules&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Now, you can get your public dns name from your instances dashboard, and you should be up and running with a copy of redmine.  To boot, this installation falls under the &amp;ldquo;free&amp;rdquo; tier of AWS, which means you won&amp;rsquo;t have to pay the hefty $0.02/hr cost of running this instance, if you&amp;rsquo;ve got no other instances running.&lt;/p&gt;

&lt;p&gt;Happy Bug Tracking!&lt;/p&gt;
</content>
 </entry>
 
 
</feed>