Code Example Template

From Guidance Share

Jump to: navigation, search

Contents

Template

  • Title
  • Applies To
  • Summary
  • Contents
  • Objectives
  • Scenarios
  • Solution Example
  • Problem Example
  • Test Case
  • Expected Result
  • Additional Resources
  • Attributes


Test Cases

Title

<< Insert title that resonates from a findability perspective.>>


Test Cases:

  • Does the title distinguish by product or version where possible?
  • Does the title distinguish it from related examples?
  • If technology is in the title, is the version included?
  • Are important nouns a user might scan for towards the left of the title?


Applies To

<< Identify the most directly relevant product or technologies this information applies to >>


Test Cases:

  • Is it clear what technologies or products this applies to?
  • Conversely, is it clear what technologies of products this does not apply to?


Summary

<< Insert 3-5 lines max description of the intent of the code example, highlighting when to use and key scenarios.>>


Test Cases:

  • Does the description crisply summarize the solution?
  • Is the intent of the code clear?


Objectives

<< Insert bulleted list of task-based outcomes for the code example. Identify the user objectives for choosing this code. Identify the intent of the code. >>


Test Cases

  • Are the user objectives for choosing this code identified?
  • Are the objectives of the code identified?
  • When would a user need this code example?
  • Is it clear why the solution example is preferred over the problem example?


Scenarios

<< Insert a bulleted list of example usage scenarios you have seen this code used in practice.>>


Test Cases

  • Are the example scenarios based on real solutions seen in practice?
  • Do the example scenarios help highlight when to use the code or when not to?


Solution Example

<< Insert commented code illustrating the solution. Insert code example as a blob within a function. The blob allows quick reading of the code. It also allows quickly testing from a function, inlining within other code, or refactoring for a given context. The alternative is to factor up front, but this increases complexity and can negatively impact consumption. This leaves refactoring to the developer for their given scenario.>>


Test Cases

  • Is the code example organized as a blob within a function that can easily be tested or refactored?
  • Do the comments add insights around decisions?
  • Are the comments concise enough so they don't break the code flow?


Problem Example

<< Insert commented code illustrating issues. List examples of common mistakes along with issues.>>


Test Cases:

  • Are comments concise enough so that they does not break the code flow?
  • Are the mistakes clear?
  • Are the patterns and variations of the problems clear?


Test Case

<< Insert relevant setup information. Write the code to call the functional blob from Solution Example.>>


Test Cases:

  • Is setup Information included?
  • Does the example call the functional blob in the Solution example?
  • Can you copy+paste the code and execute it?


Expected Result

<< Insert what you expect to see when running the test case. >>


Test Cases:

  • If you run the Test Case, do the Expected Results match?


More Information

<<Optional. Insert more information as necessary. This could be background information or interesting additional details.>>

Additional Resources

<< Optional. Insert bulleted list of descriptive links to resources that have direct value or relevancy.>>


Test Cases:

  • The links starts with the pattern "For more information on X, see ..."?
  • The links are directly relevant versus simply nice to have?


Attributes

<< Insert the following:

  • Applies To
  • Category
  • Author

>>


Example

Hash a Password Using a Random Salt (C#)

Applies To

  • ASP.NET 2.0
  • C#


Summary

The purpose of this code snippet is to demonstrate how to implement secure password persistence using a cryptographic hashing algorithm with a randomly generated "salt" (or "nonce") value. Cryptographic hashing algorithms are one-way encryption algorithms used to store sensitive data in a non-readable format. A salt can be used in conjunction with cryptographic hashing to add additional entropy to encrypted values and to protect against pre-computed hash or dictionary attacks on a compromised hash value.


Objectives

  • Protect user credentials
  • Avoid storing user passwords
  • Protect against certain brute-force attacks on a compromised hash value
  • Generate a cryptographically random value for the salt that cannot be predicted
  • Add enough entropy to the password hash to increase the difficulty of a cracking attempt exponentially


Scenarios

  • Application makes use of a dedicated user account management system and stores passwords
  • Application stores a "Secret Question/Answer" credential for password reset operations
  • Application requires storage of highly sensitive data (social security number, credit card number, etc) but does not need to retrieve that data


Solution Example

public static byte[] [CreatePasswordHash(string] password)
{
{
   	// Convert the string password value to a byte array
   	byte[] passwordData = [UnicodeEncoding.ASCII.GetBytes(password);]
}

{
   	// Create a 4-byte salt using a cryptographically secure random number generator
   	byte[] saltData = new byte[4];
   	[RNGCryptoServiceProvider] rng = new [RNGCryptoServiceProvider();]
   	[rng.GetNonZeroBytes(saltData);] 
}

{
   	// Append the salt to the end of the password
   	byte[] [saltedPasswordData] = new byte[passwordData.Length + saltData.Length];
   	Array.Copy(passwordData, 0, [saltedPasswordData,] 0, passwordData.Length);
   	Array.Copy(saltData, 0, [saltedPasswordData,] passwordData.Length, saltData.Length);
}

{
   	// Create a new SHA-1 instance and compute the hash 
   	SHA1Managed sha = new SHA1Managed();
   	byte[] hashData = [sha.ComputeHash(saltedPasswordData);]
}

{
   	// Optional - add salt bytes onto end of the password hash for storage
   	bool APPEND_SALT_TO_HASH = true;
}

{
   	if (APPEND_SALT_TO_HASH)
   	{
       		byte[] [hashSaltData] = new byte[hashData.Length + saltData.Length];
       		Array.Copy(hashData, 0, [hashSaltData,] 0, hashData.Length);
       		Array.Copy(saltData, 0, [hashSaltData,] hashData.Length, saltData.Length);
       		return [hashSaltData;]
   	}
   	else
   	{
       		return hashData;
   	}
}
}

Problem Example

The following code snippet shows password hashing without the use of a salt and using a weaker hashing algorithm.

// password is obtained from the user as a C# string string password = Request.Form["password"];

// Convert the string password value to a byte array byte[] passwordData = [UnicodeEncoding.ASCII.GetBytes(password);]

// Create a new MD5 instance and compute the hash [MD5CryptoServiceProvider] md5 = new [MD5CryptoServiceProvider();] byte[] hashData = [md5.ComputeHash(passwordData);]

  • Hash values are vulnerable to pre-computed hash attacks
  • Depending on password value, password hash may also be vulnerable to a dictionary attack
  • MD5 offers less encryption strengtgh than SHA-1 and has recently been "broken" by cryptography researchers


Test Case

The following classes must be included in any project making use of the sample code provided above:

using System.Security.Cryptography;

Execute a test encryption and comparison of a salted password hash using the following test case methods:

static void Main(string[] args) {

{
   	// Create a Hash and compare to two subsequent hashes
   	byte[] hash = CreatePasswordHash("foobar");
   	Console.WriteLine("\nCreated new salted hash for 'foobar'");            
   	Console.WriteLine("foobar produces same hash:\t" + ComparePasswordToHash("foobar", [hash).ToString());]
   	Console.WriteLine("fo0bar produces same hash:\t" + ComparePasswordToHash("f0obar", [hash).ToString());]
}

}

public static bool [ComparePasswordToHash(string] password, byte[] hashData) {

{
   	// First, pluck the four-byte salt off of the end of the hash
   	byte[] saltData = new byte[4];
   	Array.Copy(hashData, hashData.Length - saltData.Length, saltData, 0, saltData.Length);
}

{
   	// Convert Password to bytes
   	byte[] passwordData = [UnicodeEncoding.ASCII.GetBytes(password);]
}
   
{
   	// Append the salt to the end of the password
   	byte[] [saltedPasswordData] = new byte[passwordData.Length + saltData.Length];
   	Array.Copy(passwordData, 0, [saltedPasswordData,] 0, passwordData.Length);
   	Array.Copy(saltData, 0, [saltedPasswordData,] passwordData.Length, saltData.Length);
}

{
   	// Create a new SHA-1 instance and compute the hash 
   	SHA1Managed sha = new SHA1Managed();
   	byte[] [newHashData] = [sha.ComputeHash(saltedPasswordData);]
}

{
   	// Add salt bytes onto end of the password hash for storage
   	byte[] [newHashSaltData] = new byte[newHashData.Length + saltData.Length];
   	[Array.Copy(newHashData,] 0, [newHashSaltData,] 0, [newHashData.Length);]
   	Array.Copy(saltData, 0, [newHashSaltData,] [newHashData.Length,] saltData.Length);
}

{
   	// Compare and return
   	return [(Convert.ToBase64String(hashData).Equals(Convert.ToBase64String(newHashSaltData)));]
}
}


Expected Result

Created new salted hash for 'foobar'
foobar produces same hash:      True
fo0bar produces same hash:      False


More Information

Password hash and salt values should always be securely protected in storage. An attacker able to compromise a specific hash and salt value from a database may succeed in using other types of brute-force attacks against the compromised hash.


In the example given, the four-byte salt would require an attacker to maintain 4.3 trillion values for every given plaintext value. Assuming the victim required passwords of only 4 alphabetical characters in length with no other complexity requirements (a very weak password policy by our standards), defeating a four-byte salt would require the attacker to have a database of 2 x 10^15 precomputed hashes handy. Assuming each of these hashes only required one byte to store, this would require 2 petabytes of storage.


Additional Resources


Attributes

  • Applies To: .NET Framework 2.0, C#
  • Category: Cryptography
  • Author: Jonathan Bailey
Personal tools