2016-06-12 33 views
0

所以我试图实现我为学术目的而修改的HMAC function的小版本。这里是由Wikipedia提供的算法:实施修改后的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); 
} 

我在哪里做错了?

+0

是的,当实现'i_pad'和'o_pad'时,你忘记了坚持'*'的定义。此外,“长”不是填充物的有用类型。 –

+0

@ ArtjomB。什么是'*'的定义以及哪个数据类型用于填充? –

+0

第7行有一条评论,其内容是:“// Where Where *是重复。”。你已经将符号字面地用作乘法。无论如何,因为long不能容纳512位的数据,所以你需要一些其他的数据类型,比如一个字节数组,并且将它迭代到相应的关键字节的XOR中。 –

回答

1

我不落实的关键填充逻辑,因为我 要求把前导零,而不是尾随零像原来 算法。

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

它不会在数学改变什么,但结果会不一样。

其次,我不知道如果我正确地做字节数学。

你做得不对。有许多与你的代码的问题:

  • 主要可能有任意长度,它是常见的有一个关键长于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

+0

哇!感谢您花时间帮助我! –