Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generate HMAC-SHA256 hash with BouncyCastle

I need to generate a HMAC-SHA256 hash in a PCL (developing for Xamarin Forms) which doesn't support the .NET built-in HMAC/cryptography classes, so I'm working with BouncyCastle to implement my cryptography classes.

I need to generate a HMAC-SHA256 hash, but I haven't been able to find any example on Google, nor does BouncyCastle seem to have any documentation for this. Can anyone help me out?

like image 376
Leon Cullens Avatar asked Apr 26 '16 22:04

Leon Cullens


People also ask

How do I get the HMAC sha256 key?

First, enter the plain-text and the cryptographic key to generate the code. Then, you can use select the hash function you want to apply for hashing. The default is SHA-256. Then you can submit your request by clicking on the compute hash button to generate the HMAC authentication code for you.

What is the difference between HMAC and SHA?

A: HMAC (Hashed Message Authentication Code) uses SHA-1 internally. The difference is that a MAC uses a secret key.

What is HMACSHA256 algorithm?

HMACSHA256 is a type of keyed hash algorithm that is constructed from the SHA-256 hash function and used as a Hash-based Message Authentication Code (HMAC).

How long is HMAC sha256?

The minimum length for an SHA-256 HMAC key is 32 bytes. A key longer than 32 bytes does not significantly increase the function strength unless the randomness of the key is considered weak. A key longer than 64 bytes will be hashed before it is used.


2 Answers

Thanks to the solution here I came up with this code:

public class HmacSha256
{
    public byte[] Hash(string text, string key)
    {
        var hmac = new HMac(new Sha256Digest());
        hmac.Init(new KeyParameter(Encoding.UTF8.GetBytes(key)));
        byte[] result = new byte[hmac.GetMacSize()];
        byte[] bytes = Encoding.UTF8.GetBytes(text);

        hmac.BlockUpdate(bytes, 0, bytes.Length);
        hmac.DoFinal(result, 0);

        return result;
    }
}

Corresponding unit test (uses FluentAssertions):

[TestClass]
public class HmacSha256Tests
{
    private readonly HmacSha256 _hmac = new HmacSha256();

    [TestMethod]
    public void Hash_GeneratesValidHash_ForInput()
    {
        // Arrange
        string input = "hello";
        string key = "test";
        string expected = "F151EA24BDA91A18E89B8BB5793EF324B2A02133CCE15A28A719ACBD2E58A986";

        // Act
        byte[] output = _hmac.Hash(input, key);

        string outputHex = BitConverter.ToString(output).Replace("-", "").ToUpper();

        // Assert
        expected.Should().Be(outputHex);
    }
}
like image 50
Leon Cullens Avatar answered Sep 19 '22 15:09

Leon Cullens


Using this PCL offshoot of BouncyCastle https://www.nuget.org/packages/BouncyCastle-PCL/1.0.0.6 it's really easy, in fact identical to the windows api.

 public string ComputeHMAC(string message)
    {
        var keyBytes = Encoding.UTF8.GetBytes(Constants.API_KEY);
        var messageBytes = Encoding.UTF8.GetBytes(message);

        var hmac = new HMACSHA256(keyBytes);
        byte[] result = hmac.ComputeHash(messageBytes);

        return Convert.ToBase64String(result);
    }

And a unit test using the actual .Net version:

[Test, AutoMoqData]
    public void Hash_Algorithm_Correct (
        [NoAutoProperties] HashMacService sut,
        string message)
    {
        string expected;

        var key = Encoding.UTF8.GetBytes(Constants.API_KEY);

        using (var hmac = new HMACSHA256(key))
        {
            var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(message));
            expected = Convert.ToBase64String(hash);
        }

        var result = sut.ComputeHMAC(message);

        Assert.That(result, Is.EqualTo(expected));
    }

I was using PCLCrypto but it kept crashing on Xamarin iOS, this was much cleaner and could be unit tested, wheras PCLCrypto required the platform apis so had to be deployed to a device.

like image 31
Ryan Avatar answered Sep 19 '22 15:09

Ryan