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#

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 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;
}
}