282 lines
11 KiB
C#
282 lines
11 KiB
C#
using System;
|
||
using System.IO;
|
||
using System.Security.Cryptography;
|
||
using System.Text;
|
||
using System.Text.Json;
|
||
using System.Net.Http;
|
||
using System.Threading.Tasks;
|
||
|
||
public class Program
|
||
{
|
||
// ==================== 配置区域 ====================
|
||
// 请根据实际情况修改以下配置参数
|
||
|
||
// AES加密密钥 (16进制字符串,32位)
|
||
|
||
// API接口配置
|
||
private const string InterfaceName = "XXXXXXXX"; // 接口编号
|
||
private const string AccessId = "XXXXXXXXXXX"; // 访问ID
|
||
private const string EncryptionKey = "XXXXXXXXXXXXXXXXXXX"; // 加密密钥
|
||
private const string BaseUrl = "https://api.tianyuanapi.com"; // API基础URL
|
||
|
||
// 测试数据配置
|
||
private const string TestMobileNo = "13700000000"; // 测试手机号
|
||
private const string TestIdCard = "XXXXXXXXXXXXX"; // 测试身份证号
|
||
private const string TestName = "XXXXXXXX"; // 测试姓名
|
||
private const string TestAuthDate = "20250318-20270318"; // 测试授权日期
|
||
|
||
// HTTP请求配置
|
||
private const int RequestTimeout = 30000; // 请求超时时间(毫秒)
|
||
|
||
// ==================== 主程序 ====================
|
||
public static async Task Main()
|
||
{
|
||
Console.WriteLine("===== AES CBC 加密解密演示 =====");
|
||
|
||
// 1. 创建一个JSON对象
|
||
var data = new
|
||
{
|
||
mobile_no = TestMobileNo
|
||
};
|
||
|
||
// 将JSON对象序列化为字符串
|
||
string jsonString = JsonSerializer.Serialize(data, new JsonSerializerOptions { WriteIndented = true });
|
||
|
||
Console.WriteLine("\n原始JSON:");
|
||
Console.WriteLine(jsonString);
|
||
|
||
// 2. 加密JSON
|
||
Console.WriteLine("\n开始加密...");
|
||
string encryptedJson = Encrypt(jsonString);
|
||
Console.WriteLine($"加密成功! 加密后Base64:");
|
||
Console.WriteLine(encryptedJson);
|
||
|
||
// 3. 解密JSON
|
||
Console.WriteLine("\n开始解密...");
|
||
string decryptedJson = Decrypt(encryptedJson);
|
||
Console.WriteLine($"解密成功! 解密后的原始JSON:");
|
||
Console.WriteLine(decryptedJson);
|
||
|
||
// 4. 验证加解密一致性
|
||
Console.WriteLine("\n验证结果:");
|
||
if (jsonString == decryptedJson)
|
||
{
|
||
Console.WriteLine("✅ 加解密前后内容完全一致");
|
||
|
||
// 验证原始数据是否可用
|
||
Console.WriteLine("\n尝试解析解密后的JSON:");
|
||
try
|
||
{
|
||
var deserializedObject = JsonSerializer.Deserialize(decryptedJson, typeof(object));
|
||
Console.WriteLine($"✅ JSON解析成功,类型: {deserializedObject.GetType()}");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.WriteLine($"❌ JSON解析失败: {ex.Message}");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine("❌ 加解密前后内容不一致!");
|
||
Console.WriteLine("原始长度: " + jsonString.Length);
|
||
Console.WriteLine("解密后长度: " + decryptedJson.Length);
|
||
|
||
// 找出第一个不同的位置
|
||
for (int i = 0; i < Math.Min(jsonString.Length, decryptedJson.Length); i++)
|
||
{
|
||
if (jsonString[i] != decryptedJson[i])
|
||
{
|
||
Console.WriteLine($"第一个差异在位置 {i}:");
|
||
Console.WriteLine($"原始字符: '{jsonString[i]}' ({(int)jsonString[i]})");
|
||
Console.WriteLine($"解密字符: '{decryptedJson[i]}' ({(int)decryptedJson[i]})");
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 5. 演示API调用流程(可选)
|
||
Console.WriteLine("\n===== 演示API调用流程 =====");
|
||
await DemonstrateApiCall();
|
||
}
|
||
|
||
// ==================== AES加密解密方法 ====================
|
||
|
||
/// <summary>
|
||
/// AES CBC 加密函数
|
||
/// 使用PKCS7填充,随机IV,返回Base64编码的密文
|
||
/// </summary>
|
||
/// <param name="plainText">要加密的明文</param>
|
||
/// <returns>Base64编码的密文</returns>
|
||
public static string Encrypt(string plainText)
|
||
{
|
||
byte[] key = HexToBytes(EncryptionKey);
|
||
using Aes aes = Aes.Create();
|
||
aes.Key = key;
|
||
aes.Mode = CipherMode.CBC;
|
||
aes.Padding = PaddingMode.PKCS7;
|
||
|
||
aes.GenerateIV();
|
||
byte[] iv = aes.IV;
|
||
|
||
using ICryptoTransform encryptor = aes.CreateEncryptor();
|
||
using MemoryStream ms = new();
|
||
// 先写入IV
|
||
ms.Write(iv, 0, iv.Length);
|
||
|
||
using (CryptoStream cs = new(ms, encryptor, CryptoStreamMode.Write))
|
||
using (StreamWriter sw = new(cs))
|
||
{
|
||
sw.Write(plainText);
|
||
}
|
||
|
||
return Convert.ToBase64String(ms.ToArray());
|
||
}
|
||
|
||
/// <summary>
|
||
/// AES CBC 解密函数
|
||
/// 从Base64密文中提取IV和密文数据,进行解密
|
||
/// </summary>
|
||
/// <param name="cipherText">Base64编码的密文</param>
|
||
/// <returns>解密后的明文</returns>
|
||
public static string Decrypt(string cipherText)
|
||
{
|
||
byte[] key = HexToBytes(EncryptionKey);
|
||
byte[] fullData = Convert.FromBase64String(cipherText);
|
||
|
||
// 提取前16字节作为IV
|
||
byte[] iv = new byte[16];
|
||
Buffer.BlockCopy(fullData, 0, iv, 0, iv.Length);
|
||
|
||
// 实际密文数据
|
||
byte[] cipherData = new byte[fullData.Length - 16];
|
||
Buffer.BlockCopy(fullData, 16, cipherData, 0, cipherData.Length);
|
||
|
||
using Aes aes = Aes.Create();
|
||
aes.Key = key;
|
||
aes.IV = iv;
|
||
aes.Mode = CipherMode.CBC;
|
||
aes.Padding = PaddingMode.PKCS7;
|
||
|
||
using ICryptoTransform decryptor = aes.CreateDecryptor();
|
||
using MemoryStream ms = new(cipherData);
|
||
using CryptoStream cs = new(ms, decryptor, CryptoStreamMode.Read);
|
||
using StreamReader sr = new(cs);
|
||
return sr.ReadToEnd();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 将16进制字符串转换为字节数组
|
||
/// </summary>
|
||
/// <param name="hex">16进制字符串</param>
|
||
/// <returns>字节数组</returns>
|
||
private static byte[] HexToBytes(string hex)
|
||
{
|
||
byte[] bytes = new byte[hex.Length / 2];
|
||
for (int i = 0; i < hex.Length; i += 2)
|
||
{
|
||
bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
|
||
}
|
||
return bytes;
|
||
}
|
||
|
||
// ==================== API调用演示方法 ====================
|
||
|
||
/// <summary>
|
||
/// 演示完整的API调用流程
|
||
/// 包括:参数构建、加密、发送请求、接收响应、解密响应
|
||
/// </summary>
|
||
private static async Task DemonstrateApiCall()
|
||
{
|
||
try
|
||
{
|
||
// 构建完整的API URL
|
||
string url = $"{BaseUrl}/api/v1/{InterfaceName}";
|
||
|
||
// 构建请求参数
|
||
var apiParams = new
|
||
{
|
||
mobile_no = TestMobileNo,
|
||
id_card = TestIdCard,
|
||
auth_date = TestAuthDate,
|
||
name = TestName
|
||
};
|
||
|
||
// 将参数转换为JSON字符串并加密
|
||
string jsonStr = JsonSerializer.Serialize(apiParams);
|
||
Console.WriteLine($"请求参数: {jsonStr}");
|
||
|
||
string encryptedData = Encrypt(jsonStr);
|
||
Console.WriteLine($"加密后的数据: {encryptedData}");
|
||
|
||
// 构建请求体
|
||
var payload = new { data = encryptedData };
|
||
string requestBody = JsonSerializer.Serialize(payload);
|
||
|
||
Console.WriteLine($"发送请求到: {url}");
|
||
|
||
// 发送HTTP请求
|
||
using (var httpClient = new HttpClient())
|
||
{
|
||
// 设置请求头
|
||
httpClient.DefaultRequestHeaders.Add("Access-Id", AccessId);
|
||
httpClient.DefaultRequestHeaders.Add("Content-Type", "application/json");
|
||
|
||
// 设置超时时间
|
||
httpClient.Timeout = TimeSpan.FromMilliseconds(RequestTimeout);
|
||
|
||
var content = new StringContent(requestBody, Encoding.UTF8, "application/json");
|
||
var response = await httpClient.PostAsync(url, content);
|
||
|
||
Console.WriteLine($"响应状态码: {response.StatusCode}");
|
||
|
||
if (response.IsSuccessStatusCode)
|
||
{
|
||
string responseBody = await response.Content.ReadAsStringAsync();
|
||
Console.WriteLine($"API响应: {responseBody}");
|
||
|
||
// 解析响应
|
||
try
|
||
{
|
||
var responseData = JsonSerializer.Deserialize<JsonElement>(responseBody);
|
||
|
||
if (responseData.TryGetProperty("code", out var codeElement))
|
||
{
|
||
int code = codeElement.GetInt32();
|
||
string message = responseData.TryGetProperty("message", out var msgElement) ? msgElement.GetString() : "";
|
||
string encryptedResponse = responseData.TryGetProperty("data", out var dataElement) ? dataElement.GetString() : "";
|
||
|
||
Console.WriteLine($"API响应码: {code}");
|
||
Console.WriteLine($"API消息: {message}");
|
||
|
||
if (code == 0 && !string.IsNullOrEmpty(encryptedResponse))
|
||
{
|
||
// 解密响应数据
|
||
try
|
||
{
|
||
string decryptedResponse = Decrypt(encryptedResponse);
|
||
Console.WriteLine($"解密后的响应: {decryptedResponse}");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.WriteLine($"解密响应数据失败: {ex.Message}");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.WriteLine($"解析响应失败: {ex.Message}");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine($"请求失败: {response.StatusCode}");
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.WriteLine($"API调用异常: {ex.Message}");
|
||
}
|
||
}
|
||
} |