实施修改后的 HMAC

Implementing Modified HMAC

所以我正在尝试实现 HMAC function for academic purposes. Here is the algorithm as provided by Wikipedia:

的小型修改版本
function hmac (key, message)
    if (length(key) > blocksize) then
        key = hash(key) // keys longer than blocksize are shortened
    end if
    if (length(key) < blocksize) then
        // keys shorter than blocksize are zero-padded (where ∥ is concatenation)
        key = key ∥ [0x00 * (blocksize - length(key))] // Where * is repetition.
    end if

    o_key_pad = [0x5c * blocksize] ⊕ key // Where blocksize is that of the underlying hash function
    i_key_pad = [0x36 * blocksize] ⊕ key // Where ⊕ is exclusive or (XOR)

    return hash(o_key_pad ∥ hash(i_key_pad ∥ message)) // Where ∥ is concatenation
end function

这是我写的代码(显然这给了我不合适的结果,我检查了给定的解决方案)。 块大小为 512 位。

我想我已经确定了我的代码失败的一个关键原因,我没有实现密钥的填充逻辑,因为我被要求放置前导零而不是像原来那样放置尾随零算法.

而且我真的不知道使用前导零填充是否会对数学有任何影响,或者如何使用它

其次,我不确定我是否正确地进行了字节运算。

这是我的代码:

private static string HMAC(string message)
{
    //Every charecter corresponds to 4bits.
    long hex_key = 0x0a7cb27e52;

    //padding for an 64 Bit Key. 2 Chars  = 1 Byte. Leading zeros I need (512-(10*4))/4 = 118
    string asc_key = "0a7cb27e52";
    //Did Not KnowWhere To Use
    asc_key = asc_key.PadLeft(128, '0');

    byte[] keyInBytes = Encoding.UTF8.GetBytes(asc_key);
    var hexString = BitConverter.ToString(keyInBytes);
    hexString = hexString.Replace("-", "");

    //Wikipedia Style naming

    long o_key_pad = (0x5c * 0x40) ^ hex_key;
    long i_key_pad = (0x36 * 0x40) ^ hex_key;
    return GetMD5Hash(o_key_pad.ToString() + GetMD5Hash(i_key_pad.ToString() + message));
}


public static String GetMD5Hash(String TextToHash)
{
    //Check wether data was passed
    if ((TextToHash == null) || (TextToHash.Length == 0))
    {
        return String.Empty;
    }

    //Calculate MD5 hash. This requires that the string is splitted into a byte[].
    MD5 md5 = new MD5CryptoServiceProvider();
    byte[] textToHash = Encoding.Default.GetBytes(TextToHash);
    byte[] result = md5.ComputeHash(textToHash);

    //Convert result back to string.
    return System.BitConverter.ToString(result);
}

我哪里做错了?

I am not implementing the padding logic for the key, because I am asked to put leading zeros and not trailing zeroes like the original algorithm.

And I don't really know if using leading zeroes padding will make any difference for the mathematics, or how to use it

它不会改变数学中的任何内容,但结果会有所不同。

Secondly, I am not sure if I am doing the byte math correctly.

你做的不对。您的代码有很多问题:

  • 密钥可以有任何长度,并且密钥长度超过 64 位是很常见的,这将超过 long.

  • 的大小
  • o_key_padi_key_pad不重复填满块大小

  • HMACGetMD5Hash 获取并传送 string 数据。密码操作应该在二进制数据上执行,而不是在字符串上执行。

代码:

private static int BlockSize = 64;

public static byte[] HMAC(byte[] message)
{
    byte[] key = {0x0a, 0x7c, 0xb2, 0x7e, 0x52};
    if (key.Length > BlockSize) {
        key = GetMD5Hash(key);
    }
    byte[] paddedKey = new byte[BlockSize];
    key.CopyTo(paddedKey, BlockSize-key.Length);

    byte[] o_key_pad = new byte[BlockSize];
    byte[] i_key_pad = new byte[BlockSize];
    for(int i = 0; i < BlockSize; i++) {
        o_key_pad[i] = (byte)(0x5c ^ paddedKey[i]);
        i_key_pad[i] = (byte)(0x36 ^ paddedKey[i]);
    }

    byte[] inner_hash = GetMD5Hash(concat(i_key_pad, message));
    return GetMD5Hash(concat(o_key_pad, inner_hash));
}

private static byte[] concat(byte[] a1, byte[] a2) {
    byte[] res = new byte[a1.Length + a2.Length];
    a1.CopyTo(res, 0);
    a2.CopyTo(res, a1.Length);
    return res;
}

private static byte[] GetMD5Hash(byte[] ToHash)
{
    MD5 md5 = new MD5CryptoServiceProvider();
    return md5.ComputeHash(ToHash);
}

您可以围绕 HMAC 编写一个包装器来接收和传送 string