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