c# - 使用 Sytem.Secuirty.Cryptography 的 C# AES-GCM 和 RSA 加密
问题描述
我正在用 c# 开发发布数据请求并使用 AES GCM 加密和 RSA 加密。与使用 Node.js / Python 进行加密的 C# 代码相比,我们发现 C# AES GCM 加密在方法中没有标记值。例如,加密后如何在 C# 中返回以下数据。
return {
key: aesKey,
cipher_text: encrypted,
tag,
iv
}
在使用 JsEncrypt 的 Python 和 Node.js 中,forge.js.... 和实现工作正常。但是,现在在 C# 中开发相同的客户端,找不到我可以直接使用的此类库。
但是,我在 C# AesGcm 和 AesManaged 中找到了两个用于 AES 加密的类。但我认为 AesManages 仅适用于 AES 而不是 GCM 加密。因此,我在下面的示例中使用 AesGcm 类,但不确定。
代码执行以下步骤:
- 从 DSG 请求客户端证书。
- 从证书中提取公钥。
- 使用 AES 密钥加密 PII。
- 使用 RSA 公钥加密 AES 密钥。
- 将打包的密钥和 PII 有效负载发送到 DSG 标记化。
class Program
{
static void Main(string[] args)
{
string _ApiKey = "--- YOUR API KEY ----";
string _SecretKey = " ---- YOUR SECRET KEY --------";
string jsonPlainText = "<JSON TExT>";
#region Certificate
string certificate = GetCertificate();
Certificate rawSigningCert = JsonConvert.DescrializeObject<Certificate>(certificate);
var certBytes = Encoding.UTF8.GetBytes(rawSigningCert.crt);
// X509Certificate2
var x509Certificate2 = new System.Security.Cryptography.X509Certificates.X509Certificate2(certBytes);
byte[] publicKey = x509Certificate2.GetPublicKey();
#endregion
#region AES GCM Encryption
byte[] aesGcmKey = new byte[16];
RandomNumberGenerator.Fill(aesGcmKey);
byte[] nonce = new byte[12];
RandomNumberGenerator.Fill(nonce);
byte[] tag = new byte[16];
byte[] dataToEncrypt = Encoding.UTF8.GetBytes(jsonPlainText);
byte[] cipherText = new byte[dataToEncrypt.Length];
using (AesGcm aesGcm = new AesGcm(aesGcmKey))
{
aesGcm.Encrypt(nonce, dataToEncrypt, cipherText, tag);
}
string encryptedCipher = Convert.ToBase64String(cipherText);
var keyString = Convert.ToBase64String(aesGcmKey);
var iVString = Convert.ToBase64String(nonce);
var tagString = Convert.ToBase64String(tag);
string aesGcmEncryptionString = string.Format("{0}:{1}:{2}", keyString, iVString, tagString);
#endregion
#region RSA Encryption
var rsa = new RSACryptoServiceProvider();
RSAParameters RSAKeyInfo = rsa.ExportParameters(false);
RSAKeyInfo.Modulus = publicKey;
rsa.ImportParameters(RSAKeyInfo);
byte[] encryptedSymmetricKey = RSAEncrypt(Encoding.UTF8.GetBytes(aesGcmEncryptionString), RSAKeyInfo, false);
var enc_key = Convert.ToBase64String(encryptedSymmetricKey);
var requestBodyObject = new { message = encryptedCipher, enckey = enc_key };
string jsonRequestBody = JsonConvert.SerializeObject(requestBodyObject);
#endregion
#region Calculating Message Signature
Random random = new Random();
int ClientRequestId = random.Next(0, 99999999);
var time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
var rawSignature = _ApiKey + ClientRequestId + time + jsonRequestBody;
HMACSHA256 hashObject = new HMACSHA256(Encoding.UTF8.GetBytes(_SecretKey));
var signature = hashObject.ComputeHash(Encoding.UTF8.GetBytes(rawSignature));
var computedHmac = Convert.ToBase64String(signature);
#endregion
#region Make Request
try
{
var client = new RestClient("< API URL>");
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.AddHeader("contentType", "application/json");
request.AddHeader("clientRequestId", ClientRequestId.ToString());
request.AddHeader("apiKey", _ApiKey);
request.AddHeader("timestamp", time.Tostring);
request.AddHeader("messageSignature", computedHmac);
request.AddJsonBody(jsonRequestBody);
request.RequestFormat = DataFormat.Json;
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
#endregion
}
static string GetCertificate()
{
string cer = string.Empty;
// Code to get certicate .crt from the service.
//"<GET CERTICATE HERE>";
return cer;
}
static public byte[] RSAEncrpt(byte[] data, RSAParameters keyInfo, bool doOAEPPadding)
{
byte[] encryptedData;
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
rsa.ImportParameters(keyInfo);
encryptedData = rsa.Encrypt(data, RSAEncryptionPadding.Pkcs1);
}
return encryptedData;
}
}
class Certificate
{
public string crt { get; set; }
}
当服务以不正确的消息签名响应时,我如何跟踪每个步骤。有什么方法可以验证和跟踪上述代码步骤?
帮助!提前致谢
解决方案
推荐阅读
- azure - 如果使用 azure datafactory 存在准备好的文件,如何加载 csv 文件
- javascript - 我可以将一行代码作为变量并应用这行代码(如果存在)吗?
- python - 如何将 pd.Series 添加到多索引 DataFrame 的子集?
- reactjs - 我需要在组件的多个函数中使用我的变量,但似乎无法访问它
- synchronization - 用于同步流式传输多个预先录制的视频的工具,就好像它们是实时网络摄像机一样
- javascript - 启用chartsJS条形图从y轴开始
- javascript - 如何获取 Azure 的 Auth Token 以编程方式创建 azure 资源
- javascript - *ngFor 无法与引导下拉菜单一起正常工作
- python - 根据条件更改数据框行中的值
- python - 如何保存由 zelle 图形模块制作的动画?