实现修改后的 HMAC



所以我正在尝试实现我的小型修改版本的HMAC函数,用于学术目的。以下是维基百科提供的算法:

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);
}

我哪里做错了?

我没有实现键的填充逻辑,因为我是 要求输入前导零,而不是像原始那样尾随零 算法。

而且我真的不知道使用前导零填充是否会使任何 数学的差异,或如何使用它

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

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

你做得不对。您的代码存在很多问题:

  • 密钥可能具有任何长度,并且密钥长度超过 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

最新更新