C#實(shí)現(xiàn)WebAPI接口安全加密的具體方案
前言
在項(xiàng)目開(kāi)發(fā)過(guò)程中,接口的安全性往往是一個(gè)容易被忽視但極其關(guān)鍵的環(huán)節(jié)。尤其是在項(xiàng)目上線后,面對(duì)外部攻擊、攻防演練等情況,如果沒(méi)有一套完善的加密機(jī)制,我們的數(shù)據(jù)極有可能遭受竊取或篡改。
本文介紹了一套實(shí)際項(xiàng)目中已落地的 Web API 安全加密方案,涵蓋了 SHA256 加簽、RSA 非對(duì)稱加密、AES 對(duì)稱加密 以及相關(guān)數(shù)據(jù)格式轉(zhuǎn)換等內(nèi)容,適用于對(duì)外暴露的 API 接口保護(hù)場(chǎng)景。希望通過(guò)本文,能夠幫助大家構(gòu)建更安全的接口通信體系。
一、方案設(shè)計(jì)
為了保障接口調(diào)用過(guò)程中的安全性,我們采用以下加密策略:
加簽(Sign):使用 SHA256 對(duì)請(qǐng)求參數(shù)進(jìn)行簽名,防止請(qǐng)求內(nèi)容被篡改;
加密傳輸:
- 使用 RSA 進(jìn)行非對(duì)稱加密,用于加密密鑰;
- 使用 AES 進(jìn)行對(duì)稱加密,用于加密實(shí)際數(shù)據(jù);
數(shù)據(jù)編碼轉(zhuǎn)換:涉及 Base64 編碼、16進(jìn)制與字節(jié)數(shù)組之間的相互轉(zhuǎn)換,確保數(shù)據(jù)在網(wǎng)絡(luò)中正確傳輸和解析。
該方案不僅提升了接口的安全性,也兼顧了性能和易用性。
1、SHA256 加簽實(shí)現(xiàn)
加簽是為了驗(yàn)證請(qǐng)求的完整性,防止請(qǐng)求參數(shù)在傳輸過(guò)程中被篡改。以下是 C# 實(shí)現(xiàn)的 SHA256 加簽方法:
#region 加簽SHA256 public static string GetSHA256Hash(string input) { using (SHA256 sha256Hash = SHA256.Create()) { byte[] bytes = sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(input)); StringBuilder builder = new StringBuilder(); for (int i = 0; i < bytes.Length; i++) { builder.Append(bytes[i].ToString("x2")); } return builder.ToString(); } } #endregion
通過(guò)此方法可以生成唯一的哈希值,作為請(qǐng)求的簽名字段附加在請(qǐng)求頭或參數(shù)中。
2、RSA 加密與解密
RSA 是一種非對(duì)稱加密算法,適合用于密鑰交換或數(shù)字簽名等場(chǎng)景。以下是 C# 中的 RSA 加解密實(shí)現(xiàn):
#region RSA加密/解密 private readonly RSA _privateKeyRsaProvider; private readonly RSA _publicKeyRsaProvider; private readonly Encoding _encoding; /// <param name="encoding">編碼類型</param> /// <param name="privateKey">私鑰</param> /// <param name="publicKey">公鑰</param> public RSAHelper(Encoding encoding, string privateKey, string publicKey = null) { _encoding = encoding; if (!string.IsNullOrEmpty(privateKey)) { _privateKeyRsaProvider = CreateRsaProviderFromPrivateKey(privateKey); } if (!string.IsNullOrEmpty(publicKey)) { _publicKeyRsaProvider = CreateRsaProviderFromPublicKey(publicKey); } } // 解密 public string Decrypt(string cipherText) { if (_privateKeyRsaProvider == null) { throw new Exception("_privateKeyRsaProvider is null"); } return Encoding.UTF8.GetString(_privateKeyRsaProvider.Decrypt(Convert.FromBase64String(cipherText), RSAEncryptionPadding.Pkcs1)); } // 加密 public string Encrypt(string text) { if (_publicKeyRsaProvider == null) { throw new Exception("_publicKeyRsaProvider is null"); } return Convert.ToBase64String(_publicKeyRsaProvider.Encrypt(Encoding.UTF8.GetBytes(text), RSAEncryptionPadding.Pkcs1)); } #endregion
客戶端使用公鑰加密敏感信息,服務(wù)端使用私鑰解密,從而保證傳輸數(shù)據(jù)的機(jī)密性。
3、AES 加密與解密
AES 是一種對(duì)稱加密算法,常用于大量數(shù)據(jù)的加密處理。以下是 C# 中的 AES 加解密示例:
#region AES加密/解密 /// <summary> /// 加密不帶偏移量 /// </summary> /// <param name="input"></param> /// <param name="key">秘鑰</param> /// <returns></returns> public static string EncryptByAES(string input, string key) { if (string.IsNullOrWhiteSpace(input)) { return input; } using (RijndaelManaged rijndaelManaged = new RijndaelManaged()) { rijndaelManaged.Mode = CipherMode.ECB; rijndaelManaged.Padding = PaddingMode.PKCS7; rijndaelManaged.FeedbackSize = 128; byte[] data3 = Enumerable.Range(0, key.Length / 2) .Select(x => Byte.Parse(key.Substring(x * 2, 2), NumberStyles.HexNumber)) .ToArray(); rijndaelManaged.Key = data3; ICryptoTransform encryptor = rijndaelManaged.CreateEncryptor(rijndaelManaged.Key, rijndaelManaged.IV); using (MemoryStream msEncrypt = new MemoryStream()) { using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) { using (StreamWriter swEncrypt = new StreamWriter(csEncrypt)) { swEncrypt.Write(input); } byte[] bytes = msEncrypt.ToArray(); return HexConvert.byteToHexStr(bytes); } } } } /// <summary> /// 返回解密后的字符串 /// </summary> /// <param name="input"></param> /// <param name="key">秘鑰</param> /// <returns></returns> public static string DecryptByAES(string input, string key) { if (string.IsNullOrWhiteSpace(input)) { return input; } var buffer = HexConvert.strToToHexByte(input); using (RijndaelManaged rijndaelManaged = new RijndaelManaged()) { rijndaelManaged.Mode = CipherMode.ECB; rijndaelManaged.Padding = PaddingMode.PKCS7; rijndaelManaged.FeedbackSize = 128; byte[] data3 = Enumerable.Range(0, key.Length / 2) .Select(x => Byte.Parse(key.Substring(x * 2, 2), NumberStyles.HexNumber)) .ToArray(); rijndaelManaged.Key = data3; ICryptoTransform decryptor = rijndaelManaged.CreateDecryptor(rijndaelManaged.Key, rijndaelManaged.IV); using (MemoryStream msEncrypt = new MemoryStream(buffer)) { using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, decryptor, CryptoStreamMode.Read)) { using (StreamReader srEncrypt = new StreamReader(csEncrypt)) { return srEncrypt.ReadToEnd(); } } } } } #endregion
AES 通常用于加密業(yè)務(wù)數(shù)據(jù)本身,結(jié)合 RSA 可以實(shí)現(xiàn)更完整的安全體系。
4、數(shù)據(jù)格式轉(zhuǎn)換工具類
為了支持不同格式的數(shù)據(jù)處理,還需要一些輔助函數(shù)來(lái)完成數(shù)據(jù)轉(zhuǎn)換:
#region 數(shù)據(jù)轉(zhuǎn)換 // 字符串轉(zhuǎn)換為字節(jié)數(shù)組 byte[] originalBytes = System.Text.Encoding.UTF8.GetBytes(originalText); // 進(jìn)行Base64編碼 string base64Encoded = Convert.ToBase64String(originalBytes); // 進(jìn)行Base64解碼 byte[] base64DecodedBytes = Convert.FromBase64String(base64Encoded); // 字節(jié)數(shù)組轉(zhuǎn)字符串 string base64DecodedText = System.Text.Encoding.UTF8.GetString(base64DecodedBytes); // 16進(jìn)制轉(zhuǎn)base64字符串 byte[] enterpriseCode_ = HexConvert.strToToHexByte(data.enterpriseCode); string enterpriseCode = Convert.ToBase64String(enterpriseCode_); /// <summary> /// 字節(jié)數(shù)組轉(zhuǎn)16進(jìn)制字符串 /// </summary> /// <param name="byteArray"></param> /// <returns></returns> public static string byteToHexStr2(byte[] byteArray) { string hexString = BitConverter.ToString(byteArray); return hexString.Replace("-", ""); } /// <summary> /// 字節(jié)數(shù)組轉(zhuǎn)16進(jìn)制字符串 /// </summary> /// <param name="bytes"></param> /// <returns></returns> public static string byteToHexStr(byte[] bytes) { string returnStr = ""; if (bytes != null) { for (int i = 0; i < bytes.Length; i++) { returnStr += bytes[i].ToString("X2"); } } return returnStr; } /// <summary> /// 字符串轉(zhuǎn)16進(jìn)制字節(jié)數(shù)組 /// </summary> /// <param name="hexString"></param> /// <returns></returns> public static byte[] strToToHexByte(string hexString) { hexString = hexString.Replace(" ", ""); if ((hexString.Length % 2) != 0) hexString += " "; byte[] returnBytes = new byte[hexString.Length / 2]; for (int i = 0; i < returnBytes.Length; i++) returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16); return returnBytes; } #endregion
這些方法廣泛應(yīng)用于加密前后數(shù)據(jù)格式的處理,如將加密結(jié)果轉(zhuǎn)為16進(jìn)制字符串、Base64編碼等。
項(xiàng)目效果
通過(guò)上述加密機(jī)制,API 請(qǐng)求在傳輸前會(huì)經(jīng)過(guò)如下流程:
1、參數(shù)拼接并計(jì)算 SHA256 簽名;
2、敏感數(shù)據(jù)使用 AES 加密;
3、AES 密鑰使用 RSA 公鑰加密;
4、所有數(shù)據(jù)打包發(fā)送至服務(wù)端;
5、服務(wù)端使用 RSA 私鑰解密密鑰,再使用 AES 解密數(shù)據(jù),并驗(yàn)證簽名。
整個(gè)流程有效防止了中間人攻擊、數(shù)據(jù)篡改和重放攻擊等問(wèn)題,極大增強(qiáng)了接口的安全性。
總結(jié)
本文詳細(xì)介紹了在實(shí)際項(xiàng)目中使用的 Web API 接口安全加密方案,包括:
- 使用 SHA256 對(duì)請(qǐng)求參數(shù)進(jìn)行簽名;
- 使用 RSA 進(jìn)行非對(duì)稱加密傳輸密鑰;
- 使用 AES 進(jìn)行對(duì)稱加密保護(hù)數(shù)據(jù);
- 提供了完整的 C# 示例代碼;
- 包含常用數(shù)據(jù)格式轉(zhuǎn)換方法。
這套方案已在生產(chǎn)環(huán)境中穩(wěn)定運(yùn)行,具有良好的兼容性和擴(kuò)展性。如果你也有類似的加密需求,歡迎交流分享你的經(jīng)驗(yàn)!
最后
到此這篇關(guān)于C#實(shí)現(xiàn)WebAPI接口安全加密的具體方案的文章就介紹到這了,更多相關(guān)C# WebAPI接口加密內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
WPF自定義實(shí)現(xiàn)上傳文件顯示進(jìn)度的按鈕控件
自定義控件在WPF開(kāi)發(fā)中是很常見(jiàn)的,有時(shí)候某些控件需要契合業(yè)務(wù)或者美化統(tǒng)一樣式,這時(shí)候就需要對(duì)控件做出一些改造,本文就來(lái)自定義實(shí)現(xiàn)一個(gè)上傳文件顯示進(jìn)度的按鈕控件吧2023-06-06C# SynchronizationContext以及Send和Post使用解讀
這篇文章主要介紹了C# SynchronizationContext以及Send和Post使用解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05C#操作Access數(shù)據(jù)庫(kù)的實(shí)現(xiàn)過(guò)程(vs2019)
這篇文章主要介紹了C#操作Access數(shù)據(jù)庫(kù)的實(shí)現(xiàn)過(guò)程(vs2019),打開(kāi)Office Access新建一個(gè)空白數(shù)據(jù)庫(kù)DATA.accdb,并改好存放位置,本文給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2024-02-02C#使用代碼實(shí)現(xiàn)春晚?yè)淇伺颇g(shù)
這篇文章主要為大家詳細(xì)介紹了C#如何使用代碼實(shí)現(xiàn)龍年春晚?yè)淇伺颇g(shù)(守歲共此時(shí)),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2024-02-02微信公眾號(hào)被動(dòng)消息回復(fù)原理解析
這篇文章主要介紹了公眾號(hào)被動(dòng)消息回復(fù)原理解析,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-06-06C#程序中類數(shù)量對(duì)程序啟動(dòng)的影響詳解
這篇文章主要給大家介紹了關(guān)于C#程序中類數(shù)量對(duì)程序啟動(dòng)的影響的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-10-10