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

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

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

image

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

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

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

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

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

//数据签名

staticbyte[] SignData(byte[] key, byte[] data, HMAC alg)

{

    //设置密钥

    alg.Key = key;

    //计算哈希值

    var hash = alg.ComputeHash(data);

    //返回具有签名的数据(哈希值+数组本身)

    return hash.Concat(data).ToArray();

}

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

//数据认证

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

}

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

完整代码:

staticvoid Main()

{

    //使用SHA1的HMAC

    HMAC hmac =HMACSHA1.Create();

    //源数据

    var data =newbyte[] { 1, 2, 3, 4, 5, 6, 7 };

    //密钥

    var key =newbyte[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) ?"数据正确" : "数据已被修改");

}

//数据签名

staticbyte[] SignData(byte[] key, byte[] data, HMAC alg)

{

    //设置密钥

    alg.Key = key;

    //计算哈希值

    var hash = alg.ComputeHash(data);

    //返回具有签名的数据(哈希值+数组本身)

    return hash.Concat(data).ToArray();

}

//数据认证

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

}

staticvoid 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后便无法通过认证了。

HMAC、MD5、SHA256介绍:

HMAC算法以及工作原理-CSDN博客

使用MD5或sha-256 C#哈希密码#_用于生成密码哈希的C/C++函数(使用MD5或其他算法)?_C#,如何检查值是否使用MD5密码加密? - 腾讯云开发者社区 - 腾讯云 (tencent.com)

详解SHA-256算法的原理以及C#和JS的实现_其它综合_脚本之家 (jb51.net)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值