更新於 2024/09/15閱讀時間約 21 分鐘

玩轉C#之【Encrypt加密解密】

介紹

這章節純看智商
  • 不可逆加密:原文加密後變成密文,但密文沒辦法解密文回原文
  • 可逆加密:原文加密過後的密文,可以在將密文解密回原文
  • 對稱:表示加解密是否使用同一個key

MD5 不可逆加密

MD5 使用的命名空間是 System.Security.Cryptography
/// <summary>
   /// 不可逆加密
   /// 1 防止被篡改
   /// 2 防止明文儲存
   /// 3 防止抵赖,數字簽名
   /// </summary>
   public class MD5Encrypt
   {
       #region MD5
       /// <summary>
       /// MD5加密
       /// 使用的UTF8編碼
       /// </summary>
       /// <param name="source">待加密字串</param>
       /// <param name="length">16或32值之一,其他則採用.net默認MD5加密算法</param>
       /// <returns>加密后的字串</returns>
       public static string Encrypt(string source, int length = 32)//默認參數
       {
           if (string.IsNullOrEmpty(source)) return string.Empty;
           HashAlgorithm provider = CryptoConfig.CreateFromName("MD5") as HashAlgorithm;
           byte[] bytes = Encoding.UTF8.GetBytes(source);//這裡需要區別編碼的
           byte[] hashValue = provider.ComputeHash(bytes);
           StringBuilder sb = new StringBuilder();
           switch (length)
           {
               case 16:
                   for (int i = 4; i < 12; i++)
                   {
                       sb.Append(hashValue[i].ToString("x2"));
                   }
                   break;
               case 32:
                   for (int i = 0; i < 16; i++)
                   {
                       sb.Append(hashValue[i].ToString("x2"));
                   }
                   break;
               default:
                   for (int i = 0; i < hashValue.Length; i++)
                   {
                       sb.Append(hashValue[i].ToString("x2"));
                   }
                   break;
           }
           return sb.ToString();
       }
       #endregion MD5

       #region MD5摘要
       /// <summary>
       /// 獲取檔案的MD5摘要
       /// </summary>
       /// <param name="fileName"></param>
       /// <returns></returns>
       public static string AbstractFile(string fileName)
       {
           using (FileStream file = new FileStream(fileName, FileMode.Open))
           {
               return AbstractFile(file);
           }
       }

       /// <summary>
       /// 根據stream獲取檔案摘要
       /// </summary>
       /// <param name="stream"></param>
       /// <returns></returns>
       public static string AbstractFile(Stream stream)
       {
           MD5 md5 = new MD5CryptoServiceProvider();
           byte[] retVal = md5.ComputeHash(stream);

           StringBuilder sb = new StringBuilder();
           for (int i = 0; i < retVal.Length; i++)
           {
               sb.Append(retVal[i].ToString("x2"));
           }
           return sb.ToString();
       }
       #endregion
   }
MD5是一種公開的算法,相同的字串可以得到一樣的結果 應用:可以做密碼檢查=將使用者密碼md5一下,存到資料庫裡,下一次使用者輸入密碼的時候md5一下在做比對 MD5網路上的解密,都是使用樣本比對的方式 密碼複雜一點的方式,加鹽(密碼加上一段文字在做MD5) 或做兩次MD5
以下運用得原理,只有相同文件才能有相同的md5 應用:
  • 防止程式串改:下載VS安裝文件(md5)從官方網站下載,到非官方網站下載只要確認檔案的md5碼有沒有樣就可以
  • 急速秒傳:百度雲 一瞬間就傳完了,第一次上傳,傳完保存MD5,先計算md5--比對-匹配了就不需要上傳了
  • GIT/Svn: md5比對
任何數據MD5後結果都不一樣,到目前為止還沒碰過 2的128次方可能性

DES 對稱可逆加密

應用:數據傳輸 優點:加密速度快 缺點:密鑰的安全是問題 是公開的演算法,即使拿到密文,也推算不了密鑰,也推算不回原文
/// <summary>
   /// DES AES Blowfish
   ///  對稱加密算法的優點是速度快,
   ///  缺點是密鑰管理不方便,要求共享密鑰。
   /// 可逆對稱加密,密鑰長度8
   /// </summary>
   public class DesEncrypt
   {
       private static byte[] _rgbKey = ASCIIEncoding.ASCII.GetBytes(Constant.DesKey.Substring(0, 8));
       private static byte[] _rgbIV = ASCIIEncoding.ASCII.GetBytes(Constant.DesKey.Insert(0, "w").Substring(0, 8));

       /// <summary>
       /// DES 加密
       /// </summary>
       /// <param name="text">需要加密的值</param>
       /// <returns>加密后的结果</returns>
       public static string Encrypt(string text)
       {
           DESCryptoServiceProvider dsp = new DESCryptoServiceProvider();
           using (MemoryStream memStream = new MemoryStream())
           {
               CryptoStream crypStream = new CryptoStream(memStream, dsp.CreateEncryptor(_rgbKey, _rgbIV), CryptoStreamMode.Write);
               StreamWriter sWriter = new StreamWriter(crypStream);
               sWriter.Write(text);
               sWriter.Flush();
               crypStream.FlushFinalBlock();
               memStream.Flush();
               return Convert.ToBase64String(memStream.GetBuffer(), 0, (int)memStream.Length);
           }
       }

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

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

RSA 非對稱可逆加密

加密鑰做為私鑰 解密鑰做為公鑰 保證訊息一定來自某個人
加密鑰做為公開 解密鑰做為私有 表示訊息只有我能看的到
加密解密速度不快,安全性好
/// <summary>
   /// RSA ECC
   /// 可逆非對稱加密
   /// 非對稱加密算法的優點是密鑰管理很方便,缺點速度慢。
   /// </summary>
   public class RsaEncrypt
   {
       /// <summary>
       /// 獲取加密/解密對
       /// 给你一個,是無法推算出另外一个的
       ///
       /// Encrypt   Decrypt
       /// </summary>
       /// <returns>Encrypt   Decrypt</returns>
       public static KeyValuePair<string, string> GetKeyPair()
       {
           RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
           string publicKey = RSA.ToXmlString(false);
           string privateKey = RSA.ToXmlString(true);
           return new KeyValuePair<string, string>(publicKey, privateKey);
       }

       /// <summary>
       /// 加密:内容+加密key
       /// </summary>
       /// <param name="content"></param>
       /// <param name="encryptKey">加密key</param>
       /// <returns></returns>
       public static string Encrypt(string content, string encryptKey)
       {
           RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
           rsa.FromXmlString(encryptKey);
           UnicodeEncoding ByteConverter = new UnicodeEncoding();
           byte[] DataToEncrypt = ByteConverter.GetBytes(content);
           byte[] resultBytes = rsa.Encrypt(DataToEncrypt, false);
           return Convert.ToBase64String(resultBytes);
       }

       /// <summary>
       /// 解密  内容+解密key
       /// </summary>
       /// <param name="content"></param>
       /// <param name="decryptKey">解密key</param>
       /// <returns></returns>
       public static string Decrypt(string content, string decryptKey)
       {
           byte[] dataToDecrypt = Convert.FromBase64String(content);
           RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
           RSA.FromXmlString(decryptKey);
           byte[] resultBytes = RSA.Decrypt(dataToDecrypt, false);
           UnicodeEncoding ByteConverter = new UnicodeEncoding();
           return ByteConverter.GetString(resultBytes);
       }


       /// <summary>
       /// 可以合併在一起的,每次產生一组新的密鑰
       /// </summary>
       /// <param name="content"></param>
       /// <param name="encryptKey">加密key</param>
       /// <param name="decryptKey">解密key</param>
       /// <returns>加密后结果</returns>
       private static string Encrypt(string content, out string publicKey, out string privateKey)
       {
           RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider();
           publicKey = rsaProvider.ToXmlString(false);
           privateKey = rsaProvider.ToXmlString(true);

           UnicodeEncoding ByteConverter = new UnicodeEncoding();
           byte[] DataToEncrypt = ByteConverter.GetBytes(content);
           byte[] resultBytes = rsaProvider.Encrypt(DataToEncrypt, false);
           return Convert.ToBase64String(resultBytes);
       }
   }
關於數字證書SSL之後會專門寫一篇文章跟大家講解

參考資料

本篇已同步發表至個人部落格 https://moushih.com/2022ithome16/
我的鐵人賽文章
分享至
成為作者繼續創作的動力吧!
© 2024 vocus All rights reserved.