关键词搜索

源码搜索 ×
×

C#中的那些常用加密算法

发布2021-05-11浏览1000次

详情内容

前言
本文主要讲解一下C#常用的那些加密算法。

本文源码
本文所用源码均以为大家整理完毕,大家使用以下方式获取

需要的小伙伴,请关注微信公众号: 程序员零距离, 或者扫描下方公众号二维码,回复关键字:加密算法 , 即可获取本文所用的所有源码资源。

关注上方公众号,回复 加密算法获取

MD5加密
MD5加密是最常见的加密方式,因为MD5是不可逆的,所以很多系统的密码都是用MD5加密保存的。

虽然MD5是不可以解码的,但因为MD5加密的字符串是固定的,所以,理论上只需要建立一个庞大的数据库,把所有的字符串都加密一遍,那就可以解码所有的MD5密文了。

虽然建立一个可以解码全部MD5的数据库不太现实,但一个五六百亿数据量的数据库就可以解码绝大部分字符串了,毕竟大部分情况下,我们的密码也是有长度限制的。

实际应用中MD5有64位和32位加密之分,代码如下:

#region MD5加密 32和64 
public static string GetMd532(string ConvertString)
{
  MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
  string t2 = BitConverter.ToString(md5.ComputeHash(UTF8Encoding.Default.GetBytes(ConvertString)), 4, 8);
  t2 = t2.Replace("-", "");
 
  return t2;
} 
public static string Get64Md5(string str)
{
  string cl = str;
  string pwd = "";
  var md5 = MD5.Create();
  byte[] s = md5.ComputeHash(Encoding.UTF8.GetBytes(cl)); 
  for (int i = 0; i < s.Length; i++)
  {
    pwd = pwd + s[i].ToString("X2");
  } 
  return pwd;
} 
#endregion

    我们运行一下,加密函数。

    Console.WriteLine($"MD5-64:{ MD5Helper.Get64Md5("Kiba518")}");
    Console.WriteLine($"MD5-32:{ MD5Helper.Get32Md5("Kiba518")}");
    
    • 1
    • 2

    结果如下图所示:

    在这里插入图片描述

    SHA1加密
    SHA1加密算法与MD5加密类似,都是不可逆的,只是算法不同。所以也和MD5一样,存在容易被大数据解码的问题。

    代码如下:

    private static readonly Encoding Encoder = Encoding.UTF8;
    public static String Sha1(String content )
    {
      try
      {
        SHA1 sha1 = new SHA1CryptoServiceProvider();//创建SHA1对象
        byte[] bytes_in = Encoder.GetBytes(content);//将待加密字符串转为byte类型
        byte[] bytes_out = sha1.ComputeHash(bytes_in);//Hash运算
        sha1.Dispose();//释放当前实例使用的所有资源
        String result = BitConverter.ToString(bytes_out);//将运算结果转为string类型
        result = result.Replace("-", "").ToUpper();
        return result;
      }
      catch (Exception ex)
      {
        return ex.Message;
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    运行加密函数,结果如下图所示:
    在这里插入图片描述

    Base64加密
    准确的来说,Base64是一种编码,而不是加密,通常Base64编码后字符串会用于传输数据。不过也因为Base64编码后字符串具有不可读性,所以,不少人也把他当做加密算法来使用。

    代码如下:

    private static readonly Encoding Encoder = Encoding.UTF8;
    public static string EncodeBase64(string source)
    {
      string target = "";
      byte[] bytes = Encoder.GetBytes(source);
      try
      {
        target = Convert.ToBase64String(bytes);
      }
      catch
      {
        target = source;
      }
      return target;
    }
    public static string DecodeBase64(string result)
    {
      string decode = "";
      byte[] bytes = Convert.FromBase64String(result);
      try
      {
        decode = Encoder.GetString(bytes);
      }
      catch
      {
        decode = result;
      }
      return decode;
    }
    
      23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    运行Base64编码函数。

    string base64Str = Base64Helper.EncodeBase64("Kiba518");
    Console.WriteLine($"SHA1编码:{ base64Str}");
    Console.WriteLine($"SHA1解码:{ Base64Helper.DecodeBase64(base64Str)}");
    
    • 1
    • 2
    • 3

    结果如下图所示:

    在这里插入图片描述

    Des加密
    DES加密算法是对密钥进行保密,而公开算法,即只有拥有相同密钥的人才能解密。

    DES加密算法对密钥有要求,必须是8个字符,如abcdefgh这样的。

    代码如下:

    public static string Encrypt(string stringToEncrypt, string shortKey)
    {
      DESCryptoServiceProvider des = new DESCryptoServiceProvider();
      byte[] inputByteArray = Encoding.GetEncoding("UTF-8").GetBytes(stringToEncrypt);
      des.Key = ASCIIEncoding.UTF8.GetBytes(shortKey);
      des.IV = ASCIIEncoding.UTF8.GetBytes(shortKey);
      MemoryStream ms = new MemoryStream();
      CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);
      cs.Write(inputByteArray, 0, inputByteArray.Length);
      cs.FlushFinalBlock();
      StringBuilder ret = new StringBuilder();
      foreach (byte b in ms.ToArray())
      {
        ret.AppendFormat("{0:X2}", b);
      }
      ret.ToString();
      return ret.ToString();
    }
    public static string Decrypt(string stringToDecrypt, string sKey)
    {
      DESCryptoServiceProvider des = new DESCryptoServiceProvider();
     
      byte[] inputByteArray = new byte[stringToDecrypt.Length / 2];
      for (int x = 0; x < stringToDecrypt.Length / 2; x++)
      {
        int i = (Convert.ToInt32(stringToDecrypt.Substring(x * 2, 2), 16));
        inputByteArray[x] = (byte)i;
      }
      des.Key = ASCIIEncoding.UTF8.GetBytes(sKey);
      des.IV = ASCIIEncoding.UTF8.GetBytes(sKey);
      MemoryStream ms = new MemoryStream();
      CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write);
      cs.Write(inputByteArray, 0, inputByteArray.Length);
      cs.FlushFinalBlock();
      StringBuilder ret = new StringBuilder();
      return System.Text.Encoding.Default.GetString(ms.ToArray());
    }
    
      23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    如代码所示,我们使用DESCryptoServiceProvider类来进行DES加密。

    DESCryptoServiceProvider类的Mode属性可以指定加密运算模式。

    加密运算模式如下:

    CBC:密码块链模式。
    ECB:电子密码本模式。
    OFB:输出反馈模式。
    CFB:密码反馈模式。
    CTS:密码文本窃取模式。
    在C#中默认的加密运算模式是CBC—密码块链模式。

    在Java中默认的加密运算模式是ECB—电子密码本模式。

    即,如果密文是在C#项目和Java项目之间传递,那么必须配置相同的加密运算模式。

    运行DES加密函数代码如下:

    string key_8 = "abcdefgh";
    string desShortKeyStr = DESHelper.Encrypt("Kiba518", key_8);
    Console.WriteLine($"DES加密:{ desShortKeyStr}");
    Console.WriteLine($"DES解密:{ DESHelper.Decrypt(desShortKeyStr, key_8)}");
    
    • 1
    • 2
    • 3
    • 4

    结果如下图所示:

    在这里插入图片描述

    有时候,我们的密钥不是正好8个字符,那我们就截取前8为作为密钥就可以了。

    RSA加密
    RSA加密采用公钥加密,私钥解密的模式。Https的数字证书也是使用这种模式加密的。

    代码如下:

    public static string RSADecrypt(string xmlPrivateKey, string enptStr)
    {
      RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
      provider.FromXmlString(xmlPrivateKey);
      byte[] rgb = Convert.FromBase64String(enptStr);
      byte[] bytes = provider.Decrypt(rgb, RSAEncryptionPadding.OaepSHA1);
      return new UnicodeEncoding().GetString(bytes);
    }
    public static string RSAEncrypt(string xmlPublicKey, string enptStr)
    {
      RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
      provider.FromXmlString(xmlPublicKey);
      byte[] bytes = new UnicodeEncoding().GetBytes(enptStr);
      return Convert.ToBase64String(provider.Encrypt(bytes, RSAEncryptionPadding.OaepSHA1));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    运行DES加密函数代码如下:

    //加密公钥 
    string publicKey = "18+I2j3HU/fXQasRXOWGegP3dG75I/It2n42rgeIATeftBkoQNH73Rz0IYW++arqd0Yy5hFpNkqzY/dOmD+bDXWUheWA0P/dVZf+qeWwVV+iW3lRAU8SmnPcaD35Ic1jMEPFQVeX1zGI2ofD8aGodeSRA4+JKo+KLgyGVGDI+d0=AQAB";
    //解密私钥 
    string privateKey = " 18+I2j3HU/fXQasRXOWGegP3dG75I/It2n42rgeIATeftBkoQNH73Rz0IYW++arqd0Yy5hFpNkqzY/dOmD+bDXWUheWA0P/dVZf+qeWwVV+iW3lRAU8SmnPcaD35Ic1jMEPFQVeX1zGI2ofD8aGodeSRA4+JKo+KLgyGVGDI+d0=AQAB
    2EEAI+cO1fyvmGpg3ywMLHHZ1/X3ZrF6xZBNM2AL7bJFVfL8RS8UznUCdsL/R/o1b+lGo1CetlI++n6IvYYwyw==
     
    /3muAXWOU3SMKFWSDpHUgeM9kZev0ekQDefRSayXM8q9ItkaWTOJcIN614A0UGdYE6VX1ztPgveQFzm0qJDy9w==NM/i/eGewOmd5IYONFJogq4nOlOKYNz1E6yC/gn1v83qmuvlaevuk+EFggVrHKPhSvxYUOgOao45bSlbsZVE8w==MKU7w91dh3iWw4tfr1SHUWAytglbGi41t2Af0taBSARftUX/pWKR1hHDD0vDKlgzRjJiooIRps966WE8jChliw==YEIfQArVNP27AJn3WOBswHP/+gJ6Bk434MZ80CJONp4b6e+Ilxd2dwloxGKNbGgCyaNJEFI5J8qYSNNe0KqPkw==ZAscSPesqLtS+WlBMkxgy719AGfVbRl+sjQiSwjIvq+3hDjJVUtCs90RO10SDBF0gfhz7f2SRY3ZnXTu5VtPF9KEQyUaY0F6eXwz4YQNzJTI2c1o5SFXZP8Ynqwltg8gNIhMe8bB6nVgASeADBim22DlSFCzmD3vt1gTI8nxmO0=";
    string myname = "my name is Kiba518!my name is Kiba518!!!!43"; //最大长度43
    string rsaStr = RSAHelper.RSAEncrypt(publicKey, myname);
    Console.WriteLine($"RSA加密:{ rsaStr}");
    string dersaStr = RSAHelper.RSADecrypt(privateKey, rsaStr);
    Console.WriteLine($"RSA解密:{ dersaStr}");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    结果如下图所示:

    在这里插入图片描述

    RSA加密有个特点,就是他对被加密的字符串有长度限制。

    长度限制规则:待加密的字节数不能超过密钥的长度值除以 8 再减去 11(即:RSACryptoServiceProvider.KeySize / 8 - 11),而加密后得到密文的字节数,正好是密钥的长度值除以 8(即:RSACryptoServiceProvider.KeySize / 8)。注:该长度指的是byte[]数组的长度,而不是字符串的长度。

    简单来说,就是被加密字符串不能太长。

    但是,在真实的业务中,我们需要加密的字符串往往会很长,那么,RSA又对被加密字符串有长度限制,我们该怎么办呢?很简单,把待加密的字符串拆开,每段长度都小于等于限制长度,然后分段加密,这样,问题就解决了。

    分段加密代码如下:

    public static String SubRSAEncrypt(string xmlPublicKey, string enptStr)
    {
      RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
      provider.FromXmlString(xmlPublicKey);
      Byte[] bytes = Encoder.GetBytes(enptStr);
      int MaxBlockSize = provider.KeySize / 8 - 11;  //加密块最大长度限制
     
      if (bytes.Length <= MaxBlockSize)
        return Convert.ToBase64String(provider.Encrypt(bytes, false));
     
      using (MemoryStream PlaiStream = new MemoryStream(bytes))
      using (MemoryStream CrypStream = new MemoryStream())
      {
        Byte[] Buffer = new Byte[MaxBlockSize];
        int BlockSize = PlaiStream.Read(Buffer, 0, MaxBlockSize);
     
        while (BlockSize > 0)
        {
          Byte[] ToEncrypt = new Byte[BlockSize];
          Array.Copy(Buffer, 0, ToEncrypt, 0, BlockSize);
     
          Byte[] Cryptograph = provider.Encrypt(ToEncrypt, false);
          CrypStream.Write(Cryptograph, 0, Cryptograph.Length);
     
          BlockSize = PlaiStream.Read(Buffer, 0, MaxBlockSize);
        }
     
        return Convert.ToBase64String(CrypStream.ToArray(), Base64FormattingOptions.None);
      }
     
    }
    /// 
     
    /// 分段解密,应对长字符串
    /// 
    /// 
    /// 
    /// 
    public static String SubRSADecrypt(string xmlPublicKey, string enptStr)
    {
      RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
      provider.FromXmlString(xmlPublicKey);
      Byte[] bytes = Convert.FromBase64String(enptStr);
      int MaxBlockSize = provider.KeySize / 8;  //解密块最大长度限制
     
      if (bytes.Length <= MaxBlockSize)
        return Encoder.GetString(provider.Decrypt(bytes, false));
     
      using (MemoryStream CrypStream = new MemoryStream(bytes))
      using (MemoryStream PlaiStream = new MemoryStream())
      {
        Byte[] Buffer = new Byte[MaxBlockSize];
        int BlockSize = CrypStream.Read(Buffer, 0, MaxBlockSize);
     
        while (BlockSize > 0)
        {
          Byte[] ToDecrypt = new Byte[BlockSize];
          Array.Copy(Buffer, 0, ToDecrypt, 0, BlockSize);
     
          Byte[] Plaintext = provider.Decrypt(ToDecrypt, false);
          PlaiStream.Write(Plaintext, 0, Plaintext.Length);
     
          BlockSize = CrypStream.Read(Buffer, 0, MaxBlockSize);
        }
     
        return Encoder.GetString(PlaiStream.ToArray());
      }
    }
    
      23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68

    结果如下图所示:
    在这里插入图片描述

    结语

    到此C#常用的那些加密算法就介绍完了,下面我们vb.net教程一起看一下,同一字符串,加密后情况。

    在这里插入图片描述

    可以看到,不同加密方式得到的密文长度都不一样,其中DES加密后在Base64编码的模式的密文长度最短。RSA加密的密文最长。

    本文源码
    本文所用源码均以为大家整理完毕,大家使用以下方式获取

    相关技术文章

    点击QQ咨询
    开通会员
    返回顶部
    ×
    微信扫码支付
    微信扫码支付
    确定支付下载
    请使用微信描二维码支付
    ×

    提示信息

    ×

    选择支付方式

    • 微信支付
    • 支付宝付款
    确定支付下载