HMAC is a message authentication code (MAC) that can be used to verify the integrity and authentication of a message. It involves hashing the message with a secret key and thus differs from standard hashing, which is purely a one-way function. As with any MAC, it can be used with a standard hash function, such as MD5 or SHA-1, which results in methods such as HMAC-MD5 or HMAC-SHA-1. Also, as with any hashing function, the strength depends on the quality of the hashing function, and the resulting number of hash code bits. Along with this, the number of bits in the secret key is a factor in the strength of the hash. The figure below outlines the operation, where the message to be sent is converted with a secret key, and the hashing function, to an HMAC code. This is then sent with the message. On receipt, the receiver recalculates the HMAC code from the same secret key, and the message, and checks it against the received version. If they match, it validates both the sender and the message. In this case we will implement for HMAC-MD5, HMAC-SHA1, HMAC-SHA256, HMAC-SHA384 and HMAC-SHA512
HMAC with C# |
Method
HMAC is a message authentication code (MAC) that can be used to verify the integrity and authentication of a message. It involves hashing the message with a secret key and thus differs from standard hashing, which is purely a one-way function. As with any MAC, it can be used with a standard hash function, such as MD5 or SHA-1, which results in methods such as HMAC-MD5 or HMAC-SHA-1. Also, as with any hashing function, the strength depends on the quality of the hashing function, and the resulting number of hash code bits. Along with this, the number of bits in the secret key is a factor in the strength of the hash. The figure below outlines the operation, where the message to be sent is converted with a secret key, and the hashing function, to an HMAC code. This is then sent with the message. On receipt, the receiver recalculates the HMAC code from the same secret key, and the message, and checks it against the received version. If they match, it validates both the sender and the message.
Coding
First we create a folder named "hmac", and then go into that folder.We can create a Dotnet console project for .NET 8.0 with:
dotnet new console --framework net8.0
This produces a Csproject file of:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net8.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> </PropertyGroup> </Project>
Some simple code is:
namespace Hashing { class Program { static void Main(string[] args) { string message="Hello"; string secret="qwerty"; if (args.Length >0) message=args[0]; if (args.Length >1) secret=args[1]; try { string str1 = "Message: " + message; str1 = str1 + "\nSecret: " + secret; System.Security.Cryptography.HMACMD5 hmacsha1 = new System.Security.Cryptography.HMACMD5(); hmacsha1.Key = System.Text.Encoding.ASCII.GetBytes(secret); byte [] hash1 = hmacsha1.ComputeHash(System.Text.Encoding.UTF8.GetBytes(message)); str1 = str1 + "\nHMAC-MD5: " + Convert.ToBase64String(hash1); str1 = str1 + "\nHMAC-MD5: " + BitConverter.ToString(hash1).Replace("-", string.Empty); System.Security.Cryptography.HMACSHA1 hmacsha2 = new System.Security.Cryptography.HMACSHA1(); hmacsha2.Key = System.Text.Encoding.ASCII.GetBytes(secret); byte[] hash2 = hmacsha2.ComputeHash(System.Text.Encoding.UTF8.GetBytes(message)); str1 = str1 + "\nHMAC-SHA1: " + Convert.ToBase64String(hash2); str1 = str1 + "\nHMAC-SHA1: " + BitConverter.ToString(hash2).Replace("-", string.Empty); System.Security.Cryptography.HMACSHA256 hmacsha3 = new System.Security.Cryptography.HMACSHA256(); hmacsha3.Key = System.Text.Encoding.ASCII.GetBytes(secret); byte[] hash3 = hmacsha3.ComputeHash(System.Text.Encoding.UTF8.GetBytes(message)); str1 = str1 + "\nHMACSHA256: " + Convert.ToBase64String(hash3); str1 = str1 + "\nHMACSHA256: " + BitConverter.ToString(hash3).Replace("-", string.Empty); System.Security.Cryptography.HMACSHA384 hmacsha4 = new System.Security.Cryptography.HMACSHA384(); hmacsha4.Key = System.Text.Encoding.ASCII.GetBytes(secret); byte[] hash4 = hmacsha4.ComputeHash(System.Text.Encoding.UTF8.GetBytes(message)); str1 = str1 + "\nHMACSHA384: " + Convert.ToBase64String(hash4); str1 = str1 + "\nHMACSHA384: " + BitConverter.ToString(hash4).Replace("-", string.Empty); System.Security.Cryptography.HMACSHA512 hmacsha5 = new System.Security.Cryptography.HMACSHA512(); hmacsha5.Key = System.Text.Encoding.ASCII.GetBytes(secret); byte[] hash5 = hmacsha5.ComputeHash(System.Text.Encoding.UTF8.GetBytes(message)); str1 = str1 + "\nHMACSHA512: " + Convert.ToBase64String(hash5); str1 = str1 + "\nHMACSHA512: " + BitConverter.ToString(hash5).Replace("-", string.Empty); Console.WriteLine("{0}",str1); } catch (Exception e) { Console.WriteLine("Error: {0}",e.Message); } } } }
A sample run shows:
Message: message Secret: secret HMAC-MD5: fg0HZ3dTEhVLoW/Tr5dxog== HMAC-MD5: 7E0D0767775312154BA16FD3AF9771A2 HMAC-SHA1: DK9kn+7klT2Hv5A6wRdsReAo3xY= HMAC-SHA1: 0CAF649FEEE4953D87BF903AC1176C45E028DF16 HMACSHA256: i19IcCmVwVmMVz2x4hhmqbgl1KeU0WnXBgoDYFeWNgs= HMACSHA256: 8B5F48702995C1598C573DB1E21866A9B825D4A794D169D7060A03605796360B HMACSHA384: rQ706A2kJ7KjPURXyXK/dZ9Qdm+7ZlaQ1Qt8s43VIX21Wck+p8vuSOKuGltKr9NL HMACSHA384: AD0EF4E80DA427B2A33D4457C972BF759F50766FBB665690D50B7CB38DD5217DB559C93EA7CBEE48E2AE1A5B4AAFD34B HMACSHA512: G7pYfHMO7box9Tq7C2ylieCd5OiU7kVeYUCAc5l1mtqvoGnux8AWR7sXPcsX9V0ir0mhgHG3SMXC7df3qCnGMg== HMACSHA512: 1BBA587C730EEDBA31F53ABB0B6CA589E09DE4E894EE455E6140807399759ADAAFA069EEC7C01647BB173DCB17F55D22AF49A18071B748C5C2EDD7F7A829C632