Return to HomePage



Generate a Message Authentication Code MAC (VB)



Applies to

* ASP.NET 2.0
* VB.NET


Summary

To create a cryptographically secure message authentication code or integrity check of a portion of data.

Message Authentication Codes or MACs are used by two parties to validate that a message hadn't been altered in transit. Only the nodes which posses the keys may compute the MAC and validate the MAC against an input text. This code sample demonstrates the use of an HMAC.

Objectives

* Provide a method to detect message modification and tampering, this method should not allow an attacker to easily generate and modify the MAC in transit.
* Generate a cryptographically strong key which appears random in value for use as an HMAC signing key


Scenarios

* Two entities are communicating over a sockets interface (clear-text or encrypted communications) and wish to detect message modification for data in transit
* Two entities wish to prevent message modification for data in transit via a sockets interface (clear-text or encrypted communications)

Solution Example

		        Public Function [GenerateHMAC(ByVal] input As String, [ByVal] secret As String) As String
		            ' Instantiate the HMAC class
		            Dim hmac As HMACSHA256 =  New HMACSHA256() 
	

		            Try
		                ' We pass in a user supplied password to generate a strong key to be used in our HMAC
		                ' since people tend to use weak and potentially dictionary values for keys.  
		                ' Using the [PasswordDerivedBytes] helps to mitigate the risk of dictionary attacks
		                ' on our HMAC key
	

		                ' In the current implementation, regardless of the salt passed to the [PasswordDeriveBytes]
		                ' constructor the same derived password will be generated.
		                Dim pdb As [PasswordDeriveBytes] =  New [PasswordDeriveBytes(secret,Nothing)] 
	

		                Dim pbytes() As Byte =  pdb.CryptDeriveKey("TripleDES","SHA1"() As Byte,192() As Byte,New() As Byte {0, 0, 0, 0, 0, 0, 0, 0}
	
)

		                hmac.Key = pbytes
	

		            Catch e As Exception
		                [Console.Error.WriteLine(e.ToString())]
		            End Try
		            Return [ASCIIEncoding.ASCII.GetString(hmac.ComputeHash(ASCIIEncoding.ASCII.GetBytes(input)))]
		        End Function
	


Problem Example

The following code sample demonstrates the use of a message authenticating
code prone to tampering because it simply uses a publicly know hashing mechanism
with no shared secret:

		        public static string [GenerateDigest(string] input)
		        {
	

		            // Instantiate the SHA1 Digest
		            SHA1 sha = new [SHA1CryptoServiceProvider();]
		            return [ASCIIEncoding.ASCII.GetString(sha.ComputeHash(ASCIIEncoding.ASCII.GetBytes(input)));]
		        }
	

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 two iterations of our plaintext, one which is unaltered and a second which emulates being altered in transit:

		        Sub [Main(ByVal] args() As String)
		            Dim secret As String =  "thisisaweaksecretkeywhichweuseinourhmac" 
	

		            Dim cs As [CodeSample] =  New [CodeSample()] 
		            Dim text As String =  "the quick brown fox jumped over the lazy dog" 
		            ' Generate the SHA256 HMAC for the given value based on the keys setup in our constructor
	

		            Dim strHmac As String =  GenerateHMAC(text,secret) 
	

		            ' Append the HMAC to the original text to be sent on the wire. The HMAC serves the purpose
		            ' of validating the integrity of the original message
		            Dim msg1 As String =  text + strHmac 
		            Dim isValid As Boolean =  ValidateHMAC(msg1,secret) 
	

		            Console.Out.WriteLine("Validating MSG1 (Unaltered in transit): " + [isValid.ToString())]
	

		            ' Test a variation of the original message with the original HMAC to test validation of the
		            ' HMAC and message.
		            Dim msg2 As String =  "the quick brown dog jumped over the lazy fox" + strHmac 
		            isValid = ValidateHMAC(msg2, secret)
		            Console.Out.WriteLine("Validating MSG2 (Altered in transit / text rearranged): " + [isValid.ToString())]
	

		            ' Show our problem example
		            'Console.Out.WriteLine("Digest of '{0}': {1}", msg2, [GenerateDigest(msg1));]
		        End Sub
	

The ValidateHMAC method is shown below for the purposes of validating the
HMAC:

		        Public Function [ValidateHMAC(ByVal] input As String, [ByVal] secret As String) As Boolean
		            Dim isValid As Boolean =  False 
		            Try
		                ' Instantiate the HMAC class
		                Dim hmac As HMACSHA256 =  New HMACSHA256() 
	

		                ' Since we're using SHA256, we'll take the last 32 bytes from the message,
		                ' recompute the hmac on the first half and compare the two [HMACs]
	

		                Dim strOrigHMAC As String =  input.Remove(0,input.Length - 32) 
		                Dim strMsg As String =  input.Substring(0,input.Length - 32) 
		                If strOrigHMAC = GenerateHMAC(strMsg,secret) Then
		                    isValid = True
		                Else 
		                    isValid = False
		                End If
	

		            Catch
		                isValid = False
		            End Try
		            Return isValid
		        End Function
	

Expected Result

Validating MSG1 (Unaltered in transit): True
Validating MSG2 (Altered in transit / text rearranged): False



More Information

* An HMAC consists of taking a secret known only to entities wishing to communicate, concatenating this value to the front of a message to be sent. Next, this value is digested with a secure hash function, after which the secret is prepended to the resulting digest and performs a second digest using the secure hash function.
* The .NET framework provides several HMAC providers. In this example, we've demonstrated the use of creation and validation of an HMAC using the SHA256 hash function.
* Another goal in choosing a key for the HMAC process is to ensure that keys are strongly generated. Assuming two entities share a weak password it is possible to generate a derived key which resembles a strong and random key to an eavesdropper.


Additional Resources

* Cryptopgraphy (.NET): http://msdn.microsoft.com/library/en-us/dnpag2/html/PAGGuidelines0003.asp?frame=true#pagguidelines0003_cryptography
* HMAC definition: http://en.wikipedia.org/wiki/HMAC
* HMAC class: http://msdn2.microsoft.com/en-US/library/system.security.cryptography.hmac.aspx
* Protecting keys using the DPAPI: http://msdn.microsoft.com/library/en-us/dnpag2/html/paght000005.asp
* Generating a key from a password: http://blogs.msdn.com/shawnfa/archive/2004/04/14/113514.aspx

Attributes

* Applies To: .NET Framework 2.0, VB
* Category: Cryptography
* Author: George Gal




Return to HomePage
Microsoft Communities