How to generate HMAC-SHA1 in C#?

C#JavaPhpRubyHmac

C# Problem Overview


I am trying to make use of a REST API using C#. The API creator has provided sample libraries in PHP, Ruby and Java. I am getting hung up on one part of it where I need to generate an HMAC.

Here's how it is done in the sample libraries they have provided.

PHP

hash_hmac('sha1', $signatureString, $secretKey, false);

Ruby

digest = OpenSSL::Digest::Digest.new('sha1')
return OpenSSL::HMAC.hexdigest(digest, secretKey, signatureString)

Java

SecretKeySpec signingKey = new SecretKeySpec(secretKey.getBytes(), HMAC_SHA1_ALGORITHM);

Mac mac = null;
mac = Mac.getInstance(HMAC_SHA1_ALGORITHM);
mac.init(signingKey);

byte[] bytes = mac.doFinal(signatureString.getBytes());

String form = "";
for (int i = 0; i < bytes.length; i++)
{
    String str = Integer.toHexString(((int)bytes[i]) & 0xff);
    if (str.length() == 1)
    {
        str = "0" + str;
    }

    form = form + str;
}
return form;

Here's my attempt in C#. It is not working. UPDATE: The C# example below works just fine. I found out that the real problem was due to some cross-platform differences in newline characters in my signatureString.

var enc = Encoding.ASCII;
HMACSHA1 hmac = new HMACSHA1(enc.GetBytes(secretKey));
hmac.Initialize();

byte[] buffer = enc.GetBytes(signatureString);
return BitConverter.ToString(hmac.ComputeHash(buffer)).Replace("-", "").ToLower();

C# Solutions


Solution 1 - C#

an extension to https://stackoverflow.com/questions/6067751/how-to-generate-hmac-sha1-in-c/6067882#6067882">Vimvq1987's answer:

return hashValue.ToString(); doesn't produce the output you want/need. You have to convert the bytes in the array hashValue to their hex-string representation.
Can be as simple as return BitConverter.toString(hashValue); (prints upper-case letters A-F) or if you like it a bit more complex:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.IO;

namespace ConsoleApplication1
{
	class Program
	{
		public static string Encode(string input, byte[] key)
		{
			HMACSHA1 myhmacsha1 = new HMACSHA1(key);
			byte[] byteArray = Encoding.ASCII.GetBytes(input);
			MemoryStream stream = new MemoryStream(byteArray);
			return myhmacsha1.ComputeHash(stream).Aggregate("", (s, e) => s + String.Format("{0:x2}",e), s => s );
		}


		static void Main(string[] args)
		{
			byte[] key = Encoding.ASCII.GetBytes("abcdefghijklmnopqrstuvwxyz");
			string input = "";
			foreach (string s in new string[] { "Marry", " had", " a", " little", " lamb" })
			{
				input += s;
				System.Console.WriteLine( Encode(input, key) );
			}
			return;
		}
	}
}

which prints

3545e064fb59bc4bfc02b6e1c3d4925c898aa504
3249f4c8468d4d67f465937da05b809eaff22fdb
87baaadf5d096677f944015e53d283834eb1e943
6325376820c29a09e3ab30db000033aa71d6927d
54579b0146e2476595381d837ee38863be358213

and I get the exact same result for

<?php
$secretKey = 'abcdefghijklmnopqrstuvwxyz';

$signatureString = '';
foreach( array('Marry',' had',' a',' little',' lamb') as $s ) {
	$signatureString .= $s;
	echo hash_hmac('sha1', $signatureString, $secretKey, false), "\n";
}

edit: Dmitriy Nemykin suggested the following edit

public static string Encode(string input, byte[] key)
{
	byte[] byteArray = Encoding.ASCII.GetBytes(input);
	using(var myhmacsha1 = new HMACSHA1(key))
	{
		var hashArray = myhmacsha1.ComputeHash(byteArray);
		return hashArray.Aggregate("", (s, e) => s + String.Format("{0:x2}",e), s => s );
	}
}

which was rejected. But as James already pointed out in a comment to this answer at the very least the using statement is a good point.

Solution 2 - C#

This site has some pretty good examples across languages: http://jokecamp.wordpress.com/2012/10/21/examples-of-creating-base64-hashes-using-hmac-sha256-in-different-languages/

The c# implementation at the time of writing is:

private string CreateToken(string message, string secret)
{
 secret = secret ?? "";
 var encoding = new System.Text.ASCIIEncoding();
 byte[] keyByte = encoding.GetBytes(secret);
 byte[] messageBytes = encoding.GetBytes(message);
 using (var hmacsha256 = new HMACSHA256(keyByte))
 {
 byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
 return Convert.ToBase64String(hashmessage);
 }
}

Solution 3 - C#

Try this:

http://msdn.microsoft.com/en-us/library/system.security.cryptography.hmacsha1.aspx

quick and dirty code:

public string Encode(string input, byte [] key)
{
        HMACSHA1 myhmacsha1 = new HMACSHA1(key);
        byte[] byteArray = Encoding.ASCII.GetBytes( input );
        MemoryStream stream = new MemoryStream( byteArray ); 
        byte[] hashValue = myhmacsha1.ComputeHash(stream);
        return hashValue.ToString();
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionjessegavinView Question on Stackoverflow
Solution 1 - C#VolkerKView Answer on Stackoverflow
Solution 2 - C#ctrlplusbView Answer on Stackoverflow
Solution 3 - C#Quan MaiView Answer on Stackoverflow