本文主要讲解一下C#常用加密算法其中包含对称加密算法和非对称加密算法,包括MD5加密SHA1加密Base64加密Des加密RSA加密等

MD5

MD5加密是最常见的加密方式,因为MD5是不可逆的,所以很多系统的密码都是用MD5加密保存的。虽然MD5加密不可逆,但MD5加密的字符串是固定的。所以,理论上只需要建立一个庞大的数据库,把所有的字符串都加密一遍,那就可以解码所有的MD5密文了。但建立一个可以解码全部MD5的数据库不太现实。

实际应用中MD5有64位和32位加密之分。

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;
}

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;
  }
}

Base64

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

private static readonly Encoding Encoder = Encoding.UTF8;
        /// <summary>
        /// base64编码
        /// </summary>
        /// <param name="result"></param>
        /// <returns></returns>
        public static string EncodeBase64(string source)
        {
            string target = "";
            byte[] bytes = Encoder.GetBytes(source);
            try
            {
                target = Convert.ToBase64String(bytes);
            }
            catch
            {
                target = source;
            }
            return target;
        }

        /// <summary>
        /// base64解码
        /// </summary>
        /// <param name="result"></param>
        /// <returns></returns>
        public static string DecodeBase64(string result)
        {
            string decode = "";
            byte[] bytes = Convert.FromBase64String(result);
            try
            {
                decode = Encoder.GetString(bytes);
            }
            catch
            {
                decode = result;
            }
            return decode;
        }

DES

  • DES加密算法是对密钥进行保密,而公开算法,即只有拥有相同密钥的人才能解密。
  • DES加密算法对密钥有要求,必须是8个字符,如12345678这样的。
  • DESCryptoServiceProvider类的Mode属性可以指定加密运算模式,加密运算模式分为CBC:密码块链模式、ECB:电子密码本模式、OFB:输出反馈模式、CFB:密码反馈模式、CTS:密码文本窃取模式。
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());
}

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

但是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());
  }
}
最后修改:2022 年 09 月 30 日
如果觉得我的文章对你有用,请随意赞赏