Question

i try to coding HMAC-SHA256 Algorithm as Function

HMAC (K,m) = H((K ⊕ opad) ∥ H((K ⊕ ipad) ∥ m))

where

  • H is a cryptographic hash function,
  • K is a secret key padded to the right with extra zeros to the input block size of the hash function, or the hash of the original key if it's longer than that block size,
  • m is the message to be authenticated,
  • ∥ denotes concatenation,
  • ⊕ denotes exclusive or (XOR),
  • opad is the outer padding (0x5c5c5c…5c5c, one-block-long hexadecimal constant),
  • ipad is the inner padding(0x363636…3636, one-block-long hexadecimal constant).

and this my code

public static string MyHMACHash(string key , string message)
{
    Encoding encoding = Encoding.UTF8;
    //var md = System.Security.Cryptography.MD5CryptoServiceProvider.Create();
    SHA256 hash = SHA256Managed.Create();
    byte[] trans_5C = new byte[32];
    byte[] trans_36 = new byte[32];

    byte[] b_key = encoding.GetBytes(key);
    // TODO: also check if key is to short
    if (b_key.Length > 32)
        b_key = hash.ComputeHash(b_key);

    for (int i = 0; i < 32; i++)
    {
        trans_5C[i] = 92;
        trans_36[i] = 54;
        if (i < key.Length)
        {
            trans_5C[i] ^= b_key[i];
            trans_36[i] ^= b_key[i];
        }
    }

    byte[] inner = hash.ComputeHash(trans_36.Concat(encoding.GetBytes(message)).ToArray());
    var Fhash = hash.ComputeHash(trans_5C.Concat(inner).ToArray());

    StringBuilder sb = new StringBuilder();
    foreach (byte b in Fhash)
        sb.Append(b.ToString("x2"));

    string result = sb.ToString(); // = 9036a1a3f654aefeab426e9f7e17288e
    return result;
}

but when i try to test this code the result Non-conforming to standard HMAC-SHA256 hashing on the standard internet web sites

Was it helpful?

Solution

Here is the modified version with custom HMAC generation. Main thing to consider is that Input Block Size referred in the K, is the hash algorithm block size; not returned hashed byte length. For SHA256, block size is 64 bytes. I believe you were using 32byte block size. You can find different block size references here: http://en.wikipedia.org/wiki/Secure_Hash_Algorithm.

public static string MyHMACHash(string key, string message)
{
    Encoding encoding = Encoding.UTF8;

    //Reference http://en.wikipedia.org/wiki/Secure_Hash_Algorithm
    //SHA256 block size is 512 bits => 64 bytes.
    const int HashBlockSize = 64;

    var keyBytes = encoding.GetBytes(key);
    var opadKeySet = new byte[HashBlockSize];
    var ipadKeySet = new byte[HashBlockSize];


    if (keyBytes.Length > HashBlockSize)
    {
        keyBytes = GetHash(keyBytes);
    }

    // This condition is independent of previous
    // condition. If previous was true
    // we still need to execute this to make keyBytes same length
    // as blocksize with 0 padded if its less than block size
    if (keyBytes.Length < HashBlockSize)
    {
        var newKeyBytes = new byte[HashBlockSize];
        keyBytes.CopyTo(newKeyBytes, 0);
        keyBytes = newKeyBytes;
    }


    for (int i = 0; i < keyBytes.Length; i++)
    {
        opadKeySet[i] = (byte)(keyBytes[i] ^ 0x5C);
        ipadKeySet[i] = (byte)(keyBytes[i] ^ 0x36);
    }

    var hash = GetHash(ByteConcat(opadKeySet, 
        GetHash(ByteConcat(ipadKeySet, encoding.GetBytes(message)))));

    // Convert to standard hex string 
    return hash.Select<byte, string>(a => a.ToString("x2"))
                .Aggregate<string>((a, b) => string.Format("{0}{1}", a, b));            
}

public static byte[] GetHash(byte[] bytes)
{
    using (var hash = new SHA256Managed())
    {
        return hash.ComputeHash(bytes);
    }
}

public static byte[] ByteConcat(byte[] left, byte[] right)
{
    if (null == left)
    {
        return right;
    }

    if (null == right)
    {
        return left;
    }

    byte[] newBytes = new byte[left.Length + right.Length];
    left.CopyTo(newBytes, 0);
    right.CopyTo(newBytes, left.Length);

    return newBytes;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top