问题描述
我尝试编码HMAC-SHA256算法功能
i try to coding HMAC-SHA256 Algorithm as Function
HMAC(K,M)= H((K⊕OPAD)∥H((K ⊕新iPad)∥M))
其中,
- ^ h是加密散列函数,
- K是一个秘密密钥软垫与额外的零到散列函数的输入块尺寸,还是原来的密钥的散列,如果它比长的权利该块大小,
- m是要进行身份验证的消息,
- ∥表示连接,
- ⊕表示异或(XOR),
- OPAD是外部填充(0x5c5c5c ... 5c5c,单块长的十六进制常数),
- iPad是内部填充(0x363636 ... 3636,单块长的十六进制常数)。
- 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).
和本我的代码
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;
}
但是当我尝试测试此代码的结果不合格以标准的HMAC-SHA256散列在标准的互联网网站
but when i try to test this code the result Non-conforming to standard HMAC-SHA256 hashing on the standard internet web sites
推荐答案
下面是修改的版本定制HMAC代。考虑主要的是在K称该输入块的大小,是散列算法块大小;不返回散列字节长度。为SHA256,块大小为64字节。我相信你是使用32字节的块大小。你可以在这里找到不同的块大小的参考: http://en.wikipedia.org/wiki/Secure_Hash_Algorithm。
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;
}
这篇关于尝试代码HMAC-SHA256使用C#.NET的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!