【.NET Core】加解密

概述

编码、加密、哈希的区别

  • 编码:是信息从一种形式或格式转换成另一种的过程,是可逆的。如:url编码、base64、utf-8
  • 加密:是可逆的,通过特定的秘钥加解密,加解密算法算法有两种:对称加密、非对称加密
  • 哈希:也叫散列,把任意长度的数据转换成固定长度的指纹,过程不可逆

Hash算法

MD5、SHA系列(1、224、256、384、512)……
无论消息有多长,计算出的摘要长度都是固定的
用途:文件校验、数字签名(防篡改),建议用SHA系列

Hmac算法

为了防止黑客通过彩虹表根据哈希值反推原始口令,在计算哈希的时候,不能仅针对原始输入计算,需要增加一个salt来使得相同的输入也能得到不同的哈希,这样,大大增加了黑客破解的难度。
如果salt是我们自己随机生成的,通常我们计算MD5时采用md5(message + salt),这实际上就是Hmac算法。Hmac通过一个标准算法,在计算哈希的过程中,把key混入计算过程中。采用Hmac替代我们自己的salt算法,可以使程序算法更标准化,也更安全。
Hmac算法针对所有哈希算法都通用,如:HMAC-MD5HMAC-SHA1HMAC-SHA256HMAC-SHA384...

对称加密算法

AES(也称为Rijndael)、DES、3DES、IDEA、RC2、RC4、SKIPJACKTripleDES 算法……
加解密使用相同密钥,这个是对称加密。对称加密相比非对称加密优点是速度快

DES已破解,被AES取代,弃用
3DES有安全漏洞,弃用

非对称加密算法

RSA、DSA、DH、ECC、EL GAMAL……
公钥加密数据,然后私钥解密的情况被称为加密解密;
因为公钥加密的数据只有它相对应的私钥可以解开,所以你可以把公钥给人和人,让他加密他想要传送给你的数据,这个数据只有到了有私钥的你这里,才可以解开成有用的数据,其他人就是得到了,也看懂内容
实际应用中,一般都是和对方交换公钥,然后你要发给对方的数据,用他的公钥加密,他得到后用他的私钥解密,他要发给你的数据,用你的公钥加密,你得到后用你的私钥解密,这样最大程度保证了安全性.
缺点:速度慢

RSA签名、验签

上面的Hash算法属于对称签名,RSA签名是非对称签名
私钥签名和公钥验证签名;如果你用你的私钥对数据进行签名,那这个数据就只有配对的公钥可以解开,有这个私钥的只有你,所以如果配对的公钥解开了数据,就说明这数据是你发的,相反,则不是.这个被称为签名。数字签名的意义就是这些数据与原文数据比对是否修改过。

算法实现

各种算法微软都有实现,都是基于 System.Security.Cryptography.Algorithms这个程序集实现的。
文档地址:https://docs.microsoft.com/zh-cn/dotnet/api/system.security.cryptography?view=netcore-3.1
源码地址:https://github.com/dotnet/corefx/tree/master/src/System.Security.Cryptography.Algorithms

Hash

//MD5
{
    var srcString = "fan001";
    //(和后面开源库的实现相比多了些 -,可以利用replace去掉)
    var md5 = MD5.Create();
    byte[] result = md5.ComputeHash(Encoding.UTF8.GetBytes(srcString));
    string md5String= BitConverter.ToString(result).Replace("-","");
}
//SHA系列
{
    var srcString = "fan001";
    //SHA-256,SHA-384 和 SHA-512 用法类似(和后面开源库的实现相比多了些-,可以利用replace去掉)
    var sha1 = SHA1.Create();
    byte[] result = sha1.ComputeHash(Encoding.UTF8.GetBytes(srcString));
    string sha1HashString = BitConverter.ToString(result).Replace("-", "");
}

HMAC

//HMAC相关
{
    var secretKey = "sflkasfkksfs";
    var srcString = "fan001";
    //HMAC-SHA384、HMAC-SHA512的用法类似 (和后面开源库的实现相比多了些-,可以利用replace去掉)
    HMACSHA1 hmacsha1 = new HMACSHA1(Encoding.UTF8.GetBytes(secretKey));
    HMACSHA256 hmacsha2 = new HMACSHA256(Encoding.UTF8.GetBytes(secretKey));
    byte[] bytes1 = hmacsha1.ComputeHash(Encoding.UTF8.GetBytes(srcString));
    byte[] bytes2 = hmacsha2.ComputeHash(Encoding.UTF8.GetBytes(srcString));
    string hmacSha1String = BitConverter.ToString(bytes1).Replace("-", "");
    string hmacSha2String = BitConverter.ToString(bytes2).Replace("-", "");
}

对称加密

DesEncrypt
public class DesEncrypt
    {
        //8位长度
        private static byte[] rgbKey = ASCIIEncoding.ASCII.GetBytes("ioeruwoe");  //密钥(转为byte数组)
        private static byte[] rgbIV = ASCIIEncoding.ASCII.GetBytes("fan00001");   //矢量(配合密钥更加安全)

        #region 01-DES加密
        /// <summary>
        /// DES 加密
        /// </summary>
        /// <param name="strValue">需要加密的字符串</param>
        /// <returns></returns>
        public static string Encrypt(string strValue)
        {
            DESCryptoServiceProvider dsp = new DESCryptoServiceProvider();
            using (MemoryStream memStream = new MemoryStream())
            {
                CryptoStream crypStream = new CryptoStream(memStream, dsp.CreateEncryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
                byte[] buffer = Encoding.Default.GetBytes(strValue);
                crypStream.Write(buffer, 0, buffer.Length);
                crypStream.FlushFinalBlock();
                memStream.Flush();
                return Convert.ToBase64String(memStream.GetBuffer(), 0, (int)memStream.Length);
            }
        }
        #endregion

        #region 02-DES解密
        /// <summary>
        /// DES解密
        /// </summary>
        /// <param name="EncValue">加密后的结果</param>
        /// <returns></returns>
        public static string Decrypt(string EncValue)
        {
            DESCryptoServiceProvider dsp = new DESCryptoServiceProvider();
            byte[] buffer = Convert.FromBase64String(EncValue);

            using (MemoryStream memStream = new MemoryStream())
            {
                CryptoStream crypStream = new CryptoStream(memStream, dsp.CreateDecryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
                crypStream.Write(buffer, 0, buffer.Length);
                crypStream.FlushFinalBlock();
                return ASCIIEncoding.UTF8.GetString(memStream.ToArray());
            }
        }
        #endregion
    }
//DES算法
{
    //具体实现详见:DesEncrypt
    string msg1 = "mr1";
    //密钥写在DesEncrypt类中了
    string result1 = DesEncrypt.Encrypt(msg1);
    string result2 = DesEncrypt.Decrypt(result1);
}

非对称加密

另一篇文章

Core版算法开源库

说明:通过Nuget安装:Install-Package NETCore.Encrypt
包括的算法有:Base64MD5SHA系列HAMC系列AESDESRSA

PS:还支持MD5SHA系列HMAC系列 对于String类型的扩展,如:var hashed3 = "fan".MD5(); 大部分算法支持 stringbyte[] 两种格式。

案例

{
    //1. Base64的编码和解码
    var srcString = "fan001";
    var hashed1 = EncryptProvider.Base64Encrypt(srcString);  //default encoding is UTF-8
    var hashed2 = EncryptProvider.Base64Encrypt(srcString, Encoding.ASCII); //按照ascii进行编码
    var strValue1 = EncryptProvider.Base64Decrypt(hashed1);   //default encoding is UTF-8
    var strValue2 = EncryptProvider.Base64Decrypt(hashed2, Encoding.ASCII);   //按照ascii进行解码
}
{
    //2. MD5
    var srcString = "fan001";
    var hashed1 = EncryptProvider.Md5(srcString);  //默认32位
    var hashed2 = EncryptProvider.Md5(srcString, MD5Length.L16); //16位
    Console.WriteLine($"fan001的MD5加密(32位):{hashed1}");
    Console.WriteLine($"fan002的MD5加密(64位):{hashed2}");
    //扩展用法
    var hashed3 = srcString.MD5();
}
{
    //3. SHA相关
    var srcString = "fan001";
    var hashed1 = EncryptProvider.Sha1(srcString);
    var hashed2 = EncryptProvider.Sha256(srcString);
    var hashed3 = EncryptProvider.Sha384(srcString);
    var hashed4 = EncryptProvider.Sha512(srcString);
    //扩展用法(如下,其余类似)
    var extHash = srcString.SHA1();
}
{
    //4. HAMC相关
    var secretKey = "sflkasfkksfs";
    var srcString = "fan001";
    var hashed1 = EncryptProvider.HMACMD5(srcString, secretKey);
    var hashed2 = EncryptProvider.HMACSHA1(srcString, secretKey);
    var hashed3 = EncryptProvider.HMACSHA256(srcString, secretKey);
    var hashed4 = EncryptProvider.HMACSHA384(srcString, secretKey);
    var hashed5 = EncryptProvider.HMACSHA512(srcString, secretKey);
    //扩展用法(如下,其余类似)
    var extHash = srcString.HMACSHA1(secretKey);
}
{
    //5. AES
    //利用算法生成key和iv(32位和16位),当然这里可以自己指定并保存好
    //var aesKey = EncryptProvider.CreateAesKey();
    //var key = aesKey.Key;
    //var iv = aesKey.IV;
    var secretKey = "asdfjketjnddkkaakkuyerbdsbgrtsaw";  //这里的key得32位
    var iv = "ioeruwoeruo2aqwe";  //加密和解密的过程中可以加上iv矢量,使其安全性更高,这里的iv得16位
    var srcString = "fan001";
    //加密
    var encrypted1 = EncryptProvider.AESEncrypt(srcString, secretKey);
    var encrypted2 = EncryptProvider.AESEncrypt(srcString, secretKey, iv);
    //解密
    var decrypted1 = EncryptProvider.AESDecrypt(encrypted1, secretKey);
    var decrypted2 = EncryptProvider.AESDecrypt(encrypted2, secretKey, iv);
    //PS:这里除了string加密,还可以对byte数组加密
}
{
    //6. DES
    //利用算法生成key(24位),当然这里可以自己指定并保存好
    //var desKey = EncryptProvider.CreateDesKey();
    var secretKey = "asdfjketjnddkkaakkuyerbd";  //这里的key得24位
    var srcString = "fan001";
    //加密
    var encrypted1 = EncryptProvider.DESEncrypt(srcString, secretKey);
    //解密
    var decrypted1 = EncryptProvider.DESDecrypt(encrypted1, secretKey);
    //PS:这里除了string加密,还可以对byte数组加密
}
{
    //7.RSA
    //利用算法生成公钥和私钥,然后保存;当然这里可以自己指定并保存好
    var rsaKey = EncryptProvider.CreateRsaKey();    //default is 2048
    // var rsaKey = EncryptProvider.CreateRsaKey(RsaSize.R3072);
    var publicKey = rsaKey.PublicKey;
    var privateKey = rsaKey.PrivateKey;
    var srcString = "fan001";
    //加密
    var encrypted1 = EncryptProvider.RSAEncrypt(publicKey, srcString);   //公钥加密
    //解密
    var decrypted = EncryptProvider.RSADecrypt(privateKey, encrypted1);  //私钥解密
}
  public enum RsaSize
    {
        R2048 = 2048,
        R3072 = 3072,
        R4096 = 4096
    }

助手类封装

点击查看代码
/// <summary>
  /// 各种加密解密算法
  /// 依赖程序集【NETCore.Encrypt】
  /// </summary>
  public class SecurityHelp
  {
      /// <summary>
      /// Base64编码
      /// </summary>
      /// <param name="srcString">需要编码的字符串</param>
      /// <returns></returns>
      public static string Base64Encrypt(string srcString)
      {
          return EncryptProvider.Base64Encrypt(srcString);  //default encoding is UTF-8
      }

      /// <summary>
      /// Base64编码
      /// </summary>
      /// <param name="encString">需要解码的字符串</param>
      /// <returns></returns>
      public static string Base64Decrypt(string encString)
      {
          return EncryptProvider.Base64Decrypt(encString);  //default encoding is UTF-8
      }


      /// <summary>
      /// MD5加密
      /// </summary>
      /// <param name="srcString">需要加密的字符串</param>
      /// <param name="num">位数,默认为32位,也可以是16位</param>
      /// <returns></returns>
      public static string Md5(string srcString, int num = 32)
      {
          if (num == 32)
          {
              return EncryptProvider.Md5(srcString);  //默认32位
          }
          else
          {
              return EncryptProvider.Md5(srcString, MD5Length.L16);   //16位
          }
      }


      /// <summary>
      /// SHA系列算法
      /// </summary>
      /// <param name="srcString">需要加密的字符串</param>
      /// <param name="kind">类型</param>
      /// <returns></returns>
      public static string SHA(string srcString, string kind = "Sha512")
      {
          if (kind.Equals("Sha1"))
          {
              return EncryptProvider.Sha1(srcString);
          }
          else if (kind.Equals("Sha256"))
          {
              return EncryptProvider.Sha256(srcString);
          }
          else if (kind.Equals("Sha384"))
          {
              return EncryptProvider.Sha384(srcString);
          }
          else
          {
              return EncryptProvider.Sha512(srcString);
          }
      }

      /// <summary>
      /// HMAC系列算法
      /// </summary>
      /// <param name="srcString">需要加密的字符串</param>
      /// <param name="secretKey">密钥</param>
      /// <param name="kind">类型</param>
      /// <returns></returns>
      public static string HMAC(string srcString, string secretKey, string kind = "HMACSHA512")
      {
          if (kind.Equals("HMACMD5"))
          {
              return EncryptProvider.HMACMD5(srcString, secretKey);
          }
          else if (kind.Equals("HMACSHA1"))
          {
              return EncryptProvider.HMACSHA1(srcString, secretKey);
          }
          else if (kind.Equals("HMACSHA256"))
          {
              return EncryptProvider.HMACSHA256(srcString, secretKey);
          }
          else if (kind.Equals("HMACSHA384"))
          {
              return EncryptProvider.HMACSHA384(srcString, secretKey);
          }
          else
          {
              return EncryptProvider.HMACSHA512(srcString, secretKey);
          }
      }


      /// <summary>
      /// 生成AES算法所需的Key和iv
      /// (当然这里可以自己指定并保存好)
      /// </summary>
      /// <param name="key">加密所需的key</param>
      /// <param name="iv">加密所需的矢量</param>
      public static void CreateAesKey(ref string key, ref string iv)
      {
          //利用算法生成key和iv(32位和16位),当然这里可以自己指定并保存好
          var aesKey = EncryptProvider.CreateAesKey();
          key = aesKey.Key;
          iv = aesKey.IV;
      }

      /// <summary>
      /// AES加密算法
      /// </summary>
      /// <param name="srcString">需要加密的字符串</param>
      /// <param name="secretKey">密钥</param>
      /// <param name="iv">矢量(可以不填)</param>
      /// <returns></returns>
      public static string AESEncrypt(string srcString, string secretKey, string iv = "")
      {
          if (string.IsNullOrEmpty(iv))
          {
              return EncryptProvider.AESEncrypt(srcString, secretKey);    //表示不需要iv矢量的AES加密算法
          }
          else
          {
              return EncryptProvider.AESEncrypt(srcString, secretKey, iv);    //表示需要iv矢量的AES加密算法
          }
      }


      /// <summary>
      /// AES解密算法
      /// </summary>
      /// <param name="encString">需要解密的字符串</param>
      /// <param name="secretKey">密钥</param>
      /// <param name="iv">矢量(可以不填)</param>
      /// <returns></returns>
      public static string AESDecrypt(string encString, string secretKey, string iv = "")
      {
          if (string.IsNullOrEmpty(iv))
          {
              return EncryptProvider.AESDecrypt(encString, secretKey);    //表示不需要iv矢量的AES解密算法
          }
          else
          {
              return EncryptProvider.AESDecrypt(encString, secretKey, iv);    //表示需要iv矢量的AES解密算法
          }
      }


      /// <summary>
      /// DES加密算法
      /// </summary>
      /// <param name="srcString">需要加密的字符串</param>
      /// <param name="secretKey">密钥(这里的密钥需要是24位)</param>
      /// <returns></returns>
      public static string EDSEncrypt(string srcString, string secretKey)
      {
          return EncryptProvider.DESEncrypt(srcString, secretKey);
      }


      /// <summary>
      /// DES解密算法
      /// </summary>
      /// <param name="encString">需要解密的字符串</param>
      /// <param name="secretKey">密钥</param>
      /// <returns></returns>
      public static string DESDecrypt(string encString, string secretKey)
      {
          return EncryptProvider.DESDecrypt(encString, secretKey);
      }



      /// <summary>
      /// 生成RSA算法所需的Key和iv
      /// (当然这里可以自己指定并保存好)
      /// </summary>
      /// <param name="PublicKey">公钥</param>
      /// <param name="PrivateKey">私钥</param>
      public static void CreateRsaKey(ref string PublicKey, ref string PrivateKey)
      {
          //利用算法生成公钥和私钥,然后保存;当然这里可以自己指定并保存好
          var rsaKey = EncryptProvider.CreateRsaKey();    //default is 2048
                                                          // var rsaKey = EncryptProvider.CreateRsaKey(RsaSize.R3072);
          PublicKey = rsaKey.PublicKey;
          PrivateKey = rsaKey.PrivateKey;
      }



      /// <summary>
      /// RSA加密算法
      /// </summary>
      /// <param name="srcString">需要加密的字符串</param>
      /// <param name="publicKey">公钥 加密</param>
      /// <returns></returns>
      public static string RSAEncrypt(string srcString, string publicKey)
      {
          return EncryptProvider.RSAEncrypt(publicKey, srcString);   //公钥加密
      }


      /// <summary>
      /// RSA解密算法
      /// </summary>
      /// <param name="encString">需要解密的字符串</param>
      /// <param name="privateKey">私钥 解密</param>
      /// <returns></returns>
      public static string RSADecrypt(string encString, string privateKey)
      {
          return EncryptProvider.RSADecrypt(privateKey, encString);  //私钥解密
      }



  }



  public enum RsaSize
  {
      R2048 = 2048,
      R3072 = 3072,
      R4096 = 4096
  }
posted @ 2022-05-18 23:31  .Neterr  阅读(1453)  评论(0编辑  收藏  举报