JSLint.VS2010: Automatic JavaScript Static Analysis

Recently, I was working on a project that used some asynchronous JSON-to-HTML databiding. Testers sent a bug that the site was working in Chrome, Firefox, Safari and IE9 but nothing was happening in IE8. The IE8 javascript debugger didn’t report any errors, it just didn’t do anything.

This sort of thing is no fun to debug and I spent an increasingly desperate evening staring at code that couldn’t possibly be wrong  failing to see the problem. Eventually, in desperation, I pasted the code into Douglas Crockford’s jslint and it quickly pointed out a stray comma which made all the difference.

I later discovered that there is a jslint extension available for Visual Studio 2010.

jslint-options

The really cool thing about the JSLint Visual Studio extension is that it reports its warnings and errors into the Visual Studio Error List window where they work just like other code errors. Even better, it has the option to cancel the build on error. That means if jslint finds an error, the project build dies. In my world, this is fantastic. It means I don’t even try to test something if jslint finds something wrong with it. I consider this to be a huge productivity win.skip-on-build

The following JSLint global options were key for me to use jslint as a build-time checker:

  • Output: Errors – causes Visual Studio to interpret JSLint output as errors
  • Run JSLint on build: true – causes JSLint to test all .JS files during build
  • Cancel build on error true– causes JSLint errors to cancel the build, just like C# compiler errors
  • Assume a browser: true
  • Predefined Vars: jQuery, $
  • Strict whitespace: false
  • Maximum line length: 999
    One issue with cancelling the build on error is that jslint is pedantic and some of its warnings are not strictly errors which means that standard libraries like jquery aren’t going to pass jslint. Fortunately, you can exclude individual .js files from build-time testing by right-clicking on the files you want to exclude in the Solution Explorer window. (Note that jslint doesn’t plug its menus into the Solution Navigator window from the “Productivity Power Tools” extension. You have to use the Solution Explorer.)
    Happy linting.
Advertisements

Secure Password Hashing in C#

Long-term storage of logon credentials in computer systems is a serious point of vulnerability. Too many systems store credentials in an unencrypted or weakly encrypted form that system administrators or database power-users can view or edit. This may seem OK as long as a set of conditions were true:

  • The administrators of the system are known to be trustworthy and no untrusted users have the ability to view, alter or copy the password file or table.
  • The normal execution flow of the system could not be used to reveal plaintext passwords.
  • The online and backup repositories of authentication data are secure.
    Employee turnover, the increasing complexity of internet-connected systems, and the spread of knowledge and tools for executing simple security exploits all work together to change the rules of the game so that storing passwords in plaintext is no longer acceptable.  Disgruntled employees are now widely acknowledged to be the single largest vulnerability for most companies, and are the most common attackers of computer systems.  Defects in production software, runtimes and platforms can also disclose sensitive information to attackers. A litany of recent headlines where a wide range of organizations have lost control of their authentication database prove that systems that store “secret” but plaintext logon information are unsafe.

Theory of Password Hashing in Brief

The key to hardening authentication systems to use a strong cryptographic function to hash passwords into an unrecoverable blob. A strong hashing algorithm must guard against brute force offline attack via a rainbow tables precompiled hashes on dictionary words. Rainbow tables and software to use them are publicly available which lowers the password cracking bar to the level of script kiddie.

Niels Furguson and Bruce Schneier in Practical Cryptography describe strong a strong hashing technique for safe storage of passwords which requires.

  • A publicly tested secure hashing algorithm such as SHA-256. Neither MD5 nor SHA-1 are good enough anymore.
  • A randomly-generated value known as a Salt is mixed with the plaintext. The salt value is not a secret, it exists to make the output of the hash non-deterministic. There should be a unique salt for each user and a new random salt value should be generated every time a password is set.
  • The hash is stretched, meaning that the output is fed back through the algorithm a large number of times in order to slow down the hashing algorithm to make brute force attacks impractical.

In order to authenticate a user, the system retrieves the salt for the username, calculates the hash for the password the user provided and compares that hash to the value in the authentication database. If the hashes match, then access is granted.

Implementation in C#

In hope of making it easy for .NET developers to implement good authentication security, my company published a secure password hashing algorithm in C# under the BSD license in 2005. This algorithm is a part of the security subsystem of our PeopleMatrix product.

Because the code is no longer available on thoughtfulcomputing.com, so I’m republishing hit here.

Download HashManager source with a sample application.

//*****************************************************************
// <copyright file="HashManager.cs" company="WolfeReiter">
// Copyright (c) 2005 WolfeReiter, LLC.
// </copyright>
//*****************************************************************

/*
** Copyright (c) 2005 WolfeReiter, LLC
**
** This software is provided 'as-is', without any express or implied warranty. In no 
** event will the authors be held liable for any damages arising from the use of 
** this software.
**
** Permission is granted to anyone to use this software for any purpose, including 
** commercial applications, and to alter it and redistribute it freely, subject to 
** the following restrictions:
**
**    1. The origin of this software must not be misrepresented; you must not claim 
**       that you wrote the original software. If you use this software in a product,
**       an acknowledgment in the product documentation would be appreciated but is 
**       not required.
**
**    2. Altered source versions must be plainly marked as such, and must not be 
**       misrepresented as being the original software.
**
**    3. This notice may not be removed or altered from any source distribution.
**
*/

using System;
using System.Globalization;
using System.Text;
using System.Security.Cryptography;

namespace WolfeReiter.Security.Cryptography
{
	/// <summary>
	/// HashManager provides the service of cryptographically hashing and verifying strings
	/// against an existing hash. HashManager uses the SHA-256 hashing transform by default.
	/// </summary>
	/// <remarks>
	/// <para>The MD5 and SHA1 algorithms should be avoided because they are not strong enough
	/// to resist attack with modern processors. Also, it appears that the algorithms for MD5 and SHA1
	/// may have a flaw known as "collision". The short story is that  an attacker can discover the 
	/// plaintext used to generate the hash in much fewer steps than expected.</para>
	/// <para>For example, SHA1 should theoretically require 2<sup>80</sup> steps to brute-force recover 
	/// the original plaintext. Researchers have recently claimed to have a method of recovering SHA1 plaintext
	/// in 2<sup>33</sup> steps.</para></remarks>
	[Serializable]
	public sealed class HashManager 
	{
		private HashAlgorithm _transform;
		private readonly ulong _iterations;

		/// <summary>
		/// CTOR. Creates a new HashManager object that uses the SHA-256 algorithm and stretches the entropy in the hash
		/// with 2<sup>16</sup> iterations.
		/// </summary>
		public HashManager() : this("SHA-256",65536){}
		/// <summary>
		/// CTOR. Creates a new HashManager object that uses the specified well-known hash transform algorithm.
		/// </summary>
		/// <param name="transform">Well-known transform algorithm (eg. MD5, SHA-1, SHA-256, SHA-384, SHA-512, etc.).</param>
		/// <param name="iterations">Number of iterations used to sretch the entropy of the plaintext. 2<sup>16</sup> iterations
		/// is a recommended minimum.</param>
		/// <exception cref="ArgumentOutOfRangeException">Throws if iterations is less than 1.</exception>
		public HashManager(string transform, ulong iterations) : this(HashAlgorithm.Create(transform),iterations){}

		/// <summary>
		/// CTOR. Creates a new HashManager object that uses provided transform hash algorithm.
		/// </summary>
		/// <param name="transform">HashAlgorithm object to use.</param>
		/// <param name="iterations">Number of iterations used to sretch the entropy of the plaintext. 2<sup>16</sup> iterations
		/// is a recommended minimum.</param>
		/// <exception cref="ArgumentOutOfRangeException">Throws if iterations is less than 1.</exception>
		public HashManager(HashAlgorithm transform, ulong iterations)
		{
			if( iterations < 1 )
				throw new ArgumentOutOfRangeException("iterations", iterations, "The number of iterations cannot be less than 1");
			_transform  = transform;
			_iterations = iterations;
		}
		/// <summary>
		/// CTOR. Creates a new HashManager object that uses the specified well-known hash transform algorithm.
		/// </summary>
		/// <param name="transform">Well-known transform algorithm (eg. MD5, SHA-1, SHA-256, SHA-384, SHA-512, etc.).</param>
		/// <param name="iterations">Number of iterations used to sretch the entropy of the plaintext. 2<sup>16</sup> iterations
		/// is a recommended minimum.</param>
		/// <exception cref="ArgumentOutOfRangeException">Throws if iterations is less than 1.</exception>
		public HashManager(string transform, long iterations) : this(HashAlgorithm.Create(transform),iterations){}

		/// <summary>
		/// CTOR. Creates a new HashManager object that uses provided transform hash algorithm.
		/// </summary>
		/// <param name="transform">HashAlgorithm object to use.</param>
		/// <param name="iterations">Number of iterations used to sretch the entropy of the plaintext. 2<sup>16</sup> iterations
		/// is a recommended minimum.</param>
		/// <exception cref="ArgumentOutOfRangeException">Throws if iterations is less than 1.</exception>
		public HashManager(HashAlgorithm transform, long iterations)
		{
			if( iterations < 1 )
				throw new ArgumentOutOfRangeException("iterations", iterations, "The number of iterations cannot be less than 1");
			_transform  = transform;
			_iterations = (ulong)iterations;
		}
		/// <summary>
		/// Hashes a plaintext string.
		/// </summary>
		/// <param name="s">Plaintext to hash. (not nullable)</param>
		/// <param name="salt">Salt entropy to mix with the s. (not nullable)</param>
		/// <returns>HashManager byte array.</returns>
		/// <exception cref="ArgumentNullException">Throws if either the s or salt arguments are null.</exception>
		public byte[] Encode( string s, byte[] salt )
		{
			if( s==null )
				throw new ArgumentNullException("s");
			if( salt==null )
				throw new ArgumentNullException("salt");

            return Encode( ConvertStringToByteArray( s ), salt );
		}

        public byte[] Encode( byte[] plaintext, byte[] salt )
        {
            byte[] sp = salt;
            byte[] hash = plaintext;
            //stretching via multiple iterations injects entropy that makes collision plaintext recovery much
            //more difficult.
            for( ulong i = 0; i < _iterations; i++ )
            {
                sp = Salt( hash, salt );
                hash = _transform.ComputeHash( sp );
            }

            return hash;
        }

		private byte[] Salt( byte[] p, byte[] salt )
		{
			byte[] buff = new byte[p.Length + salt.Length];
			for( int i=0; i<p.Length; i++ )
				buff[i] = p[i];
			for( int i=0; i<salt.Length; i++ )
				buff[i + p.Length] = salt[i];
			
			return buff;
		}

		/// <summary>
		/// Verifies a plaintext string against an existing hash. This is a case-sensitive operation.
		/// </summary>
		/// <param name="s">Plaintext to verify</param>
		/// <param name="hash">HashManager to compare with the s</param>
		/// <param name="salt">Salt that was used with the original s to generate the hash</param>
		/// <returns>True if the s is the same as the one used to generate the original hash.
		/// Otherwise false.</returns>
		/// <exception cref="ArgumentNullException">Throws if any of the s, hash or salt arguments are null.</exception>
		public bool Verify( string s, byte[] hash, byte[] salt )
		{
			if( s == null )
				throw new ArgumentNullException("s");
			if( salt == null )
				throw new ArgumentNullException("salt");
			if( hash == null )
				throw new ArgumentNullException("hash");

            byte[] testhash = Encode( s, salt );
            return _Verify( testhash, hash );
		}

        public bool Verify( byte[] plaintext, byte[] hash, byte[] salt )
        {
            if( plaintext == null )
                throw new ArgumentNullException( "plaintext" );
            if( salt == null )
                throw new ArgumentNullException( "salt" );
            if( hash == null )
                throw new ArgumentNullException( "hash" );

            byte[] testhash = Encode( plaintext, salt );
            return _Verify( testhash, hash );
        }

        private bool _Verify( byte[] a, byte[] b )
        {
            if( a.Length != b.Length )
                return false;
            for( int i = 0; i < a.Length; i++ )
            {
                if( a[i] != b[i] )
                    return false;
            }
            return true;
        }

		/// <summary>
		/// Generates a 32 byte (256 bit) cryptographically random salt.
		/// </summary>
		/// <returns>256 element Byte array containing cryptographically random bytes.</returns>
		public static byte[] GenerateSalt()
		{
			return GenerateSalt(32);
		}
		/// <summary>
		/// Generates a cryptogrpahically random salt of arbirary size.
		/// </summary>
		/// <param name="size">size of the salt</param>
		/// <returns>Byte array containing cryptographically random bytes.</returns>
		public static byte[] GenerateSalt(int size)
		{
			Byte[] saltBuff = new Byte[size];
			RandomNumberGenerator.Create().GetBytes( saltBuff );
			return saltBuff;
		}

		/// <summary>
		/// Convert a hash (or salt or any other) byte[] to a hexadecimal string.
		/// </summary>
		/// <param name="hash">Byte[] to convert to hex.</param>
		/// <returns></returns>
		public static string ConvertToHexString( byte[] hash )
		{
			StringBuilder sb = new StringBuilder();
			foreach( byte b in hash )
			{
				string bytestr = Convert.ToInt32(b).ToString("X").ToLower();
				if( bytestr.Length==1)
					bytestr = '0' + bytestr;
				sb.Append( bytestr );
			}
			return sb.ToString();
		}

		/// <summary>
		/// Convert a hexadecimal string to byte[].
		/// </summary>
		/// <param name="s"></param>
		/// <returns></returns>
		public static byte[] ConvertFromHexString( string s )
		{
			string hex = s.ToLower();
			if( hex.StartsWith("0x") )
				hex = hex.Substring(2);

			//ensure an even hex number
			hex = (hex.Length % 2 == 0) ? hex : '0' + hex;
			//2 hex digits per byte
			byte[] b = new byte[hex.Length/2];
			for(int i=0,j=0; i<hex.Length; i+=2,j++)
			{
				b[j] = byte.Parse( hex.Substring(i,2), NumberStyles.HexNumber );
			}
			return b;
		}

		/// <summary>
		/// Convert a hash (or salt or any other) byte[] to a base64 string.
		/// </summary>
		/// <param name="hash">Byte[] to convert to base64</param>
		/// <returns></returns>
		public static string ConvertToBase64String( byte[] hash )
		{
			return Convert.ToBase64String(hash);
		}
		
		/// <summary>
		/// Convert a base64 encoded string into a byte array.
		/// </summary>
		/// <param name="s">Base64 string.</param>
		/// <returns>Byte array.</returns>
		public static byte[] ConvertFromBase64String( string s )
		{
			return Convert.FromBase64String( s );
		}

		/// <summary>
		/// Converts a String to a Byte array.
		/// </summary>
		/// <remarks>Only works on .NET string objects or Unicode encoded strings.</remarks>
		/// <param name="s">String to convert</param>
		/// <returns>Byte array.</returns>
		public static byte[] ConvertStringToByteArray( string s )
		{
			if (s == null)
				return null;
			Char[] chars = s.ToCharArray();
			Encoder encoder = Encoding.Unicode.GetEncoder();
			int bytecount = encoder.GetByteCount( chars, 0, chars.Length, true );
			byte[] outbuff = new byte[bytecount];
			encoder.GetBytes(chars, 0, chars.Length, outbuff, 0, true );
			return outbuff;
		}
	}
}

Ximian is Dead, Long Live Xamarin

I was depressed when I heard that Attachmate disbanded the Mono team as a part of it’s acquisition of Novell but Miguel de Icaza has a lot of chutzpa. He has reformed his team in nothing flat and launched a new company to continue the development of Mono and its associated C#-based mobile toolkits, MonoToch (iOS) and  MonoDriod (Android) and Moonlight (Silverlight for Linux).

To make a long story short, the plan to spin off was not executed. Instead on Monday May 2nd, the Canadian and American teams were laid off; Europe, Brazil and Japan followed a few days later. These layoffs included all the MonoTouch and MonoDroid engineers and other key Mono developers. Although Attachmate allowed us to go home that day, we opted to provide technical support to our users until our last day at Novell, which was Friday last week.

Now, two weeks later, we have a plan in place, which includes both angel funding for keeping the team together, as well as a couple of engineering contracts that will help us stay together as a team while we ship our revenue generating products.

~Miguel de Icaza

All the best Miguel.

Fail: Useless IE8 Compatibility VM

I downloaded a virtual disk image today—May 11, 2011—from Microsoft that is purported to be configured specifically for testing compatibility with IE8. The readme had a nasty gram in it.

This image will expire on May 18, 2011.  At that time the Operating System will no longer boot, and you will be locked out of the VHD.  Please ensure you back up any relevant data before May 18, 2011.

I guess the date was a little optimistic because I am already locked out. All I get is a perpetual loop of Windows Product Activation and I cannot log in. Fail!.

useless-vhd

These pre-built virtual machine images seem to be more of a time suck than a time saver. I should have—and now will—install Windows XP from MSDN ISO and patch it to IE8.

Smashed Nexus One, RIP

After having survived being drowned, my Nexus One has finally succumbed to my (unintentional) abuse. It fell off my night stand this morning and landed face down exactly wrong on the tile floor, shattering the glass touch screen. To be fair, the N1 is still working, it’s just that I’m in serious danger of glass splinters and sliced fingertips using it.

IMG_0094

This happened just a day after getting the latest Gingerbread. Arg! I will miss this phone while I “suffer” with my iPhone 3Gs until I can get a Nexus S shipped to me in Ghana or when I am in the UK. For all its cache and cool hardware, the iPhone doesn’t do the things I love in Android:

  • Background services (used to great effect by Google Listen and Google Voice) not just multitasking
  • Unobtrusive notifications
  • Custom status icons (WeatherBug and BBC do a great job with these)
  • Native SIP client support (gingerbread)
  • Unlocked without jailbreak ultrasn0w shenanigans

IP Address is Not Identity

whois

When TCP/IP first developed by DARPA in the 1970s, every host on the ARPANET got an IP address. The “hosts” file which still exists on every computer mapped addresses to hosts until it was superseded by the Domain Name System (DNS). Certainly it was possible to do tricks like mapping more than one name (A record) to an IP address or provide CNAME aliases and multihomed hosts with multiple IP addresses are allowed. But more-or-less, historically an IP address maps to a computer. Furthermore, until recently IP addresses were doled out by ARIN and others in big blocks. Anyone who had a hint of a need could get IP addresses in lots of 256 addresses, sometimes called a Class C subnet or a “/24”. In the late 1990s in the Mid-Atlantic region of the USA, a T-1 came with 256 IP addresses and it was easy to get another 256 or more with the most modest excuse.

Historically, therefore, there is a notion that an IP address is pretty much a host and that host is part of a block of IP addresses which are managed by some entity which owns that computer and all the others in the subnet.

We are out of IP addresses and this world where a host is an IP address and a /24 is controlled by a single entity  no longer exists.

IPv6 may be the solution but the reality is that nobody is using it. In today’s world IP addresses are shared by multiple computers and even multiple companies using a variety of schemes including

  • Virtual hosting
  • Network Address Translation (NAT)
  • Proxies
  • Dynamic address allocation (DHCP)
  • Shared service computing (SaaS, Application Service Provider, Cloud Computing, etc) The bottom line is that an IP address is no longer reliably associated with any kind of identity. That email you just got might be coming from a Google Apps IP address or maybe one from Office 365 that is originating mail for hundreds of companies. The IP address behind this web server is most assuredly being used to host hundreds or thousands of sites. On the client end, if you have a Verizon LTE device, then you have a publically un-routable 10.x.x.x address and are being NATed onto the public Internet with some IP address shared by many others.This new reality complicates Internet security decisions because these days IP addresses are more granular than hosts and maybe more granular than organizations. The bottom line is that manipulating access control by IP address should be considered a blunt instrument virtually guaranteed to carry unintended side-effects unless the parties owning the addresses are well-known to each other.

    Related

Reducing the Need for Manual Reload of Color Calibration when Docking in Windows 7

Windows 7 has native support for monitor color calibration (though the OS X calibration wizard is more advanced). Unfortunately, at least with my MacBook Pro 5,3 and Apple Cinema display, Windows unloads the calibrations every time the external display is hot-plugged into my laptop. This forces me to go to Control Panel | Color Management | Advanced and click Reload current calibrations on a regular basis. I’ve even pinned this applet to my start menu for this purpose.

I’ve been looking for a command-line way to invoke this so that I can automate it and haven’t come up with anything other than possibly invoking colorcpl.exe and programmatically selecting the Advanced tab and sending a click to the Reload current calibrations button. However, poking around, I recently discovered that there is a scheduled task “\Microsoft\Windows\WindowsColorSystem\Calibration Loader”. This thing appears to do exactly what I want: reload the current calibrations.

The Action of the task is a “Custom Hander” which means it’s a COM handler. The XML definition of this task is in “%systemroot%\System32\Tasks\Microsoft\Windows\WindowsColorSystem\Calibration Loader”. Looking in there you will find the COM CLSID:

  <Actions Context="Group">
    <ComHandler>
      <ClassId>{B210D694-C8DF-490D-9576-9E20CDBC20BD}</ClassId>
    </ComHandler>
  </Actions>

I’ll have to dig into that at a later time.

Meanwhile, my main use-case is docking my laptop which usually has a closed lid or has just been re-opened so it is waking from sleep and locked. There are system events defined for those cases. The other case is just hot-plugging my monitor which is comparatively rare and doesn’t seem to generate an event. In any case, I can add the resume-from-sleep and workstation-unlocked events to the triggers for the calibration re-load task. This largely addresses my issues.

In Scheduled Tasks, navigate to \Microsoft\Windows\WindowsColorSystem and open Calibration Loader. Go to Triggers and add two new events to trigger the task.

Add On Wakeup Event Trigger

resume-from-sleep

  • Begin the task: On an event
      • Basic
      • Log: System
      • Source: Power-Troubleshooter
      • Event ID: 1
      • [check] Delay task for: 5 seconds (optional, I’m experimenting with this)

Add On Workstation Unlock Event Trigger

on-workstation-unlock

  • Begin the task: On workstation unlock
  • Any user

Remaining Annoyances

If you have a MacBook and like to customize the brightness of your external Cinematic Display and/or you like have overridden the default behavior so that function keys behave like function keys rather than Mac OS X-like macro keys by default, then you find when you hot dock your settings aren’t respected. The problem is that when a monitor or keyboard is hot docked, the bootcamp.exe process that interfaces with the Apple system controller doesn’t apply your settings. The solution is to restart bootcamp.exe.

I have a simple convenience powershell script to restart bootcamp.exe.

get-process | where { $_.Name -eq 'bootcamp' } | stop-process
start-process 'C:\Program Files\Boot Camp\Bootcamp.exe'

You may wish to have this also run on an event trigger. However, if you do, the annoyance is that it will litter your system tray with dead “Boot Camp” black diamond icons. I tend to have a powershell console open all the time, so I just invoke the script manually whenever I dock my monitor and keyboard.

%d bloggers like this: