You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

160 lines
5.4 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using NPOI.POIFS.Crypt.Dsig;
using Org.BouncyCastle.Crypto.Signers;
using System;
using System.Buffers.Text;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reactive;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Text.Unicode;
using System.Threading.Tasks;
namespace Infrastructure.Helpers
{
public class EncryptionHelper
{
String privateKey = "ABA4354EFAFE944C2F226A3981C7DC70F43BD6053EDA83F4DC274242BBB23CAA";
String publicKey = "04F1BF1BEFD63F16E5DB3BCD32CA5D9A8E8DF7ADD67D6C4F293FB23F7BDA74F52D31B8DDAD03D955D566505A15D8B7DBE83B42378B8E8749C0EB6E2FBC8675838B";
string publickey = "04D6974E2384ECE39F5ADF1473E4B9B60E0D438A6F701F667C0C88D25BE2F8508A3AAFF9D9500ECFFD8E79B2DE58C024B689B5C207486646EA08A352FBB0016D46";
byte[] sm4Key = null;
public EncryptionHelper()
{
}
/// <summary>
/// 获取x-lc-secret
/// </summary>
/// <returns></returns>
public string getxseret()
{
if (sm4Key == null)
{
sm4Key = SM4CryptoHelper.GenerateSM4Key();
}
//十六进制字符串 → 字节数组 publickey
byte[] publickeybyte = HexToBytes(publickey);
var encryptdatasm2 = SM2CryptoHelper.Encrypt(publickeybyte, sm4Key);
return Convert.ToBase64String(encryptdatasm2);
}
/// <summary>
/// 数据加密
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public string Encrypt(byte[] input)
{
if (sm4Key == null)
{
sm4Key = SM4CryptoHelper.GenerateSM4Key();
}
var encryptdatasm4 = SM4CryptoHelper.Encrypt(sm4Key, input);
return Convert.ToBase64String(encryptdatasm4);
}
/// <summary>
/// 数据解密
/// </summary>
/// <param name="x_lc_screte"></param>
/// <param name="output"></param>
/// <returns></returns>
public string Decrypt(byte[] x_lc_screte,byte[] output)
{
byte[] privatekeybyte = HexToBytes(privateKey);
byte[] sm4key = SM2CryptoHelper.Decrypt(privatekeybyte, x_lc_screte);
var decryptdata = SM4CryptoHelper.Decrypt(sm4key, output);
return Encoding.UTF8.GetString(decryptdata);
}
/// <summary>
/// 获取x-lc-token
/// </summary>
/// <param name="certCode"></param>
/// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
public string GetToken(string certCode)
{
// 获取毫秒级时间戳(.NET 中 Ticks 转换为毫秒)
long timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
//long timestamp = 1751274197662;
// 拼接待签名数据
string needSignData = certCode + timestamp;
byte[] needSignDataByte = Encoding.UTF8.GetBytes(needSignData);
// 4. SM2签名
byte[] signData;
byte[] privatekeybyte = HexToBytes(privateKey);
try
{
signData = SM2CryptoHelper.Sign(privatekeybyte, needSignDataByte);
}
catch (Exception ex)
{
throw new InvalidOperationException("SM2签名失败", ex);
}
// Base64 编码签名(直接使用 Convert
string signDataBase64 = Convert.ToBase64String(signData);
// 生成 token
string token = $"{certCode}.{timestamp}.{signDataBase64}";
return token;
}
public bool Verify(string str)
{
string signData = "";
// 拼接待签名数据
string needSignData = "";
if (!string.IsNullOrEmpty(str))
{
string[] tokenstr = str.Split(".");
signData=tokenstr[2];
needSignData = tokenstr[0] + tokenstr[1];
}
byte[] signbyte=Convert.FromBase64String(signData);
byte[] needSignDataByte = Encoding.UTF8.GetBytes(needSignData);
// 4. SM2验签 publickey
byte[] publickeybyte = HexToBytes(publickey);
try
{
return SM2CryptoHelper.Verify(publickeybyte, needSignDataByte, signbyte);
}
catch (Exception ex)
{
throw new InvalidOperationException("SM2签名失败", ex);
}
}
/// <summary>
/// 内部转byte方法
/// </summary>
/// <param name="hex"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="ArgumentException"></exception>
public static byte[] HexToBytes(string hex)
{
if (hex == null)
throw new ArgumentNullException(nameof(hex));
if (hex.Length % 2 != 0)
throw new ArgumentException("十六进制字符串长度必须是偶数");
byte[] bytes = new byte[hex.Length / 2];
for (int i = 0; i < bytes.Length; i++)
{
string byteStr = hex.Substring(i * 2, 2);
bytes[i] = Convert.ToByte(byteStr, 16);
}
return bytes;
}
}
}