C#教程

关注公众号 jb51net

关闭
首页 > 软件编程 > C#教程 > C# WebAPI接口加密

C#实现WebAPI接口安全加密的具体方案

作者:小码编匠

在项目开发过程中,接口的安全性往往是一个容易被忽视但极其关键的环节,本文介绍了一套实际项目中已落地的 Web API 安全加密方案,涵盖了 SHA256 加签、RSA 非对称加密、AES 对称加密 以及相关数据格式转换等内容,需要的朋友可以参考下

前言

在项目开发过程中,接口的安全性往往是一个容易被忽视但极其关键的环节。尤其是在项目上线后,面对外部攻击、攻防演练等情况,如果没有一套完善的加密机制,我们的数据极有可能遭受窃取或篡改。

本文介绍了一套实际项目中已落地的 Web API 安全加密方案,涵盖了 SHA256 加签、RSA 非对称加密、AES 对称加密 以及相关数据格式转换等内容,适用于对外暴露的 API 接口保护场景。希望通过本文,能够帮助大家构建更安全的接口通信体系。

一、方案设计

为了保障接口调用过程中的安全性,我们采用以下加密策略:

加签(Sign):使用 SHA256 对请求参数进行签名,防止请求内容被篡改;

加密传输

数据编码转换:涉及 Base64 编码、16进制与字节数组之间的相互转换,确保数据在网络中正确传输和解析。

该方案不仅提升了接口的安全性,也兼顾了性能和易用性。

1、SHA256 加签实现

加签是为了验证请求的完整性,防止请求参数在传输过程中被篡改。以下是 C# 实现的 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

通过此方法可以生成唯一的哈希值,作为请求的签名字段附加在请求头或参数中。

2、RSA 加密与解密

RSA 是一种非对称加密算法,适合用于密钥交换或数字签名等场景。以下是 C# 中的 RSA 加解密实现:

#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

客户端使用公钥加密敏感信息,服务端使用私钥解密,从而保证传输数据的机密性。

3、AES 加密与解密

AES 是一种对称加密算法,常用于大量数据的加密处理。以下是 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 通常用于加密业务数据本身,结合 RSA 可以实现更完整的安全体系。

4、数据格式转换工具类

为了支持不同格式的数据处理,还需要一些辅助函数来完成数据转换:

#region 数据转换
// 字符串转换为字节数组
byte[] originalBytes = System.Text.Encoding.UTF8.GetBytes(originalText);

// 进行Base64编码
string base64Encoded = Convert.ToBase64String(originalBytes);

// 进行Base64解码
byte[] base64DecodedBytes = Convert.FromBase64String(base64Encoded);

// 字节数组转字符串
string base64DecodedText = System.Text.Encoding.UTF8.GetString(base64DecodedBytes);

// 16进制转base64字符串
byte[] enterpriseCode_ = HexConvert.strToToHexByte(data.enterpriseCode);
string enterpriseCode = Convert.ToBase64String(enterpriseCode_);

/// <summary> 
/// 字节数组转16进制字符串 
/// </summary> 
/// <param name="byteArray"></param> 
/// <returns></returns> 
public static string byteToHexStr2(byte[] byteArray)
{
    string hexString = BitConverter.ToString(byteArray);
    return hexString.Replace("-", "");
}

/// <summary> 
/// 字节数组转16进制字符串 
/// </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> 
/// 字符串转16进制字节数组 
/// </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

这些方法广泛应用于加密前后数据格式的处理,如将加密结果转为16进制字符串、Base64编码等。

项目效果

通过上述加密机制,API 请求在传输前会经过如下流程:

1、参数拼接并计算 SHA256 签名;

2、敏感数据使用 AES 加密;

3、AES 密钥使用 RSA 公钥加密;

4、所有数据打包发送至服务端;

5、服务端使用 RSA 私钥解密密钥,再使用 AES 解密数据,并验证签名。

整个流程有效防止了中间人攻击、数据篡改和重放攻击等问题,极大增强了接口的安全性。

总结

本文详细介绍了在实际项目中使用的 Web API 接口安全加密方案,包括:

这套方案已在生产环境中稳定运行,具有良好的兼容性和扩展性。如果你也有类似的加密需求,欢迎交流分享你的经验!

最后

到此这篇关于C#实现WebAPI接口安全加密的具体方案的文章就介绍到这了,更多相关C# WebAPI接口加密内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文