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.

97 lines
3.0 KiB
C#

using System;
using System.Text;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Crypto.Signers;
public class TokenGenerator
{
// 1. 获取当前时间的毫秒级时间戳 A
public static long GetCurrentTimestamp()
{
return DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
}
// 2. 拼接 B + A 得到 C
public static string ConcatenateCodeAndTimestamp(string codeB, long timestampA)
{
return $"{codeB}{timestampA}";
}
// 3. 获取 C 的 UTF-8 字节数组 D
public static byte[] GetUtf8Bytes(string input)
{
return Encoding.UTF8.GetBytes(input);
}
// 4. 将 Hex 或 Base64 字符串私钥转换为 ECPrivateKeyParameters
public static ECPrivateKeyParameters ParsePrivateKey(string privateKeyStr)
{
// 假设私钥是 Hex 字符串(如 "ABCD1234..."
byte[] privateKeyBytes = HexToBytes(privateKeyStr); // 如果是 Base64用 Convert.FromBase64String
// SM2 曲线参数
var curve = ECNamedCurveTable.GetByName("sm2p256v1");
var domainParams = new ECDomainParameters(curve.Curve, curve.G, curve.N, curve.H);
// 创建私钥
var privateKey = new ECPrivateKeyParameters(new BigInteger(1, privateKeyBytes), domainParams);
return privateKey;
}
// 5. 使用 SM2 私钥签名 D 得到 E
public static byte[] SignWithSm2(byte[] data, ECPrivateKeyParameters privateKey)
{
var signer = new SM2Signer();
signer.Init(true, privateKey);
signer.BlockUpdate(data, 0, data.Length);
return signer.GenerateSignature();
}
// 6. 对 E 进行 Base64 编码得到 F
public static string Base64Encode(byte[] data)
{
return Convert.ToBase64String(data);
}
// 7. 组装 Token: {B}.{A}.{F}
public static string GenerateToken(string codeB, string privateKeyStr)
{
// 1. 获取时间戳 A
long timestampA = GetCurrentTimestamp();
// 2. 拼接 B + A 得到 C
string c = ConcatenateCodeAndTimestamp(codeB, timestampA);
// 3. 获取 UTF-8 字节数组 D
byte[] d = GetUtf8Bytes(c);
// 4. 解析私钥字符串
ECPrivateKeyParameters privateKey = ParsePrivateKey(privateKeyStr);
// 5. SM2 签名得到 E
byte[] e = SignWithSm2(d, privateKey);
// 6. Base64 编码得到 F
string f = Base64Encode(e);
// 7. 组装 Token
return $"{codeB}.{timestampA}.{f}";
}
// 辅助方法Hex 字符串转字节数组
private static byte[] HexToBytes(string hex)
{
if (hex.Length % 2 != 0)
throw new ArgumentException("Hex 字符串长度必须是偶数");
byte[] bytes = new byte[hex.Length / 2];
for (int i = 0; i < bytes.Length; i++)
{
bytes[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
}
return bytes;
}
}