写点什么

幸运赛车赛马游艇游戏开发逻辑分析

  • 2022 年 5 月 30 日
  • 本文字数:4396 字

    阅读完需:约 14 分钟

Hash,一般翻译做散列,或音译为哈希,普遍将其称之为散列函数,是把任意长度的输入(又叫做预映射 pre-image)哈希算法的处理,转变为固定长度的输出,则输出的数据就可称之为散列值,或称之为哈希值。这种转换是一种压缩映射,也就是一种合理压缩的过程,输出的哈希值所占用的空间远小于输入的空间,但不同的输入可能会散列成相同的输出,换言之,输出值是唯一的,但无法找寻与其一一对应的输入值。

  项目开发咨询薇芯 hkkf5566

  由于散列函数应用的多样性,它们经常是专为某一应用而设计的。

  错误校验

  使用一个散列函数可以很直观地检测出数据在传输时发生的错误。在数据的发送方,将散列函数应用于未发送的数据中,并将计算结果和原始数据一同发送。那么,在数据的接收方,将接收到的数据利用相同的散列函数进行处理,如果两次散列函数计算出来的结果不同,那么就说明数据在传输的过程中出现了差错。这就叫做冗余校验。

  信息安全

  Hash 算法是现代密码体系中保密程度最高的一种方式。由于非对称算法既费时又费力的弊端,所以在数字签名协议中,单向散列函数完全的取代了传统的加密方式。

NET 6 中哈希算法的简化用法

  Intro

  微软在.NET 6 中引入一些更简单的 API 来使用 HMAC 哈希算法(MD5/SHA1/SHA256/SHA384/SHA512)

  微软的叫法叫做 HMAC One-Shoot method,HMAC 算法在普通的哈希算法基础上增加了一个 key,通过 key 提升了安全性,能够有效避免密码泄露被彩虹表反推出真实密码,JWT(Json Web Token)除了可以使用 RSA 方式外也支持使用 HMAC。

  New API

  新增的 API 定义如下:

  namespace System.Security.Cryptography{

  public partial class HMACMD5{

  public static byte[]HashData(byte[]key,byte[]source);

  public static byte[]HashData(ReadOnlySpan<byte>key,ReadOnlySpan<byte>source);

  public static int HashData(ReadOnlySpan<byte>key,ReadOnlySpan<byte>source,Span<byte>destination);

  public static bool TryHashData(ReadOnlySpan<byte>key,ReadOnlySpan<byte>source,Span<byte>destination,out int bytesWritten);

  }

  public partial class HMACSHA1{

  public static byte[]HashData(byte[]key,byte[]source);

  public static byte[]HashData(ReadOnlySpan<byte>key,ReadOnlySpan<byte>source);

  public static int HashData(ReadOnlySpan<byte>key,ReadOnlySpan<byte>source,Span<byte>destination);

  public static bool TryHashData(ReadOnlySpan<byte>key,ReadOnlySpan<byte>source,Span<byte>destination,out int bytesWritten);

  }

  public partial class HMACSHA256{

  public static byte[]HashData(byte[]key,byte[]source);

  public static byte[]HashData(ReadOnlySpan<byte>key,ReadOnlySpan<byte>source);

  public static int HashData(ReadOnlySpan<byte>key,ReadOnlySpan<byte>source,Span<byte>destination);

  public static bool TryHashData(ReadOnlySpan<byte>key,ReadOnlySpan<byte>source,Span<byte>destination,out int bytesWritten);

  }

  public partial class HMACSHA384{

  public static byte[]HashData(byte[]key,byte[]source);

  public static byte[]HashData(ReadOnlySpan<byte>key,ReadOnlySpan<byte>source);

  public static int HashData(ReadOnlySpan<byte>key,ReadOnlySpan<byte>source,Span<byte>destination);

  public static bool TryHashData(ReadOnlySpan<byte>key,ReadOnlySpan<byte>source,Span<byte>destination,out int bytesWritten);

  }

  public partial class HMACSHA512{

  public static byte[]HashData(byte[]key,byte[]source);

  public static byte[]HashData(ReadOnlySpan<byte>key,ReadOnlySpan<byte>source);

  public static int HashData(ReadOnlySpan<byte>key,ReadOnlySpan<byte>source,Span<byte>destination);

  public static bool TryHashData(ReadOnlySpan<byte>key,ReadOnlySpan<byte>source,Span<byte>destination,out int bytesWritten);

  }

  }

  Sample Before

  在之前的版本中想要实现计算 HMAC 算法会比较复杂,之前实现了一个 HashHelper 来封装了常用的 Hash 算法和 HMAC 算法,HashHelper 部分代码如下,完整代码可以从 Github 获取:https://github.com/WeihanLi/WeihanLi.Common/blob/dev/src/WeihanLi.Common/Helpers/HashHelper.cs

  ///<summary>

  ///获取哈希之后的字符串

  ///</summary>

  ///<param name="type">哈希类型 </param>

  ///<param name="source">源 </param>

  ///<param name="key">key</param>

  ///<param name="isLower">是否是小写 </param>

  ///<returns>哈希算法处理之后的字符串 </returns>

  public static string GetHashedString(HashType type,byte[]source,byte[]?key,bool isLower=false)

  {

  Guard.NotNull(source,nameof(source));

  if(source.Length==0)

  {

  return string.Empty;

  }

  var hashedBytes=GetHashedBytes(type,source,key);

  var sbText=new StringBuilder();

  if(isLower)

  {

  foreach(var b in hashedBytes)

  {

  sbText.Append(b.ToString("x2"));

  }

  }

  else

  {

  foreach(var b in hashedBytes)

  {

  sbText.Append(b.ToString("X2"));

  }

  }

  return sbText.ToString();

  }

  ///<summary>

  ///计算字符串 Hash 值

  ///</summary>

  ///<param name="type">hash 类型 </param>

  ///<param name="str">要 hash 的字符串 </param>

  ///<returns>hash 过的字节数组 </returns>

  public static byte[]GetHashedBytes(HashType type,string str)=>GetHashedBytes(type,str,Encoding.UTF8);

  ///<summary>

  ///计算字符串 Hash 值

  ///</summary>

  ///<param name="type">hash 类型 </param>

  ///<param name="str">要 hash 的字符串 </param>

  ///<param name="encoding">编码类型 </param>

  ///<returns>hash 过的字节数组 </returns>

  public static byte[]GetHashedBytes(HashType type,string str,Encoding encoding)

  {

Guard.NotNull(str,nameof(str));

  if(str==string.Empty)

  {

  return Array.Empty<byte>();

  }

  var bytes=encoding.GetBytes(str);

  return GetHashedBytes(type,bytes);

  }

  ///<summary>

  ///获取 Hash 后的字节数组

  ///</summary>

  ///<param name="type">哈希类型 </param>

  ///<param name="bytes">原字节数组 </param>

  ///<returns></returns>

  public static byte[]GetHashedBytes(HashType type,byte[]bytes)=>GetHashedBytes(type,bytes,null);

  ///<summary>

  ///获取 Hash 后的字节数组

  ///</summary>

  ///<param name="type">哈希类型 </param>

  ///<param name="key">key</param>

  ///<param name="bytes">原字节数组 </param>

  ///<returns></returns>

  public static byte[]GetHashedBytes(HashType type,byte[]bytes,byte[]?key)

  {

  Guard.NotNull(bytes,nameof(bytes));

  if(bytes.Length==0)

  {

  return bytes;

  }

  HashAlgorithm algorithm=null!;

  try

  {

  if(key==null)

  {

  algorithm=type switch

  {

  HashType.SHA1=>new SHA1Managed(),

  HashType.SHA256=>new SHA256Managed(),

  HashType.SHA384=>new SHA384Managed(),

  HashType.SHA512=>new SHA512Managed(),

  _=>MD5.Create()

  };

  }

  else

  {

  algorithm=type switch

  {

  HashType.SHA1=>new HMACSHA1(key),

  HashType.SHA256=>new HMACSHA256(key),

  HashType.SHA384=>new HMACSHA384(key),

  HashType.SHA512=>new HMACSHA512(key),

  _=>new HMACMD5(key)

  };

  }

  return algorithm.ComputeHash(bytes);

  }

  finally

  {

  algorithm.Dispose();

  }

  }

  使用示例如下:

  HashHelper.GetHashedBytes(HashType.MD5,"test");

  HashHelper.GetHashedBytes(HashType.MD5,"test".GetBytes());

  HashHelper.GetHashedBytes(HashType.MD5,"test","testKey");

  HashHelper.GetHashedBytes(HashType.MD5,"test".GetBytes(),"testKey".GetBytes());

  HashHelper.GetHashedString(HashType.MD5,"test");

  HashHelper.GetHashedString(HashType.SHA1,"test".GetBytes());

  HashHelper.GetHashedString(HashType.SHA256,"test","testKey");

  HashHelper.GetHashedString(HashType.MD5,"test".GetBytes(),"testKey".GetBytes());

  New API Sample

  有了新的 API 以后可以怎么简化呢,来看下面的示例:

  var bytes="test".GetBytes();

  var keyBytes="test-key".GetBytes();

  //HMACMD5

  var hmd5V1=HMACMD5.HashData(keyBytes,bytes);

  var hmd5V2=HashHelper.GetHashedBytes(HashType.MD5,bytes,keyBytes);

  Console.WriteLine(hmd5V2.SequenceEqual(hmd5V1));

  //HMACSHA1

  var hsha1V1=HMACSHA1.HashData(keyBytes,bytes);

  var hsha1V2=HashHelper.GetHashedBytes(HashType.SHA1,bytes,keyBytes);

  Console.WriteLine(hsha1V2.SequenceEqual(hsha1V1));

  //HMACSHA256

  var hsha256V1=HMACSHA256.HashData(keyBytes,bytes);

  var hsha256V2=HashHelper.GetHashedBytes(HashType.SHA256,bytes,keyBytes);

  Console.WriteLine(hsha256V2.SequenceEqual(hsha256V1));

  //HMACSHA384

  var hsha384V1=HMACSHA384.HashData(keyBytes,bytes);

  var hsha384V2=HashHelper.GetHashedBytes(HashType.SHA384,bytes,keyBytes);

  Console.WriteLine(hsha384V2.SequenceEqual(hsha384V1));

  //HMACSHA512

  var hsha512V1=HMACSHA512.HashData(keyBytes,bytes);

  var hsha512V2=HashHelper.GetHashedBytes(HashType.SHA512,bytes,keyBytes);

  Console.WriteLine(hsha512V2.SequenceEqual(hsha512V1));

用户头像

还未添加个人签名 2022.05.23 加入

还未添加个人简介

评论

发布
暂无评论
幸运赛车赛马游艇游戏开发逻辑分析_开发微hkkf5566_InfoQ写作社区