NET(C#):中的基于哈希算法的消息认证码(HMAC)

基于哈希算法的消息认证码(HMAC:Hash-based Message Authentication Code )在.NET也可以很轻松地实现。

 

在目前的.NET Framework中(.NET 4.0)HMAC位于如下位置:

《NET(C#):中的基于哈希算法的消息认证码(HMAC)》

HMAC继承与HashAlgorithm,后者代表抽象的哈希(散列)算法,而他的直接父类:KeyedHashAlgorithm代表有密钥的哈希算法。KeyHashAlgorithm定义了新的属性成员Key代表密钥。而HMAC类还定义了BlockSizeValue代表HMAC处理块的大小(单位:比特)。

这就是HMAC相比.NET中的常规哈希算法(HashAlgorithm类)的区别,并没有加入太多复杂的东西。

 

最后注意HMAC是基于一个哈希算法的,HMAC的安全程度也跟这个背后的哈希算法紧紧相关,你可以选择MD5, SHA1, SHA256, SHA512……等许多哈希算法。

着我们利用HMAC做一个简单的数据验证方法。

首先利用HMAC对数据进行签名,我们把根据密钥计算好的哈希值保存在数据内容的前面,最后返回整个字节数组:

//数据签名
static byte[] SignData(byte[] key, byte[] data, HMAC alg)
{
    //设置密钥
    alg.Key = key;
    //计算哈希值
    var hash = alg.ComputeHash(data);
    //返回具有签名的数据(哈希值+数组本身)
    return hash.Concat(data).ToArray();
}

 

数据认证则是先提取收到的哈希值和数据内容,最后再利用密钥对收到的数据内容进行哈希值的计算,拿这个计算好的哈希值和收到的哈希值作比较,如果相同则数据完整,不同则数据已经被修改。

//数据认证
static bool VerityData(byte[] key, byte[] data, HMAC alg)
{
    //提取收到的哈希值
    var receivedHash = data.Take(alg.HashSize >> 3);
    //提取数据本身
    var dataContent = data.Skip(alg.HashSize >> 3).ToArray();
    //设置密钥
    alg.Key = key;
    //计算数据哈希值和收到的哈希值
    var computedHash = alg.ComputeHash(dataContent);
    //如果相等则数据正确
    return receivedHash.SequenceEqual(computedHash);
}

 

而如果一个被签名的数据被修改了,那么根据双方都知道的密钥就可以判断出数据不完整(已被修改)。

完整代码:

static void Main()
{
    //使用SHA1的HMAC
    HMAC hmac = HMACSHA1.Create();

    //源数据
    var data = new byte[] { 1, 2, 3, 4, 5, 6, 7 };
    //密钥
    var key = new byte[100];

    //创建一个随即密钥
    using (var rng = RandomNumberGenerator.Create())
    {
        rng.GetBytes(key);
    }

    //对数据进行签名
    var signedData = SignData(key, data, hmac);
    //输出数据
    PrintData(signedData, hmac);
    //认证
    Console.WriteLine(VerityData(key, signedData, hmac) ? "数据正确" : "数据已被修改");

    //故意修改数据(将源数据的5修改成4)
    signedData[(hmac.HashSize >> 3) + 4] = 4;
    //输出数据
    PrintData(signedData, hmac);
    //认证
    Console.WriteLine(VerityData(key, signedData, hmac) ? "数据正确" : "数据已被修改");

}

//数据签名
static byte[] SignData(byte[] key, byte[] data, HMAC alg)
{
    //设置密钥
    alg.Key = key;
    //计算哈希值
    var hash = alg.ComputeHash(data);
    //返回具有签名的数据(哈希值+数组本身)
    return hash.Concat(data).ToArray();
}

//数据认证
static bool VerityData(byte[] key, byte[] data, HMAC alg)
{
    //提取收到的哈希值
    var receivedHash = data.Take(alg.HashSize >> 3);
    //提取数据本身
    var dataContent = data.Skip(alg.HashSize >> 3).ToArray();
    //设置密钥
    alg.Key = key;
    //计算数据哈希值和收到的哈希值
    var computedHash = alg.ComputeHash(dataContent);
    //如果相等则数据正确
    return receivedHash.SequenceEqual(computedHash);
}

static void PrintData(byte[] data, HMAC alg)
{
    Console.WriteLine("哈希值: {0}\n文件值: {1}",
        BitConverter.ToString(data.Take(alg.HashSize >> 3).ToArray()),
        BitConverter.ToString(data.Skip(alg.HashSize >> 3).ToArray()));
}

 

输出:

哈希值: 39-FD-E8-2D-3C-0D-5F-A5-53-7A-37-3C-9B-F6-17-D9-CC-0D-FC-90
文件值: 01-02-03-04-05-06-07
数据正确

哈希值: 39-FD-E8-2D-3C-0D-5F-A5-53-7A-37-3C-9B-F6-17-D9-CC-0D-FC-90
文件值: 01-02-03-04-04-06-07
数据已被修改

当源数据的5被改成4后便无法通过认证了。

 

相关文章

    原文作者:哈希算法
    原文地址: https://blog.csdn.net/u014293234/article/details/40950451
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞